1"""This file contains BUILD extensions for generating source code from LLVM's table definition files using the TableGen tool. 2 3See http://llvm.org/cmds/tblgen.html for more information on the TableGen 4tool. 5TODO(chandlerc): Currently this expresses include-based dependencies as 6"sources", and has no transitive understanding due to these files not being 7correctly understood by the build system. 8""" 9 10def _dict_add(*dictionaries): 11 """Returns a new `dict` that has all the entries of the given dictionaries. 12 13 If the same key is present in more than one of the input dictionaries, the 14 last of them in the argument list overrides any earlier ones. 15 16 This function is designed to take zero or one arguments as well as multiple 17 dictionaries, so that it follows arithmetic identities and callers can avoid 18 special cases for their inputs: the sum of zero dictionaries is the empty 19 dictionary, and the sum of a single dictionary is a copy of itself. 20 21 Re-implemented here to avoid adding a dependency on skylib. 22 23 Args: 24 *dictionaries: Zero or more dictionaries to be added. 25 26 Returns: 27 A new `dict` that has all the entries of the given dictionaries. 28 """ 29 result = {} 30 for d in dictionaries: 31 result.update(d) 32 return result 33 34def gentbl(name, tblgen, td_file, td_srcs, tbl_outs, library = True, **kwargs): 35 """gentbl() generates tabular code from a table definition file. 36 37 Args: 38 name: The name of the build rule for use in dependencies. 39 tblgen: The binary used to produce the output. 40 td_file: The primary table definitions file. 41 td_srcs: A list of table definition files included transitively. 42 tbl_outs: A list of tuples (opts, out), where each opts is a string of 43 options passed to tblgen, and the out is the corresponding output file 44 produced. 45 library: Whether to bundle the generated files into a library. 46 **kwargs: Keyword arguments to pass to subsidiary cc_library() rule. 47 """ 48 if td_file not in td_srcs: 49 td_srcs += [td_file] 50 includes = [] 51 for (opts, out) in tbl_outs: 52 outdir = out[:out.rindex("/")] 53 if outdir not in includes: 54 includes.append(outdir) 55 rule_suffix = "_".join(opts.replace("-", "_").replace("=", "_").split(" ")) 56 native.genrule( 57 name = "%s_%s_genrule" % (name, rule_suffix), 58 srcs = td_srcs, 59 outs = [out], 60 tools = [tblgen], 61 message = "Generating code from table: %s" % td_file, 62 cmd = (("$(location %s) " + "-I external/llvm-project/llvm/include " + 63 "-I external/llvm-project/clang/include " + 64 "-I $$(dirname $(location %s)) " + ("%s $(location %s) --long-string-literals=0 " + 65 "-o $@")) % ( 66 tblgen, 67 td_file, 68 opts, 69 td_file, 70 )), 71 ) 72 73 # For now, all generated files can be assumed to comprise public interfaces. 74 # If this is not true, you should specify library = False 75 # and list the generated '.inc' files in "srcs". 76 if library: 77 native.cc_library( 78 name = name, 79 textual_hdrs = [f for (_, f) in tbl_outs], 80 includes = includes, 81 **kwargs 82 ) 83 84def llvm_target_cmake_vars(native_arch, target_triple): 85 return { 86 "LLVM_HOST_TRIPLE": target_triple, 87 "LLVM_DEFAULT_TARGET_TRIPLE": target_triple, 88 "LLVM_NATIVE_ARCH": native_arch, 89 } 90 91def _quote(s): 92 """Quotes the given string for use in a shell command. 93 94 This function double-quotes the given string (in case it contains spaces or 95 other special characters) and escapes any special characters (dollar signs, 96 double-quotes, and backslashes) that may be present. 97 98 Args: 99 s: The string to quote. 100 101 Returns: 102 An escaped and quoted version of the string that can be passed to a shell 103 command. 104 """ 105 return ('"' + 106 s.replace("\\", "\\\\").replace("$", "\\$").replace('"', "\\\"") + 107 '"') 108 109def cmake_var_string(cmake_vars): 110 """Converts a dictionary to an input suitable for expand_cmake_vars. 111 112 Ideally we would jist stringify in the expand_cmake_vars() rule, but select() 113 interacts badly with genrules. 114 115 TODO(phawkins): replace the genrule() with native rule and delete this rule. 116 117 Args: 118 cmake_vars: a dictionary with string keys and values that are convertable to 119 strings. 120 121 Returns: 122 cmake_vars in a form suitable for passing to expand_cmake_vars. 123 """ 124 return " ".join([ 125 _quote("{}={}".format(k, str(v))) 126 for (k, v) in cmake_vars.items() 127 ]) 128 129def expand_cmake_vars(name, src, dst, cmake_vars): 130 """Expands #cmakedefine, #cmakedefine01, and CMake variables in a text file. 131 132 Args: 133 name: the name of the rule 134 src: the input of the rule 135 dst: the output of the rule 136 cmake_vars: a string containing the CMake variables, as generated by 137 cmake_var_string. 138 """ 139 expand_cmake_vars_tool = "@org_tensorflow//third_party/llvm:expand_cmake_vars" 140 native.genrule( 141 name = name, 142 srcs = [src], 143 tools = [expand_cmake_vars_tool], 144 outs = [dst], 145 cmd = ("$(location {}) ".format(expand_cmake_vars_tool) + cmake_vars + 146 "< $< > $@"), 147 ) 148 149# TODO(phawkins): the set of CMake variables was hardcoded for expediency. 150# However, we should really detect many of these via configure-time tests. 151 152# The set of CMake variables common to all targets. 153cmake_vars = { 154 # LLVM features 155 "ENABLE_BACKTRACES": 1, 156 "LLVM_BINDIR": "/dev/null", 157 "LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING": 0, 158 "LLVM_ENABLE_ABI_BREAKING_CHECKS": 0, 159 "LLVM_ENABLE_THREADS": 1, 160 "LLVM_ENABLE_ZLIB": 1, 161 "LLVM_HAS_ATOMICS": 1, 162 "LLVM_INCLUDEDIR": "/dev/null", 163 "LLVM_INFODIR": "/dev/null", 164 "LLVM_MANDIR": "/dev/null", 165 "LLVM_NATIVE_TARGET": 1, 166 "LLVM_NATIVE_TARGETINFO": 1, 167 "LLVM_NATIVE_TARGETMC": 1, 168 "LLVM_NATIVE_ASMPRINTER": 1, 169 "LLVM_NATIVE_ASMPARSER": 1, 170 "LLVM_NATIVE_DISASSEMBLER": 1, 171 "LLVM_PREFIX": "/dev/null", 172 "LLVM_VERSION_MAJOR": 0, 173 "LLVM_VERSION_MINOR": 0, 174 "LLVM_VERSION_PATCH": 0, 175 "PACKAGE_NAME": "llvm", 176 "PACKAGE_STRING": "llvm tensorflow-trunk", 177 "PACKAGE_VERSION": "tensorflow-trunk", 178 "RETSIGTYPE": "void", 179} 180 181# The set of CMake variables common to POSIX targets. 182posix_cmake_vars = { 183 # Headers 184 "HAVE_DIRENT_H": 1, 185 "HAVE_DLFCN_H": 1, 186 "HAVE_ERRNO_H": 1, 187 "HAVE_EXECINFO_H": 1, 188 "HAVE_FCNTL_H": 1, 189 "HAVE_INTTYPES_H": 1, 190 "HAVE_PTHREAD_H": 1, 191 "HAVE_SIGNAL_H": 1, 192 "HAVE_STDINT_H": 1, 193 "HAVE_SYSEXITS_H": 1, 194 "HAVE_SYS_IOCTL_H": 1, 195 "HAVE_SYS_MMAN_H": 1, 196 "HAVE_SYS_PARAM_H": 1, 197 "HAVE_SYS_RESOURCE_H": 1, 198 "HAVE_SYS_STAT_H": 1, 199 "HAVE_SYS_TIME_H": 1, 200 "HAVE_SYS_TYPES_H": 1, 201 "HAVE_TERMIOS_H": 1, 202 "HAVE_UNISTD_H": 1, 203 "HAVE_ZLIB_H": 1, 204 205 # Features 206 "HAVE_BACKTRACE": 1, 207 "BACKTRACE_HEADER": "execinfo.h", 208 "HAVE_DLOPEN": 1, 209 "HAVE_FUTIMES": 1, 210 "HAVE_GETCWD": 1, 211 "HAVE_GETPAGESIZE": 1, 212 "HAVE_GETRLIMIT": 1, 213 "HAVE_GETRUSAGE": 1, 214 "HAVE_GETTIMEOFDAY": 1, 215 "HAVE_INT64_T": 1, 216 "HAVE_ISATTY": 1, 217 "HAVE_LIBEDIT": 1, 218 "HAVE_LIBPTHREAD": 1, 219 "HAVE_LIBZ": 1, 220 "HAVE_MKDTEMP": 1, 221 "HAVE_MKSTEMP": 1, 222 "HAVE_MKTEMP": 1, 223 "HAVE_PREAD": 1, 224 "HAVE_PTHREAD_GETSPECIFIC": 1, 225 "HAVE_PTHREAD_MUTEX_LOCK": 1, 226 "HAVE_PTHREAD_RWLOCK_INIT": 1, 227 "HAVE_REALPATH": 1, 228 "HAVE_SBRK": 1, 229 "HAVE_SETENV": 1, 230 "HAVE_SETRLIMIT": 1, 231 "HAVE_SIGALTSTACK": 1, 232 "HAVE_STRERROR": 1, 233 "HAVE_STRERROR_R": 1, 234 "HAVE_STRTOLL": 1, 235 "HAVE_SYSCONF": 1, 236 "HAVE_UINT64_T": 1, 237 "HAVE__UNWIND_BACKTRACE": 1, 238 239 # LLVM features 240 "LLVM_ON_UNIX": 1, 241 "LTDL_SHLIB_EXT": ".so", 242} 243 244# CMake variables specific to the Linux platform 245linux_cmake_vars = { 246 "HAVE_MALLOC_H": 1, 247 "HAVE_LINK_H": 1, 248 "HAVE_MALLINFO": 1, 249 "HAVE_FUTIMENS": 1, 250} 251 252# CMake variables specific to the FreeBSD platform 253freebsd_cmake_vars = { 254 "HAVE_MALLOC_H": 1, 255 "HAVE_LINK_H": 1, 256} 257 258# CMake variables specific to the Darwin (Mac OS X) platform. 259darwin_cmake_vars = { 260 "HAVE_MALLOC_MALLOC_H": 1, 261 "HAVE_MALLOC_ZONE_STATISTICS": 1, 262} 263 264# CMake variables specific to the Windows platform. 265win32_cmake_vars = { 266 # Headers 267 "HAVE_ERRNO_H": 1, 268 "HAVE_EXECINFO_H": 1, 269 "HAVE_FCNTL_H": 1, 270 "HAVE_FENV_H": 1, 271 "HAVE_INTTYPES_H": 1, 272 "HAVE_MALLOC_H": 1, 273 "HAVE_SIGNAL_H": 1, 274 "HAVE_STDINT_H": 1, 275 "HAVE_SYS_STAT_H": 1, 276 "HAVE_SYS_TYPES_H": 1, 277 "HAVE_ZLIB_H": 1, 278 279 # Features 280 "BACKTRACE_HEADER": "execinfo.h", 281 "HAVE_GETCWD": 1, 282 "HAVE_INT64_T": 1, 283 "HAVE_STRERROR": 1, 284 "HAVE_STRTOLL": 1, 285 "HAVE_SYSCONF": 1, 286 "HAVE_UINT64_T": 1, 287 "HAVE__CHSIZE_S": 1, 288 "HAVE___CHKSTK": 1, 289 290 # MSVC specific 291 "stricmp": "_stricmp", 292 "strdup": "_strdup", 293 294 # LLVM features 295 "LTDL_SHLIB_EXT": ".dll", 296} 297 298# Select a set of CMake variables based on the platform. 299# TODO(phawkins): use a better method to select the right host triple, rather 300# than hardcoding x86_64. 301llvm_all_cmake_vars = select({ 302 "@org_tensorflow//tensorflow:macos_x86_64": cmake_var_string( 303 _dict_add( 304 cmake_vars, 305 llvm_target_cmake_vars("X86", "x86_64-apple-darwin"), 306 posix_cmake_vars, 307 darwin_cmake_vars, 308 ), 309 ), 310 "@org_tensorflow//tensorflow:macos_arm64": cmake_var_string( 311 _dict_add( 312 cmake_vars, 313 llvm_target_cmake_vars("AArch64", "arm64-apple-darwin"), 314 posix_cmake_vars, 315 darwin_cmake_vars, 316 ), 317 ), 318 "@org_tensorflow//tensorflow:linux_aarch64": cmake_var_string( 319 _dict_add( 320 cmake_vars, 321 llvm_target_cmake_vars("AArch64", "aarch64-unknown-linux_gnu"), 322 posix_cmake_vars, 323 linux_cmake_vars, 324 ), 325 ), 326 "@org_tensorflow//tensorflow:linux_ppc64le": cmake_var_string( 327 _dict_add( 328 cmake_vars, 329 llvm_target_cmake_vars("PowerPC", "powerpc64le-unknown-linux_gnu"), 330 posix_cmake_vars, 331 linux_cmake_vars, 332 ), 333 ), 334 "@org_tensorflow//tensorflow:windows": cmake_var_string( 335 _dict_add( 336 cmake_vars, 337 llvm_target_cmake_vars("X86", "x86_64-pc-win32"), 338 win32_cmake_vars, 339 ), 340 ), 341 "@org_tensorflow//tensorflow:freebsd": cmake_var_string( 342 _dict_add( 343 cmake_vars, 344 llvm_target_cmake_vars("X86", "x86_64-unknown-freebsd"), 345 posix_cmake_vars, 346 ), 347 ), 348 "@org_tensorflow//tensorflow:linux_s390x": cmake_var_string( 349 _dict_add( 350 cmake_vars, 351 llvm_target_cmake_vars("SystemZ", "systemz-unknown-linux_gnu"), 352 posix_cmake_vars, 353 linux_cmake_vars, 354 ), 355 ), 356 "//conditions:default": cmake_var_string( 357 _dict_add( 358 cmake_vars, 359 llvm_target_cmake_vars("X86", "x86_64-unknown-linux_gnu"), 360 posix_cmake_vars, 361 linux_cmake_vars, 362 ), 363 ), 364}) 365 366llvm_linkopts = select({ 367 "@org_tensorflow//tensorflow:windows": [], 368 "@org_tensorflow//tensorflow:freebsd": ["-ldl", "-lm", "-lpthread", "-lexecinfo"], 369 "//conditions:default": ["-ldl", "-lm", "-lpthread"], 370}) 371 372llvm_defines = select({ 373 "@org_tensorflow//tensorflow:windows": [ 374 "_CRT_SECURE_NO_DEPRECATE", 375 "_CRT_SECURE_NO_WARNINGS", 376 "_CRT_NONSTDC_NO_DEPRECATE", 377 "_CRT_NONSTDC_NO_WARNINGS", 378 "_SCL_SECURE_NO_DEPRECATE", 379 "_SCL_SECURE_NO_WARNINGS", 380 "UNICODE", 381 "_UNICODE", 382 ], 383 "//conditions:default": [], 384}) + [ 385 "LLVM_ENABLE_STATS", 386 "__STDC_LIMIT_MACROS", 387 "__STDC_CONSTANT_MACROS", 388 "__STDC_FORMAT_MACROS", 389 "LLVM_BUILD_GLOBAL_ISEL", 390] 391 392llvm_copts = select({ 393 "@org_tensorflow//tensorflow:windows": [ 394 "-Zc:inline", 395 "-Zc:strictStrings", 396 "-Zc:rvalueCast", 397 "-Oi", 398 "-wd4141", 399 "-wd4146", 400 "-wd4180", 401 "-wd4244", 402 "-wd4258", 403 "-wd4267", 404 "-wd4291", 405 "-wd4345", 406 "-wd4351", 407 "-wd4355", 408 "-wd4456", 409 "-wd4457", 410 "-wd4458", 411 "-wd4459", 412 "-wd4503", 413 "-wd4624", 414 "-wd4722", 415 "-wd4800", 416 "-wd4100", 417 "-wd4127", 418 "-wd4512", 419 "-wd4505", 420 "-wd4610", 421 "-wd4510", 422 "-wd4702", 423 "-wd4245", 424 "-wd4706", 425 "-wd4310", 426 "-wd4701", 427 "-wd4703", 428 "-wd4389", 429 "-wd4611", 430 "-wd4805", 431 "-wd4204", 432 "-wd4577", 433 "-wd4091", 434 "-wd4592", 435 "-wd4319", 436 "-wd4324", 437 "-w14062", 438 "-we4238", 439 ], 440 "//conditions:default": [], 441}) 442 443# Platform specific sources for libSupport. 444 445def llvm_support_platform_specific_srcs_glob(): 446 return select({ 447 "@org_tensorflow//tensorflow:windows": native.glob([ 448 "lib/Support/Windows/*.inc", 449 "lib/Support/Windows/*.h", 450 ]), 451 "//conditions:default": native.glob([ 452 "lib/Support/Unix/*.inc", 453 "lib/Support/Unix/*.h", 454 ]), 455 }) 456