fix(abi): 修复void类型的ABI计算缺少break语句

在scc_type_abi.c文件中,void类型的case分支缺少break语句,
导致执行流程错误地进入下一个case分支。

feat(ast): 为参数声明添加索引字段

在ast_def.h头文件中为参数声明结构体添加param_idx字段,
用于跟踪参数在函数参数列表中的位置索引。

feat(ast): 更新参数初始化函数以支持索引参数

修改scc_ast.h中的scc_ast_decl_param_init函数签名,
添加参数索引idx参数,并将该值存储到参数声明结构体中。

feat(ast2ir): 添加IR转换上下文的值使用提示选项

在ast2ir.h中为scc_ast2ir_ctx_t结构体添加hint_using_value字段,
控制参数转换时是使用值还是分配内存的方式。

fix(ast2ir): 正确处理void类型到IR的转换

当遇到大小为0的类型(如void)时,直接返回void类型,
而不是尝试匹配其他大小分支。

refactor(ast2ir): 统一基本块引用类型为value_ref

将逻辑表达式、条件语句、循环语句中的基本块引用类型
从bblock_ref_t改为value_ref_t,保持类型一致性。

fix(ast2ir): 修正函数引用空值检查

使用SCC_IR_REF_nullptr常量替代0进行函数引用的空值检查,
提高代码的可读性和正确性。

refactor(ast2ir): 简化参数处理逻辑

移除不必要的函数参数获取和命名设置逻辑,
通过递归调用scc_ast2ir_decl来处理参数声明。

feat(ast2ir): 实现参数声明到IR的转换

为参数声明添加完整的IR转换逻辑,包括类型转换、
参数引用创建和内存分配处理。

refactor(ast2ir): 更新哈希表初始化接口

适配新的哈希表初始化函数签名,添加userdata参数支持,
并初始化hint_using_value字段为false。

refactor(ir): 移除函数参数的预分配逻辑

删除IR构建器中函数参数的预分配和循环添加逻辑,
简化函数开始构建的处理流程。

refactor(ir): 更新类型哈希表键值处理

修改类型哈希表的哈希和比较函数以接受模块参数,
正确处理空引用情况并支持新的键值传递方式。

fix(ir): 修复IR转储中的字符串格式

移除IR函数转储时多余的换行符,确保输出格式正确。

refactor(ir): 更新模块哈希表初始化

适配哈希表初始化接口变更,添加userdata参数,
并为各种向量预留UID 0作为无效引用。

fix(ir): 修复模块清理中的循环起始索引

将模块清理循环的起始索引从0改为1,跳过预留的
无效引用项,避免访问空指针。

refactor(ir): 调整向量和哈希表操作顺序

调整模块中向量push和哈希表set的操作顺序,
确保数据一致性和正确的UID分配。

chore(build): 移除ir2mcode模块相关文件

移除ir2mcode相关的头文件和源文件,这些组件
将在后续重构中重新设计或替换。
This commit is contained in:
zzy
2026-04-15 14:52:11 +08:00
parent 8054f20375
commit 5a9f816ccf
38 changed files with 260 additions and 1497 deletions

View File

@@ -1,21 +0,0 @@
[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

@@ -1,21 +0,0 @@
#ifndef __SCC_FRAME_ALLOC_H__
#define __SCC_FRAME_ALLOC_H__
#include <scc_ir.h>
typedef struct scc_frame_alloc_ops scc_frame_alloc_ops_t;
struct scc_frame_alloc_ops {
/// maybe have direct function to new
scc_frame_alloc_ops_t *(*new)(scc_ir_func_t *func);
int (*drop)(scc_frame_alloc_ops_t *alloc);
int (*alloc_spill_slot)(scc_frame_alloc_ops_t *frame, int size, int align);
int (*alloc_local_slot)(scc_frame_alloc_ops_t *frame, int size, int align,
const char *name);
void (*finalize)(scc_frame_alloc_ops_t *frame);
int (*get_slot_offset)(scc_frame_alloc_ops_t *frame, int slot_id);
int (*get_frame_size)(scc_frame_alloc_ops_t *frame);
};
#endif

View File

@@ -1,77 +0,0 @@
#ifndef __SCC_REG_ALLOC_H__
#define __SCC_REG_ALLOC_H__
#include "frame_alloc.h"
#include <scc_core.h>
#include <scc_ir.h>
#include <scc_utils.h>
typedef enum {
SCC_REG_KIND_UNDEF,
SCC_REG_KIND_FUNC_ARG,
SCC_REG_KIND_GPR, ///< 通用寄存器(整数)
SCC_REG_KIND_FPR, ///< 浮点数寄存器
SCC_REG_KIND_STACK, ///< 栈
SCC_REG_KIND_STACK_ADDR, ///< 栈地址(如 alloc 节点)
SCC_REG_KIND_IMM, ///< 整数立即数
SCC_REG_KIND_IMM_FP, ///< 浮点数常量
} scc_reg_kind_t;
typedef struct {
scc_reg_kind_t kind;
union {
usize data;
int slot_idx;
int gpr_idx;
int fpr_idx;
} data;
} 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 void (*scc_reg_alloc_func_t)(scc_reg_alloc_t *ctx, scc_ir_func_t *func,
scc_frame_alloc_ops_t *frame_alloc);
typedef struct scc_reg_alloc {
scc_frame_alloc_ops_t *frame_alloc;
scc_ir_module_t *ir_module; ///< IR存储节点
scc_hashtable_t node2loc; ///< 输出结果哈希表
scc_reg_loc_vec_t loc_vec;
scc_reg_alloc_func_t reg_alloc_func;
} scc_reg_alloc_t;
void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t strategy,
scc_ir_module_t *ir_module);
static inline scc_hashtable_t *
scc_reg_alloc_run(scc_reg_alloc_t *ctx, scc_ir_func_t *func,
const scc_frame_alloc_ops_t *frame_alloc) {
if (ctx->frame_alloc != nullptr) {
ctx->frame_alloc->drop(ctx->frame_alloc);
ctx->frame_alloc = nullptr;
}
Assert(ctx->frame_alloc == nullptr);
ctx->frame_alloc = frame_alloc->new(func);
Assert(ctx->frame_alloc != nullptr);
ctx->reg_alloc_func(ctx, func, ctx->frame_alloc);
ctx->frame_alloc->finalize(ctx->frame_alloc);
return &ctx->node2loc;
}
static inline usize scc_reg_stack_size(scc_reg_alloc_t *ctx) {
return ctx->frame_alloc->get_frame_size(ctx->frame_alloc);
}
static inline int scc_reg_stack_offset(scc_reg_alloc_t *ctx,
scc_reg_loc_t *loc) {
Assert(loc->kind == SCC_REG_KIND_STACK ||
loc->kind == SCC_REG_KIND_STACK_ADDR);
return ctx->frame_alloc->get_slot_offset(ctx->frame_alloc,
loc->data.slot_idx);
}
void scc_reg_alloc_strategy_pure_stack(scc_reg_alloc_t *ctx,
scc_ir_func_t *func,
scc_frame_alloc_ops_t *frame_alloc);
#endif /* __SCC_REG_ALLOC_H__ */

