feat(ir2mcode): 添加IR到机器码转换模块并更新依赖配置

- 新增ir2mcode库用于将IR转换为机器码
- 添加sccf2target依赖以支持目标平台转换
- 在ast库中添加scc_pos依赖支持位置信息
- 更新cbuild.toml配置文件添加新库依赖
- 实现AMD64架构代码生成功能
- 添加寄存器分配器实现栈和寄存器位置管理
- 支持基本的算术运算和内存访问操作
- 添加PE格式目标文件生成支持
This commit is contained in:
zzy
2026-03-20 14:12:25 +08:00
parent 02a6c684f1
commit de6f5d510a
19 changed files with 4046 additions and 290 deletions

View File

@@ -10,4 +10,7 @@ dependencies = [
{ name = "ast", path = "./libs/ast" }, { name = "ast", path = "./libs/ast" },
{ name = "ast2ir", path = "./libs/ast2ir" }, { name = "ast2ir", path = "./libs/ast2ir" },
{ name = "ir", path = "./libs/ir" }, { name = "ir", path = "./libs/ir" },
{ name = "ir2mcode", path = "./libs/ir2mcode" },
{ name = "sccf2target", path = "./libs/target/sccf2target" },
] ]

View File

@@ -22,3 +22,7 @@ mcode 机器码
sccf 统一输出格式 sccf 统一输出格式
target 目标平台支持 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)

View File

@@ -4,6 +4,9 @@ version = "0.1.0"
authors = [] authors = []
description = "" description = ""
dependencies = [{ name = "tree_dump", path = "../tree_dump" }] dependencies = [
{ name = "tree_dump", path = "../tree_dump" },
{ name = "scc_pos", path = "../sstream" },
]
# features = {} # features = {}
# default_features = [] # default_features = []

21
libs/ir2mcode/cbuild.toml Normal file
View File

@@ -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 = []

View File

@@ -0,0 +1,47 @@
#ifndef __SCC_REG_ALLOC_H__
#define __SCC_REG_ALLOC_H__
#include <scc_core.h>
#include <scc_ir.h>
#include <scc_utils.h>
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__ */

View File

@@ -0,0 +1,25 @@
#ifndef __SCC_IR2MCODE_H__
#define __SCC_IR2MCODE_H__
#include "reg_alloc.h"
#include <scc_core.h>
#include <scc_ir.h>
#include <scc_mcode.h>
#include <sccf_builder.h>
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__ */

View File

@@ -0,0 +1,232 @@
#include <amd64/scc_amd64.h>
#include <amd64/scc_amd64_abi.h>
#include <reg_alloc.h>
#include <scc_ir2mcode.h>
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("<invalid block>\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);
}

View File

@@ -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;
}

View File

@@ -0,0 +1,12 @@
#include <scc_ir2mcode.h>
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); }

View File

@@ -0,0 +1,59 @@
#include <scc_ast2ir.h>
#include <scc_ir2mcode.h>
#include <scc_lexer.h>
#include <scc_parser.h>
#include <sccf2pe.h>
#include <stdio.h>
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 <abi/win_x64_type_abi.h>
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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
#ifndef __SCC_MCODE_H__
#define __SCC_MCODE_H__
#include <scc_core.h>
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__ */

File diff suppressed because it is too large Load Diff

View File

@@ -75,7 +75,6 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
.size = scc_vec_size(builder->strtab), .size = scc_vec_size(builder->strtab),
.sccf_sect_type = SCCF_SECT_STRTAB, .sccf_sect_type = SCCF_SECT_STRTAB,
}; };
// TODO 转换成 u8[]
sccf_builder_add_section(builder, &sect_header, sccf_builder_add_section(builder, &sect_header,
(void *)&builder->strtab); (void *)&builder->strtab);
} }
@@ -89,7 +88,6 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
.size = scc_vec_size(builder->symtab), .size = scc_vec_size(builder->symtab),
.sccf_sect_type = SCCF_SECT_SYMTAB, .sccf_sect_type = SCCF_SECT_SYMTAB,
}; };
// TODO 转换成 u8[]
sccf_builder_add_section(builder, &sect_header, sccf_builder_add_section(builder, &sect_header,
(void *)&builder->symtab); (void *)&builder->symtab);
} }
@@ -103,7 +101,6 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
.size = scc_vec_size(builder->relocs), .size = scc_vec_size(builder->relocs),
.sccf_sect_type = SCCF_SECT_RELOCS, .sccf_sect_type = SCCF_SECT_RELOCS,
}; };
// TODO 转换成 u8[]
sccf_builder_add_section(builder, &sect_header, sccf_builder_add_section(builder, &sect_header,
(void *)&builder->relocs); (void *)&builder->relocs);
} }

View File

