Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 1 | # Copyright 2023 The IREE Authors |
| 2 | # |
| 3 | # Licensed under the Apache License v2.0 with LLVM Exceptions. |
| 4 | # See https://llvm.org/LICENSE.txt for license information. |
| 5 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | |
| 7 | """Rules for compiling with clang to produce bitcode libraries.""" |
| 8 | |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 9 | def iree_arch_to_llvm_arch( |
| 10 | iree_arch = None): |
| 11 | """Converts an IREE_ARCH value to the corresponding LLVM arch name. |
| 12 | |
| 13 | Similar to the CMake function with the same name. |
| 14 | |
| 15 | Args: |
| 16 | iree_arch: IREE_ARCH string value. |
| 17 | |
| 18 | Returns: |
| 19 | The LLVM name for that architecture (first component of target triple). |
| 20 | """ |
| 21 | |
| 22 | if not iree_arch: |
| 23 | return None |
| 24 | if iree_arch == "arm_64": |
| 25 | return "aarch64" |
| 26 | if iree_arch == "arm_32": |
| 27 | return "arm" |
| 28 | if iree_arch == "x86_64": |
| 29 | return "x86_64" |
| 30 | if iree_arch == "x86_32": |
| 31 | return "i386" |
| 32 | if iree_arch == "riscv_64": |
| 33 | return "riscv64" |
| 34 | if iree_arch == "riscv_32": |
| 35 | return "riscv32" |
| 36 | if iree_arch == "wasm_64": |
| 37 | return "wasm64" |
| 38 | if iree_arch == "wasm_32": |
| 39 | return "wasm32" |
| 40 | fail("Unhandled IREE_ARCH value %s" % iree_arch) |
| 41 | |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 42 | def iree_bitcode_library( |
| 43 | name, |
bjacob | 446a542 | 2023-06-01 06:10:27 -0400 | [diff] [blame] | 44 | arch, |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 45 | srcs, |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 46 | internal_hdrs = [], |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 47 | copts = [], |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 48 | out = None, |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 49 | **kwargs): |
| 50 | """Builds an LLVM bitcode library from an input file via clang. |
| 51 | |
| 52 | Args: |
| 53 | name: Name of the target. |
bjacob | 446a542 | 2023-06-01 06:10:27 -0400 | [diff] [blame] | 54 | arch: Target architecture to compile for, in IREE_ARCH format. |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 55 | srcs: source files to pass to clang. |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 56 | internal_hdrs: all headers transitively included by the source files. |
| 57 | Unlike typical Bazel `hdrs`, these are not exposed as |
| 58 | interface headers. This would normally be part of `srcs`, |
| 59 | but separating it was easier for `bazel_to_cmake`, as |
| 60 | CMake does not need this, and making this explicitly |
| 61 | Bazel-only allows using `filegroup` on the Bazel side. |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 62 | copts: additional flags to pass to clang. |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 63 | out: output file name (defaults to name.bc). |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 64 | **kwargs: any additional attributes to pass to the underlying rules. |
| 65 | """ |
| 66 | |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 67 | clang_tool = "@llvm-project//clang:clang" |
| 68 | link_tool = "@llvm-project//llvm:llvm-link" |
| 69 | builtin_headers_dep = "@llvm-project//clang:builtin_headers_gen" |
| 70 | builtin_headers_path = "external/llvm-project/clang/staging/include/" |
| 71 | |
| 72 | base_copts = [ |
bjacob | 446a542 | 2023-06-01 06:10:27 -0400 | [diff] [blame] | 73 | # Target architecture |
| 74 | "-target", |
| 75 | iree_arch_to_llvm_arch(arch), |
| 76 | |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 77 | # C17 with no system deps. |
| 78 | "-std=c17", |
| 79 | "-nostdinc", |
| 80 | "-ffreestanding", |
| 81 | |
| 82 | # Optimized and unstamped. |
| 83 | "-O3", |
| 84 | "-DNDEBUG", |
| 85 | "-fno-ident", |
| 86 | "-fdiscard-value-names", |
| 87 | |
| 88 | # Set the size of wchar_t to 4 bytes (instead of 2 bytes). |
| 89 | # This must match what the runtime is built with. |
| 90 | "-fno-short-wchar", |
| 91 | |
bjacob | bf8588e | 2023-06-01 06:37:13 -0400 | [diff] [blame] | 92 | # Enable inline asm. |
| 93 | "-fasm", |
| 94 | |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 95 | # Object file only in bitcode format: |
| 96 | "-c", |
| 97 | "-emit-llvm", |
| 98 | |
| 99 | # Force the library into standalone mode (not depending on build-directory |
| 100 | # configuration). |
| 101 | "-DIREE_DEVICE_STANDALONE=1", |
| 102 | ] |
| 103 | |
Benoit Jacob | 7d736b5 | 2024-01-18 11:54:39 -0500 | [diff] [blame] | 104 | if arch == "arm_32": |
| 105 | # Silence "warning: unknown platform, assuming -mfloat-abi=soft" |
| 106 | base_copts.append("-mfloat-abi=soft") |
| 107 | elif arch == "riscv_32": |
| 108 | # On RISC-V, linking LLVM modules requires matching target-abi. |
| 109 | # https://lists.llvm.org/pipermail/llvm-dev/2020-January/138450.html |
| 110 | # The choice of ilp32d is simply what we have in existing riscv_32 tests. |
| 111 | # Open question - how do we scale to supporting all RISC-V ABIs? |
| 112 | base_copts.append("-mabi=ilp32d") |
| 113 | elif arch == "riscv_64": |
| 114 | # Same comments as above riscv_32 case. |
| 115 | base_copts.append("-mabi=lp64d") |
| 116 | |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 117 | bitcode_files = [] |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 118 | for src in srcs: |
| 119 | bitcode_out = "%s_%s.bc" % (name, src) |
bjacob | 446a542 | 2023-06-01 06:10:27 -0400 | [diff] [blame] | 120 | bitcode_files.append(bitcode_out) |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 121 | native.genrule( |
| 122 | name = "gen_%s" % (bitcode_out), |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 123 | srcs = [src, builtin_headers_dep] + internal_hdrs, |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 124 | outs = [bitcode_out], |
| 125 | cmd = " && ".join([ |
| 126 | " ".join([ |
| 127 | "$(location %s)" % (clang_tool), |
MaheshRavishankar | 29647b3 | 2023-05-19 10:54:42 -0700 | [diff] [blame] | 128 | "-isystem $(BINDIR)/%s" % builtin_headers_path, |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 129 | " ".join(base_copts + copts), |
MaheshRavishankar | 29647b3 | 2023-05-19 10:54:42 -0700 | [diff] [blame] | 130 | " ".join(["-I $(BINDIR)/runtime/src"]), |
| 131 | " ".join(["-I runtime/src"]), |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 132 | "-o $(location %s)" % (bitcode_out), |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 133 | "$(location %s)" % (src), |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 134 | ]), |
| 135 | ]), |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 136 | tools = [ |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 137 | clang_tool, |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 138 | ], |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 139 | message = "Compiling %s to %s..." % (src, bitcode_out), |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 140 | output_to_bindir = 1, |
| 141 | **kwargs |
| 142 | ) |
| 143 | |
| 144 | if not out: |
| 145 | out = "%s.bc" % (name) |
MaheshRavishankar | 37c79f0 | 2023-06-27 11:31:33 -0700 | [diff] [blame] | 146 | |
| 147 | native.genrule( |
| 148 | name = name, |
| 149 | srcs = bitcode_files, |
| 150 | outs = [out], |
| 151 | cmd = " && ".join([ |
| 152 | " ".join([ |
| 153 | "$(location %s)" % (link_tool), |
| 154 | "-o $(location %s)" % (out), |
| 155 | " ".join(["$(locations %s)" % (src) for src in bitcode_files]), |
| 156 | ]), |
| 157 | ]), |
| 158 | tools = [link_tool], |
| 159 | message = "Linking bitcode library %s to %s..." % (name, out), |
| 160 | output_to_bindir = 1, |
| 161 | **kwargs |
| 162 | ) |
| 163 | |
| 164 | def iree_cuda_bitcode_library( |
| 165 | name, |
| 166 | cuda_arch, |
| 167 | srcs, |
| 168 | internal_hdrs = [], |
| 169 | copts = [], |
| 170 | out = None, |
| 171 | **kwargs): |
| 172 | """Builds an LLVM bitcode library for CUDA from an input file via clang. |
| 173 | |
| 174 | Args: |
| 175 | name: Name of the target. |
| 176 | cuda_arch: Target sm architecture to compile for. |
| 177 | srcs: source files to pass to clang. |
| 178 | internal_hdrs: all headers transitively included by the source files. |
| 179 | Unlike typical Bazel `hdrs`, these are not exposed as |
| 180 | interface headers. This would normally be part of `srcs`, |
| 181 | but separating it was easier for `bazel_to_cmake`, as |
| 182 | CMake does not need this, and making this explicitly |
| 183 | Bazel-only allows using `filegroup` on the Bazel side. |
| 184 | copts: additional flags to pass to clang. |
| 185 | out: output file name (defaults to name.bc). |
| 186 | **kwargs: any additional attributes to pass to the underlying rules. |
| 187 | """ |
| 188 | |
| 189 | clang_tool = "@llvm-project//clang:clang" |
| 190 | link_tool = "@llvm-project//llvm:llvm-link" |
| 191 | builtin_headers_dep = "@llvm-project//clang:builtin_headers_gen" |
| 192 | builtin_headers_path = "external/llvm-project/clang/staging/include/" |
| 193 | |
| 194 | base_copts = [ |
| 195 | "-x", |
| 196 | "cuda", |
| 197 | |
| 198 | # Target architecture |
| 199 | "--cuda-gpu-arch=%s" % (cuda_arch), |
| 200 | |
| 201 | # Suppress warnings |
| 202 | "-Wno-unknown-cuda-version", |
| 203 | "-nocudalib", |
| 204 | "--cuda-device-only", |
| 205 | |
| 206 | # Optimized. |
| 207 | "-O3", |
| 208 | |
| 209 | # Object file only in bitcode format: |
| 210 | "-c", |
| 211 | "-emit-llvm", |
| 212 | ] |
| 213 | |
| 214 | bitcode_files = [] |
| 215 | for src in srcs: |
| 216 | bitcode_out = "%s_%s.bc" % (name, src) |
| 217 | bitcode_files.append(bitcode_out) |
| 218 | native.genrule( |
| 219 | name = "gen_%s" % (bitcode_out), |
| 220 | srcs = [src, builtin_headers_dep] + internal_hdrs, |
| 221 | outs = [bitcode_out], |
| 222 | cmd = " && ".join([ |
| 223 | " ".join([ |
| 224 | "$(location %s)" % (clang_tool), |
| 225 | " ".join(base_copts + copts), |
| 226 | "-o $(location %s)" % (bitcode_out), |
| 227 | "$(location %s)" % (src), |
| 228 | ]), |
| 229 | ]), |
| 230 | tools = [ |
| 231 | clang_tool, |
| 232 | ], |
| 233 | message = "Compiling %s to %s..." % (src, bitcode_out), |
| 234 | output_to_bindir = 1, |
| 235 | **kwargs |
| 236 | ) |
| 237 | |
| 238 | if not out: |
| 239 | out = "%s.bc" % (name) |
| 240 | |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 241 | native.genrule( |
| 242 | name = name, |
| 243 | srcs = bitcode_files, |
| 244 | outs = [out], |
| 245 | cmd = " && ".join([ |
| 246 | " ".join([ |
| 247 | "$(location %s)" % (link_tool), |
| 248 | "-o $(location %s)" % (out), |
| 249 | " ".join(["$(locations %s)" % (src) for src in bitcode_files]), |
| 250 | ]), |
| 251 | ]), |
bjacob | 041b4e8 | 2023-05-30 19:59:26 -0400 | [diff] [blame] | 252 | tools = [link_tool], |
Ben Vanik | 7f6c57c | 2023-02-07 18:04:32 -0800 | [diff] [blame] | 253 | message = "Linking bitcode library %s to %s..." % (name, out), |
| 254 | output_to_bindir = 1, |
| 255 | **kwargs |
| 256 | ) |
MaheshRavishankar | 29647b3 | 2023-05-19 10:54:42 -0700 | [diff] [blame] | 257 | |
| 258 | def iree_link_bitcode( |
| 259 | name, |
| 260 | bitcode_files, |
| 261 | out = None, |
| 262 | link_tool = "@llvm-project//llvm:llvm-link", |
| 263 | **kwargs): |
| 264 | """Builds an LLVM bitcode library from an input file via clang. |
| 265 | |
| 266 | Args: |
| 267 | name: Name of the target. |
| 268 | bitcode_files: bitcode files to link together. |
| 269 | out: output file name (defaults to name.bc). |
| 270 | link_tool: llvm-link tool used for linking bitcode files. |
| 271 | **kwargs: any additional attributes to pass to the underlying rules. |
| 272 | """ |
| 273 | |
Benoit Jacob | 7d736b5 | 2024-01-18 11:54:39 -0500 | [diff] [blame] | 274 | bitcode_files_qualified = [("//" + native.package_name() + b) if b.startswith(":") else ("//" + native.package_name() + "/" + b) if b.count(":") else b for b in bitcode_files] |
MaheshRavishankar | 29647b3 | 2023-05-19 10:54:42 -0700 | [diff] [blame] | 275 | |
| 276 | if not out: |
| 277 | out = "%s.bc" % (name) |
| 278 | native.genrule( |
| 279 | name = name, |
| 280 | srcs = bitcode_files_qualified, |
| 281 | outs = [out], |
| 282 | cmd = " && ".join([ |
| 283 | " ".join([ |
| 284 | "$(location %s)" % (link_tool), |
| 285 | "-o $(location %s)" % (out), |
| 286 | " ".join(["$(locations %s)" % (src) for src in bitcode_files_qualified]), |
| 287 | ]), |
| 288 | ]), |
| 289 | tools = [link_tool], |
| 290 | message = "Linking bitcode library %s to %s..." % (name, out), |
| 291 | output_to_bindir = 1, |
| 292 | **kwargs |
| 293 | ) |