View File

@@ -1,30 +0,0 @@
#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;
sccf_builder_t *builder;
scc_mcode_t sect_mcode;
sccf_sect_data_t sect_data;
// FIXME
usize stack_size;
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,
sccf_builder_t *builder, scc_mcode_arch_t arch);
void scc_ir2mcode_drop(scc_ir2mcode_ctx_t *ctx);
void scc_ir2mcode(scc_ir2mcode_ctx_t *ctx);
#endif /* __SCC_IR2MCODE_H__ */

View File

@@ -1,3 +0,0 @@
#include <scc_ir.h>
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type);

View File

@@ -1,159 +0,0 @@
#include <frame_alloc.h>
#include <scc_utils.h>
#include <type_manager.h>
static const int WIN64_DEFAULT_ALIGN = 8;
static const int WIN64_STACK_ALIGN = 16;
typedef struct {
int size;
int align;
int slot_id;
int offset; // 最终计算的偏移(负值)
} win64_slot_t;
typedef SCC_VEC(win64_slot_t) win64_slot_vec_t;
typedef struct {
scc_frame_alloc_ops_t base;
scc_ir_func_t *func;
win64_slot_vec_t slots; // 所有已分配的槽位
scc_hashtable_t offset_cache; // slot_id -> offset
int stack_size; // 最终对齐后的栈帧大小
int finalized; // 是否已调用 finalize
} win64_alloc_t;
/* ---------- 辅助函数 ---------- */
static u32 hash_ptr(const void *key) { return (u32)(uintptr_t)key; }
static int cmp_ptr(const void *a, const void *b) {
return (uintptr_t)a != (uintptr_t)b;
}
/* ---------- 槽位分配 ---------- */
static int win64_alloc_slot_common(win64_alloc_t *self, int size, int align) {
if (self->finalized) {
Panic("frame_alloc: cannot allocate after finalize");
}
win64_slot_t slot;
slot.size = (size <= 0) ? WIN64_DEFAULT_ALIGN : size;
slot.align = (align <= 0) ? WIN64_DEFAULT_ALIGN : align;
// 对齐不能小于自然对齐
if (slot.align < 1)
slot.align = 1;
slot.slot_id = (int)scc_vec_size(self->slots);
slot.offset = 0; // 暂未计算
scc_vec_push(self->slots, slot);
return slot.slot_id;
}
static int win64_alloc_spill_slot(scc_frame_alloc_ops_t *ops, int size,
int align) {
win64_alloc_t *self = (win64_alloc_t *)ops;
return win64_alloc_slot_common(self, size, align);
}
static int win64_alloc_local_slot(scc_frame_alloc_ops_t *ops, int size,
int align, const char *name) {
(void)name; // 本实现不记录名称
return win64_alloc_spill_slot(ops, size, align);
}
/* ---------- 最终布局计算 ---------- */
static void win64_finalize(scc_frame_alloc_ops_t *ops) {
win64_alloc_t *self = (win64_alloc_t *)ops;
if (self->finalized)
return;
int current_offset = -WIN64_DEFAULT_ALIGN; // 从 -8 开始
for (usize i = 0; i < scc_vec_size(self->slots); i++) {
win64_slot_t *slot = &scc_vec_at(self->slots, i);
int align = slot->align;
// 向下对齐到 align 的倍数current_offset 为负数)
int rem = ((-current_offset) % align);
if (rem != 0) {
current_offset -= (align - rem);
}
current_offset -= slot->size;
slot->offset = current_offset;
scc_hashtable_set(&self->offset_cache, (void *)(intptr_t)slot->slot_id,
(void *)(intptr_t)slot->offset);
}
int total_size = -current_offset + 32; // 加上影子空间
// 16 字节栈对齐
int aligned =
(total_size + WIN64_STACK_ALIGN - 1) & ~(WIN64_STACK_ALIGN - 1);
self->stack_size = aligned;
self->finalized = 1;
}
static int win64_get_slot_offset(scc_frame_alloc_ops_t *ops, int slot_id) {
win64_alloc_t *self = (win64_alloc_t *)ops;
if (!self->finalized) {
Panic("frame_alloc: get_slot_offset before finalize");
}
void *offset =
scc_hashtable_get(&self->offset_cache, (void *)(intptr_t)slot_id);
if (!offset) {
Panic("frame_alloc: invalid slot_id %d", slot_id);
}
return (int)(intptr_t)offset;
}
static int win64_get_frame_size(scc_frame_alloc_ops_t *ops) {
win64_alloc_t *self = (win64_alloc_t *)ops;
if (!self->finalized) {
Panic("frame_alloc: get_frame_size before finalize");
}
return self->stack_size;
}
/* ---------- 析构 ---------- */
static int win64_drop(scc_frame_alloc_ops_t *ops) {
win64_alloc_t *self = (win64_alloc_t *)ops;
scc_vec_free(self->slots);
scc_hashtable_drop(&self->offset_cache);
scc_free(self);
return 0;
}
/* ---------- 构造函数 ---------- */
scc_frame_alloc_ops_t *scc_frame_alloc_win64_new(scc_ir_func_t *func) {
win64_alloc_t *self = scc_malloc(sizeof(win64_alloc_t));
scc_memset(self, 0, sizeof(*self));
self->base.alloc_spill_slot = win64_alloc_spill_slot;
self->base.alloc_local_slot = win64_alloc_local_slot;
self->base.finalize = win64_finalize;
self->base.get_slot_offset = win64_get_slot_offset;
self->base.get_frame_size = win64_get_frame_size;
self->base.drop = win64_drop;
self->func = func;
self->finalized = 0;
self->stack_size = 0;
scc_vec_init(self->slots);
scc_hashtable_init(&self->offset_cache, hash_ptr, cmp_ptr);
return &self->base;
}
/* 提供一个全局的 ops 模板(可选,便于外部使用) */
static const scc_frame_alloc_ops_t win64_ops_template = {
.new = scc_frame_alloc_win64_new,
.drop = win64_drop,
.alloc_spill_slot = win64_alloc_spill_slot,
.alloc_local_slot = win64_alloc_local_slot,
.finalize = win64_finalize,
.get_slot_offset = win64_get_slot_offset,
.get_frame_size = win64_get_frame_size,
};
const scc_frame_alloc_ops_t *scc_frame_alloc_win64_ops(void) {
return &win64_ops_template;
}

