| # Copyright 2023 The IREE Authors | |
| # | |
| # Licensed under the Apache License v2.0 with LLVM Exceptions. | |
| # See https://llvm.org/LICENSE.txt for license information. | |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| """Rules for compiling with clang to produce bitcode libraries.""" | |
| def iree_arch_to_llvm_arch( | |
| iree_arch = None): | |
| """Converts an IREE_ARCH value to the corresponding LLVM arch name. | |
| Similar to the CMake function with the same name. | |
| Args: | |
| iree_arch: IREE_ARCH string value. | |
| Returns: | |
| The LLVM name for that architecture (first component of target triple). | |
| """ | |
| if not iree_arch: | |
| return None | |
| if iree_arch == "arm_64": | |
| return "aarch64" | |
| if iree_arch == "arm_32": | |
| return "arm" | |
| if iree_arch == "x86_64": | |
| return "x86_64" | |
| if iree_arch == "x86_32": | |
| return "i386" | |
| if iree_arch == "riscv_64": | |
| return "riscv64" | |
| if iree_arch == "riscv_32": | |
| return "riscv32" | |
| if iree_arch == "wasm_64": | |
| return "wasm64" | |
| if iree_arch == "wasm_32": | |
| return "wasm32" | |
| fail("Unhandled IREE_ARCH value %s" % iree_arch) | |
| def iree_bitcode_library( | |
| name, | |
| arch, | |
| srcs, | |
| internal_hdrs = [], | |
| copts = [], | |
| out = None, | |
| **kwargs): | |
| """Builds an LLVM bitcode library from an input file via clang. | |
| Args: | |
| name: Name of the target. | |
| arch: Target architecture to compile for, in IREE_ARCH format. | |
| srcs: source files to pass to clang. | |
| internal_hdrs: all headers transitively included by the source files. | |
| Unlike typical Bazel `hdrs`, these are not exposed as | |
| interface headers. This would normally be part of `srcs`, | |
| but separating it was easier for `bazel_to_cmake`, as | |
| CMake does not need this, and making this explicitly | |
| Bazel-only allows using `filegroup` on the Bazel side. | |
| copts: additional flags to pass to clang. | |
| out: output file name (defaults to name.bc). | |
| **kwargs: any additional attributes to pass to the underlying rules. | |
| """ | |
| clang_tool = "@llvm-project//clang:clang" | |
| link_tool = "@llvm-project//llvm:llvm-link" | |
| builtin_headers_dep = "@llvm-project//clang:builtin_headers_gen" | |
| builtin_headers_path = "external/llvm-project/clang/staging/include/" | |
| base_copts = [ | |
| # Target architecture | |
| "-target", | |
| iree_arch_to_llvm_arch(arch), | |
| # C17 with no system deps. | |
| "-std=c17", | |
| "-nostdinc", | |
| "-ffreestanding", | |
| # Optimized and unstamped. | |
| "-O3", | |
| "-DNDEBUG", | |
| "-fno-ident", | |
| "-fdiscard-value-names", | |
| # Set the size of wchar_t to 4 bytes (instead of 2 bytes). | |
| # This must match what the runtime is built with. | |
| "-fno-short-wchar", | |
| # Enable inline asm. | |
| "-fasm", | |
| # Object file only in bitcode format: | |
| "-c", | |
| "-emit-llvm", | |
| # Force the library into standalone mode (not depending on build-directory | |
| # configuration). | |
| "-DIREE_DEVICE_STANDALONE=1", | |
| ] | |
| if arch == "arm_32": | |
| # Silence "warning: unknown platform, assuming -mfloat-abi=soft" | |
| base_copts.append("-mfloat-abi=soft") | |
| elif arch == "riscv_32": | |
| # On RISC-V, linking LLVM modules requires matching target-abi. | |
| # https://lists.llvm.org/pipermail/llvm-dev/2020-January/138450.html | |
| # The choice of ilp32d is simply what we have in existing riscv_32 tests. | |
| # Open question - how do we scale to supporting all RISC-V ABIs? | |
| base_copts.append("-mabi=ilp32d") | |
| elif arch == "riscv_64": | |
| # Same comments as above riscv_32 case. | |
| base_copts.append("-mabi=lp64d") | |
| bitcode_files = [] | |
| for src in srcs: | |
| bitcode_out = "%s_%s.bc" % (name, src) | |
| bitcode_files.append(bitcode_out) | |
| native.genrule( | |
| name = "gen_%s" % (bitcode_out), | |
| srcs = [src, builtin_headers_dep] + internal_hdrs, | |
| outs = [bitcode_out], | |
| cmd = " && ".join([ | |
| " ".join([ | |
| "$(location %s)" % (clang_tool), | |
| "-isystem $(BINDIR)/%s" % builtin_headers_path, | |
| " ".join(base_copts + copts), | |
| " ".join(["-I $(BINDIR)/runtime/src"]), | |
| " ".join(["-I runtime/src"]), | |
| "-o $(location %s)" % (bitcode_out), | |
| "$(location %s)" % (src), | |
| ]), | |
| ]), | |
| tools = [ | |
| clang_tool, | |
| ], | |
| message = "Compiling %s to %s..." % (src, bitcode_out), | |
| output_to_bindir = 1, | |
| **kwargs | |
| ) | |
| if not out: | |
| out = "%s.bc" % (name) | |
| native.genrule( | |
| name = name, | |
| srcs = bitcode_files, | |
| outs = [out], | |
| cmd = " && ".join([ | |
| " ".join([ | |
| "$(location %s)" % (link_tool), | |
| "-o $(location %s)" % (out), | |
| " ".join(["$(locations %s)" % (src) for src in bitcode_files]), | |
| ]), | |
| ]), | |
| tools = [link_tool], | |
| message = "Linking bitcode library %s to %s..." % (name, out), | |
| output_to_bindir = 1, | |
| **kwargs | |
| ) | |
| def iree_cuda_bitcode_library( | |
| name, | |
| cuda_arch, | |
| srcs, | |
| internal_hdrs = [], | |
| copts = [], | |
| out = None, | |
| **kwargs): | |
| """Builds an LLVM bitcode library for CUDA from an input file via clang. | |
| Args: | |
| name: Name of the target. | |
| cuda_arch: Target sm architecture to compile for. | |
| srcs: source files to pass to clang. | |
| internal_hdrs: all headers transitively included by the source files. | |
| Unlike typical Bazel `hdrs`, these are not exposed as | |
| interface headers. This would normally be part of `srcs`, | |
| but separating it was easier for `bazel_to_cmake`, as | |
| CMake does not need this, and making this explicitly | |
| Bazel-only allows using `filegroup` on the Bazel side. | |
| copts: additional flags to pass to clang. | |
| out: output file name (defaults to name.bc). | |
| **kwargs: any additional attributes to pass to the underlying rules. | |
| """ | |
| clang_tool = "@llvm-project//clang:clang" | |
| link_tool = "@llvm-project//llvm:llvm-link" | |
| builtin_headers_dep = "@llvm-project//clang:builtin_headers_gen" | |
| builtin_headers_path = "external/llvm-project/clang/staging/include/" | |
| base_copts = [ | |
| "-x", | |
| "cuda", | |
| # Target architecture | |
| "--cuda-gpu-arch=%s" % (cuda_arch), | |
| # Suppress warnings | |
| "-Wno-unknown-cuda-version", | |
| "-nocudalib", | |
| "--cuda-device-only", | |
| # Optimized. | |
| "-O3", | |
| # Object file only in bitcode format: | |
| "-c", | |
| "-emit-llvm", | |
| ] | |
| bitcode_files = [] | |
| for src in srcs: | |
| bitcode_out = "%s_%s.bc" % (name, src) | |
| bitcode_files.append(bitcode_out) | |
| native.genrule( | |
| name = "gen_%s" % (bitcode_out), | |
| srcs = [src, builtin_headers_dep] + internal_hdrs, | |
| outs = [bitcode_out], | |
| cmd = " && ".join([ | |
| " ".join([ | |
| "$(location %s)" % (clang_tool), | |
| " ".join(base_copts + copts), | |
| "-o $(location %s)" % (bitcode_out), | |
| "$(location %s)" % (src), | |
| ]), | |
| ]), | |
| tools = [ | |
| clang_tool, | |
| ], | |
| message = "Compiling %s to %s..." % (src, bitcode_out), | |
| output_to_bindir = 1, | |
| **kwargs | |
| ) | |
| if not out: | |
| out = "%s.bc" % (name) | |
| native.genrule( | |
| name = name, | |
| srcs = bitcode_files, | |
| outs = [out], | |
| cmd = " && ".join([ | |
| " ".join([ | |
| "$(location %s)" % (link_tool), | |
| "-o $(location %s)" % (out), | |
| " ".join(["$(locations %s)" % (src) for src in bitcode_files]), | |
| ]), | |
| ]), | |
| tools = [link_tool], | |
| message = "Linking bitcode library %s to %s..." % (name, out), | |
| output_to_bindir = 1, | |
| **kwargs | |
| ) | |
| def iree_link_bitcode( | |
| name, | |
| bitcode_files, | |
| out = None, | |
| link_tool = "@llvm-project//llvm:llvm-link", | |
| **kwargs): | |
| """Builds an LLVM bitcode library from an input file via clang. | |
| Args: | |
| name: Name of the target. | |
| bitcode_files: bitcode files to link together. | |
| out: output file name (defaults to name.bc). | |
| link_tool: llvm-link tool used for linking bitcode files. | |
| **kwargs: any additional attributes to pass to the underlying rules. | |
| """ | |
| 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] | |
| if not out: | |
| out = "%s.bc" % (name) | |
| native.genrule( | |
| name = name, | |
| srcs = bitcode_files_qualified, | |
| outs = [out], | |
| cmd = " && ".join([ | |
| " ".join([ | |
| "$(location %s)" % (link_tool), | |
| "-o $(location %s)" % (out), | |
| " ".join(["$(locations %s)" % (src) for src in bitcode_files_qualified]), | |
| ]), | |
| ]), | |
| tools = [link_tool], | |
| message = "Linking bitcode library %s to %s..." % (name, out), | |
| output_to_bindir = 1, | |
| **kwargs | |
| ) |