@@ -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_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp); (scc_hashtable_equal_func_t)scc_strcmp);
scc_vec_init(ctx->idata_libs); 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) { 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; sccf_sym_vec_t symtab;
scc_vec_init(symtab); scc_vec_init(symtab);
sccf_sect_data_t *text_data = null; sccf_sect_data_t *code_data = null;
sccf_sect_data_t *data_data = null;
scc_pe_reserve_header(builder, 3); int num_of_section = 1;
scc_pe_section_range code_range = {0};
scc_pe_section_range data_range = {0};
scc_pe_section_range idata_range = {0};
scc_vec_foreach(sccf->sect_headers, i) { scc_vec_foreach(sccf->sect_headers, i) {
sccf_sect_header_t *sect_header = &scc_vec_at(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); sccf_sect_data_t *sect_data = &scc_vec_at(sccf->sect_datas, i);
if (sect_header->sccf_sect_type == SCCF_SECT_CODE) { if (sect_header->sccf_sect_type == SCCF_SECT_CODE) {
text_data = sect_data; if (scc_vec_size(*sect_data) != 0) {
code_range = scc_pe_reserve_text_section_header( code_data = sect_data;
builder, scc_vec_size(*sect_data)); num_of_section += 1;
}
} else if (sect_header->sccf_sect_type == SCCF_SECT_DATA) { } else if (sect_header->sccf_sect_type == SCCF_SECT_DATA) {
data_range = scc_pe_reserve_data_section_header( if (scc_vec_size(*sect_data) != 0) {
builder, scc_vec_size(*sect_data)); data_data = sect_data;
num_of_section += 1;
}
} else if (sect_header->sccf_sect_type == SCCF_SECT_STRTAB) { } else if (sect_header->sccf_sect_type == SCCF_SECT_STRTAB) {
scc_vec_unsafe_from_buffer( scc_vec_unsafe_from_buffer(
strtab, (char *)scc_vec_unsafe_get_data(*sect_data), 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_ctx_t idata_lib_ctx;
pe_idata_lib_init(&idata_lib_ctx); pe_idata_lib_init(&idata_lib_ctx);
scc_vec_foreach(symtab, i) { 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); Assert(reloc->sect_type == SCCF_SECT_CODE);
rva -= code_range.virual_address + reloc->offset + reloc->addend; rva -= code_range.virual_address + reloc->offset + reloc->addend;
Assert(text_data != null); Assert(code_data != null);
// FIXME 需要确保宿主机与目标机器大小端一致 // 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_pe_write_header(builder, &config);
scc_vec_foreach(sccf->sect_headers, i) { if (code_data != null) {
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, scc_pe_write_section(builder, &code_range,
(u8 *)scc_vec_unsafe_get_data(*sect_data), (u8 *)scc_vec_unsafe_get_data(*code_data),
scc_vec_size(*sect_data)); scc_vec_size(*code_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 (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_pe_write_section(builder, &idata_range,
scc_vec_unsafe_get_data(idata_buffer), scc_vec_unsafe_get_data(idata_buffer),

11
src/init.c Normal file
View File

@@ -0,0 +1,11 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
void init_platform(void) {
#ifdef _WIN32
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
#endif
}

View File

@@ -1,19 +1,16 @@
#include <argparse.h> #include <argparse.h>
#include <scc_lexer.h> #include <scc_lexer.h>
#include <scc_parser.h>
#include <scc_pproc.h> #include <scc_pproc.h>
#include <ast_dump.h> #include <ast_dump.h>
#include <ir_dump.h> #include <ir_dump.h>
#include <scc_ast2ir.h> #include <scc_ast2ir.h>
#include <scc_parser.h> #include <scc_ir2mcode.h>
#include <sccf2pe.h>
#include "config.h" #include "config.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) { static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) {
scc_lexer_tok_t tok = {0}; scc_lexer_tok_t tok = {0};
int ret = 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); scc_fclose(fp);
} }
void init_platform(void);
int main(int argc, const char **argv, const char **envp) { int main(int argc, const char **argv, const char **envp) {
#ifdef _WIN32 init_platform();
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
#endif
#ifndef SCC_DEFAULT_ARGPARSE_LANG #ifndef SCC_DEFAULT_ARGPARSE_LANG
#define SCC_DEFAULT_ARGPARSE_LANG SCC_ARGPARSE_LANG_ZH #define SCC_DEFAULT_ARGPARSE_LANG SCC_ARGPARSE_LANG_ZH
@@ -233,10 +229,19 @@ sstream_drop:
return 0; 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) { if (fp == null) {
scc_printf("output exe at %s\n", config.output_file); scc_printf("output exe at %s\n", config.output_file);
} else { } else {
scc_printf("output exe at %s\n", config.output_file); scc_pe_dump_to_file(&pe_builder, config.output_file);
} }
return 0; return 0;

View File

@@ -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