kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

arm32_target_features_test.c (6876B)


      1 /* arm32_target_features_test — the arm-none-eabi -march/-mcpu/-mfpu/-mfloat-abi
      2  * resolution at the public kit_target_new level: the apply_cpu hook (-mcpu=)
      3  * and the vfp/fpv5 features (-mfpu=) that drive the dsp feature, the float ABI
      4  * resolution, and (indirectly) the feature_predefines macro selection.
      5  *
      6  * Reds before the apply_cpu hook + arm32 wiring land; green after. */
      7 
      8 #include <kit/core.h>
      9 #include <kit/target.h>
     10 #include <string.h>
     11 
     12 #include "lib/kit_unit.h"
     13 
     14 static KitUnit g_u;
     15 #define EXPECT(c, ...) CU_EXPECT(&g_u, c, __VA_ARGS__)
     16 
     17 static KitTargetSpec arm32_spec(void) {
     18   KitTargetSpec t = kit_unit_target(KIT_ARCH_ARM_32, KIT_OS_FREESTANDING,
     19                                     KIT_OBJ_ELF);
     20   t.ptr_size = 4;
     21   t.ptr_align = 4;
     22   return t;
     23 }
     24 
     25 /* Build an arm32 target with optional -march (isa), -mcpu (cpu), -mabi (abi),
     26  * and an explicit feature list (the -mfpu lowering records vfp/fpv5 there). */
     27 static KitStatus make_arm32(KitSlice isa, KitSlice cpu, KitSlice abi,
     28                             const KitTargetFeature* features, uint32_t nfeatures,
     29                             KitTarget** out) {
     30   KitTargetOptions opts;
     31   memset(&opts, 0, sizeof opts);
     32   opts.spec = arm32_spec();
     33   opts.isa = isa;
     34   opts.cpu = cpu;
     35   opts.abi = abi;
     36   opts.features = features;
     37   opts.nfeatures = nfeatures;
     38   return kit_target_new(&g_u.ctx, &opts, out);
     39 }
     40 
     41 static int has(KitTarget* t, const char* name) {
     42   return kit_target_has_feature(t, kit_slice_cstr(name));
     43 }
     44 
     45 static void check_cpu_dsp(void) {
     46   KitTarget* t = NULL;
     47 
     48   /* cortex-m3 = ARMv7-M baseline: no DSP. */
     49   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m3"), KIT_SLICE_NULL,
     50                     NULL, 0, &t) == KIT_OK,
     51          "cortex-m3 target");
     52   EXPECT(!has(t, "dsp"), "cortex-m3 lacks dsp");
     53   EXPECT(!has(t, "vfp"), "cortex-m3 lacks vfp (soft)");
     54   kit_target_free(t);
     55 
     56   /* cortex-m4 = ARMv7E-M: DSP. */
     57   t = NULL;
     58   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m4"), KIT_SLICE_NULL,
     59                     NULL, 0, &t) == KIT_OK,
     60          "cortex-m4 target");
     61   EXPECT(has(t, "dsp"), "cortex-m4 has dsp");
     62   kit_target_free(t);
     63 
     64   /* cortex-m7 = ARMv7E-M: DSP. */
     65   t = NULL;
     66   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m7"), KIT_SLICE_NULL,
     67                     NULL, 0, &t) == KIT_OK,
     68          "cortex-m7 target");
     69   EXPECT(has(t, "dsp"), "cortex-m7 has dsp");
     70   kit_target_free(t);
     71 }
     72 
     73 static void check_march_dsp(void) {
     74   KitTarget* t = NULL;
     75 
     76   /* -march=armv7-m: no DSP. */
     77   EXPECT(make_arm32(KIT_SLICE_LIT("armv7-m"), KIT_SLICE_NULL, KIT_SLICE_NULL,
     78                     NULL, 0, &t) == KIT_OK,
     79          "armv7-m target");
     80   EXPECT(!has(t, "dsp"), "armv7-m lacks dsp");
     81   kit_target_free(t);
     82 
     83   /* -march=armv7e-m: DSP. */
     84   t = NULL;
     85   EXPECT(make_arm32(KIT_SLICE_LIT("armv7e-m"), KIT_SLICE_NULL, KIT_SLICE_NULL,
     86                     NULL, 0, &t) == KIT_OK,
     87          "armv7e-m target");
     88   EXPECT(has(t, "dsp"), "armv7e-m has dsp");
     89   kit_target_free(t);
     90 
     91   /* thumbv7em alias: DSP. */
     92   t = NULL;
     93   EXPECT(make_arm32(KIT_SLICE_LIT("thumbv7em"), KIT_SLICE_NULL, KIT_SLICE_NULL,
     94                     NULL, 0, &t) == KIT_OK,
     95          "thumbv7em target");
     96   EXPECT(has(t, "dsp"), "thumbv7em has dsp");
     97   kit_target_free(t);
     98 }
     99 
    100 static void check_mfpu_features(void) {
    101   /* -mfpu=fpv4-sp-d16 lowers to the "vfp" feature (the driver does the
    102    * name->feature mapping; here we record it directly). cortex-m4 + vfp =
    103    * dsp + vfp. */
    104   KitTargetFeature vfp[] = {
    105       {KIT_SLICE_LIT("vfp"), true},
    106   };
    107   KitTargetFeature fpv5[] = {
    108       {KIT_SLICE_LIT("vfp"), true},
    109       {KIT_SLICE_LIT("fpv5"), true},
    110   };
    111   KitTarget* t = NULL;
    112 
    113   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m4"), KIT_SLICE_NULL,
    114                     vfp, 1, &t) == KIT_OK,
    115          "cortex-m4 + vfp target");
    116   EXPECT(has(t, "dsp"), "cortex-m4 + vfp has dsp");
    117   EXPECT(has(t, "vfp"), "cortex-m4 + vfp has vfp");
    118   EXPECT(!has(t, "fpv5"), "cortex-m4 + vfp lacks fpv5");
    119   kit_target_free(t);
    120 
    121   /* cortex-m7 + fpv5 (the fpv5-d16 fpu). */
    122   t = NULL;
    123   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m7"), KIT_SLICE_NULL,
    124                     fpv5, 2, &t) == KIT_OK,
    125          "cortex-m7 + fpv5 target");
    126   EXPECT(has(t, "dsp"), "cortex-m7 + fpv5 has dsp");
    127   EXPECT(has(t, "vfp"), "cortex-m7 + fpv5 has vfp");
    128   EXPECT(has(t, "fpv5"), "cortex-m7 + fpv5 has fpv5");
    129   kit_target_free(t);
    130 }
    131 
    132 static void check_float_abi(void) {
    133   KitTargetFeature vfp[] = {
    134       {KIT_SLICE_LIT("vfp"), true},
    135   };
    136   KitTarget* t = NULL;
    137   KitTargetSpec resolved;
    138 
    139   /* Default / soft: float_abi resolves to SOFT (gates soft-float lowering). */
    140   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m3"), KIT_SLICE_NULL,
    141                     NULL, 0, &t) == KIT_OK,
    142          "cortex-m3 soft target");
    143   resolved = kit_target_spec(t);
    144   EXPECT(resolved.float_abi == (uint8_t)KIT_FLOAT_ABI_SOFT,
    145          "cortex-m3 resolves SOFT float ABI");
    146   kit_target_free(t);
    147 
    148   /* -mabi=hard with a VFP feature resolves to a hardware (single) float ABI.
    149    * (The driver still rejects -mfloat-abi=hard, but the resolver is exercisable
    150    * here at the API level.) */
    151   t = NULL;
    152   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m4"),
    153                     KIT_SLICE_LIT("hard"), vfp, 1, &t) == KIT_OK,
    154          "cortex-m4 hard+vfp target");
    155   resolved = kit_target_spec(t);
    156   EXPECT(resolved.float_abi == (uint8_t)KIT_FLOAT_ABI_SINGLE,
    157          "cortex-m4 hard+vfp resolves SINGLE float ABI");
    158   kit_target_free(t);
    159 
    160   /* -mabi=hard WITHOUT a VFP feature is invalid. */
    161   t = NULL;
    162   g_u.last_diag[0] = '\0';
    163   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-m4"),
    164                     KIT_SLICE_LIT("hard"), NULL, 0, &t) == KIT_INVALID,
    165          "hard ABI without FPU rejected");
    166   EXPECT(t == NULL, "hard ABI without FPU leaves target NULL");
    167   kit_target_free(t);
    168 }
    169 
    170 static void check_errors(void) {
    171   KitTarget* t = NULL;
    172 
    173   /* Unknown CPU is rejected (KIT_INVALID, with a diagnostic). */
    174   g_u.last_diag[0] = '\0';
    175   EXPECT(make_arm32(KIT_SLICE_NULL, KIT_SLICE_LIT("cortex-a9"), KIT_SLICE_NULL,
    176                     NULL, 0, &t) == KIT_INVALID,
    177          "unknown cpu rejected");
    178   EXPECT(t == NULL, "unknown cpu leaves target NULL");
    179   EXPECT(strstr(g_u.last_diag, "unsupported CPU") != NULL,
    180          "unknown cpu diagnostic");
    181 
    182   /* Unknown -march is rejected. */
    183   t = NULL;
    184   g_u.last_diag[0] = '\0';
    185   EXPECT(make_arm32(KIT_SLICE_LIT("armv6-m"), KIT_SLICE_NULL, KIT_SLICE_NULL,
    186                     NULL, 0, &t) == KIT_INVALID,
    187          "unknown march rejected");
    188   EXPECT(t == NULL, "unknown march leaves target NULL");
    189 }
    190 
    191 int main(void) {
    192   kit_unit_init(&g_u);
    193   check_cpu_dsp();
    194   check_march_dsp();
    195   check_mfpu_features();
    196   check_float_abi();
    197   check_errors();
    198   kit_unit_summary(&g_u, "arm32_target_features_test");
    199   return kit_unit_status(&g_u);
    200 }