View File

@@ -1,786 +0,0 @@
#include <amd64/scc_amd64.h>
#include <amd64/scc_amd64_abi.h>
#include <reg_alloc.h>
#include <scc_ir2mcode.h>
#include <type_manager.h>
#define GET_MODULE(ctx) (&(ctx->cprog->module))
static bool scc_type_is_signed(scc_ir_type_t *type) {
return (type->tag == SCC_IR_TYPE_i8 || type->tag == SCC_IR_TYPE_i16 ||
type->tag == SCC_IR_TYPE_i32 || type->tag == SCC_IR_TYPE_i64);
}
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
scc_ir_value_ref_t node_ref) {
Assert(ctx != nullptr && loc != nullptr);
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
if (value == nullptr) {
LOG_FATAL("invalid value ref");
UNREACHABLE();
return;
}
usize idx = 0;
switch (value->tag) {
case SCC_IR_VALUE_TAG_CONST_INT:
scc_ir_type_t *type =
scc_ir_module_get_type(GET_MODULE(ctx), value->type);
Assert(type != 0);
switch (type->tag) {
case SCC_IR_TYPE_u8:
case SCC_IR_TYPE_i8:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int8,
};
break;
case SCC_IR_TYPE_u16:
case SCC_IR_TYPE_i16:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int16,
};
break;
case SCC_IR_TYPE_u32:
case SCC_IR_TYPE_i32:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int32,
};
break;
case SCC_IR_TYPE_u64:
case SCC_IR_TYPE_i64:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int64,
};
break;
default:
break;
}
return;
case SCC_IR_VALUE_TAG_CONST_UINT:
case SCC_IR_VALUE_TAG_CONST_FLOAT:
TODO();
break;
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
TODO();
break;
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
case SCC_IR_VALUE_TAG_ALLOC:
default:
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
(void *)(usize)node_ref);
break;
}
Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.loc_vec));
*loc = scc_vec_at(ctx->reg_alloc.loc_vec, idx - 1);
}
static void load_value_to_reg(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
int reg) {
scc_mcode_t *mcode = &ctx->sect_mcode;
switch (loc->kind) {
case SCC_REG_KIND_GPR:
if (loc->data.gpr_idx != reg) {
scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->data.gpr_idx);
} else {
TODO();
}
break;
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_r64_m64_disp32(
mcode, reg, SCC_AMD64_RBP,
scc_reg_stack_offset(&ctx->reg_alloc, loc));
break;
case SCC_REG_KIND_STACK_ADDR:
// 将栈地址加载到寄存器(取地址)
scc_mcode_amd64_lea_r64_m64_disp32(
mcode, reg, SCC_AMD64_RBP,
scc_reg_stack_offset(&ctx->reg_alloc, loc));
break;
case SCC_REG_KIND_IMM:
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->data.data); // 或 imm32
break;
default:
LOG_FATAL("unsupported location");
}
}
static void store_value_from_reg(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
int reg) {
scc_mcode_t *mcode = &ctx->sect_mcode;
switch (loc->kind) {
case SCC_REG_KIND_GPR:
if (loc->data.gpr_idx != reg) {
scc_mcode_amd64_mov_r64_r64(mcode, loc->data.gpr_idx, reg);
}
break;
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_m64_disp32_r64(
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
reg);
break;
case SCC_REG_KIND_STACK_ADDR:
// 将寄存器的值存储到栈地址
scc_mcode_amd64_mov_m64_disp32_r64(
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
reg);
break;
case SCC_REG_KIND_IMM:
LOG_FATAL("cannot store to immediate");
break;
default:
Panic("unsupported location %d", loc->kind);
break;
}
}
// 临时存储待修补条目
typedef struct patch {
usize pos;
usize target_bb_ref;
} patch_t;
typedef SCC_VEC(patch_t) patch_vec_t;
static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
patch_vec_t *patches) {
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
if (value == nullptr) {
LOG_ERROR("invalid value ref");
return;
}
switch (value->tag) {
case SCC_IR_VALUE_TAG_BUILTIN: {
scc_ir_builtin_t *builtin = &value->data.builtin;
switch (builtin->tag) {
case SCC_IR_BUILTIN_TAG_MEMCPY: {
// 1. 获取操作数的位置
scc_reg_loc_t dest_loc, src_loc, size_loc;
parse_location(ctx, &dest_loc, builtin->func.memcpy.dest);
parse_location(ctx, &src_loc, builtin->func.memcpy.src);
scc_ir_value_t *const_value = scc_ir_module_get_value(
GET_MODULE(ctx), builtin->func.memcpy.size);
Assert(const_value->tag == SCC_IR_VALUE_TAG_CONST_INT);
size_loc.kind = SCC_REG_KIND_IMM;
size_loc.data.data = const_value->data.const_int.int64;
// 2. 将 dest 地址加载到 RDIrep movsb 目标)
load_value_to_reg(ctx, &dest_loc, SCC_AMD64_RDI);
// 3. 将 src 地址加载到 RSI
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RSI);
// 4. 将长度加载到 RCX
load_value_to_reg(ctx, &size_loc, SCC_AMD64_RCX);
// 5. 如果长度可能为 0可以跳过但 rep movsb 处理 0
// 也没问题,只是多一次指令。 生成 rep movsb 指令(字节复制)
// 需要使用 REX.W 前缀保证 64 位操作,但 rep movsb 本身不需要 REX.W
// 为了复制字节,使用 rep movsb (0xF3 0xA4)
scc_mcode_add_u8(&ctx->sect_mcode, 0xF3); // rep prefix
scc_mcode_add_u8(&ctx->sect_mcode, 0xA4); // movsb
break;
}
default:
Panic("unsupported builtin");
}
break;
}
case SCC_IR_VALUE_TAG_CONV: ///< 类型转换
LOG_FATAL("Unsupported value type: %d", value->tag);
break;
///< 函数参数引用
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
///< ABI
break;
case SCC_IR_VALUE_TAG_BLOCK_ARG_REF: ///< 基本块参数引用
break;
case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack)
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss
break;
///< 加载数据
case SCC_IR_VALUE_TAG_LOAD: {
// value->data.load.target
scc_reg_loc_t from;
scc_reg_loc_t to;
parse_location(ctx, &from, value->data.load.target);
parse_location(ctx, &to, node_ref);
load_value_to_reg(ctx, &from, SCC_AMD64_RCX);
// 获取基类型宽度
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
GET_MODULE(ctx), value->data.load.target);
scc_ir_type_t *base_type = scc_ir_module_get_type(
GET_MODULE(ctx), ptr_type->data.pointer.base);
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
bool is_signed = scc_type_is_signed(base_type);
// 间接加载到 RAX
if (width == 1) {
if (is_signed)
scc_mcode_amd64_movsx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
else
scc_mcode_amd64_movzx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else if (width == 2) {
if (is_signed)
scc_mcode_amd64_movsx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
else
scc_mcode_amd64_movzx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else if (width == 4) {
if (is_signed)
scc_mcode_amd64_movsx_r64_m32(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
else
scc_mcode_amd64_mov_r32_m32(
&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX); // 32位加载自动清零高位
} else if (width == 8) { // 8
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else {
LOG_WARN("unsupported type width: %d", width);
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
}
// 存储结果
store_value_from_reg(ctx, &to, SCC_AMD64_RAX);
break;
}
///< 存储数据
case SCC_IR_VALUE_TAG_STORE: {
scc_reg_loc_t val_loc, addr_loc;
parse_location(ctx, &val_loc, value->data.store.value);
parse_location(ctx, &addr_loc, value->data.store.target);
// 将值加载到 RAX
load_value_to_reg(ctx, &val_loc, SCC_AMD64_RAX);
// 将目标地址加载到 RCX
load_value_to_reg(ctx, &addr_loc, SCC_AMD64_RCX);
// 获取目标指针的基类型宽度
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
GET_MODULE(ctx), value->data.store.target);
scc_ir_type_t *base_type = scc_ir_module_get_type(
GET_MODULE(ctx), ptr_type->data.pointer.base);
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
// 根据宽度生成存储指令
if (width == 1) {
scc_mcode_amd64_mov_m8_r8(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
} else if (width == 2) {
scc_mcode_amd64_mov_m16_r16(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
} else if (width == 4) {
scc_mcode_amd64_mov_m32_r32(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
} else { // width == 8
scc_mcode_amd64_mov_m64_r64(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
}
break;
}
///< 获取指针
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: {
scc_reg_loc_t loc_res;
parse_location(ctx, &loc_res, node_ref);
scc_ir_value_t *src_addr = scc_ir_module_get_value(
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
Assert(src_addr != nullptr);
if (value->data.get_elem_ptr.index == 0) {
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
// 全局变量RIP相对寻址
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode,
SCC_AMD64_RAX, 0);
usize sym_idx =
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder,
(sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
// 栈上变量:地址为 rbp - offset
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc,
value->data.get_elem_ptr.src_addr);
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
} else {
// 其他情况如链式getptr源地址值已经存储在某个位置直接加载到
// RAX
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc,
value->data.get_elem_ptr.src_addr);
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
}
} else {
// TODO
// parse_value(ctx, value->data.get_elem_ptr.index, patches);
scc_reg_loc_t src_loc;
scc_reg_loc_t idx_loc;
parse_location(ctx, &src_loc, value->data.get_elem_ptr.src_addr);
parse_location(ctx, &idx_loc, value->data.get_elem_ptr.index);
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX);
// 获取 src_addr 所指向的类型的元素大小
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
scc_ir_type_t *base_type = scc_ir_module_get_type(
GET_MODULE(ctx), ptr_type->data.pointer.base);
scc_ir_type_t ir_type = *base_type;
if (ir_type.tag == SCC_IR_TYPE_ARRAY) {
ir_type.tag = SCC_IR_TYPE_PTR;
}
int elem_size = scc_ir2mcode_type_width(GET_MODULE(ctx), &ir_type);
// 然后生成 LEA 时使用 scale = elem_size
scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX, SCC_AMD64_RDX,
elem_size, 0);
}
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
break;
}
///< 二元运算
case SCC_IR_VALUE_TAG_OP: {
scc_reg_loc_t loc_lhs;
parse_location(ctx, &loc_lhs, value->data.op.lhs);
scc_reg_loc_t loc_rhs;
parse_location(ctx, &loc_rhs, value->data.op.rhs);
scc_reg_loc_t loc_res;
parse_location(ctx, &loc_res, node_ref);
// 将左操作数加载到 RAX临时结果寄存器
load_value_to_reg(ctx, &loc_lhs, SCC_AMD64_RAX);
// 将右操作数加载到 RCX
load_value_to_reg(ctx, &loc_rhs, SCC_AMD64_RCX);
switch (value->data.op.op) {
case SCC_IR_OP_EMPTY:
Panic("unsupported empty op");
break;
case SCC_IR_OP_ADD:
scc_mcode_amd64_add_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_SUB:
scc_mcode_amd64_sub_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_MUL:
scc_mcode_amd64_mul_r64(&ctx->sect_mcode, SCC_AMD64_RCX);
break;
case SCC_IR_OP_DIV:
case SCC_IR_OP_MOD:
TODO();
break;
case SCC_IR_OP_AND:
scc_mcode_amd64_and_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_OR:
scc_mcode_amd64_or_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_XOR:
scc_mcode_amd64_xor_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_NOT:
scc_mcode_amd64_not_r64(&ctx->sect_mcode, SCC_AMD64_RAX);
break;
case SCC_IR_OP_SHL:
case SCC_IR_OP_SHR:
case SCC_IR_OP_SAR:
TODO();
break;
case SCC_IR_OP_NEQ:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_NE,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_EQ:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_E,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_GT:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_G,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_LT:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_L,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_GE:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_GE,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_LE:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_LE,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
default:
LOG_FATAL("unknown op: %d", value->data.op.op);
break;
}
// 将 RAX 中的结果存储到 res 位置
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
break;
}
///< 有条件分支
case SCC_IR_VALUE_TAG_BRANCH: {
scc_reg_loc_t loc;
parse_location(ctx, &loc, value->data.branch.cond);
// (void)loc;
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
scc_mcode_amd64_cmp_r64_imm32(&ctx->sect_mcode, SCC_AMD64_RAX, 0);
scc_mcode_amd64_jcc_rel32(&ctx->sect_mcode, SCC_AMD64_COND_NE, 0);
patch_t patch_true = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
.target_bb_ref =
(usize)value->data.branch.true_bblock};
scc_vec_push(*patches, patch_true);
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
patch_t patch_false = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
.target_bb_ref =
(usize)value->data.branch.false_bblock};
scc_vec_push(*patches, patch_false);
break;
}
///< 无条件跳转
case SCC_IR_VALUE_TAG_JUMP: {
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
usize pos = scc_vec_size(ctx->sect_mcode.mcode);
patch_t patch = {
.pos = pos, .target_bb_ref = (usize)value->data.jump.target_bblock};
scc_vec_push(*patches, patch);
break;
}
///< 调用函数
case SCC_IR_VALUE_TAG_CALL: {
scc_reg_loc_t loc;
usize nargs = scc_vec_size(value->data.call.args);
// 影子空间 32 字节 + 每个额外参数 8 字节(按 8 字节对齐)
usize stack_args_count = (nargs > 4) ? (nargs - 4) : 0;
usize stack_args_size = stack_args_count * 8;
usize total_stack_alloc = 32 + stack_args_size;
// 调整栈指针(保持 16 字节对齐)
if (total_stack_alloc > 0) {
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
}
// 处理寄存器参数(前 4 个)
for (usize i = 0; i < nargs && i < 4; i++) {
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
SCC_AMD64_R9};
load_value_to_reg(ctx, &loc, reg[i]);
}
// 处理栈参数(第 5 个及以后)
// 从右向左依次写入栈(即最后一个参数放在最高地址)
for (usize i = 4; i < nargs; i++) {
scc_reg_loc_t loc;
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
// 加载到临时寄存器(如 RAX
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
// 计算栈偏移:影子空间(32) + (i-4)*8
int offset = 32 + (i - 4) * 8;
scc_mcode_amd64_mov_m64_disp32_r64(&ctx->sect_mcode, SCC_AMD64_RSP,
offset, SCC_AMD64_RAX);
}
scc_ir_func_t *func =
scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
// FIXME hack func value
if (scc_vec_size(func->bblocks)) {
scc_mcode_amd64_call_rel32(&ctx->sect_mcode, 0);
} else {
scc_mcode_amd64_call_mem_rip_rel32(&ctx->sect_mcode, 0);
}
usize sym_idx = sccf_builder_get_symbol_idx(ctx->builder, func->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder, (sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
// 恢复栈指针
if (total_stack_alloc > 0) {
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
}
// 处理返回值
scc_ir_type_t *func_type =
scc_ir_module_get_type(GET_MODULE(ctx), func->type);
Assert(func_type);
scc_ir_type_t *ret_type = scc_ir_module_get_type(
GET_MODULE(ctx), func_type->data.function.ret_type);
if (ret_type && ret_type->tag != SCC_IR_TYPE_void) {
parse_location(ctx, &loc, node_ref);
store_value_from_reg(ctx, &loc, SCC_AMD64_RAX);
}
break;
}
///< 函数返回
case SCC_IR_VALUE_TAG_RET: {
if (value->data.ret.ret_val) {
scc_reg_loc_t loc;
parse_location(ctx, &loc, value->data.ret.ret_val);
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
}
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
scc_mcode_amd64_pop_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
scc_mcode_amd64_ret(&ctx->sect_mcode);
break;
}
default:
LOG_FATAL("unknown value type: %d", value->tag);
UNREACHABLE();
break;
}
}
static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock,
patch_vec_t *patches) {
// 打印基本块中的每条指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, i);
parse_value(ctx, node_ref, patches);
}
}
static u32 hash_func(const void *key) { return (u32)(usize)key; }
static int equal_func(const void *key1, const void *key2) {
return (usize)key1 - (usize)key2;
}
const scc_frame_alloc_ops_t *scc_frame_alloc_win64_ops(void);
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
// FIXME using other
ctx->noderef2regloc =
scc_reg_alloc_run(&ctx->reg_alloc, func, scc_frame_alloc_win64_ops());
ctx->stack_size = scc_reg_stack_size(&ctx->reg_alloc);
Assert(ctx->noderef2regloc);
usize bblock_cnt = scc_vec_size(func->bblocks);
usize *bblock_offsets = scc_calloc(bblock_cnt, sizeof(usize));
// 建立 bblock_ref -> id 的映射
scc_hashtable_t ref2id;
scc_hashtable_init(&ref2id, hash_func, equal_func);
for (usize i = 0; i < bblock_cnt; i++) {
scc_ir_bblock_ref_t ref = scc_vec_at(func->bblocks, i);
scc_hashtable_set(&ref2id, (void *)(usize)ref, (void *)i);
}
patch_vec_t patches;
scc_vec_init(patches);
scc_mcode_amd64_push_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RBP,
SCC_AMD64_RSP, ctx->stack_size);
scc_reg_loc_t loc;
scc_vec_foreach(func->params, i) {
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
parse_location(ctx, &loc, node_ref);
if (i < 4) {
// 前 4 个参数:从寄存器存入槽位
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
SCC_AMD64_R9};
store_value_from_reg(ctx, &loc, reg[i]);
} else {
// 额外参数:从栈中加载到槽位
// 偏移 = 16 (old rbp+retaddr) + 32 (shadow) + (i-4)*8
int offset = 16 + 32 + (i - 4) * 8;
// 临时将栈值加载到 RAX再存储到槽位
scc_mcode_amd64_mov_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RBP, offset);
store_value_from_reg(ctx, &loc, SCC_AMD64_RAX);
}
}
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_module_get_bblock(GET_MODULE(ctx), bblock_ref);
if (bblock == nullptr) {
LOG_FATAL("<invalid block>\n");
return;
}
bblock_offsets[i] = scc_vec_size(ctx->sect_mcode.mcode);
parse_bblock(ctx, bblock, &patches);
}
// 回填所有跳转偏移
u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode);
scc_vec_foreach(patches, idx) {
patch_t *p = &scc_vec_at(patches, idx);
usize target_id =
(usize)scc_hashtable_get(&ref2id, (void *)(usize)p->target_bb_ref);
usize target_off = bblock_offsets[target_id];
usize next_off = p->pos;
i32 rel = (i32)(target_off - next_off);
// FIXME 写入到指令的偏移字段(小端)
*(u32 *)(&buf[p->pos - 4]) = rel;
}
scc_free(bblock_offsets);
scc_vec_free(patches);
scc_hashtable_drop(&ref2id);
}
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_strategy_pure_stack,
GET_MODULE(ctx));
scc_vec_foreach(ctx->cprog->global_vals, i) {
scc_ir_value_t *galloc = scc_ir_module_get_value(
GET_MODULE(ctx), scc_vec_at(ctx->cprog->global_vals, i));
Assert(galloc->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC);
scc_ir_value_t *value = scc_ir_module_get_value(
GET_MODULE(ctx), galloc->data.global_alloc.value);
Assert(value != nullptr);
sccf_sym_t sym = (sccf_sym_t){
.sccf_sect_offset = scc_vec_size(ctx->sect_data),
.sccf_sect_type = SCCF_SECT_DATA,
.sccf_sym_bind =
galloc->name ? SCCF_SYM_BIND_GLOBAL : SCCF_SYM_BIND_LOCAL,
.sccf_sym_size =
4, // FIXME on windows using rel32, on linux using ?
.sccf_sym_type = SCCF_SYM_TYPE_DATA,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
scc_vec_foreach(value->data.const_array.fields, j) {
scc_vec_push(ctx->sect_data,
scc_vec_at(value->data.const_array.fields, j));
}
usize sym_idx =
sccf_builder_add_symbol(ctx->builder, galloc->name, &sym);
Assert(sym_idx != 0);
}
scc_vec_foreach(ctx->cprog->func_decls, i) {
scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i);
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t sym = {0};
if (scc_vec_size(func->bblocks)) {
sym = (sccf_sym_t){
.sccf_sect_offset = 0,
.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,
};
} else {
sym = (sccf_sym_t){
.sccf_sect_offset = 0,
.sccf_sect_type = SCCF_SECT_NONE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 0,
.sccf_sym_type = SCCF_SYM_TYPE_EXTERN,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
}
usize sym_idx = sccf_builder_add_symbol(ctx->builder, func->name, &sym);
Assert(sym_idx != 0);
}
scc_vec_foreach(ctx->cprog->func_defs, i) {
scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i);
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t *sym =
sccf_builder_get_symbol_unsafe(ctx->builder, func->name);
Assert(sym != nullptr);
sym->sccf_sect_offset = scc_vec_size(ctx->sect_mcode.mcode);
parse_function(ctx, func);
}
u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode);
scc_vec_foreach(ctx->builder->relocs, i) {
sccf_reloc_t *reloc = &scc_vec_at(ctx->builder->relocs, i);
if (reloc->sym_idx == 0) {
Panic("relocate to an invalid symbol");
}
sccf_sym_t *sym = &scc_vec_at(ctx->builder->symtab, reloc->sym_idx);
if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
Assert(reloc->reloc_type == SCCF_RELOC_TYPE_REL);
if (sym->sccf_sect_type == SCCF_SECT_CODE &&
sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
i64 target_off = sym->sccf_sect_offset;
i64 next_off = reloc->offset + reloc->addend;
i32 rel = (i32)(target_off - next_off);
// FIXME 写入到指令的偏移字段(小端)
*(i32 *)(&buf[reloc->offset]) = rel;
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
}
}
}
sccf_sect_data_t text_section;
scc_vec_unsafe_from_buffer(text_section,
scc_vec_unsafe_get_data(ctx->sect_mcode.mcode),
scc_vec_size(ctx->sect_mcode.mcode));
sccf_builder_add_text_section(ctx->builder, &text_section);
sccf_builder_add_data_section(ctx->builder, &ctx->sect_data);
}

