rt.mk (13108B)
1 # mk/rt.mk 2 # =========================================================================== 3 # Runtime (libkit_rt.a) variant selection and per-variant source/flag 4 # derivation -> RT_OBJS_<variant> / RT_CFLAGS_<variant> / RT_ASFLAGS_<variant>. 5 # 6 # The build rules that consume these live in the top-level Makefile. This file 7 # is the data: the variant table, the host-native variant detection, the 8 # feature->source/flag groups, and the template that expands one variant into 9 # its concrete source/object/flag lists. Paths are root-relative. 10 11 RT_BUILD_DIR ?= $(BUILD_DIR)/rt 12 RT_COMMON_CFLAGS = -Werror 13 RT_LIB_INCS = -Irt/lib/include/common -Irt/lib/impl 14 15 RT_VARIANTS = \ 16 x86_64-linux \ 17 x86_64-freebsd \ 18 x86_64-apple-darwin \ 19 x86_64-apple-ios-simulator \ 20 x86_64-elf \ 21 aarch64-linux \ 22 aarch64-linux-android \ 23 aarch64-freebsd \ 24 aarch64-apple-darwin \ 25 aarch64-apple-ios \ 26 aarch64-apple-ios-simulator \ 27 aarch64-elf \ 28 riscv64-linux \ 29 riscv64-freebsd \ 30 riscv64-elf \ 31 riscv64-elf-save-restore \ 32 aarch64-windows \ 33 x86_64-pc-windows \ 34 i386-linux \ 35 wasm32 \ 36 riscv32-elf \ 37 riscv32-elf-save-restore \ 38 riscv32-elf-hardfloat \ 39 arm-eabi-thumb2 \ 40 arm-eabi-thumb1 41 42 RT_HOST_MACHINE ?= $(shell uname -m 2>/dev/null || printf unknown) 43 RT_NATIVE_VARIANT = 44 ifeq ($(HOST_UNAME),Darwin) 45 ifneq ($(filter arm64 aarch64,$(RT_HOST_MACHINE)),) 46 RT_NATIVE_VARIANT = aarch64-apple-darwin 47 else ifneq ($(filter x86_64 amd64,$(RT_HOST_MACHINE)),) 48 RT_NATIVE_VARIANT = x86_64-apple-darwin 49 endif 50 else ifeq ($(HOST_UNAME),Linux) 51 ifneq ($(filter x86_64 amd64,$(RT_HOST_MACHINE)),) 52 RT_NATIVE_VARIANT = x86_64-linux 53 else ifneq ($(filter arm64 aarch64,$(RT_HOST_MACHINE)),) 54 RT_NATIVE_VARIANT = aarch64-linux 55 else ifneq ($(filter riscv64,$(RT_HOST_MACHINE)),) 56 RT_NATIVE_VARIANT = riscv64-linux 57 else ifneq ($(filter i386 i486 i586 i686,$(RT_HOST_MACHINE)),) 58 RT_NATIVE_VARIANT = i386-linux 59 endif 60 else ifneq ($(filter MINGW% MSYS% CYGWIN%,$(HOST_UNAME)),) 61 ifneq ($(filter x86_64 amd64,$(RT_HOST_MACHINE)),) 62 RT_NATIVE_VARIANT = x86_64-pc-windows 63 else ifneq ($(filter arm64 aarch64,$(RT_HOST_MACHINE)),) 64 RT_NATIVE_VARIANT = aarch64-windows 65 endif 66 else ifeq ($(HOST_UNAME),FreeBSD) 67 ifneq ($(filter x86_64 amd64,$(RT_HOST_MACHINE)),) 68 RT_NATIVE_VARIANT = x86_64-freebsd 69 else ifneq ($(filter arm64 aarch64,$(RT_HOST_MACHINE)),) 70 RT_NATIVE_VARIANT = aarch64-freebsd 71 else ifneq ($(filter riscv64,$(RT_HOST_MACHINE)),) 72 RT_NATIVE_VARIANT = riscv64-freebsd 73 endif 74 endif 75 76 RT_DEFAULT_VARIANTS ?= $(RT_NATIVE_VARIANT) 77 78 # ---------- variant feature flags -------------------------------------------- 79 # Every variant sets the same four core properties (target triple, ABI model, 80 # __int128 availability, coroutine micro-arch), so they come from one setter to 81 # kill the per-variant boilerplate. The sparse optional properties below stay 82 # as explicit `RT_<v>_<prop>` lines next to the variant they qualify — they 83 # carry per-target rationale comments and several hold space-containing flag 84 # strings, so keeping them literal avoids any descriptor-encoding hazard. 85 # TARGET - clang target triple (rt-core arg 2) 86 # ABI - lp64 | ilp32 | llp64 (rt-core arg 3) 87 # INT128 - 0 | 1 (rt-core arg 4) 88 # CORO - x86_64 | x86_64_win | i386 | aarch64 | 89 # arm32 | arm32_thumb1 | riscv32 | 90 # riscv64 | empty (rt-core arg 5) 91 # LDBL128 - 1 enables binary128 long double support 92 # SAVE_RESTORE - 1 enables RISC-V save-restore routines 93 # AEABI - thumb2 | thumb1 | empty 94 # ARCH_FLAGS - extra target-specific flags 95 # HOSTED - 1 ships the compiler-rt subset instead of the full libc set 96 # RT_EXTRA_SRCS - per-variant extra runtime sources 97 # $(1)=variant $(2)=TARGET $(3)=ABI $(4)=INT128 $(5)=CORO 98 define rt-core 99 RT_$(1)_TARGET = $(2) 100 RT_$(1)_ABI = $(3) 101 RT_$(1)_INT128 = $(4) 102 RT_$(1)_CORO = $(5) 103 endef 104 105 $(eval $(call rt-core,x86_64-linux,x86_64-linux-gnu,lp64,1,x86_64)) 106 $(eval $(call rt-core,x86_64-freebsd,x86_64-unknown-freebsd,lp64,1,x86_64)) 107 $(eval $(call rt-core,x86_64-apple-darwin,x86_64-apple-darwin,lp64,1,x86_64)) 108 $(eval $(call rt-core,x86_64-apple-ios-simulator,x86_64-apple-ios-simulator,lp64,1,x86_64)) 109 $(eval $(call rt-core,x86_64-elf,x86_64-unknown-elf,lp64,1,x86_64)) 110 111 $(eval $(call rt-core,aarch64-linux,aarch64-linux-gnu,lp64,1,aarch64)) 112 RT_aarch64-linux_LDBL128 = 1 113 RT_EXTRA_SRCS_aarch64-linux = rt/lib/coro/aarch64_elf.s 114 115 $(eval $(call rt-core,aarch64-linux-android,aarch64-linux-android21,lp64,1,aarch64)) 116 RT_aarch64-linux-android_LDBL128 = 1 117 RT_EXTRA_SRCS_aarch64-linux-android = rt/lib/coro/aarch64_elf.s 118 119 $(eval $(call rt-core,aarch64-freebsd,aarch64-unknown-freebsd,lp64,1,aarch64)) 120 RT_aarch64-freebsd_LDBL128 = 1 121 RT_EXTRA_SRCS_aarch64-freebsd = rt/lib/coro/aarch64_elf.s 122 123 $(eval $(call rt-core,aarch64-apple-darwin,aarch64-apple-darwin,lp64,1,aarch64)) 124 RT_EXTRA_SRCS_aarch64-apple-darwin = rt/lib/coro/aarch64_macho.s 125 126 $(eval $(call rt-core,aarch64-apple-ios,aarch64-apple-ios,lp64,1,aarch64)) 127 RT_EXTRA_SRCS_aarch64-apple-ios = rt/lib/coro/aarch64_macho.s 128 129 $(eval $(call rt-core,aarch64-apple-ios-simulator,aarch64-apple-ios-simulator,lp64,1,aarch64)) 130 RT_EXTRA_SRCS_aarch64-apple-ios-simulator = rt/lib/coro/aarch64_macho.s 131 132 $(eval $(call rt-core,aarch64-elf,aarch64-unknown-elf,lp64,1,aarch64)) 133 RT_aarch64-elf_LDBL128 = 1 134 RT_EXTRA_SRCS_aarch64-elf = rt/lib/coro/aarch64_elf.s 135 136 $(eval $(call rt-core,aarch64-windows,aarch64-w64-windows-gnu,llp64,1,aarch64)) 137 RT_aarch64-windows_HOSTED = 1 138 139 $(eval $(call rt-core,riscv64-linux,riscv64-linux-gnu,lp64,1,riscv64)) 140 # RISC-V `long double` is IEEE-754 binary128 per the psABI; ship the quad 141 # soft-float / __int128 runtime (fp_tf, fp_ti). 142 RT_riscv64-linux_LDBL128 = 1 143 RT_riscv64-linux_ARCH_FLAGS = -mabi=lp64d -march=rv64imafd 144 145 $(eval $(call rt-core,riscv64-freebsd,riscv64-unknown-freebsd,lp64,1,riscv64)) 146 RT_riscv64-freebsd_LDBL128 = 1 147 RT_riscv64-freebsd_ARCH_FLAGS = -mabi=lp64d -march=rv64imafd 148 149 $(eval $(call rt-core,riscv64-elf,riscv64-unknown-elf,lp64,1,riscv64)) 150 RT_riscv64-elf_LDBL128 = 1 151 RT_riscv64-elf_ARCH_FLAGS = -mabi=lp64 -march=rv64imafd 152 153 $(eval $(call rt-core,riscv64-elf-save-restore,riscv64-unknown-elf,lp64,1,riscv64)) 154 RT_riscv64-elf-save-restore_SAVE_RESTORE = 1 155 RT_riscv64-elf-save-restore_LDBL128 = 1 156 RT_riscv64-elf-save-restore_ARCH_FLAGS = -mabi=lp64 -march=rv64imafd 157 158 $(eval $(call rt-core,x86_64-pc-windows,x86_64-pc-windows-msvc,llp64,1,x86_64_win)) 159 RT_x86_64-pc-windows_HOSTED = 1 160 RT_EXTRA_SRCS_x86_64-pc-windows = rt/lib/stack/chkstk_x86_64_win.c 161 162 $(eval $(call rt-core,i386-linux,i386-linux-gnu,ilp32,0,i386)) 163 164 # wasm32 has no coroutine micro-arch (empty CORO). 165 $(eval $(call rt-core,wasm32,wasm32-unknown-unknown,ilp32,0,)) 166 167 # Soft-float embedded RV32 (ABI=ilp32, no F/D): integer layout is ilp32 and 168 # all FP is soft, so it reuses RT_ABI_SRCS_ilp32 / RT_ABI_INC ilp32_le. 169 $(eval $(call rt-core,riscv32-elf,riscv32-unknown-elf,ilp32,0,riscv32)) 170 RT_riscv32-elf_ARCH_FLAGS = -mabi=ilp32 -march=rv32imac 171 172 $(eval $(call rt-core,riscv32-elf-save-restore,riscv32-unknown-elf,ilp32,0,riscv32)) 173 RT_riscv32-elf-save-restore_SAVE_RESTORE = 1 174 RT_riscv32-elf-save-restore_ARCH_FLAGS = -mabi=ilp32 -march=rv32imac 175 176 # Hard-float (single-precision) RV32: ilp32f passes float in FP regs, but the 177 # integer layout is still ilp32 (double stays soft), so ABI=ilp32 here too and 178 # it reuses the same RT_ABI_SRCS_ilp32 / RT_ABI_INC ilp32_le as the soft variant. 179 $(eval $(call rt-core,riscv32-elf-hardfloat,riscv32-unknown-elf,ilp32,0,riscv32)) 180 RT_riscv32-elf-hardfloat_ARCH_FLAGS = -mabi=ilp32f -march=rv32imafc 181 182 # Coroutine support is a hand-written register-switch in ARM asm (coro/arm32.c + 183 # coro/coro.c's file-scope asm). kit-as now covers those idioms (cmp/mov #imm, 184 # SP-relative add/str/ldr incl. high-register T3, UDF, the soft-float 185 # __ARM_FP-undefined path), so the coroutine layer self-builds with kit's own 186 # toolchain — and the save/restore asm is verified correct under qemu 187 # (setjmp/longjmp round-trips). The full coro_init/resume/yield path still 188 # faults on this target (a coro/coro.c-level issue surfaced now that the layer 189 # is built at all; the asm itself disassembles byte-correct) — tracked in 190 # doc/plan/ARM32.md. 191 $(eval $(call rt-core,arm-eabi-thumb2,arm-none-eabi,ilp32,0,arm32)) 192 # AEABI alias layer (aeabi.c + aeabi_thumb2.S) is hand-written ARM asm that now 193 # self-builds with kit's own assembler: the ';' SEPARATOR, '#imm'-in-macro under 194 # __ASSEMBLER__, the __ELF__/.type %function path, and SP-relative stack 195 # manipulation all land, and the soft-float compare helpers use per-cond named 196 # labels (Laeabi_dcmp_<cond>) rather than GNU numeric local labels, which kit-as 197 # does not implement. All 19 __aeabi_* entry points assemble with correct 198 # encodings + symbols. 199 RT_arm-eabi-thumb2_AEABI = thumb2 200 201 $(eval $(call rt-core,arm-eabi-thumb1,arm-none-eabi,ilp32,0,arm32_thumb1)) 202 RT_arm-eabi-thumb1_AEABI = thumb1 203 204 # ---------- feature -> source/flag groups ------------------------------------ 205 RT_BASE_SRCS = \ 206 rt/lib/assert/assert.c \ 207 rt/lib/int/int.c \ 208 rt/lib/int/si_div.c \ 209 rt/lib/fp/fp.c \ 210 rt/lib/mem/mem.c \ 211 rt/lib/string/string.c \ 212 rt/lib/ctype/ctype.c \ 213 rt/lib/stdlib/stdlib.c \ 214 rt/lib/stdlib/qsort.c \ 215 rt/lib/stdio/printf.c \ 216 rt/lib/atomic/atomic_freestanding.c \ 217 rt/lib/cache/clear_cache.c \ 218 rt/lib/stack/backtrace.c \ 219 rt/lib/stack/print_backtrace.c \ 220 rt/lib/kit/ifunc_init.c 221 222 RT_COMPILER_SRCS = \ 223 rt/lib/int/int.c \ 224 rt/lib/int/si_div.c \ 225 rt/lib/fp/fp.c \ 226 rt/lib/atomic/atomic_freestanding.c \ 227 rt/lib/cache/clear_cache.c \ 228 rt/lib/kit/ifunc_init.c 229 230 RT_ABI_SRCS_lp64 = rt/lib/int64/int64.c 231 RT_ABI_SRCS_llp64 = rt/lib/int64/int64.c 232 RT_ABI_SRCS_ilp32 = rt/lib/int32/int32.c 233 234 RT_ABI_INC_lp64 = -Irt/lib/include/lp64_le 235 RT_ABI_INC_llp64 = -Irt/lib/include/llp64_le 236 RT_ABI_INC_ilp32 = -Irt/lib/include/ilp32_le 237 238 RT_CORO_SRCS_x86_64 = rt/lib/coro/x86_64.c rt/lib/coro/coro.c 239 RT_CORO_SRCS_x86_64_win = rt/lib/coro/x86_64_win.c rt/lib/coro/coro.c 240 RT_CORO_SRCS_i386 = rt/lib/coro/i386.c rt/lib/coro/coro.c 241 RT_CORO_SRCS_aarch64 = rt/lib/coro/aarch64.c rt/lib/coro/coro.c 242 RT_CORO_SRCS_arm32 = rt/lib/coro/arm32.c rt/lib/coro/coro.c 243 RT_CORO_SRCS_arm32_thumb1 = rt/lib/coro/arm32_thumb1.c rt/lib/coro/coro.c 244 RT_CORO_SRCS_riscv32 = rt/lib/coro/riscv32.c rt/lib/coro/coro.c 245 RT_CORO_SRCS_riscv64 = rt/lib/coro/riscv64.c rt/lib/coro/coro.c 246 247 # Extra arch-specific runtime helpers, keyed on the same micro-arch token as 248 # RT_CORO_SRCS. rv32 needs __kit_readcyclecounter to read the 64-bit cycle 249 # counter across the cycle/cycleh CSR pair (rv64 reads it inline, no helper). 250 RT_ARCH_SRCS_riscv32 = rt/lib/riscv/readcyclecounter.S 251 252 RT_LDBL128_SRCS = rt/lib/fp_tf/fp_tf.c rt/lib/fp_ti/fp_ti.c 253 RT_LDBL128_FLAGS = -Irt/lib/include/lp64_le_ldbl128 -DKITRT_LDBL128=1 254 255 RT_SAVE_RESTORE_SRCS_lp64 = rt/lib/riscv/rv64.S 256 RT_SAVE_RESTORE_SRCS_ilp32 = rt/lib/riscv/rv32.S 257 RT_SAVE_RESTORE_FLAGS = -msave-restore 258 259 RT_AEABI_SRCS_thumb2 = rt/lib/arm/aeabi_thumb2.S rt/lib/arm/aeabi.c 260 RT_AEABI_SRCS_thumb1 = rt/lib/arm/aeabi_thumb1.S rt/lib/arm/aeabi.c 261 RT_AEABI_FLAGS_thumb2 = -march=armv7-a -mthumb -mfloat-abi=soft 262 RT_AEABI_FLAGS_thumb1 = -march=armv6-m -mthumb -mfloat-abi=soft 263 264 # ---------- per-variant derivation ------------------------------------------- 265 # Expand one variant into its concrete source/object/flag lists. `:=` makes 266 # each list concrete at eval time so the rule template in the top-level 267 # Makefile can reference RT_OBJS_<variant> directly. 268 define RT_VARIANT_srcs 269 RT_SRCS_$(1) := \ 270 $$(if $$(RT_$(1)_HOSTED),$$(RT_COMPILER_SRCS),$$(RT_BASE_SRCS)) \ 271 $$(RT_ABI_SRCS_$$(RT_$(1)_ABI)) \ 272 $$(RT_CORO_SRCS_$$(RT_$(1)_CORO)) \ 273 $$(RT_ARCH_SRCS_$$(RT_$(1)_CORO)) \ 274 $$(if $$(RT_$(1)_LDBL128),$$(RT_LDBL128_SRCS)) \ 275 $$(if $$(RT_$(1)_SAVE_RESTORE),$$(RT_SAVE_RESTORE_SRCS_$$(RT_$(1)_ABI))) \ 276 $$(RT_AEABI_SRCS_$$(RT_$(1)_AEABI)) \ 277 $$(RT_EXTRA_SRCS_$(1)) 278 RT_CFLAGS_$(1) := \ 279 $$(RT_COMMON_CFLAGS) $$(RT_LIB_INCS) \ 280 -target $$(RT_$(1)_TARGET) \ 281 $$(RT_$(1)_ARCH_FLAGS) \ 282 -DHAS_INT128=$$(RT_$(1)_INT128) \ 283 $$(RT_ABI_INC_$$(RT_$(1)_ABI)) \ 284 $$(if $$(RT_$(1)_LDBL128),$$(RT_LDBL128_FLAGS)) \ 285 $$(if $$(RT_$(1)_CORO),-Irt/include) 286 RT_ASFLAGS_$(1) := \ 287 -target $$(RT_$(1)_TARGET) \ 288 $$(RT_LIB_INCS) \ 289 $$(RT_$(1)_ARCH_FLAGS) \ 290 -DHAS_INT128=$$(RT_$(1)_INT128) \ 291 -D__ASSEMBLER__=1 \ 292 $$(RT_ABI_INC_$$(RT_$(1)_ABI)) \ 293 $$(if $$(RT_$(1)_LDBL128),$$(RT_LDBL128_FLAGS)) \ 294 $$(if $$(RT_$(1)_CORO),-Irt/include) 295 RT_OBJS_$(1) := $$(patsubst rt/lib/%,$$(RT_BUILD_DIR)/$(1)/%.o,$$(RT_SRCS_$(1))) 296 endef 297 298 $(foreach variant,$(RT_VARIANTS),$(eval $(call RT_VARIANT_srcs,$(variant))))