diff --git a/cbuild.toml b/cbuild.toml index 97e77c0..4be8207 100644 --- a/cbuild.toml +++ b/cbuild.toml @@ -10,4 +10,7 @@ dependencies = [ { name = "ast", path = "./libs/ast" }, { name = "ast2ir", path = "./libs/ast2ir" }, { name = "ir", path = "./libs/ir" }, + + { name = "ir2mcode", path = "./libs/ir2mcode" }, + { name = "sccf2target", path = "./libs/target/sccf2target" }, ] diff --git a/libs/README.md b/libs/README.md index 99a9345..5f683df 100644 --- a/libs/README.md +++ b/libs/README.md @@ -22,3 +22,7 @@ mcode 机器码 sccf 统一输出格式 target 目标平台支持 + +- pe +[Windows Portable Executable Format](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#archive-library-file-format) +[中文文档](https://learn.microsoft.com/zh-cn/windows/win32/debug/pe-format#archive-library-file-format) diff --git a/libs/ast/cbuild.toml b/libs/ast/cbuild.toml index e423c3d..ee92109 100644 --- a/libs/ast/cbuild.toml +++ b/libs/ast/cbuild.toml @@ -4,6 +4,9 @@ version = "0.1.0" authors = [] description = "" -dependencies = [{ name = "tree_dump", path = "../tree_dump" }] +dependencies = [ + { name = "tree_dump", path = "../tree_dump" }, + { name = "scc_pos", path = "../sstream" }, +] # features = {} # default_features = [] diff --git a/libs/ir2mcode/cbuild.toml b/libs/ir2mcode/cbuild.toml new file mode 100644 index 0000000..b17d5ad --- /dev/null +++ b/libs/ir2mcode/cbuild.toml @@ -0,0 +1,21 @@ +[package] +name = "ir2mcode" +version = "0.1.0" +authors = [] +description = "" + +dependencies = [ + { name = "scc_utils", path = "../../runtime/scc_utils" }, + { name = "scc_ir", path = "../ir" }, + { name = "scc_mcode", path = "../mcode" }, + { name = "sccf", path = "../sccf" }, + + { name = "lexer", path = "../lexer" }, + { name = "pproc", path = "../pproc" }, + { name = "parser", path = "../parser" }, + { name = "ast", path = "../ast" }, + { name = "ast2ir", path = "../ast2ir" }, + { name = "sccf2target", path = "../target/sccf2target" }, +] +# features = {} +# default_features = [] diff --git a/libs/ir2mcode/include/reg_alloc.h b/libs/ir2mcode/include/reg_alloc.h new file mode 100644 index 0000000..e073a0c --- /dev/null +++ b/libs/ir2mcode/include/reg_alloc.h @@ -0,0 +1,47 @@ +#ifndef __SCC_REG_ALLOC_H__ +#define __SCC_REG_ALLOC_H__ + +#include +#include +#include + +typedef enum { + SCC_REG_KIND_UNDEF, + SCC_REG_KIND_GPR, ///< 通用寄存器(整数) + SCC_REG_KIND_FPR, ///< 浮点数寄存器 + SCC_REG_KIND_STACK, ///< 栈 + SCC_REG_KIND_IMM, ///< 整数立即数 + SCC_REG_KIND_IMM_FP, ///< 浮点数常量 +} scc_reg_kind_t; + +typedef struct { + scc_reg_kind_t kind; + usize idx; +} scc_reg_loc_t; +typedef SCC_VEC(scc_reg_loc_t) scc_reg_loc_vec_t; + +struct scc_reg_alloc; +typedef struct scc_reg_alloc scc_reg_alloc_t; +typedef scc_hashtable_t *(*scc_reg_alloc_func_t)( + scc_reg_alloc_t *ctx, ///< @param [in] 上下文 + scc_ir_func_t *func ///< @param [in] 待处理的 IR 函数 +); + +typedef struct scc_reg_alloc { + scc_ir_cprog_ctx_t *ir_ctx; ///< IR上下文 + scc_hashtable_t node_ref2reg_loc; ///< 输出结果哈希表 + scc_reg_loc_vec_t reg_loc_vec; + int gpr_caller_saved; ///< 函数可以随意修改,调用者如果在意需自行保护. + int gpr_callee_saved; ///< 函数必须保护这些寄存器的值. + scc_reg_alloc_func_t reg_alloc_func; + int alloc_stack_size; +} scc_reg_alloc_t; + +#define scc_reg_alloc(ctx, func) ((ctx)->reg_alloc_func(ctx, func)) + +void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t func, + scc_ir_cprog_ctx_t *ir_ctx); +scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, + scc_ir_func_t *func); + +#endif /* __SCC_REG_ALLOC_H__ */ diff --git a/libs/ir2mcode/include/scc_ir2mcode.h b/libs/ir2mcode/include/scc_ir2mcode.h new file mode 100644 index 0000000..9b49258 --- /dev/null +++ b/libs/ir2mcode/include/scc_ir2mcode.h @@ -0,0 +1,25 @@ +#ifndef __SCC_IR2MCODE_H__ +#define __SCC_IR2MCODE_H__ + +#include "reg_alloc.h" +#include +#include +#include +#include +typedef struct { + scc_ir_cprog_t *cprog; + scc_ir_cprog_ctx_t *ir_ctx; + scc_mcode_t mcode; + sccf_builder_t builder; + + scc_reg_alloc_t reg_alloc; + scc_hashtable_t *noderef2regloc; +} scc_ir2mcode_ctx_t; + +// amd64 + +void scc_ir2mcode_init(scc_ir2mcode_ctx_t *ctx, scc_ir_cprog_t *cprog, + scc_ir_cprog_ctx_t *ir_ctx, scc_mcode_arch_t arch); +void scc_ir2mcode(scc_ir2mcode_ctx_t *ctx); + +#endif /* __SCC_IR2MCODE_H__ */ diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c new file mode 100644 index 0000000..3170708 --- /dev/null +++ b/libs/ir2mcode/src/ir2amd64.c @@ -0,0 +1,232 @@ +#include +#include +#include +#include + +static scc_reg_loc_t *parse_location(scc_ir2mcode_ctx_t *ctx, + scc_ir_bblock_ref_t node_ref) { + scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref); + if (node == null) { + LOG_FATAL("invalid node ref"); + return null; + } + usize idx = 0; + switch (node->tag) { + case SCC_IR_NODE_CONST_INT: + scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type); + Assert(type != 0); + Assert(type->tag == SCC_IR_TYPE_U32 || type->tag == SCC_IR_TYPE_I32); + scc_reg_loc_t loc = {.kind = SCC_REG_KIND_IMM, + .idx = (usize)node->data.const_int.int32}; + scc_vec_push(ctx->reg_alloc.reg_loc_vec, loc); + idx = scc_vec_size(ctx->reg_alloc.reg_loc_vec); + break; + case SCC_IR_NODE_CONST_UINT: + case SCC_IR_NODE_CONST_FLOAT: + TODO(); + break; + default: + idx = (usize)scc_hashtable_get(ctx->noderef2regloc, + (void *)(usize)node_ref); + break; + } + + Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.reg_loc_vec)); + return &scc_vec_at(ctx->reg_alloc.reg_loc_vec, idx - 1); +} + +static void load_value_to_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, int reg) { + switch (loc->kind) { + case SCC_REG_KIND_GPR: + if (loc->idx != reg) { + scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->idx); + } else { + TODO(); + } + break; + case SCC_REG_KIND_STACK: + scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP, + -loc->idx); + break; + case SCC_REG_KIND_IMM: + scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32 + break; + default: + LOG_FATAL("unsupported location"); + } +} + +static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, + int reg) { + switch (loc->kind) { + case SCC_REG_KIND_GPR: + if (loc->idx != reg) { + scc_mcode_amd64_mov_r64_r64(mcode, loc->idx, reg); + } + case SCC_REG_KIND_STACK: + scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx, + reg); + break; + case SCC_REG_KIND_IMM: + LOG_FATAL("cannot store to immediate"); + break; + default: + LOG_FATAL("unsupported location"); + } +} + +static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, + int idx) { + scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref); + if (node == null) { + LOG_ERROR("invalid node ref"); + return; + } + + switch (node->tag) { + case SCC_IR_NODE_CONV: ///< 类型转换 + case SCC_IR_NODE_FUNC_ARG_REF: ///< 函数参数引用 + case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用 + LOG_ERROR("Unsupported node type: %d", node->tag); + break; + case SCC_IR_NODE_ALLOC: ///< 分配内存(stack) + case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss) + break; + case SCC_IR_NODE_LOAD: ///< 加载数据 + { + // node->data.load.target + scc_reg_loc_t *from = parse_location(ctx, node->data.load.target); + scc_reg_loc_t *to = parse_location(ctx, node_ref); + load_value_to_reg(&ctx->mcode, from, SCC_AMD64_RAX); + store_value_from_reg(&ctx->mcode, to, SCC_AMD64_RAX); + break; + } + case SCC_IR_NODE_STORE: ///< 存储数据 + { + scc_reg_loc_t *from = parse_location(ctx, node->data.store.value); + scc_reg_loc_t *to = parse_location(ctx, node->data.store.target); + load_value_to_reg(&ctx->mcode, from, SCC_AMD64_RAX); + store_value_from_reg(&ctx->mcode, to, SCC_AMD64_RAX); + break; + } + case SCC_IR_NODE_GET_PTR: ///< 获取指针 + case SCC_IR_NODE_GET_ELEM_PTR: ///< 获取元素指针(used by array) + TODO(); + case SCC_IR_NODE_OP: ///< 二元运算 + scc_reg_loc_t *loc_lhs = parse_location(ctx, node->data.op.lhs); + scc_reg_loc_t *loc_rhs = parse_location(ctx, node->data.op.rhs); + scc_reg_loc_t *loc_res = parse_location(ctx, node_ref); + + // 将左操作数加载到 RAX(临时结果寄存器) + load_value_to_reg(&ctx->mcode, loc_lhs, SCC_AMD64_RAX); + // 将右操作数加载到 RCX + load_value_to_reg(&ctx->mcode, loc_rhs, SCC_AMD64_RCX); + switch (node->data.op.op) { + case SCC_IR_OP_ADD: + scc_mcode_amd64_add_r64_r64(&ctx->mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + break; + case SCC_IR_OP_SUB: + scc_mcode_amd64_sub_r64_r64(&ctx->mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + break; + case SCC_IR_OP_MUL: + scc_mcode_amd64_mul_r64(&ctx->mcode, SCC_AMD64_RCX); + break; + default: + LOG_FATAL("unknown op: %d", node->data.op.op); + break; + } + // 将 RAX 中的结果存储到 res 位置 + store_value_from_reg(&ctx->mcode, loc_res, SCC_AMD64_RAX); + // [SCC_IR_OP_EMPTY] = "empty", [SCC_IR_OP_NEQ] = "!=", + // [SCC_IR_OP_EQ] = "==", [SCC_IR_OP_GT] = ">", + // [SCC_IR_OP_LT] = "<", [SCC_IR_OP_GE] = ">=", + // [SCC_IR_OP_LE] = "<=", [SCC_IR_OP_ADD] = "+", + // [SCC_IR_OP_SUB] = "-", [SCC_IR_OP_MUL] = "*", + // [SCC_IR_OP_DIV] = "/", [SCC_IR_OP_MOD] = "%", + // [SCC_IR_OP_AND] = "&", [SCC_IR_OP_OR] = "|", + // [SCC_IR_OP_XOR] = "^", [SCC_IR_OP_NOT] = "~", + // [SCC_IR_OP_SHL] = "<<", [SCC_IR_OP_SHR] = ">>", + // [SCC_IR_OP_SAR] = ">>a", // Arithmetic shift right + break; + case SCC_IR_NODE_BRANCH: ///< 有条件分支 + case SCC_IR_NODE_JUMP: ///< 无条件跳转 + case SCC_IR_NODE_CALL: ///< 调用函数 + LOG_ERROR("Unsupported node type: %d", node->tag); + break; + case SCC_IR_NODE_RET: ///< 函数返回 + scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RSP, SCC_AMD64_RBP); + scc_mcode_amd64_pop_r64(&ctx->mcode, SCC_AMD64_RBP); + scc_mcode_amd64_ret(&ctx->mcode); + break; + default: + UNREACHABLE(); + break; + } +} + +static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock) { + + // 打印基本块中的每条指令 + for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) { + scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, i); + parse_node(ctx, node_ref, i); + } +} + +static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { + scc_hashtable_t bblock2offset; + + ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func); + // 对齐到 16 字节 + usize stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15; + + scc_mcode_amd64_push_r64(&ctx->mcode, SCC_AMD64_RBP); + scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RBP, SCC_AMD64_RSP); + scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, stack_size); + + for (usize i = 0; i < scc_vec_size(func->bblocks); i++) { + scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i); + scc_ir_bblock_t *bblock = + scc_ir_ctx_get_bblock(ctx->ir_ctx, bblock_ref); + + if (bblock == null) { + LOG_FATAL("\n"); + return; + } + parse_bblock(ctx, bblock); + } +} + +void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { + scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_with_stack, ctx->ir_ctx); + + scc_vec_foreach(ctx->cprog->func_defs, i) { + scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i); + scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref); + if (!func) { + LOG_ERROR("invalid function reference"); + return; + } + sccf_sym_t sym = { + .sccf_sect_offset = scc_vec_size(ctx->mcode.mcode), + .sccf_sect_type = SCCF_SECT_CODE, + .sccf_sym_bind = SCCF_SYM_BIND_GLOBAL, + .sccf_sym_size = 0, + .sccf_sym_type = SCCF_SYM_TYPE_FUNC, + .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, + }; + sccf_builder_add_symbol(&ctx->builder, func->name, &sym); + + parse_function(ctx, func); + } + sccf_sect_data_t text_section; + scc_vec_unsafe_from_buffer(text_section, + scc_vec_unsafe_get_data(ctx->mcode.mcode), + scc_vec_size(ctx->mcode.mcode)); + sccf_builder_add_text_section(&ctx->builder, &text_section); + sccf_sect_data_t data_section; + scc_vec_init(data_section); + sccf_builder_add_data_section(&ctx->builder, &data_section); +} diff --git a/libs/ir2mcode/src/reg_alloc.c b/libs/ir2mcode/src/reg_alloc.c new file mode 100644 index 0000000..d0a8260 --- /dev/null +++ b/libs/ir2mcode/src/reg_alloc.c @@ -0,0 +1,59 @@ +#include "reg_alloc.h" + +u32 hash_func(const void *key) { return (usize)key; } +int equal_func(const void *key1, const void *key2) { + return (usize)key1 - (usize)key2; +} + +void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t func, + scc_ir_cprog_ctx_t *ir_ctx) { + ctx->gpr_caller_saved = 0; + ctx->gpr_callee_saved = 0; + ctx->ir_ctx = ir_ctx; + ctx->reg_alloc_func = func; + + ctx->alloc_stack_size = 0; + scc_vec_init(ctx->reg_loc_vec); + scc_hashtable_init(&ctx->node_ref2reg_loc, hash_func, equal_func); +} + +scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, + scc_ir_func_t *func) { + ctx->alloc_stack_size = 0; + scc_hashtable_drop(&ctx->node_ref2reg_loc); + scc_vec_free(ctx->reg_loc_vec); + scc_vec_init(ctx->reg_loc_vec); + + scc_vec_foreach(func->bblocks, i) { + scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i); + scc_ir_bblock_t *bblock = + scc_ir_ctx_get_bblock(ctx->ir_ctx, bblock_ref); + Assert(bblock != null); + scc_vec_foreach(bblock->instrs, j) { + scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, j); + scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref); + Assert(node != null); + + scc_reg_loc_t loc; + loc.kind = SCC_REG_KIND_UNDEF; + switch (node->tag) { + case SCC_IR_NODE_LOAD: + case SCC_IR_NODE_OP: + case SCC_IR_NODE_ALLOC: { + loc.kind = SCC_REG_KIND_STACK; + loc.idx = ctx->alloc_stack_size; + + ctx->alloc_stack_size += 8; + scc_vec_push(ctx->reg_loc_vec, loc); + scc_hashtable_set(&ctx->node_ref2reg_loc, + (void *)(usize)node_ref, + (void *)scc_vec_size(ctx->reg_loc_vec)); + break; + } + default: + break; + } + } + } + return &ctx->node_ref2reg_loc; +} diff --git a/libs/ir2mcode/src/scc_ir2mcode.c b/libs/ir2mcode/src/scc_ir2mcode.c new file mode 100644 index 0000000..7bf2c49 --- /dev/null +++ b/libs/ir2mcode/src/scc_ir2mcode.c @@ -0,0 +1,12 @@ +#include + +void scc_ir2mcode_init(scc_ir2mcode_ctx_t *ctx, scc_ir_cprog_t *cprog, + scc_ir_cprog_ctx_t *ir_ctx, scc_mcode_arch_t arch) { + ctx->cprog = cprog; + ctx->ir_ctx = ir_ctx; + scc_mcode_init(&ctx->mcode, arch); + sccf_builder_init(&ctx->builder); +} + +void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx); +void scc_ir2mcode(scc_ir2mcode_ctx_t *ctx) { scc_ir2amd64(ctx); } diff --git a/libs/ir2mcode/tests/test_run.c b/libs/ir2mcode/tests/test_run.c new file mode 100644 index 0000000..65b803d --- /dev/null +++ b/libs/ir2mcode/tests/test_run.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +#include + +void test_example(const char *input, cbool need_sema) { + int res = 0; + scc_sstream_t mem_stream; + res = scc_sstream_init_by_buffer(&mem_stream, input, scc_strlen(input), + false, 16); + Assert(res == 0); + + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); + + scc_parser_t parser; + if (need_sema) { + scc_sema_callbacks_t sema_callbacks; + scc_sema_init(&sema_callbacks); + scc_parser_init(&parser, tok_ring, &sema_callbacks); + } else { + scc_parser_init(&parser, tok_ring, null); + } + + scc_ast_translation_unit_t *tu = scc_parse_translation_unit(&parser); + + scc_ast2ir_ctx_t ast2ir_ctx; +#include + scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi); + scc_ast2ir_translation_unit(&ast2ir_ctx, tu); + + scc_ir2mcode_ctx_t mcode_ctx; + scc_ir2mcode_init(&mcode_ctx, &ast2ir_ctx.builder.cprog, + &ast2ir_ctx.builder.ctx, SCC_MCODE_ARCH_AMD64); + scc_ir2mcode(&mcode_ctx); + + const sccf_t *sccf = sccf_builder_to_sccf(&mcode_ctx.builder); + scc_pe_builder_t pe_builder; + sccf2pe(&pe_builder, sccf); + scc_pe_dump_to_file(&pe_builder, __FILE__ "/../../test.exe"); +} + +int main() { + test_example("int main() {\n" + " int a;\n" + " int b;\n" + " a = 1 + 2 * 3;\n" + " b = 7;\n" + " a = a - b + 1;\n" + " return a;\n" + "}\n", + true); + return 0; +} diff --git a/libs/mcode/include/amd64/scc_amd64.h b/libs/mcode/include/amd64/scc_amd64.h new file mode 100644 index 0000000..1725a71 --- /dev/null +++ b/libs/mcode/include/amd64/scc_amd64.h @@ -0,0 +1,2288 @@ +/** + * @file scc_mcode_amd64.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2026-03-13 + * + * @copyright Copyright (c) 2026 + * + */ +#ifndef __SCC_MCODE_AMD64_H__ +#define __SCC_MCODE_AMD64_H__ + +///< @warning WRITE BY AI + +#include // 提供 u8, u32, u64 等 +#include // 提供 scc_mcode_t 和写入函数 + +// ==================== 寄存器编号 ==================== +#define SCC_AMD64_RAX 0 +#define SCC_AMD64_RCX 1 +#define SCC_AMD64_RDX 2 +#define SCC_AMD64_RBX 3 +#define SCC_AMD64_RSP 4 +#define SCC_AMD64_RBP 5 +#define SCC_AMD64_RSI 6 +#define SCC_AMD64_RDI 7 +#define SCC_AMD64_R8 8 +#define SCC_AMD64_R9 9 +#define SCC_AMD64_R10 10 +#define SCC_AMD64_R11 11 +#define SCC_AMD64_R12 12 +#define SCC_AMD64_R13 13 +#define SCC_AMD64_R14 14 +#define SCC_AMD64_R15 15 + +// ==================== 条件码(用于 Jcc 等) ==================== +#define SCC_AMD64_COND_O 0 // overflow +#define SCC_AMD64_COND_NO 1 // not overflow +#define SCC_AMD64_COND_B 2 // below (unsigned) +#define SCC_AMD64_COND_AE 3 // above or equal (unsigned) +#define SCC_AMD64_COND_E 4 // equal +#define SCC_AMD64_COND_NE 5 // not equal +#define SCC_AMD64_COND_BE 6 // below or equal (unsigned) +#define SCC_AMD64_COND_A 7 // above (unsigned) +#define SCC_AMD64_COND_S 8 // sign (negative) +#define SCC_AMD64_COND_NS 9 // not sign +#define SCC_AMD64_COND_P 10 // parity even +#define SCC_AMD64_COND_NP 11 // parity odd +#define SCC_AMD64_COND_L 12 // less (signed) +#define SCC_AMD64_COND_GE 13 // greater or equal (signed) +#define SCC_AMD64_COND_LE 14 // less or equal (signed) +#define SCC_AMD64_COND_G 15 // greater (signed) + +// ==================== REX 前缀辅助 ==================== +/** + * @brief 生成 REX 前缀(若不为 0x40 则写入) + * + * @param mcode 机器码缓冲区 + * @param w REX.W 位 + * @param r REX.R 位 + * @param x REX.X 位 + * @param b REX.B 位 + */ +static inline void scc_mcode_amd64_rex(scc_mcode_t *mcode, u8 w, u8 r, u8 x, + u8 b) { + u8 rex = 0x40 | (w << 3) | (r << 2) | (x << 1) | b; + if (rex != 0x40) + scc_mcode_add_u8(mcode, rex); +} + +// ==================== 内部辅助函数 ==================== + +/** + * @brief 根据目标寄存器和源寄存器生成 REX 位掩码(用于 reg 和 r/m 字段) + * + * @param dst_reg 目标寄存器编号 + * @param src_reg 源寄存器编号 + * @param use_w 是否设置 REX.W + * @param p_rex 输出 REX 值 + * @param p_dst_low 输出 dst 的低 3 位 + * @param p_src_low 输出 src 的低 3 位 + * @return 是否需要写入 REX 前缀(0 表示不需要) + */ +static inline int scc_mcode_amd64_prepare_rex(int dst_reg, int src_reg, + int use_w, u8 *p_rex, + u8 *p_dst_low, u8 *p_src_low) { + u8 rex = 0x40; + if (use_w) + rex |= 0x08; + if (dst_reg >= 8) + rex |= 0x01; // REX.B + if (src_reg >= 8) + rex |= 0x04; // REX.R + *p_dst_low = dst_reg & 7; + *p_src_low = src_reg & 7; + *p_rex = rex; + return (rex != 0x40); +} + +/** + * @brief 根据操作数宽度添加必要前缀(16 位添加 0x66,32 位无前缀,64 位需配合 + * REX.W) + * + * @param mcode 机器码缓冲区 + * @param width 宽度(1=8位,2=16位,4=32位,8=64位) + */ +static inline void scc_mcode_amd64_emit_width_prefix(scc_mcode_t *mcode, + int width) { + if (width == 2) { + scc_mcode_add_u8(mcode, 0x66); + } + // 32 位无前缀,64 位通过 REX.W 处理(由调用者设置) +} + +// ==================== 栈操作 ==================== + +/** + * @brief 压入 64 位寄存器 + * + * @param mcode 机器码缓冲区 + * @param reg 寄存器编号 + */ +static inline void scc_mcode_amd64_push_r64(scc_mcode_t *mcode, int reg) { + if (reg < 8) { + scc_mcode_add_u8(mcode, 0x50 + reg); + } else { + scc_mcode_amd64_rex(mcode, 0, 0, 0, 1); // REX.B + scc_mcode_add_u8(mcode, 0x50 + (reg - 8)); + } +} + +/** + * @brief 弹出到 64 位寄存器 + * + * @param mcode 机器码缓冲区 + * @param reg 寄存器编号 + */ +static inline void scc_mcode_amd64_pop_r64(scc_mcode_t *mcode, int reg) { + if (reg < 8) { + scc_mcode_add_u8(mcode, 0x58 + reg); + } else { + scc_mcode_amd64_rex(mcode, 0, 0, 0, 1); // REX.B + scc_mcode_add_u8(mcode, 0x58 + (reg - 8)); + } +} + +/** + * @brief 压入 32 位立即数(符号扩展至 64 位) + * + * @param mcode 机器码缓冲区 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_push_imm32(scc_mcode_t *mcode, u32 imm) { + scc_mcode_add_u8(mcode, 0x68); + scc_mcode_add_u32(mcode, imm); +} + +// ==================== 数据传送 ==================== + +// ---------- 64 位 ---------- + +/** + * @brief 将 64 位立即数移动到 64 位寄存器 (mov r64, imm64) + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器 + * @param imm 64 位立即数 + */ +static inline void scc_mcode_amd64_mov_r64_imm64(scc_mcode_t *mcode, int reg, + u64 imm) { + u8 rex = 0x48; // REX.W + if (reg >= 8) { + rex |= 0x01; // REX.B + reg -= 8; + } + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xB8 + reg); + scc_mcode_add_u64(mcode, imm); +} + +/** + * @brief 将 32 位立即数移动到 64 位寄存器(高 32 位清零)(mov r64, imm32) + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_mov_r64_imm32(scc_mcode_t *mcode, int reg, + u32 imm) { + u8 rex = 0x40; // REX.W=0 + if (reg >= 8) { + rex |= 0x01; // REX.B + reg -= 8; + } + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xB8 + reg); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 64 位寄存器之间传送 (mov r64, r64) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; // REX.W + if (src >= 8) + rex |= 0x04; // REX.R + if (dst >= 8) + rex |= 0x01; // REX.B + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); // MOV r/m, r + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 存储 64 位寄存器到 [base] (mov [base], r64) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_m64_r64(scc_mcode_t *mcode, int base, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + u8 modrm = (base & 7) | ((src & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 从 [base] 加载到 64 位寄存器 (mov r64, [base]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_mov_r64_m64(scc_mcode_t *mcode, int dst, + int base) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8B); + u8 modrm = (base & 7) | ((dst & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 存储 64 位寄存器到 [base + disp32] (mov [base+disp32], r64) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + * @param disp 32 位偏移 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_m64_disp32_r64(scc_mcode_t *mcode, + int base, u32 disp, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + u8 modrm = 0x80 | (base & 7) | ((src & 7) << 3); // mod=10 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } + scc_mcode_add_u32(mcode, disp); +} + +/** + * @brief 从 [base + disp32] 加载到 64 位寄存器 (mov r64, [base+disp32]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器 + * @param disp 32 位偏移 + */ +static inline void scc_mcode_amd64_mov_r64_m64_disp32(scc_mcode_t *mcode, + int dst, int base, + u32 disp) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8B); + u8 modrm = 0x80 | (base & 7) | ((dst & 7) << 3); // mod=10 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } + scc_mcode_add_u32(mcode, disp); +} + +/** + * @brief 加载有效地址到 64 位寄存器 (lea r64, [base+disp32]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器 + * @param disp 32 位偏移 + */ +static inline void scc_mcode_amd64_lea_r64_m64_disp32(scc_mcode_t *mcode, + int dst, int base, + u32 disp) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8D); + u8 modrm = 0x80 | (base & 7) | ((dst & 7) << 3); // mod=10 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } + scc_mcode_add_u32(mcode, disp); +} + +// ---------- 32 位 ---------- + +/** + * @brief 32 位寄存器之间传送 (mov r32, r32) 高 32 位清零 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器(低 32 位) + * @param src 源寄存器(低 32 位) + */ +static inline void scc_mcode_amd64_mov_r32_r32(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; // REX.W=0 + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 将 32 位立即数移动到 32 位寄存器(高 32 位清零)(mov r32, imm32) + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_mov_r32_imm32(scc_mcode_t *mcode, int reg, + u32 imm) { + scc_mcode_amd64_mov_r64_imm32(mcode, reg, imm); // 与 64 位 imm32 版本相同 +} + +/** + * @brief 存储 32 位寄存器到 [base] (mov [base], r32) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_m32_r32(scc_mcode_t *mcode, int base, + int src) { + u8 rex = 0x40; // REX.W=0 + if (src >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + u8 modrm = (base & 7) | ((src & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 从 [base] 加载到 32 位寄存器 (mov r32, [base]) 高 32 位清零 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_mov_r32_m32(scc_mcode_t *mcode, int dst, + int base) { + u8 rex = 0x40; // REX.W=0 + if (dst >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8B); + u8 modrm = (base & 7) | ((dst & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +// ---------- 16 位 ---------- + +/** + * @brief 16 位寄存器之间传送 (mov r16, r16) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器(低 16 位) + * @param src 源寄存器(低 16 位) + */ +static inline void scc_mcode_amd64_mov_r16_r16(scc_mcode_t *mcode, int dst, + int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; // REX.W=0 + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 将 16 位立即数移动到 16 位寄存器 (mov r16, imm16) + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器 + * @param imm 16 位立即数 + */ +static inline void scc_mcode_amd64_mov_r16_imm16(scc_mcode_t *mcode, int reg, + u16 imm) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; // REX.W=0 + if (reg >= 8) { + rex |= 0x01; + reg -= 8; + } + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xB8 + reg); + scc_mcode_add_u16(mcode, imm); +} + +/** + * @brief 存储 16 位寄存器到 [base] (mov [base], r16) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_m16_r16(scc_mcode_t *mcode, int base, + int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + u8 modrm = (base & 7) | ((src & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 从 [base] 加载到 16 位寄存器 (mov r16, [base]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_mov_r16_m16(scc_mcode_t *mcode, int dst, + int base) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (dst >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8B); + u8 modrm = (base & 7) | ((dst & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +// ---------- 8 位 ---------- + +/** + * @brief 检查 8 位寄存器是否需要 REX 前缀 + * + * 若寄存器编号为 4-7(SPL、BPL、SIL、DIL),必须使用 REX 前缀 + * + * @param reg 寄存器编号 + * @return 是否需要 REX 前缀 + */ +static inline int scc_mcode_amd64_is_byte_reg_needs_rex(int reg) { + return (reg >= 4 && reg <= 7) || reg >= 8; +} + +/** + * @brief 8 位寄存器之间传送 (mov r8, r8) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器(低 8 位) + * @param src 源寄存器(低 8 位) + */ +static inline void scc_mcode_amd64_mov_r8_r8(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) || + scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x88); // MOV r/m8, r8 + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 将 8 位立即数移动到 8 位寄存器 (mov r8, imm8) + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器 + * @param imm 8 位立即数 + */ +static inline void scc_mcode_amd64_mov_r8_imm8(scc_mcode_t *mcode, int reg, + u8 imm) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(reg); + if (reg >= 8) { + rex |= 0x01; + reg -= 8; + } + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0xB0 + reg); + scc_mcode_add_u8(mcode, imm); +} + +/** + * @brief 存储 8 位寄存器到 [base] (mov [base], r8) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_m8_r8(scc_mcode_t *mcode, int base, + int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src) || + scc_mcode_amd64_is_byte_reg_needs_rex(base); + if (src >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x88); + u8 modrm = (base & 7) | ((src & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 从 [base] 加载到 8 位寄存器 (mov r8, [base]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_mov_r8_m8(scc_mcode_t *mcode, int dst, + int base) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) || + scc_mcode_amd64_is_byte_reg_needs_rex(base); + if (dst >= 8) + rex |= 0x04; + if (base >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x8A); + u8 modrm = (base & 7) | ((dst & 7) << 3); // mod=00 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +// ---------- 符号/零扩展传送 ---------- + +/** + * @brief 符号扩展传送 (movsx r64, r/m8) + * + * @param mcode 机器码缓冲区 + * @param dst 64 位目标寄存器 + * @param src 8 位源寄存器 + */ +static inline void scc_mcode_amd64_movsx_r64_r8(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; // REX.W + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0xBE); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 符号扩展传送 (movsx r64, r/m16) + * + * @param mcode 机器码缓冲区 + * @param dst 64 位目标寄存器 + * @param src 16 位源寄存器 + */ +static inline void scc_mcode_amd64_movsx_r64_r16(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0xBF); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 符号扩展传送 (movsx r64, r/m32) + * + * @param mcode 机器码缓冲区 + * @param dst 64 位目标寄存器 + * @param src 32 位源寄存器 + */ +static inline void scc_mcode_amd64_movsx_r64_r32(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x63); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 零扩展传送 (movzx r64, r/m8) + * + * @param mcode 机器码缓冲区 + * @param dst 64 位目标寄存器 + * @param src 8 位源寄存器 + */ +static inline void scc_mcode_amd64_movzx_r64_r8(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0xB6); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 零扩展传送 (movzx r64, r/m16) + * + * @param mcode 机器码缓冲区 + * @param dst 64 位目标寄存器 + * @param src 16 位源寄存器 + */ +static inline void scc_mcode_amd64_movzx_r64_r16(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0xB7); + u8 modrm = 0xC0 | ((src & 7) << 3) | (dst & 7); + scc_mcode_add_u8(mcode, modrm); +} + +// ==================== 算术运算 ==================== + +// ---------- 64 位 ---------- + +/** + * @brief 64 位加法 ADD r64, r64 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_add_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x01); // ADD r/m, r + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位加法 ADD r64, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_add_r64_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (0 << 3); // reg/opcode = 0 for ADD + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 64 位减法 SUB r64, r64 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_sub_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x29); // SUB r/m, r + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位减法 SUB r64, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_sub_r64_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (5 << 3); // reg/opcode = 5 for SUB + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 调整 RSP 专用减法 (sub rsp, imm32) + * + * @param mcode 机器码缓冲区 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_sub_rsp_imm32(scc_mcode_t *mcode, u32 imm) { + scc_mcode_amd64_sub_r64_imm32(mcode, SCC_AMD64_RSP, imm); +} + +/** + * @brief 调整 RSP 专用加法 (add rsp, imm32) + * + * @param mcode 机器码缓冲区 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_add_rsp_imm32(scc_mcode_t *mcode, u32 imm) { + scc_mcode_amd64_add_r64_imm32(mcode, SCC_AMD64_RSP, imm); +} + +/** + * @brief 64 位比较 CMP r64, r64 + * + * @param mcode 机器码缓冲区 + * @param dst 左操作数寄存器 + * @param src 右操作数寄存器 + */ +static inline void scc_mcode_amd64_cmp_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x39); // CMP r/m, r + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位比较 CMP r64, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_cmp_r64_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (7 << 3); // reg/opcode = 7 for CMP + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 两操作数有符号乘法 IMUL r64, r64 (r64 = r64 * r64) + * + * @param mcode 机器码缓冲区 + * @param dst 目标/左操作数寄存器 + * @param src 右操作数寄存器 + */ +static inline void scc_mcode_amd64_imul_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; // dst in reg field + if (src >= 8) + rex |= 0x01; // src in r/m field + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0xAF); + u8 modrm = 0xC0 | (src & 7) | ((dst & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 三操作数有符号乘法 IMUL r64, r/m64, imm32 (r64 = r/m64 * imm32) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器或内存(此处为寄存器版本) + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_imul_r64_r64_imm32(scc_mcode_t *mcode, + int dst, int src, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x69); + u8 modrm = 0xC0 | (src & 7) | ((dst & 7) << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 三操作数有符号乘法 IMUL r64, r/m64, imm8 (符号扩展) (r64 = r/m64 * + * imm8) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器或内存(此处为寄存器版本) + * @param imm 8 位立即数 + */ +static inline void scc_mcode_amd64_imul_r64_r64_imm8(scc_mcode_t *mcode, + int dst, int src, u8 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x6B); + u8 modrm = 0xC0 | (src & 7) | ((dst & 7) << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, imm); +} + +// ---------- 32 位 ---------- + +/** + * @brief 32 位加法 ADD r32, r32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_add_r32_r32(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; // REX.W=0 + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x01); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 32 位加法 ADD r32, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_add_r32_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x40; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (0 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 32 位减法 SUB r32, r32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_sub_r32_r32(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x29); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 32 位比较 CMP r32, r32 + * + * @param mcode 机器码缓冲区 + * @param dst 左操作数寄存器 + * @param src 右操作数寄存器 + */ +static inline void scc_mcode_amd64_cmp_r32_r32(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x39); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ---------- 16 位 ---------- + +/** + * @brief 16 位加法 ADD r16, r16 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_add_r16_r16(scc_mcode_t *mcode, int dst, + int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x01); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 16 位加法 ADD r16, imm16 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 16 位立即数 + */ +static inline void scc_mcode_amd64_add_r16_imm16(scc_mcode_t *mcode, int dst, + u16 imm) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (0 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u16(mcode, imm); +} + +/** + * @brief 16 位减法 SUB r16, r16 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_sub_r16_r16(scc_mcode_t *mcode, int dst, + int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x29); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 16 位比较 CMP r16, r16 + * + * @param mcode 机器码缓冲区 + * @param dst 左操作数寄存器 + * @param src 右操作数寄存器 + */ +static inline void scc_mcode_amd64_cmp_r16_r16(scc_mcode_t *mcode, int dst, + int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x39); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ---------- 8 位 ---------- + +/** + * @brief 8 位加法 ADD r8, r8 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_add_r8_r8(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) || + scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x00); // ADD r/m8, r8 + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 8 位加法 ADD r8, imm8 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 8 位立即数 + */ +static inline void scc_mcode_amd64_add_r8_imm8(scc_mcode_t *mcode, int dst, + u8 imm) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst); + if (dst >= 8) { + rex |= 0x01; + dst -= 8; + } + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x80); // ADD r/m8, imm8 + u8 modrm = 0xC0 | (dst & 7) | (0 << 3); // reg/opcode = 0 for ADD + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, imm); +} + +/** + * @brief 8 位减法 SUB r8, r8 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_sub_r8_r8(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) || + scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x28); // SUB r/m8, r8 + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 8 位比较 CMP r8, r8 + * + * @param mcode 机器码缓冲区 + * @param dst 左操作数寄存器 + * @param src 右操作数寄存器 + */ +static inline void scc_mcode_amd64_cmp_r8_r8(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) || + scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x38); // CMP r/m8, r8 + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ==================== 单操作数乘除 ==================== + +// ---------- 无符号乘法 MUL ---------- + +/** + * @brief 无符号乘法 MUL r/m64 (RDX:RAX = RAX * r/m64) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mul_r64(scc_mcode_t *mcode, int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (4 << 3); // reg/opcode = 4 for MUL + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 无符号乘法 MUL r/m32 (EDX:EAX = EAX * r/m32) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mul_r32(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 无符号乘法 MUL r/m16 (DX:AX = AX * r/m16) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mul_r16(scc_mcode_t *mcode, int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 无符号乘法 MUL r/m8 (AX = AL * r/m8) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mul_r8(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0xF6); + u8 modrm = 0xC0 | (src & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ---------- 有符号乘法 IMUL (单操作数) ---------- + +/** + * @brief 有符号乘法 IMUL r/m64 (RDX:RAX = RAX * r/m64) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_imul_r64_1op(scc_mcode_t *mcode, int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (5 << 3); // reg/opcode = 5 for IMUL + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 有符号乘法 IMUL r/m32 (EDX:EAX = EAX * r/m32) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_imul_r32_1op(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (5 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 有符号乘法 IMUL r/m16 (DX:AX = AX * r/m16) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_imul_r16_1op(scc_mcode_t *mcode, int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (5 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 有符号乘法 IMUL r/m8 (AX = AL * r/m8) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_imul_r8_1op(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0xF6); + u8 modrm = 0xC0 | (src & 7) | (5 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ---------- 无符号除法 DIV ---------- + +/** + * @brief 无符号除法 DIV r/m64 (RDX:RAX / r/m64, 商 RAX, 余 RDX) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_div_r64(scc_mcode_t *mcode, int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (6 << 3); // reg/opcode = 6 for DIV + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 无符号除法 DIV r/m32 (EDX:EAX / r/m32, 商 EAX, 余 EDX) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_div_r32(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (6 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 无符号除法 DIV r/m16 (DX:AX / r/m16, 商 AX, 余 DX) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_div_r16(scc_mcode_t *mcode, int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (6 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 无符号除法 DIV r/m8 (AX / r/m8, 商 AL, 余 AH) + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_div_r8(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0xF6); + u8 modrm = 0xC0 | (src & 7) | (6 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ---------- 有符号除法 IDIV ---------- + +/** + * @brief 有符号除法 IDIV r/m64 + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_idiv_r64(scc_mcode_t *mcode, int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (7 << 3); // reg/opcode = 7 for IDIV + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 有符号除法 IDIV r/m32 + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_idiv_r32(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (7 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 有符号除法 IDIV r/m16 + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_idiv_r16(scc_mcode_t *mcode, int src) { + scc_mcode_amd64_emit_width_prefix(mcode, 2); + u8 rex = 0x40; + if (src >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xF7); + u8 modrm = 0xC0 | (src & 7) | (7 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 有符号除法 IDIV r/m8 + * + * @param mcode 机器码缓冲区 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_idiv_r8(scc_mcode_t *mcode, int src) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src); + if (src >= 8) + rex |= 0x01; + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0xF6); + u8 modrm = 0xC0 | (src & 7) | (7 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +// ==================== 按位逻辑 ==================== + +// 仅提供 64 位和 32 位示例,其他宽度可仿照上述模式自行扩展 + +/** + * @brief 64 位与 AND r64, r64 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_and_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x21); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位与 AND r64, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_and_r64_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 64 位或 OR r64, r64 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_or_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x09); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位或 OR r64, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_or_r64_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (1 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +/** + * @brief 64 位异或 XOR r64, r64 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_xor_r64_r64(scc_mcode_t *mcode, int dst, + int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x31); + u8 modrm = 0xC0 | (dst & 7) | ((src & 7) << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位异或 XOR r64, imm32 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 32 位立即数 + */ +static inline void scc_mcode_amd64_xor_r64_imm32(scc_mcode_t *mcode, int dst, + u32 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x81); + u8 modrm = 0xC0 | (dst & 7) | (6 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u32(mcode, imm); +} + +// ==================== 移位 ==================== + +// 提供 64 位示例,其他宽度可类似添加 + +/** + * @brief 64 位左移 SHL r64, 1 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + */ +static inline void scc_mcode_amd64_shl_r64_1(scc_mcode_t *mcode, int dst) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xD1); + u8 modrm = 0xC0 | (dst & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位左移 SHL r64, imm8 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 移位次数 + */ +static inline void scc_mcode_amd64_shl_r64_imm8(scc_mcode_t *mcode, int dst, + u8 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xC1); + u8 modrm = 0xC0 | (dst & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, imm); +} + +/** + * @brief 64 位右移 SHR r64, 1 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + */ +static inline void scc_mcode_amd64_shr_r64_1(scc_mcode_t *mcode, int dst) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xD1); + u8 modrm = 0xC0 | (dst & 7) | (5 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位右移 SHR r64, imm8 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 移位次数 + */ +static inline void scc_mcode_amd64_shr_r64_imm8(scc_mcode_t *mcode, int dst, + u8 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xC1); + u8 modrm = 0xC0 | (dst & 7) | (5 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, imm); +} + +/** + * @brief 64 位算术右移 SAR r64, 1 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + */ +static inline void scc_mcode_amd64_sar_r64_1(scc_mcode_t *mcode, int dst) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xD1); + u8 modrm = 0xC0 | (dst & 7) | (7 << 3); + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 64 位算术右移 SAR r64, imm8 + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param imm 移位次数 + */ +static inline void scc_mcode_amd64_sar_r64_imm8(scc_mcode_t *mcode, int dst, + u8 imm) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xC1); + u8 modrm = 0xC0 | (dst & 7) | (7 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, imm); +} + +// ==================== 条件设置 ==================== + +/** + * @brief 根据条件码设置字节寄存器 (setcc r8) + * + * @param mcode 机器码缓冲区 + * @param cond 条件码(0-15) + * @param reg 目标 8 位寄存器 + */ +static inline void scc_mcode_amd64_setcc_r8(scc_mcode_t *mcode, int cond, + int reg) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(reg); + if (reg >= 8) { + rex |= 0x01; + reg -= 8; + } + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0x90 + cond); + u8 modrm = 0xC0 | (reg & 7); // reg/opcode 字段未使用 + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 根据条件码设置内存字节 (setcc [base]) + * + * @param mcode 机器码缓冲区 + * @param cond 条件码 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_setcc_m8(scc_mcode_t *mcode, int cond, + int base) { + u8 rex = 0x40; + int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(base); + if (base >= 8) { + rex |= 0x01; + base -= 8; + } + if (need_rex) { + scc_mcode_add_u8(mcode, rex); + } + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0x90 + cond); + u8 modrm = 0x00 | (base & 7); // mod=00, reg 字段未使用(置0) + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +// ==================== 控制转移 ==================== + +/** + * @brief 相对跳转 JMP rel32 + * + * @param mcode 机器码缓冲区 + * @param rel32 32 位相对偏移 + */ +static inline void scc_mcode_amd64_jmp_rel32(scc_mcode_t *mcode, u32 rel32) { + scc_mcode_add_u8(mcode, 0xE9); + scc_mcode_add_u32(mcode, rel32); +} + +/** + * @brief 条件跳转 Jcc rel32 + * + * @param mcode 机器码缓冲区 + * @param cond 条件码 + * @param rel32 32 位相对偏移 + */ +static inline void scc_mcode_amd64_jcc_rel32(scc_mcode_t *mcode, int cond, + u32 rel32) { + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0x80 + cond); + scc_mcode_add_u32(mcode, rel32); +} + +/** + * @brief 相对调用 CALL rel32 + * + * @param mcode 机器码缓冲区 + * @param rel32 32 位相对偏移 + */ +static inline void scc_mcode_amd64_call_rel32(scc_mcode_t *mcode, u32 rel32) { + scc_mcode_add_u8(mcode, 0xE8); + scc_mcode_add_u32(mcode, rel32); +} + +/** + * @brief 间接跳转 JMP r64 + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器(存储跳转地址) + */ +static inline void scc_mcode_amd64_jmp_r64(scc_mcode_t *mcode, int reg) { + u8 rex = 0x40; + if (reg >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xFF); + u8 modrm = 0xC0 | (reg & 7) | (4 << 3); // reg/opcode = 4 for JMP r/m64 + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 间接跳转 JMP [base] (简单基址) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_jmp_m64(scc_mcode_t *mcode, int base) { + u8 rex = 0x48; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xFF); + u8 modrm = (base & 7) | (4 << 3); // mod=00, reg/opcode=4 + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 间接调用 CALL r64 + * + * @param mcode 机器码缓冲区 + * @param reg 目标寄存器 + */ +static inline void scc_mcode_amd64_call_r64(scc_mcode_t *mcode, int reg) { + u8 rex = 0x40; + if (reg >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xFF); + u8 modrm = 0xC0 | (reg & 7) | (2 << 3); // reg/opcode = 2 for CALL r/m64 + scc_mcode_add_u8(mcode, modrm); +} + +/** + * @brief 间接调用 CALL [base] + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器 + */ +static inline void scc_mcode_amd64_call_m64(scc_mcode_t *mcode, int base) { + u8 rex = 0x48; + if (base >= 8) + rex |= 0x01; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0xFF); + u8 modrm = (base & 7) | (2 << 3); + if ((base & 7) == 4) { + u8 sib = (base & 7) | (4 << 3); + scc_mcode_add_u8(mcode, modrm); + scc_mcode_add_u8(mcode, sib); + } else { + scc_mcode_add_u8(mcode, modrm); + } +} + +/** + * @brief 返回指令 RET + * + * @param mcode 机器码缓冲区 + */ +static inline void scc_mcode_amd64_ret(scc_mcode_t *mcode) { + scc_mcode_add_u8(mcode, 0xC3); +} + +// ==================== 系统调用 ==================== + +/** + * @brief 执行系统调用 SYSCALL + * + * @param mcode 机器码缓冲区 + */ +static inline void scc_mcode_amd64_syscall(scc_mcode_t *mcode) { + scc_mcode_add_u8(mcode, 0x0F); + scc_mcode_add_u8(mcode, 0x05); +} + +// ==================== 复杂寻址模式(SIB) ==================== + +// 辅助函数:根据 base, index, scale, disp 生成 ModRM 和 SIB 字节并写入 +// 返回需要写入 disp 的字节数(0,1,4),调用者需写入 disp + +static inline int scc_mcode_amd64_emit_sib_address(scc_mcode_t *mcode, int base, + int index, int scale, + u32 disp, int has_disp, + int disp8) { + // scale 编码: 0=1, 1=2, 2=4, 3=8 + u8 scale_code = 0; + switch (scale) { + case 1: + scale_code = 0; + break; + case 2: + scale_code = 1; + break; + case 4: + scale_code = 2; + break; + case 8: + scale_code = 3; + break; + default: + break; // 非法,但默认 0 + } + u8 index_reg = (index == -1) ? 4 : (index & 7); // 4 表示无 index + u8 base_reg = (base == -1) ? 5 : (base & 7); + + u8 mod = 0; + int disp_size = 0; + if (base == -1) { + // 无基址,只有 index*scale + disp32 + mod = 0; + base_reg = 5; // 必须为 101 + disp_size = 4; + } else { + if (!has_disp) { + mod = 0; + disp_size = 0; + } else if (disp8 && (disp <= 127 || (int)disp >= -128)) { + mod = 1; + disp_size = 1; + } else { + mod = 2; + disp_size = 4; + } + } + + u8 modrm = (mod << 6) | (0 << 3) | 4; // reg 字段为 0(调用者会覆盖) + scc_mcode_add_u8(mcode, modrm); + + u8 sib = (scale_code << 6) | (index_reg << 3) | base_reg; + scc_mcode_add_u8(mcode, sib); + + return disp_size; +} + +// 示例:带 SIB 的 MOV r64, [base+index*scale+disp32] + +// /** +// * @brief 从复杂地址加载到 64 位寄存器 (mov r64, [base + index*scale + disp]) +// * +// * @param mcode 机器码缓冲区 +// * @param dst 目标寄存器 +// * @param base 基址寄存器(-1 表示无基址) +// * @param index 索引寄存器(-1 表示无索引) +// * @param scale 比例因子(1,2,4,8) +// * @param disp 位移量 +// * @param disp_size 位移大小(0=无位移,1=8位,4=32位) +// */ +// static inline void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int +// dst, +// int base, int index, int +// scale, u32 disp, int +// disp_size) { +// u8 rex = 0x48; +// if (dst >= 8) +// rex |= 0x04; +// if (base >= 8 && base != -1) +// rex |= 0x01; +// if (index >= 8 && index != -1) +// rex |= 0x02; // REX.X +// scc_mcode_add_u8(mcode, rex); +// scc_mcode_add_u8(mcode, 0x8B); + +// // 保存 ModRM 的 reg 字段为 dst +// u8 modrm_byte = (dst & 7) << 3; +// // 临时占位,实际 mod 和 rm 由 sib 函数决定 +// // 我们先写入一个占位,稍后修改?为了方便,我们重写逻辑:直接调用 sib +// // 函数后,在适当位置写入 reg 字段? 更简单:构建 modrm 时,reg +// // 已知,我们可以在 sib 函数中传入 reg 参数。 重新设计:让 sib 函数返回 +// // modrm 和 sib 的字节,然后我们组合。 +// } + +// 为了简化,我们直接实现一个完整版本,不拆分辅助函数: + +/** + * @brief 从复杂地址加载到 64 位寄存器 (mov r64, [base + index*scale + disp]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器(-1 表示无基址) + * @param index 索引寄存器(-1 表示无索引) + * @param scale 比例因子(1,2,4,8) + * @param disp 位移量 + */ +static inline void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int dst, + int base, int index, + int scale, u32 disp) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (base >= 8 && base != -1) + rex |= 0x01; + if (index >= 8 && index != -1) + rex |= 0x02; // REX.X + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8B); + + int has_disp = (base != -1) ? 1 : 0; // 无基址时必须带 disp32 + int disp8 = 0; // 不自动选择,统一用 disp32 简化 + int disp_size = 4; + if (base != -1) { + if (disp == 0) { + has_disp = 0; + disp_size = 0; + } else { + // 可添加 disp8 优化,但此处统一 disp32 + disp_size = 4; + } + } + + u8 scale_code = 0; + switch (scale) { + case 1: + scale_code = 0; + break; + case 2: + scale_code = 1; + break; + case 4: + scale_code = 2; + break; + case 8: + scale_code = 3; + break; + default: + scale_code = 0; + break; + } + u8 index_reg = (index == -1) ? 4 : (index & 7); + u8 base_reg = (base == -1) ? 5 : (base & 7); + + u8 mod = 0; + if (base == -1) { + mod = 0; + base_reg = 5; + disp_size = 4; + } else { + if (!has_disp) { + mod = 0; + } else { + mod = 2; // 强制 disp32 + } + } + + u8 modrm = (mod << 6) | ((dst & 7) << 3) | 4; // rm=4 表示使用 SIB + scc_mcode_add_u8(mcode, modrm); + + u8 sib = (scale_code << 6) | (index_reg << 3) | base_reg; + scc_mcode_add_u8(mcode, sib); + + if (disp_size == 4) { + scc_mcode_add_u32(mcode, disp); + } else if (disp_size == 1) { + scc_mcode_add_u8(mcode, (u8)disp); + } + // 无位移则不添加 +} + +/** + * @brief 存储 64 位寄存器到复杂地址 (mov [base+index*scale+disp], r64) + * + * @param mcode 机器码缓冲区 + * @param base 基址寄存器(-1 表示无基址) + * @param index 索引寄存器(-1 表示无索引) + * @param scale 比例因子 + * @param disp 位移量 + * @param src 源寄存器 + */ +static inline void scc_mcode_amd64_mov_m64_sib_r64(scc_mcode_t *mcode, int base, + int index, int scale, + u32 disp, int src) { + u8 rex = 0x48; + if (src >= 8) + rex |= 0x04; + if (base >= 8 && base != -1) + rex |= 0x01; + if (index >= 8 && index != -1) + rex |= 0x02; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x89); + + int has_disp = (base != -1) ? 1 : 0; + int disp_size = 4; + if (base != -1) { + if (disp == 0) { + has_disp = 0; + disp_size = 0; + } else { + disp_size = 4; + } + } + + u8 scale_code = 0; + switch (scale) { + case 1: + scale_code = 0; + break; + case 2: + scale_code = 1; + break; + case 4: + scale_code = 2; + break; + case 8: + scale_code = 3; + break; + default: + scale_code = 0; + break; + } + u8 index_reg = (index == -1) ? 4 : (index & 7); + u8 base_reg = (base == -1) ? 5 : (base & 7); + + u8 mod = 0; + if (base == -1) { + mod = 0; + base_reg = 5; + disp_size = 4; + } else { + if (!has_disp) { + mod = 0; + } else { + mod = 2; + } + } + + u8 modrm = (mod << 6) | ((src & 7) << 3) | 4; + scc_mcode_add_u8(mcode, modrm); + + u8 sib = (scale_code << 6) | (index_reg << 3) | base_reg; + scc_mcode_add_u8(mcode, sib); + + if (disp_size == 4) { + scc_mcode_add_u32(mcode, disp); + } else if (disp_size == 1) { + scc_mcode_add_u8(mcode, (u8)disp); + } +} + +/** + * @brief 加载有效地址到 64 位寄存器 (lea r64, [base+index*scale+disp]) + * + * @param mcode 机器码缓冲区 + * @param dst 目标寄存器 + * @param base 基址寄存器(-1 允许) + * @param index 索引寄存器(-1 允许) + * @param scale 比例因子 + * @param disp 位移量 + */ +static inline void scc_mcode_amd64_lea_r64_m64_sib(scc_mcode_t *mcode, int dst, + int base, int index, + int scale, u32 disp) { + u8 rex = 0x48; + if (dst >= 8) + rex |= 0x04; + if (base >= 8 && base != -1) + rex |= 0x01; + if (index >= 8 && index != -1) + rex |= 0x02; + scc_mcode_add_u8(mcode, rex); + scc_mcode_add_u8(mcode, 0x8D); + + int has_disp = (base != -1) ? 1 : 0; + int disp_size = 4; + if (base != -1) { + if (disp == 0) { + has_disp = 0; + disp_size = 0; + } else { + disp_size = 4; + } + } + + u8 scale_code = 0; + switch (scale) { + case 1: + scale_code = 0; + break; + case 2: + scale_code = 1; + break; + case 4: + scale_code = 2; + break; + case 8: + scale_code = 3; + break; + default: + scale_code = 0; + break; + } + u8 index_reg = (index == -1) ? 4 : (index & 7); + u8 base_reg = (base == -1) ? 5 : (base & 7); + + u8 mod = 0; + if (base == -1) { + mod = 0; + base_reg = 5; + disp_size = 4; + } else { + if (!has_disp) { + mod = 0; + } else { + mod = 2; + } + } + + u8 modrm = (mod << 6) | ((dst & 7) << 3) | 4; + scc_mcode_add_u8(mcode, modrm); + + u8 sib = (scale_code << 6) | (index_reg << 3) | base_reg; + scc_mcode_add_u8(mcode, sib); + + if (disp_size == 4) { + scc_mcode_add_u32(mcode, disp); + } else if (disp_size == 1) { + scc_mcode_add_u8(mcode, (u8)disp); + } +} + +#endif /* __SCC_MCODE_AMD64_H__ */ diff --git a/libs/mcode/include/scc_mcode.h b/libs/mcode/include/scc_mcode.h new file mode 100644 index 0000000..b9d16f8 --- /dev/null +++ b/libs/mcode/include/scc_mcode.h @@ -0,0 +1,73 @@ +#ifndef __SCC_MCODE_H__ +#define __SCC_MCODE_H__ + +#include + +typedef enum { + SCC_MCODE_ARCH_AMD64, +} scc_mcode_arch_t; + +typedef SCC_VEC(u8) scc_mcode_buff_t; +typedef struct { + cbool is_littel_endian; + scc_mcode_arch_t arch; + scc_mcode_buff_t mcode; +} scc_mcode_t; + +static inline void scc_mcode_init(scc_mcode_t *mcode, scc_mcode_arch_t arch) { + scc_vec_init(mcode->mcode); + mcode->arch = arch; + mcode->is_littel_endian = true; +} + +static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) { + scc_vec_push(mcode->mcode, data); +} + +static inline void scc_mcode_add_u16(scc_mcode_t *mcode, u16 data) { + if (mcode->is_littel_endian) { + scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + scc_vec_push(mcode->mcode, (u8)(data >> 8)); + } else { + scc_vec_push(mcode->mcode, (u8)(data >> 8)); + scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + } +} + +static inline void scc_mcode_add_u32(scc_mcode_t *mcode, u32 data) { + if (mcode->is_littel_endian) { + scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + scc_vec_push(mcode->mcode, (u8)(data >> 8)); + scc_vec_push(mcode->mcode, (u8)(data >> 16)); + scc_vec_push(mcode->mcode, (u8)(data >> 24)); + } else { + scc_vec_push(mcode->mcode, (u8)(data >> 24)); + scc_vec_push(mcode->mcode, (u8)(data >> 16)); + scc_vec_push(mcode->mcode, (u8)(data >> 8)); + scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + } +} + +static inline void scc_mcode_add_u64(scc_mcode_t *mcode, uint64_t data) { + if (mcode->is_littel_endian) { + scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + scc_vec_push(mcode->mcode, (u8)(data >> 8)); + scc_vec_push(mcode->mcode, (u8)(data >> 16)); + scc_vec_push(mcode->mcode, (u8)(data >> 24)); + scc_vec_push(mcode->mcode, (u8)(data >> 32)); + scc_vec_push(mcode->mcode, (u8)(data >> 40)); + scc_vec_push(mcode->mcode, (u8)(data >> 48)); + scc_vec_push(mcode->mcode, (u8)(data >> 56)); + } else { + scc_vec_push(mcode->mcode, (u8)(data >> 56)); + scc_vec_push(mcode->mcode, (u8)(data >> 48)); + scc_vec_push(mcode->mcode, (u8)(data >> 40)); + scc_vec_push(mcode->mcode, (u8)(data >> 32)); + scc_vec_push(mcode->mcode, (u8)(data >> 24)); + scc_vec_push(mcode->mcode, (u8)(data >> 16)); + scc_vec_push(mcode->mcode, (u8)(data >> 8)); + scc_vec_push(mcode->mcode, (u8)(data & 0xFF)); + } +} + +#endif /* __SCC_MCODE_H__ */ diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c index 9e35cb4..38be178 100644 --- a/libs/parser/tests/test_parser_unit.c +++ b/libs/parser/tests/test_parser_unit.c @@ -1,38 +1,105 @@ -void init_func(void); -#define TEST_INIT init_func() +#include +#include +#include +#include +#include +#include -#include "parser_test.h" +typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser); -static scc_ast_type_t int_type; -static scc_ast_type_t char_type; -static scc_ast_type_t void_type; -static scc_ast_type_t pointer_int_type; -static scc_ast_type_t pointer_char_type; -static scc_ast_type_t pointer_void_type; -static scc_ast_type_t pointer_pointer_int_type; -static scc_ast_type_t va_list_type; +static scc_ast_node_t *process_input(const char *input, + scc_parse_node_func parse_func, + cbool need_sema) { + int res = 0; + scc_sstream_t mem_stream; + res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, + 16); + Assert(res == 0); -void init_func(void) { - scc_ast_type_builtin_init(&int_type, SCC_AST_BUILTIN_TYPE_INT, - scc_pos_create()); - scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, - scc_pos_create()); - scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, - scc_pos_create()); - scc_ast_type_pointer_init(&pointer_int_type, &int_type, scc_pos_create()); - scc_ast_type_pointer_init(&pointer_char_type, &char_type, scc_pos_create()); - scc_ast_type_pointer_init(&pointer_void_type, &void_type, scc_pos_create()); - scc_ast_type_pointer_init(&pointer_pointer_int_type, &pointer_int_type, - scc_pos_create()); - scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST, - scc_pos_create()); + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); + + scc_parser_t parser; + if (need_sema) { + scc_sema_callbacks_t sema_callbacks; + scc_sema_init(&sema_callbacks); + scc_parser_init(&parser, tok_ring, &sema_callbacks); + } else { + scc_parser_init(&parser, tok_ring, null); + } + + scc_ast_node_t *ret = parse_func(&parser); + + cbool not_eof = false; + scc_ring_not_eof(*parser.ring, not_eof); + if (not_eof == true) { + // FIXME MAYBE free + LOG_ERROR("Didn't consume all tokens"); + return null; + } + + scc_lexer_drop_ring(parser.ring); + scc_parser_drop(&parser); + scc_lexer_drop(&lexer); + scc_sstream_drop(&mem_stream); + return ret; } +typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); + +#define BUFFER_SIZE (4096) +char expect_buffer[BUFFER_SIZE]; +char output_buffer[BUFFER_SIZE]; + +static void dump2buffer(void *_buffer, const char *fmt, ...) { + char *buffer = _buffer; + va_list args; + va_start(args, fmt); + int res = scc_vsnprintf(buffer + strlen(buffer), + BUFFER_SIZE - strlen(buffer) - 1, fmt, args); + Assert(res > 0); + va_end(args); +} + +static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, + scc_parse_node_func parse_func, cbool need_sema) { + scc_ast_node_t *output_node_ptr = process_input(str, parse_func, need_sema); + scc_tree_dump_ctx_t ctx; + expect_buffer[0] = '\n', expect_buffer[1] = '\0'; + scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer); + scc_ast_dump_node(&ctx, expect_node_ptr); + scc_tree_dump_ctx_drop(&ctx); + output_buffer[0] = '\n', output_buffer[1] = '\0'; + scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer); + scc_ast_dump_node(&ctx, output_node_ptr); + scc_tree_dump_ctx_drop(&ctx); +} + +#define SCC_CHECK_AST_WITH_SEMA(expect_node_ptr, str, parse_func) \ + do { \ + _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ + true); \ + TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ + TEST_MSG("Expected: %s", expect_buffer); \ + TEST_MSG("Produced: %s", output_buffer); \ + } while (0); + +#define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \ + do { \ + _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ + false); \ + TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ + TEST_MSG("Expected: %s", expect_buffer); \ + TEST_MSG("Produced: %s", output_buffer); \ + } while (0); + static void test_parser_unit(void) { // 1. 变量声明 int a; { scc_ast_decl_t int_decl; - scc_ast_decl_val_init(&int_decl, &int_type, "a", null, + scc_ast_decl_val_init(&int_decl, &scc_ast_builtin_type_int, "a", null, scc_pos_create()); SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration); } @@ -43,11 +110,12 @@ static void test_parser_unit(void) { scc_ast_type_t func_type; scc_ast_decl_vec_t func_params; scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null, + scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &int_type, &func_params, - scc_pos_create()); + scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, + &func_params, scc_pos_create()); // 构造复合语句块(空) scc_ast_stmt_t compound; scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); @@ -66,11 +134,12 @@ static void test_parser_unit(void) { scc_ast_type_t func_type; scc_ast_decl_vec_t func_params; scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null, + scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &int_type, &func_params, - scc_pos_create()); + scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, + &func_params, scc_pos_create()); scc_ast_stmt_t compound; scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); @@ -114,11 +183,12 @@ static void test_parser_unit(void) { scc_ast_type_t func_type; scc_ast_decl_vec_t func_params; scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null, + scc_pos_create()); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &int_type, &func_params, - scc_pos_create()); + scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, + &func_params, scc_pos_create()); scc_ast_decl_t func_decl; scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, @@ -139,11 +209,13 @@ static void test_parser_unit(void) { { // 变量声明 int a; scc_ast_decl_t a_decl; - scc_ast_decl_val_init(&a_decl, &int_type, "a", null, scc_pos_create()); + scc_ast_decl_val_init(&a_decl, &scc_ast_builtin_type_int, "a", null, + scc_pos_create()); // 变量声明 int b; scc_ast_decl_t b_decl; - scc_ast_decl_val_init(&b_decl, &int_type, "b", null, scc_pos_create()); + scc_ast_decl_val_init(&b_decl, &scc_ast_builtin_type_int, "b", null, + scc_pos_create()); // 表达式 1 + 2 * 3 scc_ast_expr_t lit1, lit2, lit3, mul, add; @@ -212,7 +284,8 @@ static void test_parser_unit(void) { // 函数类型 scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type, + scc_ast_type_function_init(&func_type, + (scc_ast_type_t *)&scc_ast_builtin_type_int, null, scc_pos_create()); scc_ast_decl_t func_decl; @@ -245,8 +318,9 @@ static void test_parser_unit(void) { // 变量声明 int x = 10; scc_ast_decl_t x_decl; - scc_ast_decl_val_init(&x_decl, (scc_ast_type_t *)&int_type, "x", &lit10, - scc_pos_create()); + scc_ast_decl_val_init(&x_decl, + (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", + &lit10, scc_pos_create()); // 表达式 x + 1 scc_ast_expr_t x_ref1, lit1, add; @@ -279,18 +353,17 @@ static void test_parser_unit(void) { scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items, scc_pos_create()); + scc_ast_stmt_compound_init(&compound, &items); // 函数类型(返回 int,无参数) scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type, - null, - scc_pos_create()); // null 表示无参数 + scc_ast_type_function_init(&func_type, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + null); // null 表示无参数 // 函数声明 int main() { ... } scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, - scc_pos_create()); + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); // 翻译单元 scc_ast_decl_vec_t tu_decls; @@ -298,7 +371,7 @@ static void test_parser_unit(void) { scc_vec_push(tu_decls, &func_decl); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); + scc_ast_translation_unit_init(&tu, &tu_decls); // 输入源代码 const char *input = "int main() {\n" @@ -314,105 +387,95 @@ static void test_parser_unit(void) { { scc_ast_decl_vec_t params; scc_ast_decl_t param0; - scc_ast_decl_param_init(¶m0, (scc_ast_type_t *)&int_type, "a", - scc_pos_create()); + scc_ast_decl_param_init( + ¶m0, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a"); scc_ast_decl_t param1; - scc_ast_decl_param_init(¶m1, (scc_ast_type_t *)&int_type, "b", - scc_pos_create()); + scc_ast_decl_param_init( + ¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, "b"); scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type, null, - scc_pos_create()); + scc_ast_decl_param_init( + ¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_va_list, null); scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2}; scc_vec_unsafe_from_static_array(params, params_array); scc_ast_type_t decl_func_type; - scc_ast_type_function_init(&decl_func_type, (scc_ast_type_t *)&int_type, - ¶ms, scc_pos_create()); + scc_ast_type_function_init(&decl_func_type, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + ¶ms); scc_ast_decl_t decl_func; - scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null, - scc_pos_create()); + scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null); SCC_CHECK_AST(&decl_func.base, "int add(int a, int b, ...);", scc_parse_declaration); } { scc_ast_decl_t typedef_decl; - scc_ast_decl_typedef_init(&typedef_decl, "int32_t", &int_type, - scc_pos_create()); + scc_ast_decl_typedef_init(&typedef_decl, "int32_t", + &scc_ast_builtin_type_int); scc_ast_type_t typedef_type; - scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl, - scc_pos_create()); + scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl); scc_ast_decl_t i32a_decl; - scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null, - scc_pos_create()); + scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null); scc_ast_node_t *array[] = {&typedef_decl.base, &i32a_decl.base}; scc_ast_stmt_t stmt; scc_ast_block_item_vec_t items; scc_vec_unsafe_from_static_array(items, array); - scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); + scc_ast_stmt_compound_init(&stmt, &items); SCC_CHECK_AST_WITH_SEMA(&stmt.base, "{typedef int int32_t;int32_t a;}", scc_parse_statement); scc_ast_type_t void_ptr; - scc_ast_type_pointer_init(&void_ptr, &void_type, scc_pos_create()); + scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void); scc_ast_decl_t void_ptr_decl; - scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr, - scc_pos_create()); + scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr); scc_ast_type_t void_ptr_type; - scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl, - scc_pos_create()); + scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl); scc_ast_decl_t void_ptr_a_decl; - scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null, - scc_pos_create()); + scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null); scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base}; scc_vec_unsafe_from_static_array(items, array2); - scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); + scc_ast_stmt_compound_init(&stmt, &items); SCC_CHECK_AST_WITH_SEMA(&stmt.base, "{typedef void* void_ptr; void_ptr a;}", scc_parse_statement); - SCC_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, - "typedef void * void_ptr; ", + SCC_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, "typedef void *void_ptr;", scc_parse_declaration); } { // struct { int x; } (匿名结构体定义) scc_ast_decl_t field; - scc_ast_decl_val_init(&field, (scc_ast_type_t *)&int_type, "x", null, - scc_pos_create()); + scc_ast_decl_val_init( + &field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null); scc_ast_decl_vec_t fields; scc_vec_init(fields); scc_vec_push(fields, &field); scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, &fields, scc_pos_create()); - SCC_CHECK_AST(&struct_def.base, "struct { int x;};", + scc_ast_decl_struct_init(&struct_def, null, &fields); + SCC_CHECK_AST(&struct_def.base, "struct { int x; };", scc_parse_declaration); scc_ast_type_t struct_type; - scc_ast_type_struct_init(&struct_type, null, &struct_def, - scc_pos_create()); + scc_ast_type_struct_init(&struct_type, null, &struct_def); scc_ast_type_t typedef_type; - scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def, - scc_pos_create()); + scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def); scc_ast_decl_t typedef_decl; - scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type, - scc_pos_create()); + scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type); SCC_CHECK_AST_WITH_SEMA(&typedef_decl.base, "typedef struct { int x; } struct_t;", scc_parse_declaration); scc_ast_decl_t typedef_impl_decl; - scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null, - scc_pos_create()); + scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null); scc_ast_node_t *array[] = {&typedef_decl.base, &typedef_impl_decl.base}; scc_ast_stmt_t stmt; scc_ast_block_item_vec_t items; scc_vec_unsafe_from_static_array(items, array); - scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); + scc_ast_stmt_compound_init(&stmt, &items); SCC_CHECK_AST_WITH_SEMA( &stmt.base, "{typedef struct { int x; } struct_t; struct_t a;}", scc_parse_statement); @@ -420,18 +483,17 @@ static void test_parser_unit(void) { { scc_ast_decl_t type_decl; - scc_ast_decl_typedef_init(&type_decl, "size_t", &int_type, - scc_pos_create()); + scc_ast_decl_typedef_init(&type_decl, "size_t", + &scc_ast_builtin_type_long_long); scc_ast_type_t type_type; - scc_ast_type_typedef_init(&type_type, "size_t", &type_decl, - scc_pos_create()); + scc_ast_type_typedef_init(&type_type, "size_t", &type_decl); scc_ast_decl_t param1; - scc_ast_decl_param_init(¶m1, &type_type, "a", scc_pos_create()); + scc_ast_decl_param_init(¶m1, &type_type, "a"); scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, &int_type, "b", scc_pos_create()); + scc_ast_decl_param_init(¶m2, &scc_ast_builtin_type_int, "b"); scc_ast_decl_t param3; - scc_ast_decl_param_init(¶m3, &va_list_type, null, scc_pos_create()); + scc_ast_decl_param_init(¶m3, &scc_ast_builtin_type_va_list, null); scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3}; scc_ast_decl_vec_t func_params; scc_vec_unsafe_from_static_array(func_params, params_array); @@ -439,35 +501,32 @@ static void test_parser_unit(void) { scc_ast_type_t return_type; - scc_ast_type_pointer_init(&return_type, &void_type, scc_pos_create()); - scc_ast_type_function_init(&func_type, &return_type, &func_params, - scc_pos_create()); + scc_ast_type_pointer_init(&return_type, &scc_ast_builtin_type_void); + scc_ast_type_function_init(&func_type, &return_type, &func_params); scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "func", null, - scc_pos_create()); + scc_ast_decl_func_init(&func_decl, &func_type, "func", null); scc_ast_decl_t *decls_array[] = {&type_decl, &func_decl}; scc_ast_translation_unit_t tu; scc_ast_decl_vec_t decls; scc_vec_unsafe_from_static_array(decls, decls_array); - scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); + scc_ast_translation_unit_init(&tu, &decls); SCC_CHECK_AST_WITH_SEMA(&tu.base, - "typedef int size_t;" + "typedef long long size_t;" "void *func(size_t a, int b, ...);", scc_parse_translation_unit); scc_ast_type_t type_func_ptr_type; - scc_ast_type_pointer_init(&type_func_ptr_type, &func_type, - scc_pos_create()); + scc_ast_type_pointer_init(&type_func_ptr_type, &func_type); scc_ast_decl_t type_func_ptr_decl; scc_ast_decl_typedef_init(&type_func_ptr_decl, "func_t", - &type_func_ptr_type, scc_pos_create()); + &type_func_ptr_type); scc_ast_decl_t *decls_array2[] = {&type_decl, &type_func_ptr_decl}; scc_vec_unsafe_from_static_array(decls, decls_array2); - scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); + scc_ast_translation_unit_init(&tu, &decls); SCC_CHECK_AST_WITH_SEMA( &tu.base, - "typedef int size_t;" + "typedef long long size_t;" "typedef void *(*func_t)(size_t a, int b, ...);", scc_parse_translation_unit); } @@ -476,27 +535,24 @@ static void test_parser_unit(void) { // 1. 构造参数类型:volatile const char *restrict,并附加 register // 存储类 scc_ast_type_t char_type; - scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, - scc_pos_create()); + _scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR); char_type.quals.is_const = true; // const char_type.quals.is_volatile = true; // volatile scc_ast_type_t ptr_to_char; - scc_ast_type_pointer_init(&ptr_to_char, &char_type, scc_pos_create()); - ptr_to_char.quals.is_restrict = true; // restrict限定指针 - ptr_to_char.quals.is_register = true; // register存储类(作用于参数) + scc_ast_type_pointer_init(&ptr_to_char, &char_type); + ptr_to_char.quals.is_restrict = true; // restrict 限定指针 + ptr_to_char.quals.is_register = true; // register 存储类(作用于参数) // 2. 参数声明 scc_ast_decl_t param_decl; - scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt", - scc_pos_create()); + scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt"); // 3. 返回类型:void * scc_ast_type_t void_type; - scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, - scc_pos_create()); + _scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID); scc_ast_type_t ptr_to_void; - scc_ast_type_pointer_init(&ptr_to_void, &void_type, scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_void, &void_type); // 4. 参数列表 scc_ast_decl_vec_t params; @@ -505,15 +561,13 @@ static void test_parser_unit(void) { // 5. 函数类型(包含 static 和 inline) scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms, - scc_pos_create()); + scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms); func_type.quals.is_static = true; func_type.quals.is_inline = true; // 6. 函数声明 scc_ast_decl_t decl; - scc_ast_decl_func_init(&decl, &func_type, "call", null, - scc_pos_create()); + scc_ast_decl_func_init(&decl, &func_type, "call", null); // 7. 与解析结果比较 SCC_CHECK_AST_WITH_SEMA(&decl.base, @@ -524,25 +578,25 @@ static void test_parser_unit(void) { { scc_ast_expr_t lvalue; - scc_ast_expr_lvalue_init(&lvalue, &void_type, scc_pos_create()); + scc_ast_expr_lvalue_init(&lvalue, &scc_ast_builtin_type_void); scc_ast_expr_t lhs1; - scc_ast_expr_member_init(&lhs1, &lvalue, "data", scc_pos_create()); + scc_ast_expr_member_init(&lhs1, &lvalue, "data"); scc_ast_expr_t lhs2; - scc_ast_expr_member_init(&lhs2, &lvalue, "size", scc_pos_create()); + scc_ast_expr_member_init(&lhs2, &lvalue, "size"); scc_ast_expr_t lhs3; - scc_ast_expr_member_init(&lhs3, &lvalue, "cap", scc_pos_create()); + scc_ast_expr_member_init(&lhs3, &lvalue, "cap"); scc_ast_expr_t rl0; - scc_ast_expr_literal_int_init(&rl0, "0", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&rl0, "0", false); scc_ast_type_t void_ptr; - scc_ast_type_pointer_init(&void_ptr, &void_type, scc_pos_create()); + scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void); scc_ast_expr_t rhs1; - scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0, scc_pos_create()); + scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0); scc_ast_expr_t rhs2; - scc_ast_expr_literal_int_init(&rhs2, "0", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&rhs2, "0", false); scc_ast_expr_t rhs3; - scc_ast_expr_literal_int_init(&rhs3, "0", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&rhs3, "0", false); scc_ast_expr_vec_t lhs_exprs; scc_ast_expr_t *lhs_array[] = {&lhs1, &lhs2, &lhs3}; @@ -553,8 +607,7 @@ static void test_parser_unit(void) { scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array); scc_ast_expr_t expr; - scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs, - scc_pos_create()); + scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs); // FIXME use real records type SCC_CHECK_AST(&expr.base, @@ -562,27 +615,25 @@ static void test_parser_unit(void) { scc_parse_expression); scc_ast_stmt_t stmt; - scc_ast_stmt_return_init(&stmt, &expr, scc_pos_create()); - SCC_CHECK_AST( - &stmt.base, - "return (void){.data = (void *)0, .size = 0, .cap = 0 }; ", - scc_parse_statement); + scc_ast_stmt_return_init(&stmt, &expr); + SCC_CHECK_AST(&stmt.base, + "return (void){.data = (void *)0, .size = 0, .cap = 0};", + scc_parse_statement); scc_ast_expr_t lhs4; scc_ast_expr_t lhs5; - scc_ast_expr_member_init(&lhs4, &lvalue, "a", scc_pos_create()); - scc_ast_expr_member_init(&lhs5, &lhs4, "b", scc_pos_create()); + scc_ast_expr_member_init(&lhs4, &lvalue, "a"); + scc_ast_expr_member_init(&lhs5, &lhs4, "b"); scc_ast_expr_t lhs6; scc_ast_expr_t lhs7; - scc_ast_expr_member_init(&lhs6, &lvalue, "c", scc_pos_create()); - scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0, scc_pos_create()); + scc_ast_expr_member_init(&lhs6, &lvalue, "c"); + scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0); scc_ast_expr_t *lhs_array_hard[] = {&lhs5, &lhs7}; scc_vec_unsafe_from_static_array(lhs_exprs, lhs_array_hard); scc_ast_expr_t *rhs_array_hard[] = {&rhs2, &rhs3}; scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array_hard); - scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs, - scc_pos_create()); + scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs); SCC_CHECK_AST(&expr.base, "(void){.a.b = 0, .c[0] = 0}", scc_parse_expression); } @@ -593,8 +644,7 @@ static void test_parser_unit(void) { scc_ast_decl_t struct_decl; scc_ast_decl_vec_t empty_members; scc_vec_init(empty_members); - scc_ast_decl_struct_init(&struct_decl, "S", &empty_members, - scc_pos_create()); + scc_ast_decl_struct_init(&struct_decl, "S", &empty_members); SCC_CHECK_AST(&struct_decl.base, "struct S;", scc_parse_declaration); } @@ -604,8 +654,7 @@ static void test_parser_unit(void) { scc_ast_decl_t union_decl; scc_ast_decl_vec_t empty_members; scc_vec_init(empty_members); - scc_ast_decl_union_init(&union_decl, "U", &empty_members, - scc_pos_create()); + scc_ast_decl_union_init(&union_decl, "U", &empty_members); SCC_CHECK_AST(&union_decl.base, "union U;", scc_parse_declaration); } @@ -614,19 +663,21 @@ static void test_parser_unit(void) { scc_ast_decl_t enum_decl; scc_ast_expr_vec_t empty_enumerators; scc_vec_init(empty_enumerators); - scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators, - scc_pos_create()); + scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators); SCC_CHECK_AST(&enum_decl.base, "enum E;", scc_parse_declaration); } } { scc_ast_stmt_t continue_stmt; - scc_ast_stmt_continue_init(&continue_stmt, scc_pos_create()); + scc_ast_stmt_continue_init(&continue_stmt); scc_ast_stmt_t stmt; - scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt, - scc_pos_create()); + scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt); SCC_CHECK_AST(&stmt.base, "NEXT: continue;", scc_parse_statement); + + scc_ast_expr_t str; + scc_ast_expr_literal_string_init(&str, "\"ab\"", false); + SCC_CHECK_AST(&str.base, "\"a\" \"b\"", scc_parse_expression); } { @@ -634,27 +685,27 @@ static void test_parser_unit(void) { { // 构造类型 int* scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init(&ptr_to_int, (scc_ast_type_t *)&int_type, - scc_pos_create()); + scc_ast_type_pointer_init( + &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); // 标识符 b scc_ast_expr_t b_expr; - scc_ast_expr_identifier_init(&b_expr, "b", scc_pos_create()); + scc_ast_expr_identifier_init(&b_expr, "b"); // 类型转换 (int*)b scc_ast_expr_t cast_expr; - scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr, - scc_pos_create()); + scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr); // 解引用 *(int*)b scc_ast_expr_t deref_expr; scc_ast_expr_unary_init(&deref_expr, SCC_AST_OP_INDIRECTION, - &cast_expr, scc_pos_create()); + &cast_expr); // 声明 int a = *(int*)b; scc_ast_decl_t decl; - scc_ast_decl_val_init(&decl, (scc_ast_type_t *)&int_type, "a", - &deref_expr, scc_pos_create()); + scc_ast_decl_val_init(&decl, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + "a", &deref_expr); SCC_CHECK_AST(&decl.base, "int a = *(int*)b;", scc_parse_declaration); @@ -663,10 +714,12 @@ static void test_parser_unit(void) { // 测试 int a, b; { scc_ast_decl_t decl_a, decl_b; - scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a", - null, scc_pos_create()); - scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b", - null, scc_pos_create()); + scc_ast_decl_val_init(&decl_a, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + "a", null); + scc_ast_decl_val_init(&decl_b, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + "b", null); scc_ast_decl_vec_t decl_vec; scc_vec_init(decl_vec); @@ -674,8 +727,7 @@ static void test_parser_unit(void) { scc_vec_push(decl_vec, &decl_b); scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &decl_vec, - scc_pos_create()); // 假设存在该函数 + scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数 SCC_CHECK_AST(&decl_list.base, "int a, b;", scc_parse_declaration); } @@ -683,14 +735,16 @@ static void test_parser_unit(void) { // 测试 int a = 1, b = 2; { scc_ast_expr_t lit1, lit2; - scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); - scc_ast_expr_literal_int_init(&lit2, "2", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit1, "1", false); + scc_ast_expr_literal_int_init(&lit2, "2", false); scc_ast_decl_t decl_a, decl_b; - scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a", - &lit1, scc_pos_create()); - scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b", - &lit2, scc_pos_create()); + scc_ast_decl_val_init(&decl_a, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + "a", &lit1); + scc_ast_decl_val_init(&decl_b, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + "b", &lit2); scc_ast_decl_vec_t decl_vec; scc_vec_init(decl_vec); @@ -698,8 +752,7 @@ static void test_parser_unit(void) { scc_vec_push(decl_vec, &decl_b); scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &decl_vec, - scc_pos_create()); // 假设存在该函数 + scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数 SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;", scc_parse_declaration); @@ -708,22 +761,17 @@ static void test_parser_unit(void) { { // 构造 struct list_head 类型(不完整) scc_ast_type_t struct_list_head; - scc_ast_type_struct_init(&struct_list_head, "list_head", null, - scc_pos_create()); + scc_ast_type_struct_init(&struct_list_head, "list_head", null); // 构造两个指针类型(分别用于 next 和 prev,指向同一结构体) scc_ast_type_t ptr_to_struct1, ptr_to_struct2; - scc_ast_type_pointer_init(&ptr_to_struct1, &struct_list_head, - scc_pos_create()); - scc_ast_type_pointer_init(&ptr_to_struct2, &struct_list_head, - scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_struct1, &struct_list_head); + scc_ast_type_pointer_init(&ptr_to_struct2, &struct_list_head); // 构造变量声明 next 和 prev scc_ast_decl_t next_decl, prev_decl; - scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null, - scc_pos_create()); - scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null, - scc_pos_create()); + scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null); + scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null); // 构造声明列表 scc_ast_decl_vec_t decl_vec; @@ -731,7 +779,7 @@ static void test_parser_unit(void) { scc_vec_push(decl_vec, &next_decl); scc_vec_push(decl_vec, &prev_decl); scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &decl_vec, scc_pos_create()); + scc_ast_decl_list_init(&decl_list, &decl_vec); SCC_CHECK_AST(&decl_list.base, "struct list_head *next, *prev;", scc_parse_declaration); @@ -741,8 +789,9 @@ static void test_parser_unit(void) { { // 构造字段 int a; scc_ast_decl_t field_a; - scc_ast_decl_val_init(&field_a, (scc_ast_type_t *)&int_type, "a", - null, scc_pos_create()); + scc_ast_decl_val_init(&field_a, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + "a", null); scc_ast_decl_vec_t fields; scc_vec_init(fields); @@ -750,28 +799,26 @@ static void test_parser_unit(void) { // 构造匿名结构体定义声明 scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, &fields, - scc_pos_create()); // fields 被移动 + scc_ast_decl_struct_init(&struct_def, null, + &fields); // fields 被移动 // 构造匿名结构体类型 scc_ast_type_t anon_struct_type; - scc_ast_type_struct_init(&anon_struct_type, null, &struct_def, - scc_pos_create()); + scc_ast_type_struct_init(&anon_struct_type, null, &struct_def); // 构造指针类型指向该匿名结构体 scc_ast_type_t ptr_to_anon; - scc_ast_type_pointer_init(&ptr_to_anon, &anon_struct_type, - scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_anon, &anon_struct_type); // 构造 typedef 声明 struct_t scc_ast_decl_t typedef_struct_t; scc_ast_decl_typedef_init(&typedef_struct_t, "struct_t", - &anon_struct_type, scc_pos_create()); + &anon_struct_type); // 构造 typedef 声明 struct_ptr_t scc_ast_decl_t typedef_struct_ptr_t; scc_ast_decl_typedef_init(&typedef_struct_ptr_t, "struct_ptr_t", - &ptr_to_anon, scc_pos_create()); + &ptr_to_anon); // 构造声明列表 scc_ast_decl_vec_t typedef_vec; @@ -779,7 +826,7 @@ static void test_parser_unit(void) { scc_vec_push(typedef_vec, &typedef_struct_t); scc_vec_push(typedef_vec, &typedef_struct_ptr_t); scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &typedef_vec, scc_pos_create()); + scc_ast_decl_list_init(&decl_list, &typedef_vec); SCC_CHECK_AST(&decl_list.base, "typedef struct { int a; } struct_t, *struct_ptr_t;", @@ -795,57 +842,53 @@ static void test_parser_unit(void) { // 步骤: // 1) 数组类型:int [5] scc_ast_expr_t size_5; - scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&size_5, "5", false); scc_ast_type_t array_of_5_int; - scc_ast_type_array_init(&array_of_5_int, (scc_ast_type_t *)&int_type, - &size_5, scc_pos_create()); + scc_ast_type_array_init(&array_of_5_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &size_5); // 2) 函数类型:返回指向数组的指针,无参数 scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int, - scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int); scc_ast_type_t func_type; scc_ast_decl_vec_t func_params; scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); scc_ast_decl_t *array[] = {&void_decl}; scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &ptr_to_array, &func_params, - scc_pos_create()); // 无参数 + scc_ast_type_function_init(&func_type, &ptr_to_array, + &func_params); // 无参数 // 3) 指向该函数的指针 scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_func, &func_type); scc_ast_decl_t ptr_to_func_decl; - scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null, - scc_pos_create()); + scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null); SCC_CHECK_AST(&ptr_to_func_decl.base, "int (*(*foo)(void))[5];", scc_parse_declaration); scc_ast_decl_t typedef_func_decl; - scc_ast_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func, - scc_pos_create()); + scc_ast_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func); scc_ast_type_t typedef_func_type; scc_ast_type_typedef_init(&typedef_func_type, "func_t", - &typedef_func_decl, scc_pos_create()); + &typedef_func_decl); scc_ast_decl_t func_hard_decl; scc_ast_type_t func_hard_type; scc_ast_decl_t param1; - scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar", scc_pos_create()); + scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar"); scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, &typedef_func_type, "a", - scc_pos_create()); + scc_ast_decl_param_init(¶m2, &typedef_func_type, "a"); scc_ast_decl_t param3; - scc_ast_decl_param_init(¶m1, &va_list_type, null, scc_pos_create()); + scc_ast_decl_param_init(¶m1, &scc_ast_builtin_type_va_list, null); scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3}; scc_ast_decl_vec_t func_hard_params; scc_vec_unsafe_from_static_array(func_hard_params, func_hard_array); scc_ast_type_function_init(&func_hard_type, &ptr_to_array, - &func_hard_params, scc_pos_create()); - scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null, - scc_pos_create()); + &func_hard_params); + scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null); scc_ast_decl_vec_t decls; scc_ast_decl_t *decls_array[] = { @@ -854,7 +897,7 @@ static void test_parser_unit(void) { }; scc_vec_unsafe_from_static_array(decls, decls_array); scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); + scc_ast_translation_unit_init(&tu, &decls); // SCC_CHECK_AST_WITH_SEMA( // &tu.base, // "typedef int (*(*func_t)(void))[5];" @@ -863,7 +906,901 @@ static void test_parser_unit(void) { } } +static void test_parser_expression(void) { + // 1. 基本表达式 + { + scc_ast_expr_t ident; + scc_ast_expr_identifier_init(&ident, "x"); + SCC_CHECK_AST(&ident.base, "x", scc_parse_expression); + + scc_ast_expr_t int_lit; + scc_ast_expr_literal_int_init(&int_lit, "42", false); + SCC_CHECK_AST(&int_lit.base, "42", scc_parse_expression); + + scc_ast_expr_t str_lit; + scc_ast_expr_literal_string_init(&str_lit, "\"hello\"", false); + SCC_CHECK_AST(&str_lit.base, "\"hello\"", scc_parse_expression); + + // 括号表达式(解析器应直接返回内部表达式) + scc_ast_expr_t paren_ident; + scc_ast_expr_identifier_init(&paren_ident, "y"); + SCC_CHECK_AST(&paren_ident.base, "(y)", scc_parse_expression); + } + + // 2. 后缀表达式 + { + // 数组下标 a[10] + scc_ast_expr_t a, index, subscript; + scc_ast_expr_identifier_init(&a, "a"); + scc_ast_expr_literal_int_init(&index, "10", false); + scc_ast_expr_array_subscript_init(&subscript, &a, &index); + SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression); + + // 函数调用 f() + scc_ast_expr_t f; + scc_ast_expr_identifier_init(&f, "f"); + scc_ast_expr_vec_t args; + scc_vec_init(args); + scc_ast_expr_t call; + scc_ast_expr_t callee1; + scc_ast_expr_identifier_init(&callee1, "f"); + scc_ast_expr_call_init(&call, &callee1, + &args); // 使用函数名,target 在语义分析时填充 + SCC_CHECK_AST(&call.base, "f()", scc_parse_expression); + + // 函数调用带参数 f(1, x) + scc_ast_expr_t arg1, arg2; + scc_ast_expr_literal_int_init(&arg1, "1", false); + scc_ast_expr_identifier_init(&arg2, "x"); + scc_ast_expr_vec_t args2; + scc_vec_init(args2); + scc_vec_push(args2, &arg1); + scc_vec_push(args2, &arg2); + scc_ast_expr_t callee2; + scc_ast_expr_identifier_init(&callee2, "f"); + scc_ast_expr_t call2; + scc_ast_expr_call_init(&call2, &callee2, &args2); + SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression); + + // 成员访问 . + scc_ast_expr_t s, dot; + scc_ast_expr_identifier_init(&s, "s"); + scc_ast_expr_member_init(&dot, &s, "field"); + SCC_CHECK_AST(&dot.base, "s.field", scc_parse_expression); + + // 指针成员访问 -> + scc_ast_expr_t p, arrow; + scc_ast_expr_identifier_init(&p, "p"); + scc_ast_expr_ptr_member_init(&arrow, &p, "field"); + SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression); + + // 后缀 ++/-- + scc_ast_expr_t x, post_inc, post_dec; + scc_ast_expr_identifier_init(&x, "x"); + scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &x); + scc_ast_expr_unary_init(&post_dec, SCC_AST_OP_POSTFIX_DECREMENT, &x); + SCC_CHECK_AST(&post_inc.base, "x++", scc_parse_expression); + SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression); + } + + // 3. 一元表达式 + { + scc_ast_expr_t x; + scc_ast_expr_identifier_init(&x, "x"); + + scc_ast_expr_t pre_inc; + scc_ast_expr_unary_init(&pre_inc, SCC_AST_OP_PREFIX_INCREMENT, &x); + SCC_CHECK_AST(&pre_inc.base, "++x", scc_parse_expression); + + scc_ast_expr_t pre_dec; + scc_ast_expr_unary_init(&pre_dec, SCC_AST_OP_PREFIX_DECREMENT, &x); + SCC_CHECK_AST(&pre_dec.base, "--x", scc_parse_expression); + + scc_ast_expr_t addr; + scc_ast_expr_unary_init(&addr, SCC_AST_OP_ADDRESS_OF, &x); + SCC_CHECK_AST(&addr.base, "&x", scc_parse_expression); + + scc_ast_expr_t deref; + scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &x); + SCC_CHECK_AST(&deref.base, "*x", scc_parse_expression); + + scc_ast_expr_t plus; + scc_ast_expr_unary_init(&plus, SCC_AST_OP_UNARY_PLUS, &x); + SCC_CHECK_AST(&plus.base, "+x", scc_parse_expression); + + scc_ast_expr_t minus; + scc_ast_expr_unary_init(&minus, SCC_AST_OP_UNARY_MINUS, &x); + SCC_CHECK_AST(&minus.base, "-x", scc_parse_expression); + + scc_ast_expr_t bit_not; + scc_ast_expr_unary_init(&bit_not, SCC_AST_OP_BITWISE_NOT, &x); + SCC_CHECK_AST(&bit_not.base, "~x", scc_parse_expression); + + scc_ast_expr_t log_not; + scc_ast_expr_unary_init(&log_not, SCC_AST_OP_LOGICAL_NOT, &x); + SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression); + + // sizeof 表达式 + scc_ast_expr_t sizeof_x_expr; + scc_ast_expr_sizeof_init(&sizeof_x_expr, null, &x); + SCC_CHECK_AST(&sizeof_x_expr.base, "sizeof(x)", scc_parse_expression); + + scc_ast_expr_t sizeof_int_expr; + scc_ast_expr_sizeof_init(&sizeof_int_expr, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + null); + SCC_CHECK_AST(&sizeof_int_expr.base, "sizeof(int)", + scc_parse_expression); + } + + // 4. 类型转换(示例: (int)x ) + { + scc_ast_expr_t x; + scc_ast_expr_identifier_init(&x, "x"); + scc_ast_expr_t cast; + scc_ast_expr_cast_init(&cast, + (scc_ast_type_t *)&scc_ast_builtin_type_int, &x); + SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression); + } + + // 5. 二元运算符优先级 + { + scc_ast_expr_t a, b, c, d; + scc_ast_expr_identifier_init(&a, "a"); + scc_ast_expr_identifier_init(&b, "b"); + scc_ast_expr_identifier_init(&c, "c"); + scc_ast_expr_identifier_init(&d, "d"); + + // a * b + c + scc_ast_expr_t mul, add; + scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &a, &b); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &mul, &c); + SCC_CHECK_AST(&add.base, "a * b + c", scc_parse_expression); + + // a - b - c => (a - b) - c + scc_ast_expr_t sub1, sub2; + scc_ast_expr_binary_init(&sub1, SCC_AST_OP_SUB, &a, &b); + scc_ast_expr_binary_init(&sub2, SCC_AST_OP_SUB, &sub1, &c); + SCC_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression); + + // a << b + scc_ast_expr_t shift; + scc_ast_expr_binary_init(&shift, SCC_AST_OP_LEFT_SHIFT, &a, &b); + SCC_CHECK_AST(&shift.base, "a << b", scc_parse_expression); + + // a < b + scc_ast_expr_t lt; + scc_ast_expr_binary_init(<, SCC_AST_OP_LESS, &a, &b); + SCC_CHECK_AST(<.base, "a < b", scc_parse_expression); + + // a == b + scc_ast_expr_t eq; + scc_ast_expr_binary_init(&eq, SCC_AST_OP_EQUAL, &a, &b); + SCC_CHECK_AST(&eq.base, "a == b", scc_parse_expression); + + // a & b ^ c | d + scc_ast_expr_t bitand, bitxor, bitor; + scc_ast_expr_binary_init(&bitand, SCC_AST_OP_BITWISE_AND, &a, &b); + scc_ast_expr_binary_init(&bitxor, SCC_AST_OP_BITWISE_XOR, &bitand, &c); + scc_ast_expr_binary_init(&bitor, SCC_AST_OP_BITWISE_OR, &bitxor, &d); + SCC_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression); + + // a && b || c + scc_ast_expr_t logand, logor; + scc_ast_expr_binary_init(&logand, SCC_AST_OP_LOGICAL_AND, &a, &b); + scc_ast_expr_binary_init(&logor, SCC_AST_OP_LOGICAL_OR, &logand, &c); + SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression); + } + + // 6. 三元运算符 + { + scc_ast_expr_t a, b, c; + scc_ast_expr_identifier_init(&a, "a"); + scc_ast_expr_identifier_init(&b, "b"); + scc_ast_expr_identifier_init(&c, "c"); + + // a ? b : c + scc_ast_expr_t cond1; + scc_ast_expr_cond_init(&cond1, &a, &b, &c); + SCC_CHECK_AST(&cond1.base, "a ? b : c", scc_parse_expression); + + // a ? b : c ? d : e => a ? b : (c ? d : e) + scc_ast_expr_t d, e; + scc_ast_expr_identifier_init(&d, "d"); + scc_ast_expr_identifier_init(&e, "e"); + scc_ast_expr_t inner, outer; + scc_ast_expr_cond_init(&inner, &c, &d, &e); + scc_ast_expr_cond_init(&outer, &a, &b, &inner); + SCC_CHECK_AST(&outer.base, "a ? b : c ? d : e", scc_parse_expression); + } + + // 7. 赋值运算符 + { + scc_ast_expr_t a, b, c; + scc_ast_expr_identifier_init(&a, "a"); + scc_ast_expr_identifier_init(&b, "b"); + scc_ast_expr_identifier_init(&c, "c"); + scc_ast_expr_t lit42; + scc_ast_expr_literal_int_init(&lit42, "42", false); + + // a = b = c + scc_ast_expr_t assign_inner, assign_outer; + scc_ast_expr_binary_init(&assign_inner, SCC_AST_OP_ASSIGN, &b, &c); + scc_ast_expr_binary_init(&assign_outer, SCC_AST_OP_ASSIGN, &a, + &assign_inner); + SCC_CHECK_AST(&assign_outer.base, "a = b = c", scc_parse_expression); + + // a = 42 + scc_ast_expr_t assign1; + scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a, &lit42); + SCC_CHECK_AST(&assign1.base, "a = 42", scc_parse_expression); + + // a = a - b + 42 + scc_ast_expr_t sub, add, assign2; + scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a, &b); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &sub, &lit42); + scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &a, &add); + SCC_CHECK_AST(&assign2.base, "a = a - b + 42", scc_parse_expression); + + // a += b + scc_ast_expr_t add_assign; + scc_ast_expr_binary_init(&add_assign, SCC_AST_OP_ASSIGN_ADD, &a, &b); + SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression); + } + + // 8. 逗号运算符 + { + scc_ast_expr_t a, b; + scc_ast_expr_identifier_init(&a, "a"); + scc_ast_expr_identifier_init(&b, "b"); + scc_ast_expr_t comma; + scc_ast_expr_binary_init(&comma, SCC_AST_OP_COMMA, &a, &b); + SCC_CHECK_AST(&comma.base, "a, b", scc_parse_expression); + } + + // 9. 混合优先级 + { + scc_ast_expr_t a, b, c, d; + scc_ast_expr_identifier_init(&a, "a"); + scc_ast_expr_identifier_init(&b, "b"); + scc_ast_expr_identifier_init(&c, "c"); + scc_ast_expr_identifier_init(&d, "d"); + + // a + b * c - d + scc_ast_expr_t mul, add, sub; + scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &b, &c); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &a, &mul); + scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &add, &d); + SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression); + + // *p++ + scc_ast_expr_t p, post_inc, deref; + scc_ast_expr_identifier_init(&p, "p"); + scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &p); + scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &post_inc); + SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression); + } +} + +static void test_parser_type(void) { + { + // 1. int + { + SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int", + scc_parse_type_name); + } + + // 2. int * + { + scc_ast_type_t ptr_to_int; + scc_ast_type_pointer_init( + &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); + SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name); + } + + // 3. int *[3] + { + scc_ast_type_t ptr_to_int; + scc_ast_type_pointer_init( + &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); + + scc_ast_expr_t size_3; + scc_ast_expr_literal_int_init(&size_3, "3", false); + + scc_ast_type_t array_of_ptr; + scc_ast_type_array_init(&array_of_ptr, &ptr_to_int, &size_3); + SCC_CHECK_AST(&array_of_ptr.base, "int *[3]", scc_parse_type_name); + } + + // 4. int (*)[3] + { + scc_ast_expr_t size_3; + scc_ast_expr_literal_int_init(&size_3, "3", false); + + scc_ast_type_t array_of_int; + scc_ast_type_array_init(&array_of_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &size_3); + + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_int); + SCC_CHECK_AST(&ptr_to_array.base, "int (*)[3]", + scc_parse_type_name); + } + + // 5. int (*)[*] + { + scc_ast_type_t array_of_int_var; + scc_ast_type_array_init(&array_of_int_var, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + null); // null 表示不定长数组 + + scc_ast_type_t ptr_to_array_var; + scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_var); + SCC_CHECK_AST(&ptr_to_array_var.base, "int (*)[*]", + scc_parse_type_name); + } + + // 6. int *() + { + // 返回类型 int* + scc_ast_type_t ptr_to_int; + scc_ast_type_pointer_init( + &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); + + // 函数类型,返回 int*,无参数 + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &ptr_to_int, null); + SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name); + } + + // 7. int (*)(void) + { + // 函数类型,返回 int,无参数 + scc_ast_type_t func_void; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, + null); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init( + &func_void, (scc_ast_type_t *)&scc_ast_builtin_type_int, + &func_params); + + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_void); + SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)", + scc_parse_type_name); + } + + // 8. int (*const [])(unsigned int, ...) + { + // --- 构造参数列表 --- + // 第一个参数:unsigned int + scc_ast_decl_t param_uint; + scc_ast_decl_param_init( + ¶m_uint, + (scc_ast_type_t *)&scc_ast_builtin_type_unsigned_int, "u"); + + // 第二个参数:... 用内置 va_list 类型近似表示 + scc_ast_type_t va_list_type; + _scc_ast_type_builtin_init(&va_list_type, + SCC_AST_BUILTIN_TYPE_VA_LIST); + scc_ast_decl_t param_var; + scc_ast_decl_param_init(¶m_var, &va_list_type, "..."); + + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, ¶m_uint); + scc_vec_push(params, ¶m_var); + + // --- 函数类型,返回 int --- + scc_ast_type_t func_type; + scc_ast_type_function_init( + &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, + ¶ms); // params 被移动 + + // --- 指向函数的指针,带 const 限定 --- + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type); + ptr_to_func.quals.is_const = true; // 设置 const + + // --- 数组,元素为上述 const 指针,大小未指定 --- + scc_ast_type_t array_of_ptr; + scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, null); + + SCC_CHECK_AST(&array_of_ptr.base, + "int (*const [])(unsigned int, ...)", + scc_parse_type_name); + } + } + + // 1. 基本内置类型及组合 + { + // int + SCC_CHECK_AST(&scc_ast_builtin_type_int.base, "int", + scc_parse_type_name); + + // char + SCC_CHECK_AST(&scc_ast_builtin_type_char.base, "char", + scc_parse_type_name); + + // long long + SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long", + scc_parse_type_name); + + // long long + SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long int", + scc_parse_type_name); + + // short + SCC_CHECK_AST(&scc_ast_builtin_type_short.base, "short int", + scc_parse_type_name); + + // unsigned int + SCC_CHECK_AST(&scc_ast_builtin_type_unsigned_int.base, "unsigned int", + scc_parse_type_name); + + // float + SCC_CHECK_AST(&scc_ast_builtin_type_float.base, "float", + scc_parse_type_name); + + // double + SCC_CHECK_AST(&scc_ast_builtin_type_double.base, "double", + scc_parse_type_name); + + // void + SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_void, "void", + scc_parse_type_name); + + // bool + SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_bool, "bool", + scc_parse_type_name); + + // long double + SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_double, + "long double", scc_parse_type_name); + + // _Complex double + SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double, + "double complex", scc_parse_type_name); + } + + // 2. 带类型限定符的基本类型 (const, volatile) + { + // const int + scc_ast_type_t const_int = scc_ast_builtin_type_int; + const_int.quals.is_const = true; + SCC_CHECK_AST(&const_int.base, "const int", scc_parse_type_name); + + // volatile unsigned long + scc_ast_type_t volatile_ulong = scc_ast_builtin_type_unsigned_long; + volatile_ulong.quals.is_volatile = true; + SCC_CHECK_AST(&volatile_ulong.base, "volatile unsigned long", + scc_parse_type_name); + + // const volatile char + scc_ast_type_t const_volatile_char = scc_ast_builtin_type_char; + const_volatile_char.quals.is_const = true; + const_volatile_char.quals.is_volatile = true; + SCC_CHECK_AST(&const_volatile_char.base, "const volatile char", + scc_parse_type_name); + } + + // 3. 指针类型 + { + // int * + scc_ast_type_t ptr_to_int; + scc_ast_type_pointer_init(&ptr_to_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int); + SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name); + + // int ** + scc_ast_type_t ptr_to_ptr_to_int; + scc_ast_type_pointer_init(&ptr_to_ptr_to_int, &ptr_to_int); + SCC_CHECK_AST(&ptr_to_ptr_to_int.base, "int **", scc_parse_type_name); + + // int * const (const pointer to int) + scc_ast_type_t const_ptr_to_int; + scc_ast_type_pointer_init(&const_ptr_to_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int); + const_ptr_to_int.quals.is_const = true; + SCC_CHECK_AST(&const_ptr_to_int.base, "int * const", + scc_parse_type_name); + + // const int * (pointer to const int) + scc_ast_type_t const_int_type = scc_ast_builtin_type_int; + const_int_type.quals.is_const = true; + scc_ast_type_t ptr_to_const_int; + scc_ast_type_pointer_init(&ptr_to_const_int, &const_int_type); + SCC_CHECK_AST(&ptr_to_const_int.base, "const int *", + scc_parse_type_name); + + // const int * const (const pointer to const int) + scc_ast_type_t const_ptr_to_const_int; + scc_ast_type_pointer_init(&const_ptr_to_const_int, &const_int_type); + const_ptr_to_const_int.quals.is_const = true; + SCC_CHECK_AST(&const_ptr_to_const_int.base, "const int * const", + scc_parse_type_name); + + // volatile int * restrict + scc_ast_type_t volatile_int = scc_ast_builtin_type_int; + volatile_int.quals.is_volatile = true; + scc_ast_type_t restrict_ptr_to_volatile_int; + scc_ast_type_pointer_init(&restrict_ptr_to_volatile_int, &volatile_int); + restrict_ptr_to_volatile_int.quals.is_restrict = true; + SCC_CHECK_AST(&restrict_ptr_to_volatile_int.base, + "volatile int * restrict", scc_parse_type_name); + } + + // 4. 数组类型 + { + // int [5] + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false); + scc_ast_type_t array_of_5_int; + scc_ast_type_array_init(&array_of_5_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &size_5); + SCC_CHECK_AST(&array_of_5_int.base, "int [5]", scc_parse_type_name); + + // int [] (不完整类型) + scc_ast_type_t array_of_int_unknown; + scc_ast_type_array_init(&array_of_int_unknown, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + null); + SCC_CHECK_AST(&array_of_int_unknown.base, "int []", + scc_parse_type_name); + + // // int [*] (变长数组原型中的不定长数组) + // FIXME + // scc_ast_type_t array_of_int_var; + // scc_ast_type_array_init(&array_of_int_var, + // (scc_ast_type_t *)&scc_ast_builtin_type_int, + // null); + // // 注意:[*] 与 [] 在AST中目前无法区分,都使用 size=null + // // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对 + // [*] + // // 也生成 size=null 的数组节点。 + // SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type); + + // int [5][3] (二维数组) + scc_ast_expr_t size_3; + scc_ast_expr_literal_int_init(&size_3, "3", false); + scc_ast_type_t inner_array; + scc_ast_type_array_init( + &inner_array, (scc_ast_type_t *)&scc_ast_builtin_type_int, &size_3); + scc_ast_type_t outer_array; + scc_ast_type_array_init(&outer_array, &inner_array, &size_5); + SCC_CHECK_AST(&outer_array.base, "int [5][3]", scc_parse_type_name); + + // int (*)[5] (指向数组的指针) 已在前面测试,这里重复以保持完整性 + scc_ast_type_t array_of_5_int2; + scc_ast_type_array_init(&array_of_5_int2, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &size_5); + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int2); + SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", scc_parse_type_name); + + // int *[5] (指针数组) + scc_ast_type_t ptr_to_int2; + scc_ast_type_pointer_init(&ptr_to_int2, + (scc_ast_type_t *)&scc_ast_builtin_type_int); + scc_ast_type_t array_of_5_ptr; + scc_ast_type_array_init(&array_of_5_ptr, &ptr_to_int2, &size_5); + SCC_CHECK_AST(&array_of_5_ptr.base, "int *[5]", scc_parse_type_name); + + // const int [5] (数组元素为const int) + scc_ast_type_t const_int2 = scc_ast_builtin_type_int; + const_int2.quals.is_const = true; + scc_ast_type_t const_array; + scc_ast_type_array_init(&const_array, &const_int2, &size_5); + SCC_CHECK_AST(&const_array.base, "const int [5]", scc_parse_type_name); + } + + // 5. 函数类型 + { + // int (void) + scc_ast_type_t func_void; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init(&func_void, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &func_params); + SCC_CHECK_AST(&func_void.base, "int (void)", scc_parse_type_name); + + // // int () (无参数声明,非原型) + // // + // 在C中,空括号表示未指定参数,但AST中可能仍然用空参数列表表示。这里假设与 + // // (void) 相同。 + // SCC_CHECK_AST(&func_void.base, "int ()", scc_parse_type); + + // int (int, float) + scc_ast_decl_t param1, param2; + scc_ast_decl_param_init( + ¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); + scc_ast_decl_param_init( + ¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_float, null); + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, ¶m1); + scc_vec_push(params, ¶m2); + + scc_ast_type_t func_with_params; + scc_ast_type_function_init(&func_with_params, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + ¶ms); + SCC_CHECK_AST(&func_with_params.base, "int (int, float)", + scc_parse_type_name); + + // int (int, ...) (可变参数) + scc_ast_decl_t param_int, param_var; + scc_ast_decl_param_init( + ¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); + scc_ast_type_t va_list_type; + _scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST); + scc_ast_decl_param_init(¶m_var, &va_list_type, null); + scc_ast_decl_vec_t params_var; + scc_vec_init(params_var); + scc_vec_push(params_var, ¶m_int); + scc_vec_push(params_var, ¶m_var); + + scc_ast_type_t func_varargs; + scc_ast_type_function_init(&func_varargs, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + ¶ms_var); + SCC_CHECK_AST(&func_varargs.base, "int (int, ...)", + scc_parse_type_name); + + // int (*)(int) (函数指针) + scc_ast_decl_t param; + scc_ast_decl_param_init( + ¶m, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); + scc_ast_decl_vec_t params2; + scc_vec_init(params2); + scc_vec_push(params2, ¶m); + + scc_ast_type_t func_type; + scc_ast_type_function_init( + &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, ¶ms2); + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type); + SCC_CHECK_AST(&ptr_to_func.base, "int (*)(int)", scc_parse_type_name); + } + + // 6. 函数指针和复杂声明符 + { + // int (*foo)(void) + // 这里应解析为类型名,但包含标识符?我们的解析函数是scc_parse_type,它应该解析类型名,不应包含标识符。 + // 所以跳过带标识符的,只测试抽象声明符。 + + // int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针) + // 步骤: + // 1) 数组类型:int [5] + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false); + scc_ast_type_t array_of_5_int; + scc_ast_type_array_init(&array_of_5_int, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &size_5); + + // 2) 函数类型:返回指向数组的指针,无参数 + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int); + scc_ast_type_t func_type; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init(&func_type, &ptr_to_array, + &func_params); // 无参数 + + // 3) 指向该函数的指针 + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type); + + SCC_CHECK_AST(&ptr_to_func.base, "int (*(*)(void))[5]", + scc_parse_type_name); + + // int (*(*)[5])(void) (指向数组的指针,数组元素为函数指针) + // 1) 函数类型:返回 int,无参数 + scc_ast_type_t func_type2; + scc_ast_decl_vec_t func_params2; + scc_vec_unsafe_from_static_array(func_params2, array); + scc_ast_type_function_init(&func_type2, + (scc_ast_type_t *)&scc_ast_builtin_type_int, + &func_params2); + + // 2) 指针指向该函数 + scc_ast_type_t ptr_to_func2; + scc_ast_type_pointer_init(&ptr_to_func2, &func_type2); + + // 3) 数组,元素为上述指针 + scc_ast_type_t array_of_ptr_to_func; + scc_ast_type_array_init(&array_of_ptr_to_func, &ptr_to_func2, &size_5); + + // 4) 指针指向该数组 + scc_ast_type_t ptr_to_array_of_ptr; + scc_ast_type_pointer_init(&ptr_to_array_of_ptr, &array_of_ptr_to_func); + SCC_CHECK_AST(&ptr_to_array_of_ptr.base, "int (*(*)[5])(void)", + scc_parse_type_name); + } + + // 7. 结构体/联合/枚举类型(标记和定义) + { + // struct S (不完整类型) + scc_ast_type_t struct_tag; + scc_ast_type_struct_init(&struct_tag, "S", + null); // name="S", members=null + SCC_CHECK_AST(&struct_tag.base, "struct S", scc_parse_type_name); + + // struct { int x; } (匿名结构体定义) + scc_ast_decl_t field; + scc_ast_decl_val_init( + &field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null); + scc_ast_decl_vec_t fields; + scc_vec_init(fields); + scc_vec_push(fields, &field); + + scc_ast_decl_t struct_def; + scc_ast_decl_struct_init(&struct_def, null, &fields); + scc_ast_type_t struct_type; + scc_ast_type_struct_init(&struct_type, null, &struct_def); + SCC_CHECK_AST(&struct_type.base, "struct { int x; }", + scc_parse_type_name); + scc_vec_init(fields); + scc_vec_push(fields, &field); + scc_ast_decl_struct_init(&struct_def, "A", &fields); + scc_ast_type_struct_init(&struct_type, "A", &struct_def); + SCC_CHECK_AST(&struct_type.base, "struct A { int x; }", + scc_parse_type_name); + + // union U (不完整类型) + scc_ast_type_t union_tag; + scc_ast_type_union_init(&union_tag, "U", null); + SCC_CHECK_AST(&union_tag.base, "union U", scc_parse_type_name); + + // union { int a; float b; } (匿名联合定义) + scc_ast_decl_t field_a, field_b; + scc_ast_decl_val_init( + &field_a, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null); + scc_ast_decl_val_init( + &field_b, (scc_ast_type_t *)&scc_ast_builtin_type_float, "b", null); + scc_ast_decl_vec_t fields_union; + scc_vec_init(fields_union); + scc_vec_push(fields_union, &field_a); + scc_vec_push(fields_union, &field_b); + + scc_ast_decl_t union_def; + scc_ast_decl_union_init(&union_def, null, &fields_union); + scc_ast_type_t union_type; + scc_ast_type_union_init(&union_type, null, &union_def); + SCC_CHECK_AST(&union_type.base, "union { int a; float b; }", + scc_parse_type_name); + scc_ast_decl_union_init(&union_def, "Union", &fields_union); + scc_ast_type_union_init(&union_type, "Union", &union_def); + SCC_CHECK_AST(&union_type.base, "union Union { int a; float b; }", + scc_parse_type_name); + + // enum E (不完整类型) + scc_ast_type_t enum_tag; + scc_ast_type_enum_init(&enum_tag, "E", null); + SCC_CHECK_AST(&enum_tag.base, "enum E", scc_parse_type_name); + + // enum { RED, GREEN, BLUE } (匿名枚举定义) + scc_ast_expr_t red, green, blue; + scc_ast_expr_identifier_init(&red, "RED"); + scc_ast_expr_identifier_init(&green, "GREEN"); + scc_ast_expr_identifier_init(&blue, "BLUE"); + scc_ast_expr_vec_t enumerators; + scc_ast_expr_t *array[] = {&red, &green, &blue}; + scc_vec_unsafe_from_static_array(enumerators, array); + + scc_ast_decl_t enum_def; + scc_ast_decl_enum_init(&enum_def, null, &enumerators); + scc_ast_type_t enum_type; + scc_ast_type_enum_init(&enum_type, null, &enum_def); + SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", + scc_parse_type_name); + + scc_vec_unsafe_from_static_array(enumerators, array); + scc_ast_decl_enum_init(&enum_def, "E", &enumerators); + scc_ast_type_enum_init(&enum_type, "E", &enum_def); + SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE, }", + scc_parse_type_name); + } + + // 8. typedef 类型 + { + // 假设存在 typedef int myint; 但类型解析时,遇到 myint + // 应得到对应的类型节点。 为了测试,我们直接构造一个 typedef 类型节点。 + // scc_ast_type_t myint_type; + // scc_ast_type_typedef_init(&myint_type, "myint", + // (scc_ast_type_t + // *)&scc_ast_builtin_type_int); + // SCC_CHECK_AST(&myint_type.base, "myint", scc_parse_type); + + // // myint * (指针指向 typedef 类型) + // scc_ast_type_t ptr_to_myint; + // scc_ast_type_pointer_init(&ptr_to_myint, &myint_type); + // SCC_CHECK_AST(&ptr_to_myint.base, "myint *", scc_parse_type); + } + + // 9. 混合复杂类型 + { + // const int * volatile (*)[10] + // 步骤: + // 1) const int + scc_ast_type_t const_int = scc_ast_builtin_type_int; + const_int.quals.is_const = true; + + // 2) 指针指向 const int (普通指针) + scc_ast_type_t ptr_to_const_int; + scc_ast_type_pointer_init(&ptr_to_const_int, &const_int); + // 该指针本身是 volatile 限定?语法上 "const int * volatile" 表示指针是 + // volatile 的,指向 const int。 + ptr_to_const_int.quals.is_volatile = true; + + // 3) 数组,元素为上述指针,大小为10 + scc_ast_expr_t size_10; + scc_ast_expr_literal_int_init(&size_10, "10", false); + scc_ast_type_t array_of_ptr; + scc_ast_type_array_init(&array_of_ptr, &ptr_to_const_int, &size_10); + + // 4) 指针指向该数组 + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_ptr); + SCC_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]", + scc_parse_type_name); + + // float (*(*)(int, ...))() + // 1) float 类型作为内部函数返回类型 + // 2) 构建返回 float 的函数类型,无参数(或者参数为空) + scc_ast_type_t func_ret_float; + scc_ast_type_function_init( + &func_ret_float, (scc_ast_type_t *)&scc_ast_builtin_type_float, + null); + + // 3) 指针指向该函数 + scc_ast_type_t ptr_to_func_ret_float; + scc_ast_type_pointer_init(&ptr_to_func_ret_float, &func_ret_float); + + // 4) 外层函数类型,返回上述指针,参数为 (int, ...) + scc_ast_decl_t param_int, param_var; + scc_ast_decl_param_init( + ¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); + scc_ast_type_t va_list_type; + _scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST); + scc_ast_decl_param_init(¶m_var, &va_list_type, null); + scc_ast_decl_vec_t params_outer; + scc_vec_init(params_outer); + scc_vec_push(params_outer, ¶m_int); + scc_vec_push(params_outer, ¶m_var); + + scc_ast_type_t outer_func; + scc_ast_type_function_init(&outer_func, &ptr_to_func_ret_float, + ¶ms_outer); + + // 5) 指针指向外层函数 + scc_ast_type_t ptr_to_outer_func; + scc_ast_type_pointer_init(&ptr_to_outer_func, &outer_func); + SCC_CHECK_AST(&ptr_to_outer_func.base, "float (*(*)(int, ...))()", + scc_parse_type_name); + } +} + TEST_LIST = { {"parser_unit", test_parser_unit}, + {"parser_expression", test_parser_expression}, + {"parser_type", test_parser_type}, + // {"parser_statement", test_parser_statement}, + // {"parser_declaration", test_parser_declaration}, + // {"parser_translation_unit", test_parser_translation_unit}, {null, null}, }; diff --git a/libs/sccf/src/sccf_builder.c b/libs/sccf/src/sccf_builder.c index f3f0517..2b9168b 100644 --- a/libs/sccf/src/sccf_builder.c +++ b/libs/sccf/src/sccf_builder.c @@ -75,7 +75,6 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) { .size = scc_vec_size(builder->strtab), .sccf_sect_type = SCCF_SECT_STRTAB, }; - // TODO 转换成 u8[] sccf_builder_add_section(builder, §_header, (void *)&builder->strtab); } @@ -89,7 +88,6 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) { .size = scc_vec_size(builder->symtab), .sccf_sect_type = SCCF_SECT_SYMTAB, }; - // TODO 转换成 u8[] sccf_builder_add_section(builder, §_header, (void *)&builder->symtab); } @@ -103,7 +101,6 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) { .size = scc_vec_size(builder->relocs), .sccf_sect_type = SCCF_SECT_RELOCS, }; - // TODO 转换成 u8[] sccf_builder_add_section(builder, §_header, (void *)&builder->relocs); } diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index 9d09386..daa7ca8 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -64,7 +64,7 @@ static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx) { (scc_hashtable_hash_func_t)scc_strhash32, (scc_hashtable_equal_func_t)scc_strcmp); scc_vec_init(ctx->idata_libs); - load_from_def(ctx, "./.dll_def", "ucrtbase.dll"); + load_from_def(ctx, __FILE__ "/../../.dll_def", "ucrtbase.dll"); } static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) { @@ -102,24 +102,22 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { sccf_sym_vec_t symtab; scc_vec_init(symtab); - sccf_sect_data_t *text_data = null; - - scc_pe_reserve_header(builder, 3); - - scc_pe_section_range code_range = {0}; - scc_pe_section_range data_range = {0}; - scc_pe_section_range idata_range = {0}; - + sccf_sect_data_t *code_data = null; + sccf_sect_data_t *data_data = null; + int num_of_section = 1; scc_vec_foreach(sccf->sect_headers, i) { sccf_sect_header_t *sect_header = &scc_vec_at(sccf->sect_headers, i); sccf_sect_data_t *sect_data = &scc_vec_at(sccf->sect_datas, i); if (sect_header->sccf_sect_type == SCCF_SECT_CODE) { - text_data = sect_data; - code_range = scc_pe_reserve_text_section_header( - builder, scc_vec_size(*sect_data)); + if (scc_vec_size(*sect_data) != 0) { + code_data = sect_data; + num_of_section += 1; + } } else if (sect_header->sccf_sect_type == SCCF_SECT_DATA) { - data_range = scc_pe_reserve_data_section_header( - builder, scc_vec_size(*sect_data)); + if (scc_vec_size(*sect_data) != 0) { + data_data = sect_data; + num_of_section += 1; + } } else if (sect_header->sccf_sect_type == SCCF_SECT_STRTAB) { scc_vec_unsafe_from_buffer( strtab, (char *)scc_vec_unsafe_get_data(*sect_data), @@ -135,6 +133,21 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { } } + scc_pe_reserve_header(builder, num_of_section); + + scc_pe_section_range code_range = {0}; + scc_pe_section_range data_range = {0}; + scc_pe_section_range idata_range = {0}; + + if (code_data) { + code_range = scc_pe_reserve_text_section_header( + builder, scc_vec_size(*code_data)); + } + if (data_data) { + data_range = scc_pe_reserve_data_section_header( + builder, scc_vec_size(*data_data)); + } + pe_idata_lib_ctx_t idata_lib_ctx; pe_idata_lib_init(&idata_lib_ctx); scc_vec_foreach(symtab, i) { @@ -204,24 +217,21 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { } Assert(reloc->sect_type == SCCF_SECT_CODE); rva -= code_range.virual_address + reloc->offset + reloc->addend; - Assert(text_data != null); + Assert(code_data != null); // FIXME 需要确保宿主机与目标机器大小端一致 - *(u32 *)(scc_vec_unsafe_get_data(*text_data) + reloc->offset) = rva; + *(u32 *)(scc_vec_unsafe_get_data(*code_data) + reloc->offset) = rva; } scc_pe_write_header(builder, &config); - scc_vec_foreach(sccf->sect_headers, i) { - sccf_sect_header_t *sect_header = &scc_vec_at(sccf->sect_headers, i); - sccf_sect_data_t *sect_data = &scc_vec_at(sccf->sect_datas, i); - if (sect_header->sccf_sect_type == SCCF_SECT_CODE) { - scc_pe_write_section(builder, &code_range, - (u8 *)scc_vec_unsafe_get_data(*sect_data), - scc_vec_size(*sect_data)); - } else if (sect_header->sccf_sect_type == SCCF_SECT_DATA) { - scc_pe_write_section(builder, &data_range, - (u8 *)scc_vec_unsafe_get_data(*sect_data), - scc_vec_size(*sect_data)); - } + if (code_data != null) { + scc_pe_write_section(builder, &code_range, + (u8 *)scc_vec_unsafe_get_data(*code_data), + scc_vec_size(*code_data)); + } + if (data_data != null) { + scc_pe_write_section(builder, &data_range, + (u8 *)scc_vec_unsafe_get_data(*data_data), + scc_vec_size(*data_data)); } scc_pe_write_section(builder, &idata_range, scc_vec_unsafe_get_data(idata_buffer), diff --git a/libs/target/sccf2target/src/main.c b/libs/target/sccf2target/tests/test_sccf2pe_run.c similarity index 100% rename from libs/target/sccf2target/src/main.c rename to libs/target/sccf2target/tests/test_sccf2pe_run.c diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..2eb07a7 --- /dev/null +++ b/src/init.c @@ -0,0 +1,11 @@ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +void init_platform(void) { +#ifdef _WIN32 + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); +#endif +} diff --git a/src/main.c b/src/main.c index 063de03..2e6e1bd 100644 --- a/src/main.c +++ b/src/main.c @@ -1,19 +1,16 @@ #include #include +#include #include #include #include #include -#include +#include +#include #include "config.h" -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#endif - static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) { scc_lexer_tok_t tok = {0}; int ret = 0; @@ -58,11 +55,10 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) { scc_fclose(fp); } +void init_platform(void); + int main(int argc, const char **argv, const char **envp) { -#ifdef _WIN32 - SetConsoleOutputCP(CP_UTF8); - SetConsoleCP(CP_UTF8); -#endif + init_platform(); #ifndef SCC_DEFAULT_ARGPARSE_LANG #define SCC_DEFAULT_ARGPARSE_LANG SCC_ARGPARSE_LANG_ZH @@ -233,10 +229,19 @@ sstream_drop: return 0; } + scc_ir2mcode_ctx_t mcode_ctx; + scc_ir2mcode_init(&mcode_ctx, &ast2ir_ctx.builder.cprog, + &ast2ir_ctx.builder.ctx, SCC_MCODE_ARCH_AMD64); + scc_ir2mcode(&mcode_ctx); + + const sccf_t *sccf = sccf_builder_to_sccf(&mcode_ctx.builder); + scc_pe_builder_t pe_builder; + sccf2pe(&pe_builder, sccf); + if (fp == null) { scc_printf("output exe at %s\n", config.output_file); } else { - scc_printf("output exe at %s\n", config.output_file); + scc_pe_dump_to_file(&pe_builder, config.output_file); } return 0; diff --git a/tests/simple/Makefile b/tests/simple/Makefile deleted file mode 100644 index 3b05474..0000000 --- a/tests/simple/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# VM := ../../rv32-vm -# CC := ../../ccompiler -# STD_CC := gcc - -# TESTS := $(wildcard *.c) - -# # 定义所有测试目标 -# TEST_TARGETS := $(patsubst %.c, %_test, $(TESTS)) - -# all: $(TEST_TARGETS) - -# %_test: %.c -# @$(STD_CC) -g -o $@ $< -# @$(CC) $< flat.bin -# @./$@ ; ret_gcc=$$? -# @$(VM) flat.bin ; ret_vm=$$? -# @echo "Testing $@" -# @if [ $$ret_gcc -eq $$ret_vm ]; then \ -# echo "$@ passed"; \ -# else \ -# echo "$@ failed: GCC returned $$ret_gcc, VM returned $$ret_vm"; \ -# exit 1; \ -# fi - -# clean: -# rm -f $(TEST_TARGETS) flat.bin - -# .PHONY: all clean -all: - python test.py \ No newline at end of file