kit

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

arch.c (6092B)


      1 /* arch_impl_wasm: Wasm target descriptor.
      2  *
      3  * Native machine-code emitters (ELF/Mach-O/COFF) and the assembler are
      4  * intentionally NULL for v1: the Wasm target produces a WasmModule attached to
      5  * the ObjBuilder, which emit_wasm flushes via wasm_encode, and there is no
      6  * assembly form for wasm32 in the toolchain. The disassembler (wasm_disasm_new)
      7  * renders the code section of a .wasm module as WAT for objdump. */
      8 
      9 #include "arch/arch.h"
     10 
     11 #include "arch/wasm/disasm.h"
     12 #include "arch/wasm/internal.h"
     13 
     14 /* Predefined macros mirroring clang/llvm conventions. */
     15 static const KitPredefinedMacro wasm_predefined_macros[] = {
     16     {KIT_SLICE_LIT("__wasm__"), KIT_SLICE_LIT("1")},
     17     {KIT_SLICE_LIT("__wasm32__"), KIT_SLICE_LIT("1")},
     18     {KIT_SLICE_LIT("__ILP32__"), KIT_SLICE_LIT("1")},
     19     {KIT_SLICE_LIT("__ORDER_LITTLE_ENDIAN__"), KIT_SLICE_LIT("1234")},
     20     {KIT_SLICE_LIT("__ORDER_BIG_ENDIAN__"), KIT_SLICE_LIT("4321")},
     21     {KIT_SLICE_LIT("__BYTE_ORDER__"), KIT_SLICE_LIT("__ORDER_LITTLE_ENDIAN__")},
     22     {KIT_SLICE_LIT("__LITTLE_ENDIAN__"), KIT_SLICE_LIT("1")},
     23 };
     24 
     25 enum {
     26   WASM_TFEAT_THREADS = 0,
     27   WASM_TFEAT_TYPED_FUNC_REFS,
     28   WASM_TFEAT_TAIL_CALLS,
     29   WASM_TFEAT_MULTI_MEMORY,
     30   WASM_TFEAT_MEMORY64,
     31   WASM_TFEAT_BULK_MEMORY,
     32   WASM_TFEAT_NONTRAPPING_FTOI,
     33 };
     34 
     35 static const ArchTargetFeature wasm_target_features[] = {
     36     {"threads"},  {"typed-func-refs"}, {"tail-calls"},       {"multi-memory"},
     37     {"memory64"}, {"bulk-memory"},     {"nontrapping-ftoi"},
     38 };
     39 
     40 static void wasm_feature_set(u64* words, u32 nwords, u32 idx) {
     41   if (!words || idx / 64u >= nwords) return;
     42   words[idx / 64u] |= 1ull << (idx % 64u);
     43 }
     44 
     45 static KitStatus wasm_target_feature_apply_isa(const Target* target,
     46                                                KitSlice isa, u64* words,
     47                                                u32 nwords) {
     48   (void)target;
     49   (void)words;
     50   (void)nwords;
     51   if (kit_slice_eq_cstr(isa, "wasm32"))
     52     return KIT_OK;
     53   return KIT_UNSUPPORTED;
     54 }
     55 
     56 static void wasm_target_feature_defaults(const Target* target, u64* words,
     57                                          u32 nwords) {
     58   (void)target;
     59   wasm_feature_set(words, nwords, WASM_TFEAT_THREADS);
     60   wasm_feature_set(words, nwords, WASM_TFEAT_TYPED_FUNC_REFS);
     61   wasm_feature_set(words, nwords, WASM_TFEAT_TAIL_CALLS);
     62   wasm_feature_set(words, nwords, WASM_TFEAT_MULTI_MEMORY);
     63   wasm_feature_set(words, nwords, WASM_TFEAT_MEMORY64);
     64   wasm_feature_set(words, nwords, WASM_TFEAT_BULK_MEMORY);
     65   wasm_feature_set(words, nwords, WASM_TFEAT_NONTRAPPING_FTOI);
     66 }
     67 
     68 static CGTarget* wasm_backend_make(Compiler* c, ObjBuilder* o,
     69                                    const KitCodeOptions* opts) {
     70   (void)opts;
     71   return wasm_cgtarget_new(c, o, NULL);
     72 }
     73 
     74 /* wasm32 emits the target-C convention and its own WASM convention; no
     75  * SysV/Win64/AAPCS. */
     76 static int wasm_supports_call_conv(const Compiler* c, KitCgCallConv cc) {
     77   (void)c;
     78   return cc == KIT_CG_CC_TARGET_C;
     79 }
     80 
     81 /* Capability twin of wasm_intrinsic (src/arch/wasm/emit.c); keep the two in
     82  * sync. wasm lowers only the portable intrinsics — the CPU/barrier/baremetal
     83  * forms have no wasm lowering (emit.c panics on them). No default case, so a
     84  * new KitCgIntrinsic trips -Wswitch here. */
     85 static int wasm_supports_intrinsic(const Compiler* c, KitCgIntrinsic intrin) {
     86   (void)c;
     87   switch (intrin) {
     88     case KIT_CG_INTRIN_TRAP:
     89     case KIT_CG_INTRIN_CLZ:
     90     case KIT_CG_INTRIN_CTZ:
     91     case KIT_CG_INTRIN_POPCOUNT:
     92     case KIT_CG_INTRIN_BSWAP:
     93     case KIT_CG_INTRIN_SMUL_HIGH:
     94     case KIT_CG_INTRIN_UMUL_HIGH:
     95     case KIT_CG_INTRIN_SADD_OVERFLOW:
     96     case KIT_CG_INTRIN_UADD_OVERFLOW:
     97     case KIT_CG_INTRIN_SSUB_OVERFLOW:
     98     case KIT_CG_INTRIN_USUB_OVERFLOW:
     99     case KIT_CG_INTRIN_SMUL_OVERFLOW:
    100     case KIT_CG_INTRIN_UMUL_OVERFLOW:
    101     case KIT_CG_INTRIN_PREFETCH:
    102     case KIT_CG_INTRIN_EXPECT:
    103     case KIT_CG_INTRIN_ASSUME_ALIGNED:
    104       return 1;
    105     /* Portable spin-loop hint: wasm has no instruction, so it is a no-op. */
    106     case KIT_CG_INTRIN_CPU_YIELD:
    107       return 1;
    108     case KIT_CG_INTRIN_SETJMP:
    109     case KIT_CG_INTRIN_LONGJMP:
    110     case KIT_CG_INTRIN_FMA:
    111     case KIT_CG_INTRIN_SYSCALL:
    112     case KIT_CG_INTRIN_IRQ_SAVE:
    113     case KIT_CG_INTRIN_IRQ_RESTORE:
    114     case KIT_CG_INTRIN_IRQ_DISABLE:
    115     case KIT_CG_INTRIN_IRQ_ENABLE:
    116     case KIT_CG_INTRIN_DMB:
    117     case KIT_CG_INTRIN_DSB:
    118     case KIT_CG_INTRIN_ISB:
    119     case KIT_CG_INTRIN_DCACHE_CLEAN:
    120     case KIT_CG_INTRIN_DCACHE_INVALIDATE:
    121     case KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE:
    122     case KIT_CG_INTRIN_ICACHE_INVALIDATE:
    123     case KIT_CG_INTRIN_CPU_NOP:
    124     case KIT_CG_INTRIN_WFI:
    125     case KIT_CG_INTRIN_WFE:
    126     case KIT_CG_INTRIN_SEV:
    127     case KIT_CG_INTRIN_CORO_SWITCH:
    128     /* wasm has no frame-pointer chain to walk. */
    129     case KIT_CG_INTRIN_FRAME_ADDRESS:
    130     case KIT_CG_INTRIN_RETURN_ADDRESS:
    131     /* wasm has no architectural cycle-counter instruction. */
    132     case KIT_CG_INTRIN_READCYCLECOUNTER:
    133       return 0;
    134   }
    135   return 0;
    136 }
    137 
    138 const ArchImpl arch_impl_wasm = {
    139     .backend = {.name = "wasm", .make = wasm_backend_make},
    140     .kind = KIT_ARCH_WASM,
    141     .name = "wasm",
    142     .cgtarget_new = wasm_cgtarget_new,
    143     .asm_new = NULL,
    144     .disasm_new = wasm_disasm_new,
    145     .apply_label_fixup = NULL,
    146     .link = NULL,
    147     .predefined_macros = wasm_predefined_macros,
    148     .npredefined_macros =
    149         (u32)(sizeof wasm_predefined_macros / sizeof wasm_predefined_macros[0]),
    150     .target_features = wasm_target_features,
    151     .ntarget_features =
    152         (u32)(sizeof wasm_target_features / sizeof wasm_target_features[0]),
    153     .target_feature_defaults = wasm_target_feature_defaults,
    154     .target_feature_apply_isa = wasm_target_feature_apply_isa,
    155     .register_name = NULL,
    156     .register_index = NULL,
    157     .register_count = NULL,
    158     .register_at = NULL,
    159     .backend_features =
    160         KIT_CG_BACKEND_STRICT_ALIGNMENT | KIT_CG_BACKEND_ICACHE_COHERENT,
    161     /* wasm32 has 4-byte pointers but lowers 8-byte (i64) atomics lock-free. */
    162     .atomic_lock_free_max = 8u,
    163     .supports_call_conv = wasm_supports_call_conv,
    164     .supports_intrinsic = wasm_supports_intrinsic,
    165 };