kit

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

arch.c (6052B)


      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") || kit_slice_eq_cstr(isa, "wasm64"))
     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   switch (cc) {
     79     case KIT_CG_CC_TARGET_C:
     80     case KIT_CG_CC_WASM:
     81       return 1;
     82     case KIT_CG_CC_SYSV:
     83     case KIT_CG_CC_WIN64:
     84     case KIT_CG_CC_AAPCS:
     85     case KIT_CG_CC_INTERRUPT:
     86       return 0;
     87   }
     88   return 0;
     89 }
     90 
     91 /* Capability twin of wasm_intrinsic (src/arch/wasm/emit.c); keep the two in
     92  * sync. wasm lowers only the portable intrinsics — the CPU/barrier/baremetal
     93  * forms have no wasm lowering (emit.c panics on them). No default case, so a
     94  * new KitCgIntrinsic trips -Wswitch here. */
     95 static int wasm_supports_intrinsic(const Compiler* c, KitCgIntrinsic intrin) {
     96   (void)c;
     97   switch (intrin) {
     98     case KIT_CG_INTRIN_TRAP:
     99     case KIT_CG_INTRIN_CLZ:
    100     case KIT_CG_INTRIN_CTZ:
    101     case KIT_CG_INTRIN_POPCOUNT:
    102     case KIT_CG_INTRIN_BSWAP:
    103     case KIT_CG_INTRIN_SADD_OVERFLOW:
    104     case KIT_CG_INTRIN_UADD_OVERFLOW:
    105     case KIT_CG_INTRIN_SSUB_OVERFLOW:
    106     case KIT_CG_INTRIN_USUB_OVERFLOW:
    107     case KIT_CG_INTRIN_SMUL_OVERFLOW:
    108     case KIT_CG_INTRIN_UMUL_OVERFLOW:
    109     case KIT_CG_INTRIN_PREFETCH:
    110     case KIT_CG_INTRIN_EXPECT:
    111     case KIT_CG_INTRIN_ASSUME_ALIGNED:
    112       return 1;
    113     case KIT_CG_INTRIN_SETJMP:
    114     case KIT_CG_INTRIN_LONGJMP:
    115     case KIT_CG_INTRIN_FMA:
    116     case KIT_CG_INTRIN_SYSCALL:
    117     case KIT_CG_INTRIN_IRQ_SAVE:
    118     case KIT_CG_INTRIN_IRQ_RESTORE:
    119     case KIT_CG_INTRIN_IRQ_DISABLE:
    120     case KIT_CG_INTRIN_IRQ_ENABLE:
    121     case KIT_CG_INTRIN_DMB:
    122     case KIT_CG_INTRIN_DSB:
    123     case KIT_CG_INTRIN_ISB:
    124     case KIT_CG_INTRIN_DCACHE_CLEAN:
    125     case KIT_CG_INTRIN_DCACHE_INVALIDATE:
    126     case KIT_CG_INTRIN_DCACHE_CLEAN_INVALIDATE:
    127     case KIT_CG_INTRIN_ICACHE_INVALIDATE:
    128     case KIT_CG_INTRIN_CPU_NOP:
    129     case KIT_CG_INTRIN_CPU_YIELD:
    130     case KIT_CG_INTRIN_WFI:
    131     case KIT_CG_INTRIN_WFE:
    132     case KIT_CG_INTRIN_SEV:
    133     case KIT_CG_INTRIN_CORO_SWITCH:
    134     /* wasm has no frame-pointer chain to walk. */
    135     case KIT_CG_INTRIN_FRAME_ADDRESS:
    136     case KIT_CG_INTRIN_RETURN_ADDRESS:
    137       return 0;
    138   }
    139   return 0;
    140 }
    141 
    142 const ArchImpl arch_impl_wasm = {
    143     .backend = {.name = "wasm", .make = wasm_backend_make},
    144     .kind = KIT_ARCH_WASM,
    145     .name = "wasm",
    146     .cgtarget_new = wasm_cgtarget_new,
    147     .asm_new = NULL,
    148     .disasm_new = wasm_disasm_new,
    149     .apply_label_fixup = NULL,
    150     .link = NULL,
    151     .predefined_macros = wasm_predefined_macros,
    152     .npredefined_macros =
    153         (u32)(sizeof wasm_predefined_macros / sizeof wasm_predefined_macros[0]),
    154     .target_features = wasm_target_features,
    155     .ntarget_features =
    156         (u32)(sizeof wasm_target_features / sizeof wasm_target_features[0]),
    157     .target_feature_defaults = wasm_target_feature_defaults,
    158     .target_feature_apply_isa = wasm_target_feature_apply_isa,
    159     .register_name = NULL,
    160     .register_index = NULL,
    161     .register_count = NULL,
    162     .register_at = NULL,
    163     .backend_features =
    164         KIT_CG_BACKEND_STRICT_ALIGNMENT | KIT_CG_BACKEND_ICACHE_COHERENT,
    165     /* wasm32 has 4-byte pointers but lowers 8-byte (i64) atomics lock-free. */
    166     .atomic_lock_free_max = 8u,
    167     .supports_call_conv = wasm_supports_call_conv,
    168     .supports_intrinsic = wasm_supports_intrinsic,
    169 };