kit

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

emit.h (6154B)


      1 /* arch/x64/emit.h — shared x86-64 byte-level encoders, ABI tables, and type
      2  * helpers. Used by emit.c (definitions), the standalone assembler (asm.c), and
      3  * the NativeTarget codegen (native.c). Carries no codegen state (XImpl lives in
      4  * native.c). */
      5 #ifndef KIT_ARCH_X64_EMIT_H
      6 #define KIT_ARCH_X64_EMIT_H
      7 
      8 #include <kit/cg.h>
      9 #include <kit/compile.h>
     10 
     11 #include "abi/abi.h"
     12 #include "arch/mc.h"
     13 #include "arch/x64/isa.h"
     14 #include "core/core.h"
     15 #include "core/slice.h"
     16 #include "obj/obj.h"
     17 
     18 /* ---- prologue placeholder budgets / Win64 constants ---- */
     19 #define X64_PROLOGUE_BYTES 96u
     20 #define X64_PROLOGUE_BYTES_WIN64 192u
     21 #define X64_PROLOGUE_BASE_BYTES 11u
     22 #define X64_PROLOGUE_SRET_BYTES 7u
     23 #define X64_PROLOGUE_SAVE_BYTES 7u
     24 #define X64_PROLOGUE_XMM_SAVE_BYTES 8u
     25 #define X64_PROLOGUE_CHKSTK_DELTA 6u
     26 #define X64_WIN64_SHADOW_SPACE 32u
     27 #define X64_MAX_CS_INT_REGS 7u
     28 
     29 /* ---- per-OS ABI register layout (SysV vs Win64) ---- */
     30 typedef struct X64ABIRegs {
     31   const u32* int_args;       /* size = n_int_args */
     32   u32 n_int_args;            /* 6 (SysV) / 4 (Win64) */
     33   u32 n_fp_args;             /* 8 (SysV) / 4 (Win64) */
     34   int slot_shared_int_fp;    /* 1 (Win64): arg slot index shared int/xmm */
     35   u32 shadow_space;          /* 0 (SysV) / 32 (Win64) */
     36   int emit_sysv_vararg_save; /* 1 (SysV): emit 176B reg-save area */
     37   int vararg_fp_dup_to_gpr;  /* 1 (Win64): variadic FP arg duped to GPR */
     38   u64 cs_int_mask;           /* callee-saved GPRs */
     39   u64 cs_fp_mask;            /* callee-saved XMMs */
     40 } X64ABIRegs;
     41 
     42 const X64ABIRegs* x64_abi_for_os(KitOSKind os);
     43 
     44 /* Per-instruction debug line rows. Declared here (mc.h only forward-declares
     45  * Debug) so emit.c's encoders and native.c's lifecycle can both record rows
     46  * without taking a full dependency on debug/debug.h. */
     47 extern void debug_emit_row(Debug*, ObjSecId text_section, u32 offset, SrcLoc);
     48 extern void debug_func_pc_range(Debug*, ObjSecId text_section, u32 begin_ofs,
     49                                 u32 end_ofs);
     50 
     51 /* ---- type helpers ---- */
     52 #define CG_BUILTIN_ID(k) ((KitCgTypeId)((1u << 6) | (u32)(k)))
     53 static inline int type_is_64(KitCgTypeId t) {
     54   return t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I64) ||
     55          t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F64) || t >= (KitCgTypeId)(2u << 6);
     56 }
     57 static inline int type_is_fp_double(KitCgTypeId t) {
     58   return t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F64);
     59 }
     60 static inline u32 type_byte_size(KitCgTypeId t) {
     61   if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I8) ||
     62       t == CG_BUILTIN_ID(KIT_CG_BUILTIN_BOOL))
     63     return 1;
     64   if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I16)) return 2;
     65   if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_I32) ||
     66       t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F32))
     67     return 4;
     68   if (t == CG_BUILTIN_ID(KIT_CG_BUILTIN_F128)) return 16;
     69   return 8;
     70 }
     71 static inline int type_is_signed(KitCgTypeId t) {
     72   (void)t;
     73   return 0;
     74 }
     75 
     76 static inline void x64_abi_direct_reg_need(const ABIArgInfo* ai, u32* need_int,
     77                                            u32* need_fp) {
     78   *need_int = 0;
     79   *need_fp = 0;
     80   if (!ai || ai->kind != ABI_ARG_DIRECT) return;
     81   for (u16 i = 0; i < ai->nparts; ++i) {
     82     const ABIArgPart* p = &ai->parts[i];
     83     if (p->cls == ABI_CLASS_FP)
     84       ++*need_fp;
     85     else if (p->cls == ABI_CLASS_INT)
     86       ++*need_int;
     87   }
     88 }
     89 
     90 /* ---- byte-level encoders (defined in emit.c) ---- */
     91 void emit1(MCEmitter* mc, u8 b);
     92 void emit_leave(MCEmitter* mc);
     93 void emit_u32le(MCEmitter* mc, u32 v);
     94 void emit_rex(MCEmitter* mc, int w, u32 reg, u32 index, u32 rm);
     95 void emit_rex_force(MCEmitter* mc, int w, u32 reg, u32 index, u32 rm);
     96 u8 modrm(u32 mod, u32 reg, u32 rm);
     97 u8 sib(u32 scale, u32 index, u32 base);
     98 void emit_mem_operand(MCEmitter* mc, u32 reg, u32 base, i32 disp);
     99 void emit_rm_reg(MCEmitter* mc, u32 reg, u32 rm);
    100 void emit_mov_rr(MCEmitter* mc, int w, u32 dst, u32 src);
    101 void emit_mov_load(MCEmitter* mc, u32 size, int signed_ext, u32 dst, u32 base,
    102                    i32 disp);
    103 void emit_mov_store(MCEmitter* mc, u32 size, u32 src, u32 base, i32 disp);
    104 void emit_lea(MCEmitter* mc, u32 dst, u32 base, i32 disp);
    105 void emit_mov_load_idx(MCEmitter* mc, u32 size, int signed_ext, u32 dst,
    106                        u32 base, u32 index, u32 log2_scale, i32 disp);
    107 void emit_mov_store_idx(MCEmitter* mc, u32 size, u32 src, u32 base, u32 index,
    108                         u32 log2_scale, i32 disp);
    109 void emit_ret(MCEmitter* mc);
    110 void x64_emit_load_imm(MCEmitter* mc, int is64, u32 dst, i64 imm);
    111 void emit_alu_rr(MCEmitter* mc, int w, u8 op, u32 dst, u32 src);
    112 void emit_imul_rr(MCEmitter* mc, int w, u32 dst, u32 src);
    113 void emit_f7_rm(MCEmitter* mc, int w, u32 sub, u32 reg);
    114 void emit_shift_cl(MCEmitter* mc, int w, u32 sub, u32 reg);
    115 void emit_shift_imm(MCEmitter* mc, int w, u32 sub, u32 reg, u8 imm);
    116 void emit_cqo_or_cdq(MCEmitter* mc, int w);
    117 void emit_xor_self(MCEmitter* mc, int w, u32 r);
    118 void emit_cmp_imm8(MCEmitter* mc, int w, u32 reg, i8 imm);
    119 void emit_alu_imm8(MCEmitter* mc, int w, u32 sub, u32 reg, i8 imm);
    120 void emit_alu_imm32(MCEmitter* mc, int w, u32 sub, u32 reg, i32 imm);
    121 void emit_imul_imm8(MCEmitter* mc, int w, u32 dst, u32 src, i8 imm);
    122 void emit_imul_imm32(MCEmitter* mc, int w, u32 dst, u32 src, i32 imm);
    123 int imm_fits_i8(i64 imm);
    124 int imm_fits_i32(i64 imm);
    125 void emit_test_self(MCEmitter* mc, int w, u32 reg);
    126 void emit_setcc(MCEmitter* mc, u32 cc, u32 reg);
    127 void emit_movzx_r32_r8(MCEmitter* mc, u32 dst, u32 src);
    128 void emit_extend_rr(MCEmitter* mc, int w, int signed_ext, u32 src_size, u32 dst,
    129                     u32 src);
    130 void emit_sse_rr(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 src);
    131 void emit_sse_load(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base,
    132                    i32 disp);
    133 void emit_sse_store(MCEmitter* mc, u8 prefix, u8 opcode, u32 src, u32 base,
    134                     i32 disp);
    135 void emit_sse_load_idx(MCEmitter* mc, u8 prefix, u8 opcode, u32 dst, u32 base,
    136                        u32 index, u32 log2_scale, i32 disp);
    137 void emit_sse_store_idx(MCEmitter* mc, u8 prefix, u8 opcode, u32 src, u32 base,
    138                         u32 index, u32 log2_scale, i32 disp);
    139 void emit_sse_rr_w(MCEmitter* mc, u8 prefix, u8 opcode, int w, u32 dst,
    140                    u32 src);
    141 
    142 #endif