View File

@@ -1,78 +0,0 @@
#include <reg_alloc.h>
#include <type_manager.h>
static u32 hash_func(const void *key) { return (usize)key; }
static 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 strategy,
scc_ir_module_t *ir_module) {
ctx->frame_alloc = nullptr;
ctx->ir_module = ir_module;
scc_hashtable_init(&ctx->node2loc, hash_func, equal_func);
scc_vec_init(ctx->loc_vec);
ctx->reg_alloc_func = strategy;
}
#define add_loc(ctx, loc, val_ref) \
do { \
scc_vec_push(ctx->loc_vec, loc); \
scc_hashtable_set(&ctx->node2loc, (void *)(usize)val_ref, \
(void *)(usize)(scc_vec_size(ctx->loc_vec))); \
} while (0)
void scc_reg_alloc_strategy_pure_stack(scc_reg_alloc_t *ctx,
scc_ir_func_t *func,
scc_frame_alloc_ops_t *frame_alloc) {
scc_reg_loc_t loc;
// 为参数分配槽位(参数通过寄存器传入,但需要保存到栈上)
scc_vec_foreach(func->params, i) {
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
loc.kind = SCC_REG_KIND_STACK_ADDR;
loc.data.slot_idx =
frame_alloc->alloc_spill_slot(frame_alloc, 8, 0); // 参数按8字节
add_loc(ctx, loc, node_ref);
}
// 遍历所有指令,为需要存储结果的节点分配槽位
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_module_get_bblock(ctx->ir_module, bblock_ref);
scc_vec_foreach(bblock->instrs, j) {
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, j);
scc_ir_value_t *node =
scc_ir_module_get_value(ctx->ir_module, node_ref);
if (node == nullptr)
continue;
switch (node->tag) {
case SCC_IR_VALUE_TAG_LOAD:
case SCC_IR_VALUE_TAG_OP:
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
case SCC_IR_VALUE_TAG_CALL: // 返回值
loc.kind = SCC_REG_KIND_STACK;
loc.data.slot_idx =
frame_alloc->alloc_spill_slot(frame_alloc, 8, 0);
add_loc(ctx, loc, node_ref);
break;
case SCC_IR_VALUE_TAG_ALLOC: {
scc_ir_type_t *type =
scc_ir_module_get_type(ctx->ir_module, node->type);
Assert(type->tag == SCC_IR_TYPE_PTR);
scc_ir_type_t *base_type = scc_ir_module_get_type(
ctx->ir_module, type->data.pointer.base);
int size = scc_ir2mcode_type_width(ctx->ir_module, base_type);
loc.kind = SCC_REG_KIND_STACK_ADDR;
loc.data.slot_idx = frame_alloc->alloc_local_slot(
frame_alloc, size, 0, node->name);
add_loc(ctx, loc, node_ref);
break;
}
default:
break;
}
}
}
}

