runtime.c (39334B)
1 #include "runtime.h" 2 3 #include <kit/archive.h> 4 #include <kit/compile.h> 5 #include <kit/core.h> 6 #include <kit/preprocess.h> 7 #include <stdint.h> 8 #include <string.h> 9 10 typedef struct RuntimeVariant { 11 const char* key; 12 KitArchKind arch; 13 KitOSKind os; 14 KitObjFmt obj; 15 uint8_t ptr_size; 16 uint8_t ptr_align; 17 const char* abi_include; 18 uint8_t has_int128; 19 uint8_t ldbl128; 20 const char* const* sources; 21 uint32_t nsources; 22 /* Float-ABI axis (orthogonal to XLEN). A single arch+ptr_size can have 23 * several float ABIs (rv32 ilp32 soft vs ilp32f single), each needing its 24 * own runtime build, so the ABI is part of the variant identity. DEFAULT (0) 25 * means "wildcard" — it matches any target.float_abi (every non-RISC-V 26 * target and rv64, whose runtime is float-ABI-agnostic, leave it 0). */ 27 uint8_t float_abi; /* KitFloatAbi */ 28 /* -march / -mabi the runtime is compiled with. NULL falls back to the arch 29 * defaults (correct for every existing variant). rv32 sets them explicitly 30 * because the default profile (rv32imafc/ilp32f) is wrong for the soft 31 * ilp32 build. */ 32 const char* isa; 33 const char* abi; 34 } RuntimeVariant; 35 36 static const char* const kRtSrcX64[] = { 37 "assert/assert.c", 38 "int/int.c", 39 "int/si_div.c", 40 "fp/fp.c", 41 "mem/mem.c", 42 "string/string.c", 43 "ctype/ctype.c", 44 "stdlib/stdlib.c", 45 "stdlib/qsort.c", 46 "stdio/printf.c", 47 "atomic/atomic_freestanding.c", 48 "cache/clear_cache.c", 49 "kit/ifunc_init.c", 50 "int64/int64.c", 51 "coro/x86_64.c", 52 "coro/coro.c", 53 "stack/backtrace.c", 54 "stack/print_backtrace.c", 55 }; 56 57 static const char* const kRtSrcX64Windows[] = { 58 "int/int.c", 59 "int/si_div.c", 60 "fp/fp.c", 61 "atomic/atomic_freestanding.c", 62 "cache/clear_cache.c", 63 "kit/ifunc_init.c", 64 "int64/int64.c", 65 "stack/chkstk_x86_64_win.c", 66 "coro/x86_64_win.c", 67 "coro/coro.c", 68 }; 69 70 static const char* const kRtSrcAarch64Elf[] = { 71 "assert/assert.c", 72 "int/int.c", 73 "int/si_div.c", 74 "fp/fp.c", 75 "mem/mem.c", 76 "string/string.c", 77 "ctype/ctype.c", 78 "stdlib/stdlib.c", 79 "stdlib/qsort.c", 80 "stdio/printf.c", 81 "atomic/atomic_freestanding.c", 82 "cache/clear_cache.c", 83 "kit/ifunc_init.c", 84 "int64/int64.c", 85 "coro/aarch64.c", 86 "coro/coro.c", 87 "fp_tf/fp_tf.c", 88 "fp_ti/fp_ti.c", 89 "coro/aarch64_elf.s", 90 "stack/backtrace.c", 91 "stack/print_backtrace.c", 92 }; 93 94 static const char* const kRtSrcAarch64Darwin[] = { 95 "assert/assert.c", 96 "int/int.c", 97 "int/si_div.c", 98 "fp/fp.c", 99 "mem/mem.c", 100 "string/string.c", 101 "ctype/ctype.c", 102 "stdlib/stdlib.c", 103 "stdlib/qsort.c", 104 "stdio/printf.c", 105 "atomic/atomic_freestanding.c", 106 "cache/clear_cache.c", 107 "kit/ifunc_init.c", 108 "int64/int64.c", 109 "coro/aarch64.c", 110 "coro/coro.c", 111 "coro/aarch64_macho.s", 112 "stack/backtrace.c", 113 "stack/print_backtrace.c", 114 }; 115 116 static const char* const kRtSrcAarch64Windows[] = { 117 "int/int.c", 118 "int/si_div.c", 119 "fp/fp.c", 120 "atomic/atomic_freestanding.c", 121 "cache/clear_cache.c", 122 "kit/ifunc_init.c", 123 "int64/int64.c", 124 "coro/aarch64.c", 125 "coro/coro.c", 126 }; 127 128 static const char* const kRtSrcRv64Elf[] = { 129 "assert/assert.c", 130 "int/int.c", 131 "int/si_div.c", 132 "fp/fp.c", 133 "mem/mem.c", 134 "string/string.c", 135 "ctype/ctype.c", 136 "stdlib/stdlib.c", 137 "stdlib/qsort.c", 138 "stdio/printf.c", 139 "atomic/atomic_freestanding.c", 140 "cache/clear_cache.c", 141 "kit/ifunc_init.c", 142 "int64/int64.c", 143 "coro/riscv64.c", 144 "coro/coro.c", 145 "fp_tf/fp_tf.c", 146 "fp_ti/fp_ti.c", 147 "stack/backtrace.c", 148 "stack/print_backtrace.c", 149 }; 150 151 /* rv32 freestanding runtime: ilp32 integer layout (int32/int32.c for the 152 * 64-bit-on-32-bit helpers — __muldi3/__ashldi3/...; int/int.c for the i64 153 * div/mod) and soft double (fp/fp.c). Shared by the ilp32 (soft) and ilp32f 154 * (hardware single-float) variants; only the -march/-mabi the sources are 155 * compiled with differ, captured per-variant in the table below. */ 156 static const char* const kRtSrcRv32Elf[] = { 157 "assert/assert.c", 158 "int/int.c", 159 "int/si_div.c", 160 "fp/fp.c", 161 "mem/mem.c", 162 "string/string.c", 163 "ctype/ctype.c", 164 "stdlib/stdlib.c", 165 "stdlib/qsort.c", 166 "stdio/printf.c", 167 "atomic/atomic_freestanding.c", 168 "cache/clear_cache.c", 169 "kit/ifunc_init.c", 170 "int32/int32.c", 171 "coro/riscv32.c", 172 "coro/coro.c", 173 "stack/backtrace.c", 174 "stack/print_backtrace.c", 175 }; 176 177 /* arm32 (ARMv7-M Thumb-2) freestanding runtime: the same ilp32 integer layout 178 * (int32/int32.c for the 64-bit-on-32-bit helpers, int/int.c for i64 div/mod) 179 * and soft double (fp/fp.c) as rv32. Kept in sync with the kit-self-built 180 * `make rt-arm-eabi-thumb2` set (RT_SRCS_arm-eabi-thumb2 in mk/rt.mk): the 181 * hand-written ARM AEABI alias layer (arm/aeabi_thumb2.S + arm/aeabi.c) and the 182 * coroutine register-switch asm (coro/arm32.c + coro/coro.c's file-scope asm) 183 * are EXCLUDED because the kit assembler does not yet cover those idioms (a 184 * follow-on); kit-compiled code references the libgcc-named helpers the C 185 * sources provide (__udivdi3 / __adddf3 / ...), not the __aeabi_* aliases. */ 186 static const char* const kRtSrcArm32[] = { 187 "assert/assert.c", 188 "int/int.c", 189 "int/si_div.c", 190 "fp/fp.c", 191 "mem/mem.c", 192 "string/string.c", 193 "ctype/ctype.c", 194 "stdlib/stdlib.c", 195 "stdlib/qsort.c", 196 "stdio/printf.c", 197 "atomic/atomic_freestanding.c", 198 "cache/clear_cache.c", 199 "kit/ifunc_init.c", 200 "int32/int32.c", 201 "stack/backtrace.c", 202 "stack/print_backtrace.c", 203 }; 204 205 static const RuntimeVariant kRtVariants[] = { 206 {"x86_64-linux", KIT_ARCH_X86_64, KIT_OS_LINUX, KIT_OBJ_ELF, 8, 8, 207 "lib/include/lp64_le", 1, 0, kRtSrcX64, 208 (uint32_t)(sizeof(kRtSrcX64) / sizeof(kRtSrcX64[0])), 209 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 210 /* FreeBSD ELF runtime mirrors the Linux ELF runtime per-arch: the 211 * compiler-rt helpers and coroutine asm are ABI/ELF-based, not kernel 212 * based, so the same source set and data model apply. */ 213 {"x86_64-freebsd", KIT_ARCH_X86_64, KIT_OS_FREEBSD, KIT_OBJ_ELF, 8, 8, 214 "lib/include/lp64_le", 1, 0, kRtSrcX64, 215 (uint32_t)(sizeof(kRtSrcX64) / sizeof(kRtSrcX64[0])), 216 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 217 {"x86_64-apple-darwin", KIT_ARCH_X86_64, KIT_OS_MACOS, KIT_OBJ_MACHO, 8, 8, 218 "lib/include/lp64_le", 1, 0, kRtSrcX64, 219 (uint32_t)(sizeof(kRtSrcX64) / sizeof(kRtSrcX64[0])), 220 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 221 {"x86_64-apple-ios-simulator", KIT_ARCH_X86_64, KIT_OS_IOS_SIMULATOR, 222 KIT_OBJ_MACHO, 8, 8, "lib/include/lp64_le", 1, 0, kRtSrcX64, 223 (uint32_t)(sizeof(kRtSrcX64) / sizeof(kRtSrcX64[0])), 224 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 225 {"x86_64-elf", KIT_ARCH_X86_64, KIT_OS_FREESTANDING, KIT_OBJ_ELF, 8, 8, 226 "lib/include/lp64_le", 1, 0, kRtSrcX64, 227 (uint32_t)(sizeof(kRtSrcX64) / sizeof(kRtSrcX64[0])), 228 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 229 {"x86_64-pc-windows", KIT_ARCH_X86_64, KIT_OS_WINDOWS, KIT_OBJ_COFF, 8, 8, 230 "lib/include/llp64_le", 1, 0, kRtSrcX64Windows, 231 (uint32_t)(sizeof(kRtSrcX64Windows) / sizeof(kRtSrcX64Windows[0])), 232 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 233 {"aarch64-linux", KIT_ARCH_ARM_64, KIT_OS_LINUX, KIT_OBJ_ELF, 8, 8, 234 "lib/include/lp64_le", 1, 1, kRtSrcAarch64Elf, 235 (uint32_t)(sizeof(kRtSrcAarch64Elf) / sizeof(kRtSrcAarch64Elf[0])), 236 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 237 {"aarch64-linux-android", KIT_ARCH_ARM_64, KIT_OS_ANDROID, KIT_OBJ_ELF, 8, 238 8, "lib/include/lp64_le", 1, 1, kRtSrcAarch64Elf, 239 (uint32_t)(sizeof(kRtSrcAarch64Elf) / sizeof(kRtSrcAarch64Elf[0])), 240 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 241 {"aarch64-freebsd", KIT_ARCH_ARM_64, KIT_OS_FREEBSD, KIT_OBJ_ELF, 8, 8, 242 "lib/include/lp64_le", 1, 1, kRtSrcAarch64Elf, 243 (uint32_t)(sizeof(kRtSrcAarch64Elf) / sizeof(kRtSrcAarch64Elf[0])), 244 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 245 {"aarch64-elf", KIT_ARCH_ARM_64, KIT_OS_FREESTANDING, KIT_OBJ_ELF, 8, 8, 246 "lib/include/lp64_le", 1, 1, kRtSrcAarch64Elf, 247 (uint32_t)(sizeof(kRtSrcAarch64Elf) / sizeof(kRtSrcAarch64Elf[0])), 248 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 249 {"aarch64-apple-darwin", KIT_ARCH_ARM_64, KIT_OS_MACOS, KIT_OBJ_MACHO, 8, 8, 250 "lib/include/lp64_le", 1, 0, kRtSrcAarch64Darwin, 251 (uint32_t)(sizeof(kRtSrcAarch64Darwin) / sizeof(kRtSrcAarch64Darwin[0])), 252 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 253 {"aarch64-apple-ios", KIT_ARCH_ARM_64, KIT_OS_IOS, KIT_OBJ_MACHO, 8, 8, 254 "lib/include/lp64_le", 1, 0, kRtSrcAarch64Darwin, 255 (uint32_t)(sizeof(kRtSrcAarch64Darwin) / sizeof(kRtSrcAarch64Darwin[0])), 256 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 257 {"aarch64-apple-ios-simulator", KIT_ARCH_ARM_64, KIT_OS_IOS_SIMULATOR, 258 KIT_OBJ_MACHO, 8, 8, "lib/include/lp64_le", 1, 0, kRtSrcAarch64Darwin, 259 (uint32_t)(sizeof(kRtSrcAarch64Darwin) / sizeof(kRtSrcAarch64Darwin[0])), 260 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 261 {"aarch64-windows", KIT_ARCH_ARM_64, KIT_OS_WINDOWS, KIT_OBJ_COFF, 8, 8, 262 "lib/include/llp64_le", 1, 0, kRtSrcAarch64Windows, 263 (uint32_t)(sizeof(kRtSrcAarch64Windows) / sizeof(kRtSrcAarch64Windows[0])), 264 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 265 {"riscv64-linux", KIT_ARCH_RV64, KIT_OS_LINUX, KIT_OBJ_ELF, 8, 8, 266 "lib/include/lp64_le", 1, 1, kRtSrcRv64Elf, 267 (uint32_t)(sizeof(kRtSrcRv64Elf) / sizeof(kRtSrcRv64Elf[0])), 268 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 269 {"riscv64-freebsd", KIT_ARCH_RV64, KIT_OS_FREEBSD, KIT_OBJ_ELF, 8, 8, 270 "lib/include/lp64_le", 1, 1, kRtSrcRv64Elf, 271 (uint32_t)(sizeof(kRtSrcRv64Elf) / sizeof(kRtSrcRv64Elf[0])), 272 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 273 {"riscv64-elf", KIT_ARCH_RV64, KIT_OS_FREESTANDING, KIT_OBJ_ELF, 8, 8, 274 "lib/include/lp64_le", 1, 1, kRtSrcRv64Elf, 275 (uint32_t)(sizeof(kRtSrcRv64Elf) / sizeof(kRtSrcRv64Elf[0])), 276 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 277 /* rv32 freestanding. ilp32 (pure soft float) and ilp32f (hardware single 278 * float, soft double) share one arch+ptr_size, so float_abi is part of the 279 * variant identity and each is built with its own -march/-mabi. Keys match 280 * the `make rt` variant dirs (riscv32-elf / riscv32-elf-hardfloat) so a 281 * checkout shares build/rt with the Makefile. */ 282 {"riscv32-elf", KIT_ARCH_RV32, KIT_OS_FREESTANDING, KIT_OBJ_ELF, 4, 4, 283 "lib/include/ilp32_le", 0, 0, kRtSrcRv32Elf, 284 (uint32_t)(sizeof(kRtSrcRv32Elf) / sizeof(kRtSrcRv32Elf[0])), 285 KIT_FLOAT_ABI_SOFT, "rv32imac", "ilp32"}, 286 {"riscv32-elf-hardfloat", KIT_ARCH_RV32, KIT_OS_FREESTANDING, KIT_OBJ_ELF, 287 4, 4, "lib/include/ilp32_le", 0, 0, kRtSrcRv32Elf, 288 (uint32_t)(sizeof(kRtSrcRv32Elf) / sizeof(kRtSrcRv32Elf[0])), 289 KIT_FLOAT_ABI_SINGLE, "rv32imafc", "ilp32f"}, 290 /* arm32 freestanding (ARMv7-M Thumb-2, soft float). Key matches the 291 * `make rt` variant dir `arm-eabi-thumb2` (RT_arm-eabi-thumb2 in mk/rt.mk) 292 * so a checkout shares build/rt with the Makefile and the on-demand build 293 * target is `make rt-arm-eabi-thumb2`. Soft-float arm objects do NOT stamp a 294 * float-ABI e_flag (ARM toolchain convention: only hard-float sets a bit, so 295 * elf_arm_float_abi_from_e_flags returns DEFAULT for kit's soft objects). 296 * There is no hard-float arm runtime to disambiguate against, so this 297 * variant is float-ABI-agnostic (DEFAULT wildcard) and resolves for any 298 * detected arm float_abi — unlike rv32, whose objects do carry the ABI bits 299 * and so pin SOFT vs SINGLE. The default `-target arm-none-eabi` profile is 300 * correct (the make recipe sets no -march/-mabi), so isa/abi stay NULL. */ 301 {"arm-eabi-thumb2", KIT_ARCH_ARM_32, KIT_OS_FREESTANDING, KIT_OBJ_ELF, 4, 4, 302 "lib/include/ilp32_le", 0, 0, kRtSrcArm32, 303 (uint32_t)(sizeof(kRtSrcArm32) / sizeof(kRtSrcArm32[0])), 304 KIT_FLOAT_ABI_DEFAULT, NULL, NULL}, 305 }; 306 307 static char* rt_dup(DriverEnv* env, const char* s, size_t* out_size) { 308 size_t len = driver_strlen(s); 309 char* p = (char*)driver_alloc(env, len + 1u); 310 if (!p) return NULL; 311 driver_memcpy(p, s, len + 1u); 312 if (out_size) *out_size = len + 1u; 313 return p; 314 } 315 316 static char* rt_join_slot(DriverEnv* env, char** slot, size_t* size_slot, 317 const char* a, const char* b) { 318 char* p = driver_path_join(env, a, b, size_slot); 319 *slot = p; 320 return p; 321 } 322 323 static void rt_store_const_ptr(const char** slot, const char* value) { 324 *slot = value; 325 } 326 327 static void rt_free_str(DriverEnv* env, char** p, size_t* n) { 328 if (*p) driver_free(env, *p, *n); 329 *p = NULL; 330 *n = 0; 331 } 332 333 static int rt_has_layout(const char* rt_root) { 334 char inc[4096]; 335 char lib[4096]; 336 size_t n = driver_strlen(rt_root); 337 if (n + 13u >= sizeof(inc)) return 0; 338 driver_memcpy(inc, rt_root, n); 339 inc[n] = '/'; 340 driver_memcpy(inc + n + 1u, "include", 8u); 341 driver_memcpy(lib, rt_root, n); 342 lib[n] = '/'; 343 driver_memcpy(lib + n + 1u, "lib", 4u); 344 return driver_path_exists(inc) && driver_path_exists(lib); 345 } 346 347 static int rt_set_layout(DriverEnv* env, DriverRuntimeSupport* out, 348 const char* support_root, const char* rt_root) { 349 out->support_root = rt_dup(env, support_root, &out->support_root_size); 350 out->rt_root = rt_dup(env, rt_root, &out->rt_root_size); 351 out->include_dir = 352 driver_path_join(env, rt_root, "include", &out->include_dir_size); 353 if (!out->support_root || !out->rt_root || !out->include_dir) { 354 driver_runtime_support_fini(env, out); 355 return 1; 356 } 357 return 0; 358 } 359 360 static int rt_try_support_root(DriverEnv* env, const char* root, 361 DriverRuntimeSupport* out) { 362 char* rt_root; 363 size_t rt_root_size = 0; 364 int ok; 365 366 rt_root = driver_path_join(env, root, "rt", &rt_root_size); 367 if (!rt_root) return 1; 368 ok = rt_has_layout(rt_root) && rt_set_layout(env, out, root, rt_root) == 0; 369 driver_free(env, rt_root, rt_root_size); 370 return ok ? 0 : 1; 371 } 372 373 /* Directory-separator test for splitting the canonical program path. */ 374 static int rt_is_path_sep(char c) { 375 return c == '/' || c == '\\'; 376 } 377 378 static char* rt_exe_dir(DriverEnv* env, const char* exe, size_t* out_size) { 379 const char* slash; 380 size_t dir_len; 381 char* dir; 382 size_t dir_size; 383 if (!exe) return NULL; 384 slash = exe + driver_strlen(exe); 385 while (slash > exe && !rt_is_path_sep(slash[-1])) --slash; 386 if (slash == exe) return NULL; 387 dir_len = (size_t)(slash - exe); 388 if (dir_len == 0) return NULL; 389 390 dir_size = dir_len + 1u; 391 dir = (char*)driver_alloc(env, dir_size); 392 if (!dir) return NULL; 393 driver_memcpy(dir, exe, dir_len); 394 dir[dir_len] = '\0'; 395 if (out_size) *out_size = dir_size; 396 return dir; 397 } 398 399 static int rt_try_canonical_support(DriverEnv* env, const char* candidate, 400 DriverRuntimeSupport* out) { 401 char* canonical = NULL; 402 size_t canonical_size = 0; 403 int rc; 404 if (driver_path_canonicalize(env, candidate, &canonical, &canonical_size) != 405 0) 406 return 1; 407 rc = rt_try_support_root(env, canonical, out); 408 driver_free(env, canonical, canonical_size); 409 return rc; 410 } 411 412 int driver_runtime_resolve(DriverEnv* env, const char* explicit_support_dir, 413 const char* argv0, DriverRuntimeSupport* out) { 414 char* self = NULL; 415 char* exe_dir = NULL; 416 char* candidate = NULL; 417 char* parent = NULL; 418 size_t self_size = 0; 419 size_t exe_dir_size = 0; 420 size_t candidate_size = 0; 421 size_t parent_size = 0; 422 int rc = 1; 423 DriverRuntimeSupport zero = {0}; 424 *out = zero; 425 426 /* An explicit root is authoritative. Normalize and validate it; never hide 427 * a bad explicit value by falling back to discovery. */ 428 if (explicit_support_dir) { 429 rc = rt_try_canonical_support(env, explicit_support_dir, out); 430 if (rc == 0 && driver_self_exe_path(env, &self, &self_size) == 0) 431 out->tool_path = rt_dup(env, self, &out->tool_path_size); 432 else if (rc == 0 && argv0) 433 out->tool_path = rt_dup(env, argv0, &out->tool_path_size); 434 if (self) driver_free(env, self, self_size); 435 return rc; 436 } 437 438 /* Default discovery has one identity and two ordered layouts: 439 * <exe-dir>/support development build 440 * <exe-dir>/../support packaged distribution 441 * No cwd/source-checkout fallback is permitted. */ 442 if (driver_self_exe_path(env, &self, &self_size) != 0 || !self) goto out; 443 exe_dir = rt_exe_dir(env, self, &exe_dir_size); 444 if (!exe_dir) goto out; 445 446 candidate = driver_path_join(env, exe_dir, "support", &candidate_size); 447 if (!candidate) goto out; 448 if (rt_try_canonical_support(env, candidate, out) == 0) { 449 rc = 0; 450 goto found; 451 } 452 driver_free(env, candidate, candidate_size); 453 candidate = NULL; 454 candidate_size = 0; 455 456 parent = driver_path_join(env, exe_dir, "..", &parent_size); 457 if (!parent) goto out; 458 candidate = driver_path_join(env, parent, "support", &candidate_size); 459 if (!candidate) goto out; 460 if (rt_try_canonical_support(env, candidate, out) == 0) { 461 out->install_layout = 1; 462 rc = 0; 463 } 464 465 found: 466 if (rc == 0) out->tool_path = rt_dup(env, self, &out->tool_path_size); 467 out: 468 if (candidate) driver_free(env, candidate, candidate_size); 469 if (parent) driver_free(env, parent, parent_size); 470 if (exe_dir) driver_free(env, exe_dir, exe_dir_size); 471 if (self) driver_free(env, self, self_size); 472 return rc; 473 } 474 475 void driver_runtime_support_fini(DriverEnv* env, DriverRuntimeSupport* s) { 476 rt_free_str(env, &s->include_dir, &s->include_dir_size); 477 rt_free_str(env, &s->rt_root, &s->rt_root_size); 478 rt_free_str(env, &s->support_root, &s->support_root_size); 479 if (s->tool_path && s->tool_path_size) { 480 driver_free(env, (void*)s->tool_path, s->tool_path_size); 481 s->tool_path = NULL; 482 s->tool_path_size = 0; 483 } 484 } 485 486 int driver_runtime_add_freestanding_headers(const DriverRuntimeSupport* s, 487 DriverCflags* cf) { 488 uint32_t i; 489 if (!s || !s->include_dir || !cf) return 1; 490 for (i = cf->nsystem_include_dirs; i > 0; --i) 491 cf->system_include_dirs[i] = cf->system_include_dirs[i - 1u]; 492 cf->system_include_dirs[0] = s->include_dir; 493 cf->nsystem_include_dirs++; 494 return 0; 495 } 496 497 int driver_runtime_append_freestanding_headers(const DriverRuntimeSupport* s, 498 DriverCflags* cf) { 499 uint32_t i; 500 if (!s || !s->include_dir || !cf) return 1; 501 i = cf->nsystem_include_dirs; 502 cf->system_include_dirs[i] = s->include_dir; 503 cf->nsystem_include_dirs = i + 1u; 504 return 0; 505 } 506 507 static const RuntimeVariant* rt_variant_for_target(KitTargetSpec target) { 508 uint32_t i; 509 for (i = 0; i < (uint32_t)(sizeof(kRtVariants) / sizeof(kRtVariants[0])); 510 ++i) { 511 const RuntimeVariant* v = &kRtVariants[i]; 512 /* A variant with float_abi DEFAULT is float-ABI-agnostic and matches any 513 * target (every non-RISC-V variant and rv64). A variant that pins a float 514 * ABI (the two rv32 entries) matches only that ABI, so ilp32 vs ilp32f 515 * targets select distinct runtimes. */ 516 if (target.arch == v->arch && target.os == v->os && target.obj == v->obj && 517 target.ptr_size == v->ptr_size && target.ptr_align == v->ptr_align && 518 (v->float_abi == KIT_FLOAT_ABI_DEFAULT || 519 v->float_abi == target.float_abi)) 520 return v; 521 } 522 return NULL; 523 } 524 525 int driver_runtime_has_variant(KitTargetSpec target) { 526 return rt_variant_for_target(target) != NULL; 527 } 528 529 static int rt_prepare_pp(DriverEnv* env, const DriverRuntimeSupport* support, 530 const RuntimeVariant* variant, int assembler, 531 KitPreprocessOptions* pp, char*** owned_dirs, 532 size_t** owned_sizes, uint32_t* owned_count) { 533 static const KitSlice def_int128_1 = KIT_SLICE_LIT("1"); 534 static const KitSlice def_int128_0 = KIT_SLICE_LIT("0"); 535 char** dirs = NULL; 536 size_t* sizes = NULL; 537 const char** include_dirs; 538 const char** system_dirs; 539 KitDefine* defs; 540 uint32_t ninc = variant->ldbl128 ? 4u : 3u; 541 uint32_t nsys = 2u; 542 uint32_t ndefs = 1u + (variant->ldbl128 ? 1u : 0u) + (assembler ? 1u : 0u); 543 uint32_t d = 0; 544 KitPreprocessOptions z = {0}; 545 546 *pp = z; 547 *owned_dirs = NULL; 548 *owned_sizes = NULL; 549 *owned_count = 0; 550 551 include_dirs = (const char**)driver_alloc_zeroed( 552 env, (size_t)ninc * sizeof(*include_dirs)); 553 system_dirs = (const char**)driver_alloc_zeroed( 554 env, (size_t)nsys * sizeof(*system_dirs)); 555 defs = (KitDefine*)driver_alloc_zeroed(env, (size_t)ndefs * sizeof(*defs)); 556 dirs = 557 (char**)driver_alloc_zeroed(env, (size_t)(ninc + nsys) * sizeof(*dirs)); 558 sizes = 559 (size_t*)driver_alloc_zeroed(env, (size_t)(ninc + nsys) * sizeof(*sizes)); 560 if (!include_dirs || !system_dirs || !defs || !dirs || !sizes) { 561 if (include_dirs) 562 driver_free(env, (void*)include_dirs, 563 (size_t)ninc * sizeof(*include_dirs)); 564 if (system_dirs) 565 driver_free(env, (void*)system_dirs, (size_t)nsys * sizeof(*system_dirs)); 566 if (defs) driver_free(env, defs, (size_t)ndefs * sizeof(*defs)); 567 if (dirs) driver_free(env, dirs, (size_t)(ninc + nsys) * sizeof(*dirs)); 568 if (sizes) driver_free(env, sizes, (size_t)(ninc + nsys) * sizeof(*sizes)); 569 return 1; 570 } 571 572 rt_join_slot(env, &dirs[0], &sizes[0], support->rt_root, 573 "lib/include/common"); 574 rt_store_const_ptr(&include_dirs[0], dirs[0]); 575 rt_join_slot(env, &dirs[1], &sizes[1], support->rt_root, "lib/impl"); 576 rt_store_const_ptr(&include_dirs[1], dirs[1]); 577 rt_join_slot(env, &dirs[2], &sizes[2], support->rt_root, 578 variant->abi_include); 579 rt_store_const_ptr(&include_dirs[2], dirs[2]); 580 if (variant->ldbl128) { 581 rt_join_slot(env, &dirs[3], &sizes[3], support->rt_root, 582 "lib/include/lp64_le_ldbl128"); 583 rt_store_const_ptr(&include_dirs[3], dirs[3]); 584 rt_join_slot(env, &dirs[4], &sizes[4], support->rt_root, "include"); 585 rt_store_const_ptr(&system_dirs[0], dirs[4]); 586 rt_join_slot(env, &dirs[5], &sizes[5], support->rt_root, "include/libc"); 587 rt_store_const_ptr(&system_dirs[1], dirs[5]); 588 d = 6; 589 } else { 590 rt_join_slot(env, &dirs[3], &sizes[3], support->rt_root, "include"); 591 rt_store_const_ptr(&system_dirs[0], dirs[3]); 592 rt_join_slot(env, &dirs[4], &sizes[4], support->rt_root, "include/libc"); 593 rt_store_const_ptr(&system_dirs[1], dirs[4]); 594 d = 5; 595 } 596 for (uint32_t i = 0; i < d; ++i) { 597 if (!dirs[i]) { 598 uint32_t j; 599 for (j = 0; j < d; ++j) 600 if (dirs[j]) driver_free(env, dirs[j], sizes[j]); 601 driver_free(env, (void*)include_dirs, 602 (size_t)ninc * sizeof(*include_dirs)); 603 driver_free(env, (void*)system_dirs, (size_t)nsys * sizeof(*system_dirs)); 604 driver_free(env, defs, (size_t)ndefs * sizeof(*defs)); 605 driver_free(env, dirs, (size_t)(ninc + nsys) * sizeof(*dirs)); 606 driver_free(env, sizes, (size_t)(ninc + nsys) * sizeof(*sizes)); 607 return 1; 608 } 609 } 610 611 defs[0].name = KIT_SLICE_LIT("HAS_INT128"); 612 defs[0].body = variant->has_int128 ? def_int128_1 : def_int128_0; 613 uint32_t i = 1; 614 if (variant->ldbl128) { 615 defs[i].name = KIT_SLICE_LIT("KITRT_LDBL128"); 616 defs[i].body = KIT_SLICE_LIT("1"); 617 ++i; 618 } 619 if (assembler) { 620 defs[i].name = KIT_SLICE_LIT("__ASSEMBLER__"); 621 defs[i].body = KIT_SLICE_LIT("1"); 622 } 623 624 pp->include_dirs = include_dirs; 625 pp->ninclude_dirs = ninc; 626 pp->system_include_dirs = system_dirs; 627 pp->nsystem_include_dirs = nsys; 628 pp->defines = defs; 629 pp->ndefines = ndefs; 630 *owned_dirs = dirs; 631 *owned_sizes = sizes; 632 *owned_count = d; 633 return 0; 634 } 635 636 static void rt_free_pp(DriverEnv* env, KitPreprocessOptions* pp, 637 char** owned_dirs, size_t* owned_sizes, 638 uint32_t owned_count) { 639 uint32_t i; 640 for (i = 0; i < owned_count; ++i) 641 if (owned_dirs[i]) driver_free(env, owned_dirs[i], owned_sizes[i]); 642 if (owned_dirs) 643 driver_free(env, owned_dirs, (size_t)owned_count * sizeof(*owned_dirs)); 644 if (owned_sizes) 645 driver_free(env, owned_sizes, (size_t)owned_count * sizeof(*owned_sizes)); 646 if (pp->include_dirs) 647 driver_free(env, (void*)pp->include_dirs, 648 (size_t)pp->ninclude_dirs * sizeof(*pp->include_dirs)); 649 if (pp->system_include_dirs) 650 driver_free( 651 env, (void*)pp->system_include_dirs, 652 (size_t)pp->nsystem_include_dirs * sizeof(*pp->system_include_dirs)); 653 if (pp->defines) 654 driver_free(env, (void*)pp->defines, 655 (size_t)pp->ndefines * sizeof(*pp->defines)); 656 } 657 658 static int rt_compile_source(DriverEnv* env, 659 const DriverRuntimeSupport* support, 660 const RuntimeVariant* variant, const char* tool, 661 KitCompiler* compiler, const char* rel, 662 KitArInput* member, KitWriter** obj_writer) { 663 KitContext ctx = driver_env_to_context(env); 664 char* lib_path = NULL; 665 char* src_path = NULL; 666 size_t lib_path_size = 0; 667 size_t src_path_size = 0; 668 DriverLoad src_load = {0}; 669 KitSlice input = {0}; 670 KitWriter* writer = NULL; 671 KitWriter* pp_writer = NULL; 672 const uint8_t* obj_data; 673 size_t obj_len = 0; 674 KitStatus st; 675 int is_asm; 676 int preprocess_asm; 677 int rc = 1; 678 679 *obj_writer = NULL; 680 lib_path = driver_path_join(env, support->rt_root, "lib", &lib_path_size); 681 if (!lib_path) goto out; 682 src_path = driver_path_join(env, lib_path, rel, &src_path_size); 683 if (!src_path) goto out; 684 if (driver_load_bytes(ctx.file_io, tool, src_path, &src_load, &input) != 0) 685 goto out; 686 if (kit_writer_mem(ctx.heap, &writer) != KIT_OK) goto out; 687 688 is_asm = driver_has_suffix(rel, ".s") || driver_has_suffix(rel, ".S"); 689 preprocess_asm = driver_has_suffix(rel, ".S"); 690 if (is_asm) { 691 KitAsmCompileOptions aopts = {0}; 692 KitSlice asm_input = input; 693 if (preprocess_asm) { 694 KitPreprocessOptions pp; 695 char** owned_dirs = NULL; 696 size_t* owned_sizes = NULL; 697 uint32_t owned_count = 0; 698 if (rt_prepare_pp(env, support, variant, 1, &pp, &owned_dirs, 699 &owned_sizes, &owned_count) != 0) 700 goto out; 701 if (kit_writer_mem(ctx.heap, &pp_writer) != KIT_OK) { 702 rt_free_pp(env, &pp, owned_dirs, owned_sizes, owned_count); 703 goto out; 704 } 705 st = kit_cpp_preprocess(compiler, &pp, kit_slice_cstr(src_path), &input, 706 pp_writer); 707 rt_free_pp(env, &pp, owned_dirs, owned_sizes, owned_count); 708 if (st != KIT_OK || kit_writer_status(pp_writer) != KIT_OK) goto out; 709 asm_input.data = kit_writer_mem_bytes(pp_writer, &asm_input.len); 710 } 711 { 712 KitCompileSessionOptions sopts; 713 KitCompileSession* session = NULL; 714 KitSourceInput sin; 715 KitObjBuilder* ob = NULL; 716 memset(&sopts, 0, sizeof(sopts)); 717 sopts.lang = KIT_LANG_ASM; 718 sopts.compile.code = aopts.code; 719 sopts.compile.diagnostics = aopts.diagnostics; 720 sopts.compile.language_options = &aopts; 721 memset(&sin, 0, sizeof(sin)); 722 sin.name = kit_slice_cstr(src_path); 723 sin.bytes = asm_input; 724 sin.lang = KIT_LANG_ASM; 725 st = kit_compile_session_new(compiler, &sopts, &session); 726 if (st == KIT_OK) st = kit_compile_session_compile(session, &sin, &ob); 727 if (st == KIT_OK) st = kit_obj_builder_emit(ob, writer); 728 kit_obj_builder_free(ob); 729 kit_compile_session_free(session); 730 } 731 } else { 732 KitCCompileOptions copts = {0}; 733 KitPreprocessOptions pp = {0}; 734 KitCompileSessionOptions sopts; 735 KitCompileSession* session = NULL; 736 KitSourceInput sin; 737 KitObjBuilder* ob = NULL; 738 char** owned_dirs = NULL; 739 size_t* owned_sizes = NULL; 740 uint32_t owned_count = 0; 741 if (rt_prepare_pp(env, support, variant, 0, &pp, &owned_dirs, &owned_sizes, 742 &owned_count) != 0) 743 goto out; 744 memset(&sopts, 0, sizeof(sopts)); 745 sopts.lang = KIT_LANG_C; 746 sopts.compile.code = copts.code; 747 sopts.compile.diagnostics = copts.diagnostics; 748 sopts.compile.preprocess = pp; 749 memset(&sin, 0, sizeof(sin)); 750 sin.name = kit_slice_cstr(src_path); 751 sin.bytes = input; 752 sin.lang = KIT_LANG_C; 753 st = kit_compile_session_new(compiler, &sopts, &session); 754 if (st == KIT_OK) st = kit_compile_session_compile(session, &sin, &ob); 755 if (st == KIT_OK) st = kit_obj_builder_emit(ob, writer); 756 kit_obj_builder_free(ob); 757 kit_compile_session_free(session); 758 rt_free_pp(env, &pp, owned_dirs, owned_sizes, owned_count); 759 } 760 if (st != KIT_OK || kit_writer_status(writer) != KIT_OK) { 761 driver_errf(tool, "failed to build runtime source: %.*s", 762 KIT_SLICE_ARG(kit_slice_cstr(src_path))); 763 goto out; 764 } 765 766 obj_data = kit_writer_mem_bytes(writer, &obj_len); 767 member->name = kit_slice_cstr(driver_basename(rel)); 768 member->bytes.data = obj_data; 769 member->bytes.len = obj_len; 770 *obj_writer = writer; 771 writer = NULL; 772 rc = 0; 773 774 out: 775 if (pp_writer) kit_writer_close(pp_writer); 776 if (writer) kit_writer_close(writer); 777 driver_release_bytes(ctx.file_io, &src_load); 778 if (src_path) driver_free(env, src_path, src_path_size); 779 if (lib_path) driver_free(env, lib_path, lib_path_size); 780 return rc; 781 } 782 783 static int rt_build_archive(DriverEnv* env, const DriverRuntimeSupport* support, 784 const RuntimeVariant* variant, const char* tool, 785 uint64_t epoch, const char* archive_path) { 786 KitContext ctx = driver_env_to_context(env); 787 KitTarget* resolved_target = NULL; 788 KitCompiler* compiler = NULL; 789 KitWriter* archive_writer = NULL; 790 KitArInput* members = NULL; 791 KitWriter** obj_writers = NULL; 792 KitArWriteOptions ar_opts = {0}; 793 KitTargetSpec target; 794 uint32_t i; 795 int rc = 1; 796 797 members = (KitArInput*)driver_alloc_zeroed( 798 env, (size_t)variant->nsources * sizeof(*members)); 799 obj_writers = (KitWriter**)driver_alloc_zeroed( 800 env, (size_t)variant->nsources * sizeof(*obj_writers)); 801 if (!members || !obj_writers) { 802 driver_errf(tool, "out of memory"); 803 goto out; 804 } 805 806 target.arch = variant->arch; 807 target.os = variant->os; 808 target.obj = variant->obj; 809 target.ptr_size = variant->ptr_size; 810 target.ptr_align = variant->ptr_align; 811 target.big_endian = 0; 812 target.pic = KIT_PIC_NONE; 813 target.code_model = KIT_CM_DEFAULT; 814 target.float_abi = KIT_FLOAT_ABI_DEFAULT; /* resolved from abi below */ 815 816 { 817 KitTargetOptions topts; 818 memset(&topts, 0, sizeof topts); 819 topts.spec = target; 820 /* Build the runtime with the variant's -march/-mabi. NULL leaves the arch 821 * defaults (every non-rv32 variant); rv32 pins them so the soft ilp32 and 822 * hard ilp32f archives are each compiled correctly, and kit_target_new 823 * resolves spec.float_abi from the ABI string to match the call sites. */ 824 if (variant->isa) topts.isa = kit_slice_cstr(variant->isa); 825 if (variant->abi) topts.abi = kit_slice_cstr(variant->abi); 826 if (kit_target_new(&ctx, &topts, &resolved_target) != KIT_OK || 827 driver_compiler_new(resolved_target, &ctx, &compiler) != KIT_OK) { 828 driver_errf(tool, "failed to initialize compiler for runtime"); 829 goto out; 830 } 831 } 832 833 for (i = 0; i < variant->nsources; ++i) { 834 if (rt_compile_source(env, support, variant, tool, compiler, 835 variant->sources[i], &members[i], 836 &obj_writers[i]) != 0) 837 goto out; 838 } 839 840 if (ctx.file_io->open_writer(ctx.file_io->user, archive_path, 841 &archive_writer) != KIT_OK) { 842 driver_errf(tool, "failed to open runtime archive: %.*s", 843 KIT_SLICE_ARG(kit_slice_cstr(archive_path))); 844 goto out; 845 } 846 847 ar_opts.epoch = epoch; 848 ar_opts.long_names = 1; 849 if (kit_ar_write(archive_writer, members, variant->nsources, &ar_opts) != 850 KIT_OK) { 851 driver_errf(tool, "failed to write runtime archive: %.*s", 852 KIT_SLICE_ARG(kit_slice_cstr(archive_path))); 853 goto out; 854 } 855 rc = 0; 856 857 out: 858 if (archive_writer) kit_writer_close(archive_writer); 859 if (compiler) driver_compiler_free(compiler); 860 kit_target_free(resolved_target); 861 if (obj_writers) { 862 for (i = 0; i < variant->nsources; ++i) 863 if (obj_writers[i]) kit_writer_close(obj_writers[i]); 864 driver_free(env, obj_writers, 865 (size_t)variant->nsources * sizeof(*obj_writers)); 866 } 867 if (members) 868 driver_free(env, members, (size_t)variant->nsources * sizeof(*members)); 869 return rc; 870 } 871 872 static int rt_is_archive_stale(DriverEnv* env, 873 const DriverRuntimeSupport* support, 874 const RuntimeVariant* variant, 875 const char* archive_path) { 876 int64_t archive_mtime; 877 int64_t tool_mtime; 878 uint32_t i; 879 if (driver_path_mtime_ns(archive_path, &archive_mtime) != 0) return 1; 880 if (support->tool_path && 881 driver_path_mtime_ns(support->tool_path, &tool_mtime) == 0 && 882 tool_mtime > archive_mtime) 883 return 1; 884 for (i = 0; i < variant->nsources; ++i) { 885 char* lib_path; 886 char* src_path; 887 size_t lib_path_size = 0; 888 size_t src_path_size = 0; 889 int64_t src_mtime; 890 int stale = 0; 891 lib_path = driver_path_join(env, support->rt_root, "lib", &lib_path_size); 892 if (!lib_path) return 1; 893 src_path = 894 driver_path_join(env, lib_path, variant->sources[i], &src_path_size); 895 driver_free(env, lib_path, lib_path_size); 896 if (!src_path) return 1; 897 if (driver_path_mtime_ns(src_path, &src_mtime) != 0 || 898 src_mtime > archive_mtime) 899 stale = 1; 900 driver_free(env, src_path, src_path_size); 901 if (stale) return 1; 902 } 903 return 0; 904 } 905 906 static char* rt_archive_dir_for_root(DriverEnv* env, const char* root, 907 const RuntimeVariant* variant, 908 size_t* out_size) { 909 char* build_rt; 910 char* dir = NULL; 911 size_t build_rt_size = 0; 912 size_t dir_size = 0; 913 build_rt = driver_path_join(env, root, "build/rt", &build_rt_size); 914 if (!build_rt) return NULL; 915 dir = driver_path_join(env, build_rt, variant->key, &dir_size); 916 driver_free(env, build_rt, build_rt_size); 917 if (out_size) *out_size = dir ? dir_size : 0; 918 return dir; 919 } 920 921 static int rt_archive_try_dir(DriverEnv* env, const char* tool, 922 const DriverRuntimeSupport* support, 923 const RuntimeVariant* variant, uint64_t epoch, 924 const char* cache_dir, char** out_path, 925 size_t* out_path_size) { 926 char* archive_path; 927 size_t archive_path_size = 0; 928 929 archive_path = 930 driver_path_join(env, cache_dir, "libkit_rt.a", &archive_path_size); 931 if (!archive_path) { 932 driver_errf(tool, "out of memory"); 933 return 1; 934 } 935 936 if (!driver_path_exists(archive_path) || 937 rt_is_archive_stale(env, support, variant, archive_path)) { 938 if (driver_mkdir_p(env, cache_dir) != 0) { 939 driver_free(env, archive_path, archive_path_size); 940 return 2; 941 } 942 if (rt_build_archive(env, support, variant, tool, epoch, archive_path) != 943 0) { 944 driver_errf(tool, "compiler runtime for %.*s could not be built", 945 KIT_SLICE_ARG(kit_slice_cstr(variant->key))); 946 driver_errf(tool, "support dir: %.*s", 947 KIT_SLICE_ARG(kit_slice_cstr(support->support_root))); 948 driver_free(env, archive_path, archive_path_size); 949 return 1; 950 } 951 } 952 953 *out_path = archive_path; 954 *out_path_size = archive_path_size; 955 return 0; 956 } 957 958 int driver_runtime_ensure_archive(DriverEnv* env, const char* tool, 959 const DriverRuntimeSupport* support, 960 KitTargetSpec target, uint64_t epoch, 961 char** out_path, size_t* out_path_size) { 962 const RuntimeVariant* variant = rt_variant_for_target(target); 963 const char* diag_tool = tool ? tool : "rt"; 964 char* in_tree_dir = NULL; /* <support_root>/build/rt/<variant> */ 965 char* cache_dir = NULL; /* <env->cache_dir>/<variant> */ 966 size_t in_tree_dir_size = 0; 967 size_t cache_dir_size = 0; 968 char* primary_dir; 969 char* fallback_dir; 970 int primary_rc; 971 int fallback_rc = 1; 972 973 *out_path = NULL; 974 *out_path_size = 0; 975 976 if (!variant) { 977 driver_errf(diag_tool, "compiler runtime is not available for this target"); 978 return 1; 979 } 980 981 /* In-tree location, shared with `make rt` when support_root is a checkout. */ 982 in_tree_dir = rt_archive_dir_for_root(env, support->support_root, variant, 983 &in_tree_dir_size); 984 if (!in_tree_dir) { 985 driver_errf(diag_tool, "out of memory"); 986 return 1; 987 } 988 /* User cache location, outside any support/install tree. */ 989 if (env->cache_dir) { 990 cache_dir = 991 driver_path_join(env, env->cache_dir, variant->key, &cache_dir_size); 992 if (!cache_dir) { 993 driver_free(env, in_tree_dir, in_tree_dir_size); 994 driver_errf(diag_tool, "out of memory"); 995 return 1; 996 } 997 } 998 999 /* A distribution install is not a build tree: prefer the user cache dir and 1000 * keep the in-tree dir only as a fallback so the build never writes into the 1001 * install. A checkout (or explicit --support-dir) keeps the historical 1002 * in-tree-first order, sharing `make rt`'s build/rt cache per checkout. */ 1003 if (support->install_layout && cache_dir) { 1004 primary_dir = cache_dir; 1005 fallback_dir = in_tree_dir; 1006 } else { 1007 primary_dir = in_tree_dir; 1008 fallback_dir = cache_dir; 1009 } 1010 1011 primary_rc = rt_archive_try_dir(env, diag_tool, support, variant, epoch, 1012 primary_dir, out_path, out_path_size); 1013 if (primary_rc == 0) { 1014 if (cache_dir) driver_free(env, cache_dir, cache_dir_size); 1015 driver_free(env, in_tree_dir, in_tree_dir_size); 1016 return 0; 1017 } 1018 1019 if (primary_rc != 2) { 1020 if (cache_dir) driver_free(env, cache_dir, cache_dir_size); 1021 driver_free(env, in_tree_dir, in_tree_dir_size); 1022 return 1; 1023 } 1024 1025 if (fallback_dir) { 1026 fallback_rc = rt_archive_try_dir(env, diag_tool, support, variant, epoch, 1027 fallback_dir, out_path, out_path_size); 1028 } 1029 1030 if (fallback_rc == 2 || !fallback_dir) { 1031 driver_errf(diag_tool, "failed to create runtime cache: %.*s", 1032 KIT_SLICE_ARG(kit_slice_cstr(primary_dir))); 1033 if (fallback_dir) { 1034 driver_errf(diag_tool, "failed to create runtime cache: %.*s", 1035 KIT_SLICE_ARG(kit_slice_cstr(fallback_dir))); 1036 } 1037 } 1038 if (cache_dir) driver_free(env, cache_dir, cache_dir_size); 1039 driver_free(env, in_tree_dir, in_tree_dir_size); 1040 return fallback_rc == 0 ? 0 : 1; 1041 } 1042 1043 int driver_runtime_prepare_archive(DriverEnv* env, const char* tool, 1044 const DriverRuntimeSupport* support, 1045 KitTargetSpec target, uint64_t epoch, 1046 DriverRuntimeArchive* out) { 1047 DriverRuntimeArchive z = {0}; 1048 if (!out) return 1; 1049 *out = z; 1050 if (driver_runtime_ensure_archive(env, tool, support, target, epoch, 1051 &out->path, &out->path_size) != 0) 1052 return 1; 1053 out->whole_archive = 0; 1054 out->link_mode = KIT_LM_STATIC; 1055 out->group_id = 0; 1056 return 0; 1057 } 1058 1059 void driver_runtime_archive_fini(DriverEnv* env, DriverRuntimeArchive* a) { 1060 if (!a) return; 1061 if (a->path) driver_free(env, a->path, a->path_size); 1062 a->path = NULL; 1063 a->path_size = 0; 1064 a->whole_archive = 0; 1065 a->link_mode = 0; 1066 a->group_id = 0; 1067 }