blob: 27b1ed64ca06f2881391e02ccc892cdc8a98c8a6 [file] [log] [blame]
# 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
)