View File

@@ -1,19 +0,0 @@
#include <scc_ir2mcode.h>
void scc_ir2mcode_init(scc_ir2mcode_ctx_t *ctx, scc_ir_cprog_t *cprog,
sccf_builder_t *builder, scc_mcode_arch_t arch) {
ctx->cprog = cprog;
ctx->builder = builder;
scc_mcode_init(&ctx->sect_mcode, arch);
scc_vec_init(ctx->sect_data);
sccf_builder_init(ctx->builder);
}
void scc_ir2mcode_drop(scc_ir2mcode_ctx_t *ctx) {
// TODO drop all objs
scc_ir_cprog_drop(ctx->cprog);
}
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx);
void scc_ir2mcode(scc_ir2mcode_ctx_t *ctx) { scc_ir2amd64(ctx); }

View File

@@ -1,23 +0,0 @@
#include <type_manager.h>
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type) {
/* clang-format off */
if (ctx == nullptr || type == nullptr) {
Panic("Invalid argument");
return 0;
}
switch (type->tag) {
case SCC_IR_TYPE_i8: case SCC_IR_TYPE_u8: return 1;
case SCC_IR_TYPE_i16: case SCC_IR_TYPE_u16: return 2;
case SCC_IR_TYPE_i32: case SCC_IR_TYPE_u32: return 4;
case SCC_IR_TYPE_i64: case SCC_IR_TYPE_u64: return 8;
case SCC_IR_TYPE_PTR: return 8;
case SCC_IR_TYPE_ARRAY:
return scc_ir2mcode_type_width(
ctx,
scc_ir_module_get_type(ctx, type->data.array.base)
) * type->data.array.len;
default: return 8; // 默认64位
}
/* clang-format on */
}

