1# This file is licensed under the Apache License v2.0 with LLVM Exceptions. 2# See https://llvm.org/LICENSE.txt for license information. 3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 5"""LLVM libc starlark rules for building individual functions.""" 6 7load("@bazel_skylib//lib:paths.bzl", "paths") 8load("@bazel_skylib//lib:selects.bzl", "selects") 9load(":libc_configure_options.bzl", "LIBC_CONFIGURE_OPTIONS") 10load(":libc_namespace.bzl", "LIBC_NAMESPACE") 11load(":platforms.bzl", "PLATFORM_CPU_X86_64") 12 13def libc_internal_target(name): 14 return name + ".__internal__" 15 16def libc_common_copts(): 17 root_label = Label(":libc") 18 libc_include_path = paths.join(root_label.workspace_root, root_label.package) 19 return [ 20 "-I" + libc_include_path, 21 "-I" + paths.join(libc_include_path, "include"), 22 "-DLIBC_NAMESPACE=" + LIBC_NAMESPACE, 23 ] 24 25def libc_release_copts(): 26 copts = [ 27 "-DLIBC_COPT_PUBLIC_PACKAGING", 28 # This is used to explicitly give public symbols "default" visibility. 29 # See src/__support/common.h for more information. 30 "-DLLVM_LIBC_FUNCTION_ATTR='[[gnu::visibility(\"default\")]]'", 31 # All other libc sources need to be compiled with "hidden" visibility. 32 "-fvisibility=hidden", 33 "-O3", 34 "-fno-builtin", 35 "-fno-lax-vector-conversions", 36 "-ftrivial-auto-var-init=pattern", 37 "-fno-omit-frame-pointer", 38 "-fstack-protector-strong", 39 ] 40 41 platform_copts = selects.with_or({ 42 PLATFORM_CPU_X86_64: ["-mno-omit-leaf-frame-pointer"], 43 "//conditions:default": [], 44 }) 45 return copts + platform_copts 46 47def _libc_library(name, copts = [], deps = [], local_defines = [], **kwargs): 48 """Internal macro to serve as a base for all other libc library rules. 49 50 Args: 51 name: Target name. 52 copts: The special compiler options for the target. 53 deps: The list of target dependencies if any. 54 local_defines: The list of target local_defines if any. 55 **kwargs: All other attributes relevant for the cc_library rule. 56 """ 57 58 native.cc_library( 59 name = name, 60 copts = copts + libc_common_copts(), 61 local_defines = local_defines + LIBC_CONFIGURE_OPTIONS, 62 deps = deps, 63 linkstatic = 1, 64 **kwargs 65 ) 66 67# A convenience function which should be used to list all libc support libraries. 68# Any library which does not define a public function should be listed with 69# libc_support_library. 70def libc_support_library(name, **kwargs): 71 _libc_library(name = name, **kwargs) 72 73def libc_function( 74 name, 75 srcs, 76 weak = False, 77 copts = [], 78 local_defines = [], 79 **kwargs): 80 """Add target for a libc function. 81 82 The libc function is eventually available as a cc_library target by name 83 "name". LLVM libc implementations of libc functions are in C++. So, this 84 rule internally generates a C wrapper for the C++ implementation and adds 85 it to the source list of the cc_library. This way, the C++ implementation 86 and the C wrapper are both available in the cc_library. 87 88 Args: 89 name: Target name. It is normally the name of the function this target is 90 for. 91 srcs: The .cpp files which contain the function implementation. 92 weak: Make the symbol corresponding to the libc function "weak". 93 copts: The list of options to add to the C++ compilation command. 94 local_defines: The preprocessor defines which will be prepended with -D 95 and passed to the compile command of this target but not 96 its deps. 97 **kwargs: Other attributes relevant for a cc_library. For example, deps. 98 """ 99 100 # We compile the code twice, the first target is suffixed with ".__internal__" and contains the 101 # C++ functions in the "LIBC_NAMESPACE" namespace. This allows us to test the function in the 102 # presence of another libc. 103 libc_support_library( 104 name = libc_internal_target(name), 105 srcs = srcs, 106 copts = copts, 107 local_defines = local_defines, 108 **kwargs 109 ) 110 111 # This second target is the llvm libc C function with default visibility. 112 func_attrs = [ 113 "LLVM_LIBC_FUNCTION_ATTR_" + name + "='LLVM_LIBC_EMPTY, [[gnu::weak]]'", 114 ] if weak else [] 115 116 _libc_library( 117 name = name, 118 srcs = srcs, 119 copts = copts + libc_release_copts(), 120 local_defines = local_defines + func_attrs, 121 **kwargs 122 ) 123 124def libc_math_function( 125 name, 126 additional_deps = None): 127 """Add a target for a math function. 128 129 Args: 130 name: The name of the function. 131 additional_deps: Other deps like helper cc_library targes used by the 132 math function. 133 """ 134 additional_deps = additional_deps or [] 135 136 #TODO(michaelrj): Fix the floating point dependencies 137 OLD_FPUTIL_DEPS = [ 138 ":__support_fputil_basic_operations", 139 ":__support_fputil_division_and_remainder_operations", 140 ":__support_fputil_fenv_impl", 141 ":__support_fputil_fp_bits", 142 ":__support_fputil_hypot", 143 ":__support_fputil_manipulation_functions", 144 ":__support_fputil_nearest_integer_operations", 145 ":__support_fputil_normal_float", 146 ":__support_math_extras", 147 ":__support_fputil_except_value_utils", 148 ] 149 libc_function( 150 name = name, 151 srcs = ["src/math/generic/" + name + ".cpp"], 152 hdrs = ["src/math/" + name + ".h"], 153 deps = [":__support_common"] + OLD_FPUTIL_DEPS + additional_deps, 154 ) 155