kit_test_target.h (4685B)
1 /* Shared KitTargetSpec setup for C test runners. 2 * 3 * Reads two env vars to pick a (arch, os, obj) triple: 4 * 5 * KIT_TEST_ARCH one of "aa64"/"aarch64"/"arm64", "x64"/"x86_64", 6 * "rv64"/"riscv64". Default: "aa64". 7 * KIT_TEST_OBJ one of "elf" (linux) or "macho" (macos). 8 * Default: "elf". Sets t->obj and t->os together so 9 * the C runners and shell drivers stay in lockstep. 10 * 11 * Header-only and self-contained: include from any runner TU. The 12 * caller still chooses whether the build's host arch matches the 13 * cross-target (e.g. JIT lanes only run when they match). */ 14 15 #ifndef KIT_TEST_TARGET_H 16 #define KIT_TEST_TARGET_H 17 18 #include <kit/core.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 static inline const char* kit_test_arch_name(void) { 24 const char* a = getenv("KIT_TEST_ARCH"); 25 if (!a || !*a) return "aa64"; 26 return a; 27 } 28 29 static inline const char* kit_test_obj_name(void) { 30 const char* o = getenv("KIT_TEST_OBJ"); 31 if (!o || !*o) return "elf"; 32 return o; 33 } 34 35 static inline int kit_test_target_init(KitTargetSpec* t) { 36 memset(t, 0, sizeof *t); 37 t->ptr_size = 8; 38 t->ptr_align = 8; 39 t->big_endian = 0; 40 41 const char* o = kit_test_obj_name(); 42 if (!strcmp(o, "elf")) { 43 t->os = KIT_OS_LINUX; 44 t->obj = KIT_OBJ_ELF; 45 } else if (!strcmp(o, "macho")) { 46 t->os = KIT_OS_MACOS; 47 t->obj = KIT_OBJ_MACHO; 48 } else { 49 fprintf(stderr, 50 "kit_test_target: unrecognized KIT_TEST_OBJ=\"%s\" " 51 "(expected elf/macho)\n", 52 o); 53 return -1; 54 } 55 56 const char* a = kit_test_arch_name(); 57 if (!strcmp(a, "aa64") || !strcmp(a, "aarch64") || !strcmp(a, "arm64")) { 58 t->arch = KIT_ARCH_ARM_64; 59 return 0; 60 } 61 if (!strcmp(a, "x64") || !strcmp(a, "x86_64") || !strcmp(a, "amd64")) { 62 t->arch = KIT_ARCH_X86_64; 63 return 0; 64 } 65 if (!strcmp(a, "rv64") || !strcmp(a, "riscv64")) { 66 if (t->os == KIT_OS_MACOS) { 67 fprintf(stderr, "kit_test_target: rv64 has no macOS target\n"); 68 return -1; 69 } 70 t->arch = KIT_ARCH_RV64; 71 return 0; 72 } 73 if (!strcmp(a, "rv32") || !strcmp(a, "riscv32")) { 74 if (t->os == KIT_OS_MACOS) { 75 fprintf(stderr, "kit_test_target: rv32 has no macOS target\n"); 76 return -1; 77 } 78 /* riscv32-none-elf: freestanding, 4-byte pointers, ilp32f (hardware single 79 * float, soft double + i64) — the verified rv32 profile. float_abi must be 80 * set so `double` routes to soft-float (rv32 has no D). */ 81 t->arch = KIT_ARCH_RV32; 82 t->os = KIT_OS_FREESTANDING; 83 t->ptr_size = 4; 84 t->ptr_align = 4; 85 t->float_abi = KIT_FLOAT_ABI_SINGLE; 86 return 0; 87 } 88 if (!strcmp(a, "arm32") || !strcmp(a, "arm")) { 89 if (t->os == KIT_OS_MACOS) { 90 fprintf(stderr, "kit_test_target: arm32 has no macOS target\n"); 91 return -1; 92 } 93 /* arm-none-eabi: freestanding Cortex-M, 4-byte pointers, soft-float (float 94 * + double via the AEABI/compiler-rt helpers). */ 95 t->arch = KIT_ARCH_ARM_32; 96 t->os = KIT_OS_FREESTANDING; 97 t->ptr_size = 4; 98 t->ptr_align = 4; 99 t->float_abi = KIT_FLOAT_ABI_SOFT; 100 return 0; 101 } 102 fprintf(stderr, 103 "kit_test_target: unrecognized KIT_TEST_ARCH=\"%s\" " 104 "(expected aa64/x64/rv64/rv32/arm32)\n", 105 a); 106 return -1; 107 } 108 109 /* ISA/ABI strings a runner must thread into KitTargetOptions so the *resolved* 110 * float ABI matches the spec's float_abi intent. 111 * 112 * RISC-V has a float-ABI axis that kit_target_new re-derives from the resolved 113 * -march/-mabi (F/D feature bits) when no -mabi is given — it does NOT honor a 114 * bare spec->float_abi byte. Since the rv32 default -march dropped F (soft is 115 * the FPU-less MCU default), kit_test_target_init's KIT_FLOAT_ABI_SINGLE 116 * request is otherwise silently downgraded to SOFT, and the emitted object's 117 * ELF e_flags regress from 0x3 (RVC|SINGLE) to 0x1 (RVC) — incompatible with 118 * the freestanding bare harness (test/lib/exec_bare.sh), whose reset stub + 119 * runtime are hard-single. Pin rv32 to rv32imafc/ilp32f to match. 120 * 121 * Mirrors scripts/cross_test.sh:freestanding_abi_flags and test/smoke/rv32.sh. 122 * No other arch has this axis (soft-float is their no-F default, which the 123 * resolver already produces), so both slices stay empty. */ 124 static inline void kit_test_target_isa_abi(const KitTargetSpec* t, 125 KitSlice* isa, KitSlice* abi) { 126 KitSlice empty; 127 empty.s = NULL; 128 empty.len = 0; 129 *isa = empty; 130 *abi = empty; 131 if (t->arch == KIT_ARCH_RV32 && t->float_abi == KIT_FLOAT_ABI_SINGLE) { 132 *isa = kit_slice_cstr("rv32imafc_zicsr_zifencei"); 133 *abi = kit_slice_cstr("ilp32f"); 134 } 135 } 136 137 #endif