View File

@@ -1,110 +0,0 @@
#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, const char *name) {
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, nullptr);
}
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_ir_cprog_t cprog;
scc_ir_cprog_init(&cprog);
scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi, &cprog);
scc_ast2ir_translation_unit(&ast2ir_ctx, tu);
scc_ast2ir_ctx_drop(&ast2ir_ctx);
scc_ir2mcode_ctx_t ir2mcode_ctx;
sccf_builder_t sccf_builder;
scc_ir2mcode_init(&ir2mcode_ctx, &cprog, &sccf_builder,
SCC_MCODE_ARCH_AMD64);
scc_ir2mcode(&ir2mcode_ctx);
scc_ir2mcode_drop(&ir2mcode_ctx);
const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
scc_pe_builder_t pe_builder;
sccf2pe(&pe_builder, sccf);
char fname[1024] = {0};
scc_snprintf(fname, sizeof(fname), "%s%s%s", __FILE__, "/../../", name);
scc_pe_dump_to_file(&pe_builder, fname);
}
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, "02_decl_expr.exe");
test_example("int main(void) {\n"
" int a;\n"
" a = 1;\n"
" if (a) {\n"
" a = 1;\n"
" } else {\n"
" a = 2;\n"
" }\n"
" return a;\n"
"}\n",
true, "04_if.exe");
test_example("int main() {\n"
" int i = 0;\n"
" while (i < 10) i = i + 1;\n"
" return i;\n"
"}\n",
true, "07_while.exe");
test_example("int add(int a, int b) {\n"
" return a + b;\n"
"}\n"
"\n"
"int main(void) {\n"
" return add(1, 2);\n"
"}\n",
true, "10_main.exe");
test_example("int factorial(int);\n"
"\n"
"int main() {\n"
" int num = 5;\n"
" int result = factorial(num);\n"
" // printf(\"%d\", result);\n"
" return result;\n"
"}\n"
"\n"
"int factorial(int num) {\n"
" if (num == 0) {\n"
" return 1;\n"
" } else {\n"
" return num * factorial(num - 1);\n"
" }\n"
"}\n",
true, "11_recursion.exe");
return 0;
}