Compare commits

..

4 Commits

Author SHA1 Message Date
zzy
aa4292a30e feat(mir): 添加函数调用和返回指令支持
添加了间接调用函数emit_indirect_call用于处理寄存器调用,
修改直接调用函数emit_direct_call使用相对分支形式,
为函数元数据添加need_va_args字段标记变参函数需求。

refactor(prolog-epilog): 重构函数序言和尾声处理逻辑

将prolog/epilog回调函数参数从void*改为scc_mir_instr_vec_t*,
添加need_epilog回调函数用于判断是否需要插入尾声代码,
修改pass处理逻辑以支持动态插入序言和尾声代码。

feat(win64-abi): 实现Windows x64平台序言尾声生成功能

实现prologue函数生成栈帧设置和变参处理代码,
实现epilogue函数生成栈清理和返回指令,
添加need_epilog判断函数识别返回指令类型并触发尾声插入。
2026-05-20 21:11:48 +08:00
zzy
c6e3bb2e20 feat(mir): 添加x86架构相关头文件并重构MIR指令表示
- 创建scc_x86_mir.h头文件,定义x86后端MIR指令结构和操作数构造器
- 创建scc_x86_isel.h头文件,定义x86_64指令选择器和相关工具函数
- 创建scc_x86_reg_alloc.h头文件,定义x86寄存器分配架构特定接口
- 移除旧的x86_64_isel.h和x86_64_reg_alloc.h文件
- 重构scc_mir.h中的指令表示,使用联合体存储伪指令数据
- 更新ABI lowering回调参数,使用void指针保持类型无关
- 扩展寄存器分配操作接口,添加指令信息查询和伪指令处理功能
- 更新目标文件包含路径以使用新的头文件命名
2026-05-20 11:07:05 +08:00
zzy
2c13ac54df feat(ast2ir): 添加浮点类型支持和复合初始化功能
- 在ABI类型计算中添加FLOAT和DOUBLE类型的映射
- 修复AST操作符注释中的歧义描述
- 为ast2ir上下文添加类型缓存以解决递归结构体定义问题
- 实现复合初始化表达式的支持,包括数组和结构体初始化
- 添加前置和后置自增/自减操作符的IR转换
- 实现三元条件表达式的IR生成
- 添加类型转换(cast)和sizeof操作符的支持
- 重构数组长度推断逻辑并添加类型大小计算函数
- 实现结构体和联合体的递归类型解析
- 添加函数指针调用相关的IR节点类型定义

fix(ast): 修正间接操作符的注释说明

refactor(ast2ir): 优化代码结构并添加必要的断言验证
2026-05-19 17:35:24 +08:00
zzy
3df858fb85 feat(mir): 添加栈偏移操作数类型并重构内存访问表示
- 将 MIR 中的 SCC_MIR_OP_MEM 替换为更精确的 SCC_MIR_OP_STACK_SLOT 和
  SCC_MIR_OP_STACK_OFFSET 类型
- 在 x86_64 指令选择中更新相应的内存操作数处理逻辑
- 修改寄存器分配器中的栈槽操作数类型检查
- 更新 IR 转机器码过程中的内存操作数转换

refactor(hir): 使用 tree_dump_node 输出函数节点

- 将 hir_dump 中的函数名输出从 append 改为 node 类型

refactor(frame-layout): 重构栈帧布局传递实现结构

- 引入函数指针实现方式替代直接函数实现
- 将栈帧分配功能集成到 MIR 传递流程中
- 移除独立的 frame_layout 实现文件

refactor(prolog-epilog): 添加函数序言/尾声传递框架

- 为 Windows x64 平台初始化序言/尾声生成器
- 在 MIR 传递阶段添加序言/尾声处理步骤

refactor(win64): 更新 Windows x64 目标平台接口

- 重命名寄存器分配填充函数为 scc_win_pc_x64_reg_alloc_fill
- 添加栈帧分配和序言/尾声初始化函数
- 修正参数传递中的栈槽操作数类型

refactor(dump): 改进 MIR 输出格式

- 将基本块显示改为分支节点类型
- 更新操作数类型的显示处理

chore: 添加 x86 编码相关数据结构定义

- 新增 scc_x86_encode.h 头文件包含内存操作数和指令编码接口定义
2026-05-13 18:47:44 +08:00
51 changed files with 2255 additions and 1010 deletions

View File

@@ -61,6 +61,12 @@ void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type,
case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG: case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG:
kind = SCC_ABI_TYPE_U_LONG_LONG; kind = SCC_ABI_TYPE_U_LONG_LONG;
break; break;
case SCC_AST_BUILTIN_TYPE_FLOAT:
kind = SCC_ABI_TYPE_FLOAT;
break;
case SCC_AST_BUILTIN_TYPE_DOUBLE:
kind = SCC_ABI_TYPE_DOUBLE;
break;
default: default:
Panic("Unsupported AST type: %d", Panic("Unsupported AST type: %d",
scc_ast_canon_type(ast_type)->builtin.type); scc_ast_canon_type(ast_type)->builtin.type);

View File

@@ -262,7 +262,7 @@ typedef enum scc_ast_expr_op {
SCC_AST_OP_UNARY_PLUS, // + (一元) SCC_AST_OP_UNARY_PLUS, // + (一元)
SCC_AST_OP_UNARY_MINUS, // - (一元) SCC_AST_OP_UNARY_MINUS, // - (一元)
SCC_AST_OP_ADDRESS_OF, // & SCC_AST_OP_ADDRESS_OF, // &
SCC_AST_OP_INDIRECTION, // * SCC_AST_OP_INDIRECTION, // * (取地址)
SCC_AST_OP_BITWISE_NOT, // ~ SCC_AST_OP_BITWISE_NOT, // ~
SCC_AST_OP_LOGICAL_NOT, // ! SCC_AST_OP_LOGICAL_NOT, // !
SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀) SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀)

View File

@@ -11,6 +11,7 @@ typedef struct {
scc_hashtable_t break_cache; ///< break cache scc_hashtable_t break_cache; ///< break cache
scc_hashtable_t continue_cache; ///< continue cache scc_hashtable_t continue_cache; ///< continue cache
scc_hashtable_t symtab; ///< symbol to ir_ref scc_hashtable_t symtab; ///< symbol to ir_ref
scc_hashtable_t type_cache; ///< scc_ast_canon_type_t* -> scc_hir_type_ref_t
// scc_strpool_t strpool; ///< string pool // scc_strpool_t strpool; ///< string pool
const scc_abi_type_calc_t *abi; const scc_abi_type_calc_t *abi;
cbool hint_using_value; // 转换时尽可能使用value而不是alloc cbool hint_using_value; // 转换时尽可能使用value而不是alloc

View File

@@ -27,39 +27,24 @@ static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx,
return SCC_HIR_REF_nullptr; return SCC_HIR_REF_nullptr;
} }
// static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {} static inline bool scc_hir_type_is_signed(scc_hir_type_tag_t tag) {
switch (tag) {
// 辅助函数计算数组实际长度如果原长度为0 case SCC_HIR_TYPE_i8:
static void resolve_array_length(scc_ast2ir_ctx_t *ctx, case SCC_HIR_TYPE_i16:
const scc_hir_type_t *orig_array_type, case SCC_HIR_TYPE_i32:
scc_hir_type_t *resolved_array_type, case SCC_HIR_TYPE_i64:
const scc_ast_expr_t *init_expr) { case SCC_HIR_TYPE_i128:
*resolved_array_type = *orig_array_type; // 拷贝 return true;
Assert(orig_array_type->tag == SCC_HIR_TYPE_ARRAY); case SCC_HIR_TYPE_u8:
if (orig_array_type->data.array.len != 0) case SCC_HIR_TYPE_u16:
return; // 长度已知,无需推断 case SCC_HIR_TYPE_u32:
case SCC_HIR_TYPE_u64:
usize new_len = 0; case SCC_HIR_TYPE_u128:
switch (init_expr->base.type) { return false;
case SCC_AST_EXPR_STRING_LITERAL:
// 字符串字面量:长度 = 字符串字符数 + 1'\0'
// TODO: L"" \n \r 计算 暂不支持
new_len = scc_strlen(init_expr->literal.lexme) + 1;
break;
case SCC_AST_EXPR_COMPOUND: {
// 复合初始化:元素个数 = 初始化列表长度
scc_vec_foreach(init_expr->compound.lhs_exprs, i) {
scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i);
// TODO: 支持嵌套的多维数组初始化(递归)
// 这里简化:只统计顶层元素个数,假设是一维数组
new_len++;
}
break;
}
default: default:
Panic("unsupported initializer for zero-length array"); // 指针可以视作无符号整数
return false;
} }
resolved_array_type->data.array.len = new_len;
} }
// 辅助函数:生成数组初始化代码 // 辅助函数:生成数组初始化代码
@@ -123,6 +108,142 @@ static void emit_array_initialization(scc_ast2ir_ctx_t *ctx,
// 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理 // 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理
} }
static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx,
scc_hir_value_ref_t base_ptr,
const scc_hir_type_t *type,
const scc_ast_expr_t *init_expr) {
Assert(type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION);
if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) {
Panic("expected compound initializer");
}
usize idx = 0;
scc_vec_foreach(init_expr->compound.rhs_exprs, i) {
if (idx >= type->data.aggregate.fields.size)
break;
scc_ast_expr_t *field_init =
scc_vec_at(init_expr->compound.rhs_exprs, i);
scc_hir_type_ref_t field_type_ref =
scc_vec_at(type->data.aggregate.fields, idx);
const scc_hir_type_t *field_type = scc_hir_module_get_type(
&ctx->builder.cprog->module, field_type_ref);
scc_ap_t idx_ap;
scc_ap_set_int(&idx_ap, idx);
scc_hir_value_ref_t idx_val = scc_hir_builder_integer(
&ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap);
scc_hir_value_ref_t field_ptr =
scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val);
if (field_type->tag == SCC_HIR_TYPE_ARRAY) {
emit_array_initialization(ctx, field_ptr, field_type, field_init);
} else if (field_type->tag == SCC_HIR_TYPE_STRUCT ||
field_type->tag == SCC_HIR_TYPE_UNION) {
emit_aggregate_initialization(ctx, field_ptr, field_type,
field_init);
} else {
scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, field_init, false);
scc_hir_builder_store(&ctx->builder, field_ptr, val);
}
idx++;
}
}
// static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {}
usize scc_hir_type_size(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *type) {
switch (type->tag) {
case SCC_HIR_TYPE_void:
return 0;
case SCC_HIR_TYPE_i8:
return 1;
case SCC_HIR_TYPE_i16:
return 2;
case SCC_HIR_TYPE_i32:
return 4;
case SCC_HIR_TYPE_i64:
return 8;
case SCC_HIR_TYPE_i128:
return 16;
case SCC_HIR_TYPE_u8:
return 1;
case SCC_HIR_TYPE_u16:
return 2;
case SCC_HIR_TYPE_u32:
return 4;
case SCC_HIR_TYPE_u64:
return 8;
case SCC_HIR_TYPE_u128:
return 16;
case SCC_HIR_TYPE_f16:
return 2;
case SCC_HIR_TYPE_f32:
return 4;
case SCC_HIR_TYPE_f64:
return 8;
case SCC_HIR_TYPE_f128:
return 16;
case SCC_HIR_TYPE_PTR: {
// 目标指针大小,可以定义为 864位或从 ABI 获取
// 假设你的目标架构是 64 位
return 8;
}
case SCC_HIR_TYPE_ARRAY: {
usize elem_size = scc_hir_type_size(
ctx, scc_hir_module_get_type(&ctx->builder.cprog->module,
type->data.array.base));
return elem_size * type->data.array.len;
}
case SCC_HIR_TYPE_FUNC:
// 函数类型大小一般是指针大小
return 8;
case SCC_HIR_TYPE_STRUCT:
case SCC_HIR_TYPE_UNION:
// 暂时无法计算,保守返回 0 或报错
LOG_ERROR("Cannot compute size of struct/union without layout info");
return 0;
default:
LOG_ERROR("Unknown type tag %d", type->tag);
return 0;
}
}
// 辅助函数计算数组实际长度如果原长度为0
static void resolve_array_length(scc_ast2ir_ctx_t *ctx,
const scc_hir_type_t *orig_array_type,
scc_hir_type_t *resolved_array_type,
const scc_ast_expr_t *init_expr) {
*resolved_array_type = *orig_array_type; // 拷贝
Assert(orig_array_type->tag == SCC_HIR_TYPE_ARRAY);
if (orig_array_type->data.array.len != 0)
return; // 长度已知,无需推断
usize new_len = 0;
switch (init_expr->base.type) {
case SCC_AST_EXPR_STRING_LITERAL:
// 字符串字面量:长度 = 字符串字符数 + 1'\0'
// TODO: L"" \n \r 计算 暂不支持
new_len = scc_strlen(init_expr->literal.lexme) + 1;
break;
case SCC_AST_EXPR_COMPOUND: {
// 复合初始化:元素个数 = 初始化列表长度
scc_vec_foreach(init_expr->compound.lhs_exprs, i) {
scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i);
// TODO: 支持嵌套的多维数组初始化(递归)
// 这里简化:只统计顶层元素个数,假设是一维数组
new_len++;
}
break;
}
default:
Panic("unsupported initializer for zero-length array");
}
resolved_array_type->data.array.len = new_len;
}
scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
const scc_ast_qual_type_t *ast_type) { const scc_ast_qual_type_t *ast_type) {
if (ctx == nullptr || ast_type == nullptr) { if (ctx == nullptr || ast_type == nullptr) {
@@ -189,22 +310,64 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
} break; } break;
case SCC_AST_TYPE_STRUCT: case SCC_AST_TYPE_STRUCT:
case SCC_AST_TYPE_UNION: { case SCC_AST_TYPE_UNION: {
scc_hir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT const scc_ast_canon_type_t *canon = scc_ast_canon_type(ast_type);
// === 1. 查缓存,如果已存在则直接返回(递归时一定会命中) ===
scc_hir_type_ref_t cached =
(scc_hir_type_ref_t)(usize)scc_hashtable_get(&ctx->type_cache,
canon);
if (cached != 0) {
return cached;
}
// === 2. 创建占位类型(字段为空) ===
scc_hir_type_t placeholder;
scc_hir_type_init(&placeholder,
ast_type->base.type == SCC_AST_TYPE_STRUCT
? SCC_HIR_TYPE_STRUCT ? SCC_HIR_TYPE_STRUCT
: SCC_HIR_TYPE_UNION); : SCC_HIR_TYPE_UNION);
if (scc_ast_canon_type(ast_type)->record.decl == nullptr) { // 可以给占位符一个调试名
Panic("%s record fields is nullptr", if (canon->record.name) {
scc_ast_canon_type(ast_type)->record.name); placeholder.name = canon->record.name;
} }
scc_vec_foreach(
scc_ast_canon_type(ast_type)->record.decl->record.fields, i) { // === 3. 直接添加到模块,不经过 builder 的 uniquing ===
scc_ast_decl_t *decl_field = scc_vec_at( // 因为此时我们不需要类型去重,只需要一个确定不移的引用
scc_ast_canon_type(ast_type)->record.decl->record.fields, i); scc_hir_type_ref_t place_ref =
Assert(decl_field->base.type == SCC_AST_DECL_VAR); scc_hir_module_add_type(&ctx->builder.cprog->module, &placeholder);
scc_hir_type_ref_t field_type =
scc_ast2ir_type(ctx, decl_field->var.type); // === 4. 将映射写入缓存(关键!必须在递归前) ===
scc_vec_push(ir_type.data.aggregate.fields, field_type); scc_hashtable_set(&ctx->type_cache, canon, (void *)(usize)place_ref);
// === 5. 递归解析所有字段 ===
// 此时若字段类型指回本结构体,将直接通过缓存返回 place_ref
scc_hir_type_ref_vec_t fields;
scc_vec_init(fields);
scc_ast_decl_t *decl = canon->record.decl;
if (decl == nullptr) {
Panic("struct/union declaration is missing");
} }
scc_vec_foreach(decl->record.fields, i) {
scc_ast_decl_t *field_decl = scc_vec_at(decl->record.fields, i);
Assert(field_decl->base.type == SCC_AST_DECL_VAR);
scc_hir_type_ref_t field_ir_type =
scc_ast2ir_type(ctx, field_decl->var.type);
scc_vec_push(fields, field_ir_type);
}
// === 6. 将字段填入占位类型 ===
scc_hir_type_t *place_type =
scc_hir_module_get_type(&ctx->builder.cprog->module, place_ref);
// 注意scc_hir_type_init 已经为 struct/union 初始化了 fields 空向量
// 这里直接 push 即可(也可以先 scc_vec_free 再 init看需要
scc_vec_foreach(fields, i) {
scc_vec_push(place_type->data.aggregate.fields,
scc_vec_at(fields, i));
}
scc_vec_free(fields); // 释放临时向量
// === 7. 返回占位符的引用(现在已经变成完整类型) ===
return place_ref;
} break; } break;
case SCC_AST_TYPE_ENUM: case SCC_AST_TYPE_ENUM:
scc_ast_canon_type_t *int_canon_type = scc_ast_ctx_get_builtin_type( scc_ast_canon_type_t *int_canon_type = scc_ast_ctx_get_builtin_type(
@@ -337,7 +500,8 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
switch (expr->base.type) { switch (expr->base.type) {
case SCC_AST_EXPR_BINARY: { case SCC_AST_EXPR_BINARY: {
scc_ast_expr_t tmp_expr; scc_ast_expr_t tmp_expr;
scc_hir_value_ref_t lhs, rhs; scc_hir_value_ref_t lhs = SCC_HIR_REF_nullptr,
rhs = SCC_HIR_REF_nullptr;
switch (expr->binary.op) { switch (expr->binary.op) {
case SCC_AST_OP_ASSIGN: // = case SCC_AST_OP_ASSIGN: // =
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
@@ -407,6 +571,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
break; break;
} }
if (is_assign) { if (is_assign) {
Assert(rhs != SCC_HIR_REF_nullptr);
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true); lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true);
return scc_hir_builder_store(&ctx->builder, lhs, rhs); return scc_hir_builder_store(&ctx->builder, lhs, rhs);
} }
@@ -452,7 +617,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
} }
// 创建操作节点 // 创建操作节点
return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs); return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs);
} } break;
case SCC_AST_EXPR_UNARY: { case SCC_AST_EXPR_UNARY: {
if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) { if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) {
return scc_ast2ir_expr(ctx, expr->unary.operand, true); return scc_ast2ir_expr(ctx, expr->unary.operand, true);
@@ -470,17 +635,6 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
} }
scc_hir_value_ref_t operand = scc_hir_value_ref_t operand =
scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue); scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue);
// /* 一元操作符 */
// SCC_AST_OP_UNARY_PLUS, // + (一元)
// SCC_AST_OP_UNARY_MINUS, // - (一元)
// SCC_AST_OP_ADDRESS_OF, // &
// SCC_AST_OP_INDIRECTION, // *
// SCC_AST_OP_BITWISE_NOT, // ~
// SCC_AST_OP_LOGICAL_NOT, // !
// SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀)
// SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀)
// SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀)
// SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀)
switch (expr->unary.op) { switch (expr->unary.op) {
case SCC_AST_OP_UNARY_PLUS: case SCC_AST_OP_UNARY_PLUS:
/* just pass */ /* just pass */
@@ -517,17 +671,138 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_EQ, zero_ref, return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_EQ, zero_ref,
operand); operand);
} }
case SCC_AST_OP_PREFIX_INCREMENT:
case SCC_AST_OP_PREFIX_DECREMENT: {
// 获取左值地址
scc_hir_value_ref_t addr =
scc_ast2ir_expr(ctx, expr->unary.operand, true);
scc_hir_value_ref_t old_val =
scc_hir_builder_load(&ctx->builder, addr);
scc_hir_type_ref_t old_type =
scc_hir_module_get_value(
scc_hir_builder_get_module(&ctx->builder), old_val)
->type;
scc_hir_type_ref_t promoted_type = old_type;
// scc_ast2ir_promoted_type(ctx, old_type);
scc_hir_value_ref_t promoted = old_val;
// scc_ast2ir_apply_promotion(ctx, old_val);
scc_hir_value_ref_t one = scc_hir_builder_integer(
&ctx->builder, scc_hir_builder_type_i32(&ctx->builder),
&(scc_ap_t){.data.digit = 1, .capacity = -1});
scc_hir_op_type_t op =
(expr->unary.op == SCC_AST_OP_PREFIX_INCREMENT)
? SCC_HIR_OP_ADD
: SCC_HIR_OP_SUB;
scc_hir_value_ref_t new_val =
scc_hir_builder_binop(&ctx->builder, op, promoted, one);
// 如果原类型不是提升后的类型,需要截断回原类型再存储
scc_hir_value_ref_t stored_val = new_val;
// if (old_type != promoted_type) {
// stored_val = scc_hir_builder_conv(&ctx->builder, new_val,
// old_type, CONV_TRUNC);
// }
scc_hir_builder_store(&ctx->builder, addr, stored_val);
Assert(new_val != SCC_HIR_REF_nullptr);
return new_val; // 表达式的值是提升后的新值(符合 C 标准)
} break;
case SCC_AST_OP_POSTFIX_INCREMENT:
case SCC_AST_OP_POSTFIX_DECREMENT: {
// 获取左值地址
scc_hir_value_ref_t addr =
scc_ast2ir_expr(ctx, expr->unary.operand, true);
scc_hir_value_ref_t old_val =
scc_hir_builder_load(&ctx->builder, addr);
scc_hir_type_ref_t old_type =
scc_hir_module_get_value(
scc_hir_builder_get_module(&ctx->builder), old_val)
->type;
scc_hir_type_ref_t promoted_type = old_type;
// scc_ast2ir_promoted_type(ctx, old_type);
scc_hir_value_ref_t promoted = old_val;
// scc_ast2ir_apply_promotion(ctx, old_val);
scc_hir_value_ref_t one = scc_hir_builder_integer(
&ctx->builder, scc_hir_builder_type_i32(&ctx->builder),
&(scc_ap_t){.data.digit = 1, .capacity = -1});
scc_hir_op_type_t op =
(expr->unary.op == SCC_AST_OP_POSTFIX_INCREMENT)
? SCC_HIR_OP_ADD
: SCC_HIR_OP_SUB;
scc_hir_value_ref_t new_val =
scc_hir_builder_binop(&ctx->builder, op, promoted, one);
scc_hir_value_ref_t stored_val = new_val;
// if (old_type != promoted_type)
// stored_val = trunc;
scc_hir_builder_store(&ctx->builder, addr, stored_val);
// 后缀返回旧的、未提升的值(但 C
// 要求返回提升后的旧值?实际是旧值按右值规则,应得到提升后的值)
// 标准规定后缀++的结果是操作数原来的值,但会经过整数提升。
// 所以需要返回 promoted已提升的旧值
Assert(promoted != SCC_HIR_REF_nullptr);
return promoted; // 旧值,但类型已提升为
// int 等
} break;
default: default:
LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); LOG_FATAL("Unsupported unary operator: %d", expr->unary.op);
return 0; return 0;
} }
UNREACHABLE(); UNREACHABLE();
break; } break;
}
case SCC_AST_EXPR_COND: { case SCC_AST_EXPR_COND: {
TODO(); scc_hir_type_ref_t true_type = SCC_HIR_REF_nullptr;
break; scc_hir_type_ref_t false_type = SCC_HIR_REF_nullptr;
scc_hir_value_ref_t true_block =
scc_hir_builder_bblock(&ctx->builder, "cond_true");
scc_hir_value_ref_t false_block =
scc_hir_builder_bblock(&ctx->builder, "cond_false");
scc_hir_value_ref_t merge_block =
scc_hir_builder_bblock(&ctx->builder, "cond_merge");
scc_hir_value_ref_t cond_node =
scc_ast2ir_expr(ctx, expr->cond.cond, false);
scc_hir_builder_branch(&ctx->builder, cond_node, true_block,
false_block);
// 生成true分支
scc_hir_builder_set_current_bblock(&ctx->builder, true_block);
scc_hir_value_ref_t true_val =
scc_ast2ir_expr(ctx, expr->cond.then_expr, false);
true_type = scc_hir_module_get_value(
scc_hir_builder_get_module(&ctx->builder), true_val)
->type;
Assert(true_type != SCC_HIR_REF_nullptr);
scc_hir_value_ref_t result_slot =
scc_hir_builder_alloca(&ctx->builder, true_type, "cond_result");
scc_hir_builder_store(&ctx->builder, result_slot, true_val);
scc_hir_builder_jump(&ctx->builder, merge_block);
// 生成false分支
scc_hir_builder_set_current_bblock(&ctx->builder, false_block);
scc_hir_value_ref_t false_val =
scc_ast2ir_expr(ctx, expr->cond.else_expr, false);
false_type = scc_hir_module_get_value(
scc_hir_builder_get_module(&ctx->builder), false_val)
->type;
Assert(false_type != SCC_HIR_REF_nullptr);
scc_hir_builder_store(&ctx->builder, result_slot, false_val);
scc_hir_builder_jump(&ctx->builder, merge_block);
// 合并并返回
scc_hir_builder_set_current_bblock(&ctx->builder, merge_block);
if (true_type != false_type) {
LOG_ERROR("Type mismatch in conditional expression");
// FIXME need panic
} }
return scc_hir_builder_load(&ctx->builder, result_slot);
} break;
case SCC_AST_EXPR_CALL: { case SCC_AST_EXPR_CALL: {
// 转换参数 // 转换参数
scc_hir_value_ref_vec_t args; scc_hir_value_ref_vec_t args;
@@ -610,12 +885,79 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
return scc_hir_builder_load(&ctx->builder, field_ptr); return scc_hir_builder_load(&ctx->builder, field_ptr);
} }
case SCC_AST_EXPR_CAST: { case SCC_AST_EXPR_CAST: {
TODO(); // 1. 转换操作数(右值)
} break; scc_hir_value_ref_t operand =
scc_ast2ir_expr(ctx, expr->cast.expr, false);
// 2. 转换目标类型为 IR 类型
scc_hir_type_ref_t target_type = scc_ast2ir_type(ctx, expr->cast.type);
// 3. 确定转换模式SEXT / ZEXT / TRUNC
// 这里用简单的启发式:根据大小变化决定
scc_hir_type_t *src_type = scc_hir_module_get_type_by_value(
&ctx->builder.cprog->module, operand);
scc_hir_type_t *dst_type =
scc_hir_module_get_type(&ctx->builder.cprog->module, target_type);
usize src_size =
scc_hir_type_size(ctx, src_type); // 你可能有这个函数,否则自行计算
usize dst_size = scc_hir_type_size(ctx, dst_type);
int conv_kind;
if (dst_size > src_size) {
// 目标更大,需要扩展。根据源类型有无符号决定符号扩展还是零扩展
conv_kind =
scc_hir_type_is_signed(src_type->tag) ? CONV_SEXT : CONV_ZEXT;
} else if (dst_size < src_size) {
conv_kind = CONV_TRUNC;
} else {
// 同大小,可以视为 NOP 转换,或者直接返回操作数
return operand; // 或创建一个 CONV_SEXT 也没问题
}
// 4. 构造转换节点
scc_hir_value_t conv_node = {
.tag = SCC_HIR_VALUE_TAG_CONV,
.type = target_type,
.data.conv.operand = operand,
.data.conv.target_type = target_type,
.data.conv.conv_type = conv_kind,
};
return scc_hir_module_add_value(&ctx->builder.cprog->module,
&conv_node);
}
case SCC_AST_EXPR_SIZE_OF: { case SCC_AST_EXPR_SIZE_OF: {
TODO(); // 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型
// return scc_hir_builder_integer( scc_hir_type_ref_t hir_type;
// &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); if (expr->attr_of.type) {
// sizeof(type)
hir_type = scc_ast2ir_type(ctx, expr->attr_of.type);
} else if (expr->attr_of.expr) {
// sizeof expression计算表达式类型
// 注意sizeof
// 不对表达式求值,只需类型,这里假设语义分析已经标注了类型
scc_hir_value_ref_t dummy =
scc_ast2ir_expr(ctx, expr->attr_of.expr, false);
hir_type =
scc_hir_module_get_value(&ctx->builder.cprog->module, dummy)
->type;
} else {
scc_ap_t val;
val.data.digit = 0;
LOG_ERROR("[ast2ir] unsupported");
return scc_hir_builder_integer(
&ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val);
}
// 2. 计算大小
const scc_hir_type_t *type =
scc_hir_module_get_type(&ctx->builder.cprog->module, hir_type);
usize dst_size = scc_hir_type_size(ctx, type);
scc_ap_t val;
val.data.digit = dst_size;
return scc_hir_builder_integer(
&ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val);
} }
case SCC_AST_EXPR_ALIGN_OF: { case SCC_AST_EXPR_ALIGN_OF: {
TODO(); TODO();
@@ -623,10 +965,50 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
// &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val);
} }
case SCC_AST_EXPR_COMPOUND: { case SCC_AST_EXPR_COMPOUND: {
TODO(); // 1. 从 base 子节点取得类型base 一定是 SCC_AST_EXPR_LVALUE
Assert(expr->compound.base != nullptr);
Assert(expr->compound.base->base.type == SCC_AST_EXPR_LVALUE);
scc_ast_qual_type_t *ast_type = expr->compound.base->lvalue.type;
scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, ast_type);
const scc_hir_type_t *type =
scc_hir_module_get_type(&ctx->builder.cprog->module, type_ref);
// 2. 分配栈上临时存储
scc_hir_value_ref_t storage =
scc_hir_builder_alloca(&ctx->builder, type_ref, "compound_literal");
// 3. 根据类型调用对应的初始化函数
if (type->tag == SCC_HIR_TYPE_ARRAY) {
emit_array_initialization(ctx, storage, type, expr);
} else if (type->tag == SCC_HIR_TYPE_STRUCT ||
type->tag == SCC_HIR_TYPE_UNION) {
emit_aggregate_initialization(ctx, storage, type, expr);
} else {
// 标量:取初始化列表的第一个值
Assert(expr->compound.rhs_exprs.size > 0);
scc_ast_expr_t *init_expr = scc_vec_at(expr->compound.rhs_exprs, 0);
scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, init_expr, false);
scc_hir_builder_store(&ctx->builder, storage, val);
}
// 4. 根据左值 / 右值返回
if (is_lvalue) {
return storage; // 左值
} else {
// 右值:数组退化为首元素指针,结构体暂时返回地址
if (type->tag == SCC_HIR_TYPE_ARRAY) {
return scc_hir_builder_get_elem_ptr(&ctx->builder, storage,
SCC_HIR_REF_nullptr);
} else if (type->tag == SCC_HIR_TYPE_STRUCT ||
type->tag == SCC_HIR_TYPE_UNION) {
return storage; // 调用者会 memcpy
} else {
return scc_hir_builder_load(&ctx->builder, storage);
}
}
} break; } break;
case SCC_AST_EXPR_LVALUE: { case SCC_AST_EXPR_LVALUE: {
TODO(); UNREACHABLE(); // should only appear as compound.base
} break; } break;
case SCC_AST_EXPR_BUILTIN: { case SCC_AST_EXPR_BUILTIN: {
TODO(); TODO();
@@ -923,10 +1305,10 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
break; break;
} }
case SCC_AST_STMT_GOTO: { case SCC_AST_STMT_GOTO: {
scc_hir_bblock_ref_t target = (usize)scc_hashtable_get( // scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(
&ctx->ast2ir_cache, (void *)stmt->goto_stmt._target); // &ctx->ast2ir_cache, (void *)stmt->goto_stmt._target);
Assert(target != SCC_HIR_REF_nullptr); // Assert(target != SCC_HIR_REF_nullptr);
scc_hir_builder_jump(&ctx->builder, target); // scc_hir_builder_jump(&ctx->builder, target);
} break; } break;
case SCC_AST_STMT_LABEL: { case SCC_AST_STMT_LABEL: {
scc_hir_value_ref_t label_block = scc_hir_value_ref_t label_block =
@@ -1009,6 +1391,10 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
if (type.tag == SCC_HIR_TYPE_ARRAY) { if (type.tag == SCC_HIR_TYPE_ARRAY) {
emit_array_initialization(ctx, alloc_val_node, &type, emit_array_initialization(ctx, alloc_val_node, &type,
decl->var.init); decl->var.init);
} else if (type.tag == SCC_HIR_TYPE_STRUCT ||
type.tag == SCC_HIR_TYPE_UNION) {
emit_aggregate_initialization(ctx, alloc_val_node, &type,
decl->var.init);
} else { } else {
// 标量类型 // 标量类型
scc_hir_value_ref_t init_val = scc_hir_value_ref_t init_val =
@@ -1023,9 +1409,11 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
scc_ast2ir_type(ctx, decl->func.type); scc_ast2ir_type(ctx, decl->func.type);
scc_hir_func_ref_t func_ref = scc_hir_func_ref_t func_ref =
(usize)scc_hashtable_get(&ctx->symtab, decl->name); (usize)scc_hashtable_get(&ctx->symtab, decl->name);
if (func_ref == SCC_HIR_REF_nullptr) { if (func_ref == SCC_HIR_REF_nullptr) {
func_ref = func_ref =
scc_hir_builder_func(&ctx->builder, func_type_ref, decl->name); scc_hir_builder_func(&ctx->builder, func_type_ref, decl->name);
// TODO: add func to cache because function pointer is needed
scc_hashtable_set(&ctx->symtab, decl->name, scc_hashtable_set(&ctx->symtab, decl->name,
(void *)(usize)func_ref); (void *)(usize)func_ref);
} }
@@ -1149,6 +1537,7 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
scc_hashtable_usize_init(&ctx->break_cache); scc_hashtable_usize_init(&ctx->break_cache);
scc_hashtable_usize_init(&ctx->continue_cache); scc_hashtable_usize_init(&ctx->continue_cache);
scc_hashtable_cstr_init(&ctx->symtab); scc_hashtable_cstr_init(&ctx->symtab);
scc_hashtable_usize_init(&ctx->type_cache);
ctx->hint_using_value = false; ctx->hint_using_value = false;
} }
@@ -1157,5 +1546,6 @@ void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) {
scc_hashtable_drop(&ctx->ast2ir_cache); scc_hashtable_drop(&ctx->ast2ir_cache);
scc_hashtable_drop(&ctx->break_cache); scc_hashtable_drop(&ctx->break_cache);
scc_hashtable_drop(&ctx->continue_cache); scc_hashtable_drop(&ctx->continue_cache);
scc_hashtable_drop(&ctx->type_cache);
scc_hashtable_drop(&ctx->symtab); scc_hashtable_drop(&ctx->symtab);
} }

View File

@@ -68,6 +68,11 @@ void scc_hir_builder_init(scc_hir_builder_t *builder, scc_hir_cprog_t *cprog);
*/ */
void scc_hir_builder_drop(scc_hir_builder_t *builder); void scc_hir_builder_drop(scc_hir_builder_t *builder);
static inline scc_hir_module_t *
scc_hir_builder_get_module(scc_hir_builder_t *builder) {
return &builder->cprog->module;
}
scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder, scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder,
scc_hir_type_ref_t type_ref, scc_hir_type_ref_t type_ref,
const char *name); const char *name);
@@ -92,7 +97,7 @@ scc_hir_value_ref_t scc_hir_builder_alloca(scc_hir_builder_t *builder,
const char *name); const char *name);
#define SCC_HIR_BUILDER_TYPE_FUNC(scc_type) \ #define SCC_HIR_BUILDER_TYPE_FUNC(scc_type) \
[[maybe_unused]] static inline scc_hir_type_ref_t \ SCC_MAYBE_UNUSED static inline scc_hir_type_ref_t \
scc_hir_builder_type_##scc_type(scc_hir_builder_t *builder) { \ scc_hir_builder_type_##scc_type(scc_hir_builder_t *builder) { \
scc_hir_type_t type_desc; \ scc_hir_type_t type_desc; \
scc_hir_type_init(&type_desc, SCC_HIR_TYPE_##scc_type); \ scc_hir_type_init(&type_desc, SCC_HIR_TYPE_##scc_type); \

View File

@@ -89,7 +89,9 @@ typedef enum scc_hir_value_tag {
SCC_HIR_VALUE_TAG_OP, ///< 二元运算 SCC_HIR_VALUE_TAG_OP, ///< 二元运算
SCC_HIR_VALUE_TAG_BRANCH, ///< 有条件分支 SCC_HIR_VALUE_TAG_BRANCH, ///< 有条件分支
SCC_HIR_VALUE_TAG_JUMP, ///< 无条件跳转 SCC_HIR_VALUE_TAG_JUMP, ///< 无条件跳转
SCC_HIR_VALUE_TAG_JUMP_INDIRECT, ///< 无条件跳转(地址)
SCC_HIR_VALUE_TAG_CALL, ///< 调用函数 SCC_HIR_VALUE_TAG_CALL, ///< 调用函数
SCC_HIR_VALUE_TAG_CALL_INDIRECT, ///< 调用函数(地址)
SCC_HIR_VALUE_TAG_RET, ///< 函数返回 SCC_HIR_VALUE_TAG_RET, ///< 函数返回
} scc_hir_value_tag_t; } scc_hir_value_tag_t;
@@ -222,11 +224,15 @@ struct scc_hir_value {
scc_hir_bblock_ref_t true_bblock; scc_hir_bblock_ref_t true_bblock;
scc_hir_bblock_ref_t false_bblock; scc_hir_bblock_ref_t false_bblock;
} branch; } branch;
struct { union {
scc_hir_value_ref_t target_ptr;
scc_hir_bblock_ref_t target_bblock; scc_hir_bblock_ref_t target_bblock;
} jump; } jump;
struct { struct {
scc_hir_func_ref_t callee; // TODO function pointer call union {
scc_hir_func_ref_t func_ref;
scc_hir_value_ref_t ptr_ref;
} callee;
scc_hir_value_ref_vec_t args; scc_hir_value_ref_vec_t args;
} call; } call;
struct { struct {

View File

@@ -105,7 +105,7 @@ void scc_hir_value_init(scc_hir_value_t *in, const char *name,
break; break;
case SCC_HIR_VALUE_TAG_CALL: case SCC_HIR_VALUE_TAG_CALL:
scc_vec_init(in->data.call.args); scc_vec_init(in->data.call.args);
in->data.call.callee = 0; in->data.call.callee.func_ref = 0;
break; break;
case SCC_HIR_VALUE_TAG_RET: case SCC_HIR_VALUE_TAG_RET:
in->data.ret.ret_val = 0; in->data.ret.ret_val = 0;

View File

@@ -625,7 +625,7 @@ scc_hir_value_ref_t scc_hir_builder_call(scc_hir_builder_t *builder,
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t call_node = {0}; scc_hir_value_t call_node = {0};
call_node.tag = SCC_HIR_VALUE_TAG_CALL; call_node.tag = SCC_HIR_VALUE_TAG_CALL;
call_node.data.call.callee = callee; call_node.data.call.callee.func_ref = callee;
scc_vec_init(call_node.data.call.args); scc_vec_init(call_node.data.call.args);
for (usize i = 0; i < arg_count; i++) { for (usize i = 0; i < arg_count; i++) {

View File

@@ -3,7 +3,9 @@
#include <scc_tree_dump.h> #include <scc_tree_dump.h>
#define GET_MODULE(ctx) (&(ctx->cprog->module)) #define GET_MODULE(ctx) (&(ctx->cprog->module))
static void dump_type_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited);
static const char *get_node_type_str(scc_hir_value_tag_t tag) { static const char *get_node_type_str(scc_hir_value_tag_t tag) {
static const char *node_types[] = { static const char *node_types[] = {
[SCC_HIR_VALUE_TAG_NULLPTR] = "NullPtr", [SCC_HIR_VALUE_TAG_NULLPTR] = "NullPtr",
@@ -168,9 +170,9 @@ static void dump_jump_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
static void dump_call_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { static void dump_call_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
scc_tree_dump_begin_line(ctx->dump_ctx); scc_tree_dump_begin_line(ctx->dump_ctx);
if (value->data.call.callee) { if (value->data.call.callee.func_ref) {
scc_hir_func_t *callee = scc_hir_func_t *callee = scc_hir_module_get_func(
scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee); GET_MODULE(ctx), value->data.call.callee.func_ref);
scc_tree_dump_value(ctx->dump_ctx, "func='%s'", scc_tree_dump_value(ctx->dump_ctx, "func='%s'",
callee ? (callee->name ? callee->name : "<unnamed>") callee ? (callee->name ? callee->name : "<unnamed>")
: "<invalid>"); : "<invalid>");
@@ -256,60 +258,12 @@ void scc_hir_dump_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) {
break; break;
} }
} }
void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) { void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) {
if (!ctx || !type_ref) { scc_hashtable_t visited;
LOG_ERROR("invalid parameter"); scc_hashtable_usize_init(&visited);
return; dump_type_with_visited(ctx, type_ref, &visited);
scc_hashtable_drop(&visited);
} }
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Type: ");
scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
switch (type->tag) {
case SCC_HIR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.pointer.base);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Array Length: ");
scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len);
scc_tree_dump_append(ctx->dump_ctx, "\n");
}
if (type->data.array.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.array.base);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_FUNC:
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
cbool is_last = (i + 1 == scc_vec_size(type->data.function.params));
scc_tree_dump_push(ctx->dump_ctx, is_last);
scc_hir_dump_type(ctx, scc_vec_at(type->data.function.params, i));
scc_tree_dump_pop(ctx->dump_ctx);
}
if (type->data.function.ret_type) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.function.ret_type);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
default:
break;
}
}
void scc_hir_dump_bblock(scc_hir_dump_t *ctx, scc_hir_bblock_ref_t bblock_ref) { void scc_hir_dump_bblock(scc_hir_dump_t *ctx, scc_hir_bblock_ref_t bblock_ref) {
if (!ctx || !bblock_ref) { if (!ctx || !bblock_ref) {
LOG_ERROR("invalid parameter"); LOG_ERROR("invalid parameter");
@@ -379,13 +333,94 @@ void scc_hir_dump_cprog(scc_hir_dump_t *ctx) {
} }
// ----- 线性输出(保留原逻辑,改用新 API----- // ----- 线性输出(保留原逻辑,改用新 API-----
void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref) { // 在 scc_hir_dump.c 中添加以下静态辅助函数(放在文件前部,现有函数之前)
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!ctx || !type) { static void dump_type_linear_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited);
static void dump_type_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter"); LOG_ERROR("invalid parameter");
return; return;
} }
// 检查循环
if (scc_hashtable_get(visited, (void *)(usize)type_ref)) {
scc_tree_dump_append(ctx->dump_ctx, " <recursive>");
return;
}
scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1);
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Type: ");
scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
switch (type->tag) {
case SCC_HIR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
dump_type_with_visited(ctx, type->data.pointer.base, visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Array Length: ");
scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len);
scc_tree_dump_append(ctx->dump_ctx, "\n");
}
if (type->data.array.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
dump_type_with_visited(ctx, type->data.array.base, visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_FUNC:
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
cbool is_last = (i + 1 == scc_vec_size(type->data.function.params));
scc_tree_dump_push(ctx->dump_ctx, is_last);
dump_type_with_visited(
ctx, scc_vec_at(type->data.function.params, i), visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
if (type->data.function.ret_type) {
scc_tree_dump_push(ctx->dump_ctx, true);
dump_type_with_visited(ctx, type->data.function.ret_type, visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
default:
break;
}
}
static void dump_type_linear_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
// 检查循环
if (scc_hashtable_get(visited, (void *)(usize)type_ref)) {
scc_tree_dump_append(ctx->dump_ctx, " <recursive>");
return;
}
scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1);
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
switch (type->tag) { switch (type->tag) {
case SCC_HIR_TYPE_unknown: case SCC_HIR_TYPE_unknown:
case SCC_HIR_TYPE_void: case SCC_HIR_TYPE_void:
@@ -407,24 +442,25 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
break; break;
case SCC_HIR_TYPE_ARRAY: case SCC_HIR_TYPE_ARRAY:
scc_tree_dump_append(ctx->dump_ctx, "["); scc_tree_dump_append(ctx->dump_ctx, "[");
scc_hir_dump_type_linear(ctx, type->data.array.base); dump_type_linear_with_visited(ctx, type->data.array.base, visited);
scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len); scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len);
break; break;
case SCC_HIR_TYPE_PTR: case SCC_HIR_TYPE_PTR:
scc_tree_dump_append(ctx->dump_ctx, "*"); scc_tree_dump_append(ctx->dump_ctx, "*");
scc_hir_dump_type_linear(ctx, type->data.pointer.base); dump_type_linear_with_visited(ctx, type->data.pointer.base, visited);
break; break;
case SCC_HIR_TYPE_FUNC: case SCC_HIR_TYPE_FUNC:
scc_tree_dump_append(ctx->dump_ctx, "("); scc_tree_dump_append(ctx->dump_ctx, "(");
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) { for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
if (i > 0) if (i > 0)
scc_tree_dump_append(ctx->dump_ctx, ", "); scc_tree_dump_append(ctx->dump_ctx, ", ");
scc_hir_dump_type_linear(ctx, dump_type_linear_with_visited(
scc_vec_at(type->data.function.params, i)); ctx, scc_vec_at(type->data.function.params, i), visited);
} }
if (type->data.function.ret_type) { if (type->data.function.ret_type) {
scc_tree_dump_append(ctx->dump_ctx, ") -> "); scc_tree_dump_append(ctx->dump_ctx, ") -> ");
scc_hir_dump_type_linear(ctx, type->data.function.ret_type); dump_type_linear_with_visited(ctx, type->data.function.ret_type,
visited);
} else { } else {
scc_tree_dump_append(ctx->dump_ctx, ")"); scc_tree_dump_append(ctx->dump_ctx, ")");
} }
@@ -434,9 +470,9 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_tree_dump_append_fmt(ctx->dump_ctx, "%s {", scc_tree_dump_append_fmt(ctx->dump_ctx, "%s {",
type->tag == SCC_HIR_TYPE_STRUCT ? "struct" type->tag == SCC_HIR_TYPE_STRUCT ? "struct"
: "union"); : "union");
scc_vec_foreach(type->data.aggregate.fields, i) { for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
scc_hir_dump_type_linear( dump_type_linear_with_visited(
ctx, scc_vec_at(type->data.aggregate.fields, i)); ctx, scc_vec_at(type->data.aggregate.fields, i), visited);
scc_tree_dump_append(ctx->dump_ctx, ";"); scc_tree_dump_append(ctx->dump_ctx, ";");
} }
scc_tree_dump_append(ctx->dump_ctx, "}"); scc_tree_dump_append(ctx->dump_ctx, "}");
@@ -447,6 +483,14 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
} }
} }
void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref) {
scc_hashtable_t visited;
scc_hashtable_usize_init(&visited);
dump_type_linear_with_visited(ctx, type_ref, &visited);
scc_hashtable_drop(&visited);
}
static void format_ref_or_value(scc_hir_dump_t *ctx, static void format_ref_or_value(scc_hir_dump_t *ctx,
scc_hir_value_ref_t value_ref) { scc_hir_value_ref_t value_ref) {
scc_hir_value_t *value = scc_hir_value_t *value =
@@ -580,8 +624,8 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx,
value->data.jump.target_bblock); value->data.jump.target_bblock);
break; break;
case SCC_HIR_VALUE_TAG_CALL: { case SCC_HIR_VALUE_TAG_CALL: {
scc_hir_func_t *func = scc_hir_func_t *func = scc_hir_module_get_func(
scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee); GET_MODULE(ctx), value->data.call.callee.func_ref);
scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(", scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(",
func ? (func->name ? func->name : "<unnamed>") func ? (func->name ? func->name : "<unnamed>")
: "<invalid>"); : "<invalid>");
@@ -658,7 +702,7 @@ void scc_hir_dump_func_linear(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref,
scc_tree_dump_append(ctx->dump_ctx, "<invalid function>"); scc_tree_dump_append(ctx->dump_ctx, "<invalid function>");
return; return;
} }
scc_tree_dump_append_fmt(ctx->dump_ctx, "func @%s", scc_tree_dump_node(ctx->dump_ctx, "func @%s",
(func->name && func->name[0]) ? func->name (func->name && func->name[0]) ? func->name
: "<unnamed>"); : "<unnamed>");

View File

@@ -358,8 +358,8 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
break; break;
} }
case SCC_HIR_VALUE_TAG_CALL: { case SCC_HIR_VALUE_TAG_CALL: {
scc_hir_func_t *callee = scc_hir_func_t *callee = scc_hir_module_get_func(
scc_hir_module_get_func(ctx->hir_module, value->data.call.callee); ctx->hir_module, value->data.call.callee.func_ref);
int arg_count = scc_vec_size(value->data.call.args); int arg_count = scc_vec_size(value->data.call.args);
scc_lir_val_t *lir_args = scc_malloc(sizeof(scc_lir_val_t) * arg_count); scc_lir_val_t *lir_args = scc_malloc(sizeof(scc_lir_val_t) * arg_count);
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {

View File

@@ -0,0 +1,69 @@
#ifndef __SCC_X86_ISEL_H__
#define __SCC_X86_ISEL_H__
#include <scc_lir_module.h>
#include <scc_tree_dump.h>
#include "../core_pass/scc_abi_lowering.h"
#include "scc_x86_mir.h"
typedef struct scc_x86_64_isel {
scc_mir_x86_instr_vec_t instrs;
scc_mir_func_t *func;
scc_pos_t pos;
scc_abi_lowering_t abi_lowering;
} scc_x86_64_isel_t;
void scc_isel_x86_64(scc_mir_module_t *mir_module,
const scc_lir_module_t *lir_module,
scc_x86_64_isel_t *isel);
// Utils
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
scc_x86_operand_value_t src, u8 size);
scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
const scc_lir_val_t *val);
static inline void emit_direct_call(scc_x86_64_isel_t *isel,
const char *callee) {
(void)callee;
scc_mir_x86_instr_t instr = {0};
scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_RELBRZ,
scc_x86_op_relbr(0), scc_pos_create());
scc_vec_push(isel->instrs, instr);
}
static inline void emit_indirect_call(scc_x86_64_isel_t *isel,
scc_x86_operand_value_t reg) {
scc_mir_x86_instr_t instr = {0};
scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_GPRV, reg,
scc_pos_create());
}
static inline void emit_ret(scc_x86_64_isel_t *isel) {
scc_mir_x86_instr_t instr = {0};
scc_mir_x86_instr_0(&instr, SCC_X86_IFORM_RET_NEAR, scc_pos_create());
scc_vec_push(isel->instrs, instr);
}
#define add_instr_0(isel, iform) \
do { \
scc_mir_x86_instr_t instr; \
scc_mir_x86_instr_0(&instr, (iform), (isel)->pos); \
scc_vec_push((isel)->instrs, instr); \
} while (0)
#define add_instr_1(isel, iform, arg1) \
do { \
scc_mir_x86_instr_t instr; \
scc_mir_x86_instr_1(&instr, (iform), (arg1), (isel)->pos); \
scc_vec_push((isel)->instrs, instr); \
} while (0)
#define add_instr_2(isel, iform, arg1, arg2) \
do { \
scc_mir_x86_instr_t instr; \
scc_mir_x86_instr_2(&instr, (iform), (arg1), (arg2), (isel)->pos); \
scc_vec_push((isel)->instrs, instr); \
} while (0)
#endif /* __SCC_X86_ISEL_H__ */

View File

@@ -0,0 +1,134 @@
#ifndef __SCC_X86_MIR_H__
#define __SCC_X86_MIR_H__
#include "../scc_mir.h"
#include <scc_cfg.h>
#include <scc_pos.h>
#include <x86/scc_x86_encode.h>
#include <x86/scc_x86_iform.h>
#include <x86/scc_x86_reg.h>
typedef struct {
int opcode;
uint8_t num_operands;
scc_x86_operand_value_t operands[6];
scc_pos_t src_loc;
} scc_x86_instr_t;
// x86 后端指令:首字段 int opcode正 = scc_x86_iform_t负 = 伪指令)
typedef union scc_mir_x86_instr {
scc_mir_instr_t instr;
scc_x86_instr_t x86_instr;
} scc_mir_x86_instr_t;
typedef SCC_VEC(scc_mir_x86_instr_t) scc_mir_x86_instr_vec_t;
// ── 基本块 values 强制转换 ──────────────────────────────────────────────
#define SCC_MIR_X86_BBLOCK_INSTRS(bb) ((scc_mir_x86_instr_vec_t *)&bb->values)
#define SCC_MIR_X86_BBLOCK_INSTRS_C(bb) \
((const scc_mir_x86_instr_vec_t *)&bb->values)
// ── vreg 编码 ──────────────────────────────────────────────────────────
static inline bool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) {
return op->kind == SCC_X86_OPR_REG &&
(int)op->reg >= (int)SCC_X86_REG_COUNT;
}
static inline int scc_x86_op_get_vreg(const scc_x86_operand_value_t *op) {
return (int)op->reg - (int)SCC_X86_REG_COUNT;
}
static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op,
scc_x86_reg_t preg) {
op->kind = SCC_X86_OPR_REG;
op->reg = preg;
}
// ── 未解析栈槽编码 (base=INVALID, disp=slot_id) ──────────────────────
static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) {
return op->kind == SCC_X86_OPR_MEM && op->mem.base == SCC_X86_REG_INVALID;
}
static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) {
return op->mem.disp;
}
// ── 指令构建辅助 ──────────────────────────────────────────────────────
static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int opcode,
scc_pos_t pos) {
out->x86_instr.opcode = opcode;
out->x86_instr.num_operands = 0;
out->x86_instr.src_loc = pos;
}
static inline void scc_mir_x86_instr_1(scc_mir_x86_instr_t *out, int opcode,
scc_x86_operand_value_t op0,
scc_pos_t pos) {
out->x86_instr.opcode = opcode;
out->x86_instr.num_operands = 1;
out->x86_instr.operands[0] = op0;
out->x86_instr.src_loc = pos;
}
static inline void scc_mir_x86_instr_2(scc_mir_x86_instr_t *out, int opcode,
scc_x86_operand_value_t op0,
scc_x86_operand_value_t op1,
scc_pos_t pos) {
out->x86_instr.opcode = opcode;
out->x86_instr.num_operands = 2;
out->x86_instr.operands[0] = op0;
out->x86_instr.operands[1] = op1;
out->x86_instr.src_loc = pos;
}
static inline void scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, int opcode,
scc_x86_operand_value_t op0,
scc_x86_operand_value_t op1,
scc_x86_operand_value_t op2,
scc_pos_t pos) {
out->x86_instr.opcode = opcode;
out->x86_instr.num_operands = 3;
out->x86_instr.operands[0] = op0;
out->x86_instr.operands[1] = op1;
out->x86_instr.operands[2] = op2;
out->x86_instr.src_loc = pos;
}
// ── 常用操作数构造器 ──────────────────────────────────────────────────
static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg) {
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_REG, .reg = reg};
return o;
}
static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg) {
scc_x86_operand_value_t o = {
.kind = SCC_X86_OPR_REG,
.reg = (scc_x86_reg_t)((int)SCC_X86_REG_COUNT + vreg)};
return o;
}
static inline scc_x86_operand_value_t scc_x86_op_relbr(i32 rel) {
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_RELBR, .imm = rel};
return o;
}
static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm) {
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_IMM, .imm = imm};
return o;
}
// slot_id 编码为 base=INVALID, disp=slot_id
static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id) {
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM};
o.mem.base = SCC_X86_REG_INVALID;
o.mem.index = SCC_X86_REG_INVALID;
o.mem.scale = 1;
o.mem.disp = slot_id;
return o;
}
static inline scc_x86_operand_value_t scc_x86_op_symbol(const char *sym) {
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_IMM,
.imm = (i64)(usize)sym};
(void)o;
// symbol 暂用一个近似值占位,编码阶段处理重定位
return o;
}
static inline scc_x86_operand_value_t
scc_x86_op_block(scc_cfg_bblock_id_t bid) {
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_RELBR, .imm = 0};
(void)bid;
return o;
}
#endif /* __SCC_X86_MIR_H__ */

View File

@@ -0,0 +1,8 @@
#ifndef __SCC_X86_REG_ALLOC_H__
#define __SCC_X86_REG_ALLOC_H__
#include "../core_pass/scc_reg_alloc.h"
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops);
#endif /* __SCC_X86_REG_ALLOC_H__ */

View File

@@ -1,66 +0,0 @@
#ifndef __SCC_X86_64_ISEL_H__
#define __SCC_X86_64_ISEL_H__
#include <scc_lir_module.h>
#include <scc_tree_dump.h>
#include <x86/scc_x86_iform.h>
#include <x86/scc_x86_reg.h>
#include "../core_pass/scc_abi_lowering.h"
#include "../scc_mir_module.h"
typedef struct scc_x86_64_isel {
scc_mir_instr_vec_t instrs;
scc_mir_func_t *func;
scc_abi_lowering_t abi_lowering;
} scc_x86_64_isel_t;
void scc_isel_x86_64(scc_mir_module_t *mir_module,
const scc_lir_module_t *lir_module,
scc_x86_64_isel_t *isel);
static void add_instr(scc_x86_64_isel_t *isel, const scc_mir_instr_t *instr) {
scc_vec_push(isel->instrs, *instr);
}
static inline void add_instr_0(scc_x86_64_isel_t *isel,
scc_x86_iform_t opcode) {
scc_mir_instr_t out = {.opcode = opcode, .num_operands = 0};
add_instr(isel, &out);
}
static inline void add_instr_1(scc_x86_64_isel_t *isel, scc_x86_iform_t opcode,
scc_mir_operand_t op1) {
scc_mir_instr_t out = {.opcode = opcode, .num_operands = 1};
out.operands[0] = op1;
add_instr(isel, &out);
}
static inline void add_instr_2(scc_x86_64_isel_t *isel, scc_x86_iform_t opcode,
scc_mir_operand_t op1, scc_mir_operand_t op2) {
scc_mir_instr_t out = {.opcode = opcode, .num_operands = 2};
out.operands[0] = op1;
out.operands[1] = op2;
add_instr(isel, &out);
}
static inline scc_mir_operand_t reg_operand(scc_x86_reg_t reg) {
return (scc_mir_operand_t){.kind = SCC_MIR_OP_PREG, .preg = reg};
}
// Utils
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst,
scc_mir_operand_t src, u8 size);
scc_mir_operand_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
const scc_lir_val_t *val);
static inline void emit_call(scc_x86_64_isel_t *isel, const char *callee) {
scc_mir_operand_t sym = {.kind = SCC_MIR_OP_SYMBOL, .symbol = callee};
add_instr_1(isel, SCC_X86_IFORM_CALL_NEAR_GPRV, sym);
}
static inline void emit_ret(scc_x86_64_isel_t *isel) {
add_instr_0(isel, SCC_X86_IFORM_RET_NEAR);
}
#endif /* __SCC_X86_64_ISEL_H__ */

View File

@@ -1,8 +0,0 @@
#ifndef __SCC_X86_64_REG_ALLOC_H__
#define __SCC_X86_64_REG_ALLOC_H__
#include "../core_pass/scc_reg_alloc.h"
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops);
#endif /* __SCC_X86_64_REG_ALLOC_H__ */

View File

@@ -4,9 +4,12 @@
#include "../scc_mir_module.h" #include "../scc_mir_module.h"
#include <scc_lir_module.h> #include <scc_lir_module.h>
// 所有回调通过 void* userdata / void* out_op 保持类型无关
typedef void (*scc_abi_lower_fn)(void *user_data, const scc_lir_instr_t *instr); typedef void (*scc_abi_lower_fn)(void *user_data, const scc_lir_instr_t *instr);
typedef scc_mir_operand_t (*scc_abi_lower_param_fn)(void *userdata, // lower_param 将 LIR 值转化为后端操作数,写入 out_op后端知道实际类型
const scc_lir_val_t *val); typedef void (*scc_abi_lower_param_fn)(void *userdata,
const scc_lir_val_t *val,
void *out_op);
typedef struct scc_abi_lowering { typedef struct scc_abi_lowering {
scc_abi_lower_fn lower_call; scc_abi_lower_fn lower_call;

View File

@@ -3,10 +3,15 @@
#include "../scc_mir_module.h" #include "../scc_mir_module.h"
typedef struct scc_frame_layout { struct scc_frame_layout;
scc_mir_func_t *func; typedef struct scc_frame_layout scc_frame_layout_t;
} scc_frame_layout_t; typedef void (*scc_frame_layout_impl_fn)(scc_frame_layout_t *ctx,
scc_mir_module_t *mir_module,
scc_mir_func_t *mir_func);
void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module); struct scc_frame_layout {
scc_frame_layout_impl_fn impl_fn;
int offset;
};
#endif /* __SCC_FRAME_LAYOUT_H__ */ #endif /* __SCC_FRAME_LAYOUT_H__ */

View File

@@ -1,14 +1,17 @@
#ifndef __SCC_PROLOG_EPILOG_H__ #ifndef __SCC_PROLOG_EPILOG_H__
#define __SCC_PROLOG_EPILOG_H__ #define __SCC_PROLOG_EPILOG_H__
#include "../scc_mir_module.h"
#include <scc_lir_module.h> #include <scc_lir_module.h>
#include <scc_mir_module.h>
typedef void (*scc_prolog_epilog_fn)(void *userdata, typedef void (*scc_prolog_epilog_fn)(scc_mir_instr_vec_t *userdata,
const scc_mir_func_t *func); const scc_mir_func_t *func);
typedef int (*scc_need_epilog_fn)(const scc_mir_instr_t *instr);
typedef struct scc_prolog_epilog { typedef struct scc_prolog_epilog {
scc_prolog_epilog_fn prolog; scc_prolog_epilog_fn prolog;
scc_prolog_epilog_fn epilog; scc_prolog_epilog_fn epilog;
scc_need_epilog_fn need_epilog;
} scc_prolog_epilog_t; } scc_prolog_epilog_t;
#endif /* __SCC_PROLOG_EPILOG_H__ */ #endif /* __SCC_PROLOG_EPILOG_H__ */

View File

@@ -7,37 +7,46 @@ typedef enum {
SCC_REG_ALLOC_OP_ACCESS_READ = 0, SCC_REG_ALLOC_OP_ACCESS_READ = 0,
SCC_REG_ALLOC_OP_ACCESS_WRITE = 1, SCC_REG_ALLOC_OP_ACCESS_WRITE = 1,
SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2, SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2,
} scc_op_access_t; } scc_reg_op_access_t;
// 后端回调表 —— 框架通过回调获取/修改指令,不感知具体布局
typedef struct scc_reg_alloc_op { typedef struct scc_reg_alloc_op {
// preg → [slot] // ── 寄存器池 ──
void (*emit_spill)(scc_mir_instr_vec_t *ctx, int preg, int slot); int (*acquire_reg)(void *ctx);
// [slot] → preg void (*release_reg)(void *ctx, int preg);
void (*emit_reload)(scc_mir_instr_vec_t *ctx, int preg, int slot);
// preg → preg
void (*emit_copy)(scc_mir_instr_vec_t *ctx, int dst_preg, int src_preg,
int size);
// 通用寄存器申请 / 释放
int (*acquire_reg)(void *ctx); // 返回一个物理寄存器编号
void (*release_reg)(void *ctx, int preg); // 归还该寄存器
// 显式标记某个寄存器已占用 / 未占用(用于隐式寄存器、固定分配等)
void (*mark_reg_used)(void *ctx, int preg); void (*mark_reg_used)(void *ctx, int preg);
void (*clean_mark_regs)(void *ctx); void (*clean_mark_regs)(void *ctx);
// ---- 指令信息查询(只读) ---- // ── 指令信息 ──
scc_op_access_t (*get_operand_access)(void *ctx, int opcode, int op_idx); int (*instr_opcode)(const void *instr);
int (*instr_num_operands)(const void *instr);
bool (*op_is_vreg)(const void *instr, int idx);
int (*op_get_vreg)(const void *instr, int idx);
void (*op_set_preg)(void *instr, int idx, int preg);
void (*op_set_slot)(void *instr, int idx, int slot);
// 读写属性与隐式寄存器
scc_reg_op_access_t (*get_operand_access)(void *ctx, int opcode,
int op_idx);
void (*get_implicit_regs)(void *ctx, int opcode, const int **out_uses, void (*get_implicit_regs)(void *ctx, int opcode, const int **out_uses,
const int **out_defs); const int **out_defs);
// ── 伪指令处理 ──
bool (*is_pseudo)(const void *instr);
void (*handle_pseudo)(scc_mir_func_t *func, void *instr, void *out);
// ── 溢出/重载(写入 out 向量) ──
void (*emit_spill)(void *out, int preg, int slot);
void (*emit_reload)(void *out, int preg, int slot);
void (*emit_copy)(void *out, int dst_preg, int src_preg, int size);
} scc_reg_alloc_op_t; } scc_reg_alloc_op_t;
typedef struct scc_reg_alloc_ctx { typedef struct scc_reg_alloc_ctx {
scc_reg_alloc_op_t ops; scc_reg_alloc_op_t ops;
scc_mir_module_t *module;
scc_mir_func_t *func; scc_mir_func_t *func;
scc_mir_instr_vec_t *instrs;
} scc_reg_alloc_ctx_t; } scc_reg_alloc_ctx_t;
// 通用寄存器分配入口:遍历所有函数/基本块,对每条指令做 vreg → preg 分配
void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module); void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module);
#endif /* __SCC_REG_ALLOC__ */ #endif /* __SCC_REG_ALLOC_H__ */

View File

@@ -1,51 +1,29 @@
// scc_mir.h (示意)
#ifndef __SCC_MIR_H__ #ifndef __SCC_MIR_H__
#define __SCC_MIR_H__ #define __SCC_MIR_H__
#include <scc_lir.h> #include <scc_cfg.h>
// 伪指令 opcode负数所有后端通用约定
typedef enum { typedef enum {
SCC_MIR_OP_NONE, SCC_MIR_PSEUDO_NONE = 0,
SCC_MIR_OP_MEM, // 内存访问 SCC_MIR_PSEUDO_ALLOCA = -1,
SCC_MIR_OP_VREG, // 虚拟寄存器 SCC_MIR_PSEUDO_VA_START = -2,
SCC_MIR_OP_PREG, // 物理寄存器 } scc_mir_pseudo_t;
SCC_MIR_OP_IMM, // 立即数
SCC_MIR_OP_SYMBOL, // 符号地址(用于重定位)
SCC_MIR_OP_BLOCK // 基本块引用(label)
} scc_mir_op_kind_t;
typedef struct scc_mir_operand {
scc_mir_op_kind_t kind;
union {
int vreg; // 虚拟寄存器索引
int preg; // 物理寄存器
i64 imm; // 立即数
const char *symbol; // 符号名
int stack_slot; // 栈槽 ID (由 FrameLayout 分配)
scc_lir_bblock_id_t block_id; // 目标基本块
};
} scc_mir_operand_t;
typedef enum {
SCC_MIR_PSUEDO_ALLOCA = -1,
} scc_mir_psuedo_op_t;
typedef struct scc_mir_instr { typedef struct scc_mir_instr {
int opcode; // 目标特定的指令编码 (如 X86::ADD32rr) int opcode;
int num_operands; // 实际使用的操作数个数 union {
scc_mir_operand_t struct {
operands[8]; // 固定小数组RISC 风格指令通常不超过 4 操作数 int size;
scc_pos_t src_loc; // 调试信息 (继承自 LIR) int align;
int vreg;
} alloc;
} data;
} scc_mir_instr_t; } scc_mir_instr_t;
typedef SCC_VEC(scc_mir_instr_t) scc_mir_instr_vec_t;
typedef scc_cfg_bblock_t scc_mir_bblock_t; #define SCC_MIR_BBLOCK_VALUES_PTR(bb) ((void *)(&(bb)->values))
typedef struct scc_mir_bblock_meta {
} scc_mir_bblock_meta_t;
#define SCC_MIR_BBLOCK_VALUES(bblock) \
((scc_mir_instr_vec_t *)&((bblock)->values))
// 栈槽信息(由 FrameLayout Pass 填充)
typedef struct scc_mir_stack_slot { typedef struct scc_mir_stack_slot {
int slot_id; int slot_id;
int size; // 通常是 8 字节 (指针大小) int size; // 通常是 8 字节 (指针大小)
@@ -54,18 +32,23 @@ typedef struct scc_mir_stack_slot {
} scc_mir_stack_slot_t; } scc_mir_stack_slot_t;
typedef SCC_VEC(scc_mir_stack_slot_t) scc_mir_stack_slot_vec_t; typedef SCC_VEC(scc_mir_stack_slot_t) scc_mir_stack_slot_vec_t;
typedef scc_cfg_bblock_t scc_mir_bblock_t;
// 函数元数据 —— 不包含任何指令结构,由各后端自行定义指令布局
typedef scc_cfg_func_t scc_mir_func_t; typedef scc_cfg_func_t scc_mir_func_t;
typedef struct scc_mir_func_meta { typedef struct scc_mir_func_meta {
// 栈帧信息 (由 FrameLayout Pass 填充) int need_va_args;
int frame_size; int frame_size;
int stack_alignment; int stack_alignment;
int vregs_count; int vregs_count;
// 寄存器分配信息 void *target_data; // 目标后端私有数据,例如 x86_64_func_info_t*
scc_mir_stack_slot_vec_t stack_slots; scc_mir_stack_slot_vec_t stack_slots;
// vreg -> phys reg and stack slot index // vreg -> phys reg / stack slot
// positive means stack slot index // 0 = not mapped (still a vreg)
// negative means physic register // >0 = stack slot index
// <0 = physical register (negated)
scc_hashtable_t vreg2physic; scc_hashtable_t vreg2physic;
} scc_mir_func_meta_t; } scc_mir_func_meta_t;
#define SCC_MIR_FUNC_META(func) ((scc_mir_func_meta_t *)(func)->meta) #define SCC_MIR_FUNC_META(func) ((scc_mir_func_meta_t *)(func)->meta)
@@ -73,10 +56,32 @@ typedef struct scc_mir_func_meta {
void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta); void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta);
int scc_mir_alloc_vreg(scc_mir_func_t *func); int scc_mir_alloc_vreg(scc_mir_func_t *func);
void scc_mir_vreg_op(const scc_mir_func_t *func, int vreg,
scc_mir_operand_t *out);
void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg); void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg);
int scc_mir_vreg_map2slot(scc_mir_func_t *func, int vreg, int size, int align); int scc_mir_vreg_map2slot(scc_mir_func_t *func, int vreg, int size, int align);
// 从 vreg2physic 表中查询映射结果:
// 返回 0 → 该 vreg 仍为 vreg未映射
// 返回 1 → 已映射到物理寄存器,*out_preg 有效
// 返回 -1 → 已溢出到栈槽,*out_slot 有效
static inline int scc_mir_vreg_lookup(const scc_mir_func_t *func, int vreg,
int *out) {
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
isize idx =
(isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg);
if (idx == 0)
return 0;
if (idx < 0) {
*out = (int)-idx;
return 1;
}
*out = (int)idx;
return -1;
}
static inline scc_mir_stack_slot_t *
scc_mir_unsafe_slot(const scc_mir_func_t *func, int slot) {
Assert(slot > 0);
return &scc_vec_at(SCC_MIR_FUNC_META(func)->stack_slots, slot);
}
#endif /* __SCC_MIR_H__ */ #endif /* __SCC_MIR_H__ */

View File

@@ -4,9 +4,16 @@
#include "scc_mir.h" #include "scc_mir.h"
#include <scc_lir_module.h> #include <scc_lir_module.h>
typedef SCC_VEC(char) scc_mir_instr_vec_t;
typedef struct {
} scc_mir_symbol_t;
typedef scc_lir_symbol_meta_vec_t scc_mir_symbol_meta_vec_t; typedef scc_lir_symbol_meta_vec_t scc_mir_symbol_meta_vec_t;
typedef SCC_VEC(scc_mir_func_meta_t *) scc_mir_func_meta_vec_t; typedef SCC_VEC(scc_mir_func_meta_t *) scc_mir_func_meta_vec_t;
typedef struct scc_mir_module { typedef struct scc_mir_module {
usize instr_size;
scc_cfg_module_t cfg_module; scc_cfg_module_t cfg_module;
scc_mir_func_meta_vec_t func_metas; scc_mir_func_meta_vec_t func_metas;
scc_mir_symbol_meta_vec_t symbol_metas; scc_mir_symbol_meta_vec_t symbol_metas;

View File

@@ -1,9 +1,14 @@
#ifndef __SCC_WIN64_H__ #ifndef __SCC_WIN64_H__
#define __SCC_WIN64_H__ #define __SCC_WIN64_H__
#include "../arch/x86_64_isel.h" #include "../arch/scc_x86_isel.h"
#include "../core_pass/scc_frame_layout.h"
#include "../core_pass/scc_prolog_epilog.h"
#include "../core_pass/scc_reg_alloc.h" #include "../core_pass/scc_reg_alloc.h"
void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t *abi_lowering); void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t *abi_lowering);
void scc_reg_alloc_fill_win_x64(scc_reg_alloc_op_t *ops); void scc_win_pc_x64_reg_alloc_fill(scc_reg_alloc_op_t *ops);
void scc_win_pc_x64_frame_alloc_init(scc_frame_layout_t *ctx);
void scc_win_pc_x64_prolog_epilog_init(scc_prolog_epilog_t *ctx);
#endif #endif

View File

@@ -1,4 +1,4 @@
#include <arch/x86_64_isel.h> #include <arch/scc_x86_isel.h>
#include <x86/scc_x86_iform.c> #include <x86/scc_x86_iform.c>
#include <x86/scc_x86_reg.c> #include <x86/scc_x86_reg.c>
@@ -9,35 +9,40 @@ static const char *preg_name(int preg_id) {
return scc_x86_reg_table[preg_id].display_str; return scc_x86_reg_table[preg_id].display_str;
} }
void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_instr_t *instr) { void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) {
scc_x86_iform_t iform = instr->opcode; if (instr->x86_instr.opcode >= SCC_X86_IFORM_COUNT ||
instr->x86_instr.opcode < 0) {
scc_tree_dump_append_fmt(td, " ???");
return;
}
scc_x86_iform_t iform = instr->x86_instr.opcode;
const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform]; const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform];
scc_tree_dump_append_fmt(td, " %s", info->iform_name); scc_tree_dump_append_fmt(td, " %s", info->iform_name);
// Assert(instr->num_operands == info->num_ops); for (int i = 0; i < instr->x86_instr.num_operands; i += 1) {
for (int i = 0; i < instr->num_operands; i += 1) {
if (i == 0) if (i == 0)
scc_tree_dump_append(td, " "); scc_tree_dump_append(td, " ");
else else
scc_tree_dump_append_fmt(td, ", "); scc_tree_dump_append_fmt(td, ", ");
scc_mir_operand_t *op = &instr->operands[i]; const scc_x86_operand_value_t *op = &instr->x86_instr.operands[i];
switch (op->kind) { switch (op->kind) {
case SCC_MIR_OP_VREG: case SCC_X86_OPR_REG:
scc_tree_dump_append_fmt(td, "%%%d", op->vreg); if (scc_x86_op_is_vreg(op))
scc_tree_dump_append_fmt(td, "%%%d", scc_x86_op_get_vreg(op));
else
scc_tree_dump_append_fmt(td, "$%s", preg_name(op->reg));
break; break;
case SCC_MIR_OP_PREG: case SCC_X86_OPR_IMM:
scc_tree_dump_append_fmt(td, "$%s", preg_name(op->preg));
break;
case SCC_MIR_OP_IMM:
scc_tree_dump_append_fmt(td, "%ld", op->imm); scc_tree_dump_append_fmt(td, "%ld", op->imm);
break; break;
case SCC_MIR_OP_BLOCK: case SCC_X86_OPR_MEM:
scc_tree_dump_append_fmt(td, "#BB%d", op->block_id); if (scc_x86_op_is_slot(op))
scc_tree_dump_append_fmt(td, "[slot:%d]",
scc_x86_op_slot_id(op));
else
scc_tree_dump_append_fmt(td, "[sp%+d]", op->mem.disp);
break; break;
case SCC_MIR_OP_SYMBOL: case SCC_X86_OPR_RELBR:
scc_tree_dump_append_fmt(td, "@%s", op->symbol); scc_tree_dump_append(td, "label");
break;
case SCC_MIR_OP_MEM:
scc_tree_dump_append_fmt(td, "[%d]", op->stack_slot);
break; break;
default: default:
break; break;
@@ -45,35 +50,36 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_instr_t *instr) {
} }
} }
// 将 LIR 值转换为 MIR 操作数 // 将 LIR 值转换为 x86 操作数
scc_mir_operand_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
const scc_lir_val_t *val) { const scc_lir_val_t *val) {
scc_mir_operand_t op = {0}; scc_x86_operand_value_t op = {0};
switch (val->kind) { switch (val->kind) {
case SCC_LIR_INSTR_KIND_NONE: case SCC_LIR_INSTR_KIND_NONE:
op.kind = SCC_MIR_OP_NONE; op.kind = SCC_X86_OPR_NONE;
break; break;
case SCC_LIR_INSTR_KIND_VREG: case SCC_LIR_INSTR_KIND_VREG:
op.kind = SCC_MIR_OP_VREG; op = scc_x86_op_vreg(val->data.reg);
op.vreg = val->data.reg; int id = 0;
int ret = scc_mir_vreg_lookup(isel->func, val->data.reg, &id);
if (ret > 0) {
op = scc_x86_op_preg(id);
} else if (ret < 0) {
op = scc_x86_op_slot(id);
}
break; break;
case SCC_LIR_INSTR_KIND_IMM: case SCC_LIR_INSTR_KIND_IMM:
op.kind = SCC_MIR_OP_IMM; op = scc_x86_op_imm(val->data.imm.data.digit);
// FIXME hack ap
op.imm = val->data.imm.data.digit;
break; break;
case SCC_LIR_INSTR_KIND_FIMM: case SCC_LIR_INSTR_KIND_FIMM:
// 浮点立即数暂时作为普通立即数处理(后端需特殊处理) op = scc_x86_op_imm(*(i64 *)&val->data.fimm);
op.kind = SCC_MIR_OP_IMM;
op.imm = *(i64 *)&val->data.fimm;
break; break;
case SCC_LIR_INSTR_KIND_SYMBOL: case SCC_LIR_INSTR_KIND_SYMBOL:
op.kind = SCC_MIR_OP_SYMBOL; op = scc_x86_op_symbol(val->data.symbol);
op.symbol = val->data.symbol;
break; break;
case SCC_LIR_INSTR_KIND_ARG: case SCC_LIR_INSTR_KIND_ARG:
Assert(isel->abi_lowering.lower_param); Assert(isel->abi_lowering.lower_param);
op = isel->abi_lowering.lower_param(isel, val); isel->abi_lowering.lower_param(isel, val, &op);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@@ -82,39 +88,40 @@ scc_mir_operand_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
} }
// 虚拟临时寄存器分配(简单递增) // 虚拟临时寄存器分配(简单递增)
static scc_mir_operand_t new_vreg_temp(scc_x86_64_isel_t *isel) { static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel) {
return (scc_mir_operand_t){.kind = SCC_MIR_OP_VREG, return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func));
.vreg = scc_mir_alloc_vreg(isel->func)};
} }
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
scc_mir_operand_t src, u8 size) { scc_x86_operand_value_t src, u8 size) {
if (dst.kind == SCC_MIR_OP_VREG || dst.kind == SCC_MIR_OP_PREG) {
if (src.kind == SCC_MIR_OP_VREG || src.kind == SCC_MIR_OP_PREG) { if (dst.kind == SCC_X86_OPR_REG) {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89, dst, src); if (src.kind == SCC_X86_OPR_REG) {
} else if (src.kind == SCC_MIR_OP_IMM) { add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, dst, src);
} else if (src.kind == SCC_X86_OPR_IMM) {
add_instr_2(isel, add_instr_2(isel,
(size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ (size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ
: SCC_X86_IFORM_MOV_GPRV_IMMV, : SCC_X86_IFORM_MOV_GPRV_IMMV,
dst, src); dst, src);
} else if (src.kind == SCC_MIR_OP_SYMBOL) { } else if (src.kind == SCC_X86_OPR_IMM && src.imm == 0) {
// 特殊:符号作为立即数地址
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src); add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src);
} else if (src.kind == SCC_MIR_OP_MEM) { } else if (src.kind == SCC_X86_OPR_MEM) {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src); add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
} else if (dst.kind == SCC_MIR_OP_MEM) { } else if (dst.kind == SCC_X86_OPR_MEM) {
if (src.kind == SCC_MIR_OP_VREG || src.kind == SCC_MIR_OP_PREG) { if (src.kind == SCC_X86_OPR_REG) {
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src); add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src);
} else if (src.kind == SCC_MIR_OP_IMM) { } else if (src.kind == SCC_X86_OPR_IMM) {
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src); add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src);
} else if (src.kind == SCC_MIR_OP_SYMBOL) { } else if (src.kind == SCC_X86_OPR_IMM) {
scc_mir_operand_t temp = new_vreg_temp(isel); scc_x86_operand_value_t temp = new_vreg_temp(isel);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, temp, src); add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, temp, src);
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, temp); add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, temp);
} else if (src.kind == SCC_MIR_OP_MEM) { } else if (src.kind == SCC_X86_OPR_MEM) {
scc_mir_operand_t temp = new_vreg_temp(isel); scc_x86_operand_value_t temp = new_vreg_temp(isel);
scc_x86_emit_move(isel, temp, src, size); scc_x86_emit_move(isel, temp, src, size);
scc_x86_emit_move(isel, dst, temp, size); scc_x86_emit_move(isel, dst, temp, size);
} else { } else {
@@ -125,19 +132,18 @@ void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst,
} }
} }
static void emit_compare(scc_x86_64_isel_t *isel, scc_mir_operand_t op0, static void emit_compare(scc_x86_64_isel_t *isel, scc_x86_operand_value_t op0,
scc_mir_operand_t op1, u8 size) { scc_x86_operand_value_t op1, u8 size) {
// cmp op0, op1 (注意 x86 是 cmp a, b 即 a - b) (void)size;
if (op0.kind == SCC_MIR_OP_VREG && op1.kind == SCC_MIR_OP_IMM) { if (scc_x86_op_is_vreg(&op0) && op1.kind == SCC_X86_OPR_IMM) {
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, op0, op1); add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, op0, op1);
} else if (op0.kind == SCC_MIR_OP_VREG && op1.kind == SCC_MIR_OP_VREG) { } else if (scc_x86_op_is_vreg(&op0) && scc_x86_op_is_vreg(&op1)) {
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_39, op0, op1); add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
} }
/* 条件码到 setcc 指令的映射 */
static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) { static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) {
switch (cond) { switch (cond) {
case SCC_LIR_COND_EQ: case SCC_LIR_COND_EQ:
@@ -149,58 +155,61 @@ static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) {
case SCC_LIR_COND_SLE: case SCC_LIR_COND_SLE:
return SCC_X86_IFORM_SETLE_GPR8; return SCC_X86_IFORM_SETLE_GPR8;
case SCC_LIR_COND_SGT: case SCC_LIR_COND_SGT:
return SCC_X86_IFORM_SETNLE_GPR8; // SETG return SCC_X86_IFORM_SETNLE_GPR8;
case SCC_LIR_COND_SGE: case SCC_LIR_COND_SGE:
return SCC_X86_IFORM_SETNL_GPR8; // SETGE return SCC_X86_IFORM_SETNL_GPR8;
case SCC_LIR_COND_ULT: case SCC_LIR_COND_ULT:
return SCC_X86_IFORM_SETB_GPR8; return SCC_X86_IFORM_SETB_GPR8;
case SCC_LIR_COND_ULE: case SCC_LIR_COND_ULE:
return SCC_X86_IFORM_SETBE_GPR8; return SCC_X86_IFORM_SETBE_GPR8;
case SCC_LIR_COND_UGT: case SCC_LIR_COND_UGT:
return SCC_X86_IFORM_SETNBE_GPR8; // SETA return SCC_X86_IFORM_SETNBE_GPR8;
case SCC_LIR_COND_UGE: case SCC_LIR_COND_UGE:
return SCC_X86_IFORM_SETNB_GPR8; // SETAE return SCC_X86_IFORM_SETNB_GPR8;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
} }
static void emit_copy_if_needed(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, static void emit_copy_if_needed(scc_x86_64_isel_t *isel,
scc_mir_operand_t src0, u8 size) { scc_x86_operand_value_t dst,
if (dst.kind == SCC_MIR_OP_VREG && src0.kind == SCC_MIR_OP_VREG && scc_x86_operand_value_t src0, u8 size) {
dst.vreg == src0.vreg) { if (scc_x86_op_is_vreg(&dst) && scc_x86_op_is_vreg(&src0) &&
scc_x86_op_get_vreg(&dst) == scc_x86_op_get_vreg(&src0)) {
return; return;
} }
scc_x86_emit_move(isel, dst, src0, size); scc_x86_emit_move(isel, dst, src0, size);
} }
static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
scc_mir_operand_t dst, scc_mir_operand_t src0, scc_x86_operand_value_t dst,
scc_mir_operand_t src1, u8 size) { scc_x86_operand_value_t src0,
scc_x86_operand_value_t src1, u8 size) {
(void)size;
emit_copy_if_needed(isel, dst, src0, size); emit_copy_if_needed(isel, dst, src0, size);
bool is_imm = (src1.kind == SCC_MIR_OP_IMM); bool is_imm = (src1.kind == SCC_X86_OPR_IMM);
scc_x86_iform_t iform; scc_x86_iform_t iform;
switch (op) { switch (op) {
case SCC_LIR_ADD: case SCC_LIR_ADD:
iform = is_imm ? SCC_X86_IFORM_ADD_GPRV_IMMZ iform = is_imm ? SCC_X86_IFORM_ADD_GPRV_IMMZ
: SCC_X86_IFORM_ADD_GPRV_GPRV_01; : SCC_X86_IFORM_ADD_GPRV_GPRV_03;
break; break;
case SCC_LIR_SUB: case SCC_LIR_SUB:
iform = is_imm ? SCC_X86_IFORM_SUB_GPRV_IMMZ iform = is_imm ? SCC_X86_IFORM_SUB_GPRV_IMMZ
: SCC_X86_IFORM_SUB_GPRV_GPRV_29; : SCC_X86_IFORM_SUB_GPRV_GPRV_2B;
break; break;
case SCC_LIR_AND: case SCC_LIR_AND:
iform = is_imm ? SCC_X86_IFORM_AND_GPRV_IMMZ iform = is_imm ? SCC_X86_IFORM_AND_GPRV_IMMZ
: SCC_X86_IFORM_AND_GPRV_GPRV_21; : SCC_X86_IFORM_AND_GPRV_GPRV_23;
break; break;
case SCC_LIR_OR: case SCC_LIR_OR:
iform = iform =
is_imm ? SCC_X86_IFORM_OR_GPRV_IMMZ : SCC_X86_IFORM_OR_GPRV_GPRV_09; is_imm ? SCC_X86_IFORM_OR_GPRV_IMMZ : SCC_X86_IFORM_OR_GPRV_GPRV_0B;
break; break;
case SCC_LIR_XOR: case SCC_LIR_XOR:
iform = is_imm ? SCC_X86_IFORM_XOR_GPRV_IMMZ iform = is_imm ? SCC_X86_IFORM_XOR_GPRV_IMMZ
: SCC_X86_IFORM_XOR_GPRV_GPRV_31; : SCC_X86_IFORM_XOR_GPRV_GPRV_33;
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@@ -208,32 +217,22 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
add_instr_2(isel, iform, dst, src1); add_instr_2(isel, iform, dst, src1);
} }
static scc_mir_operand_t stack_slot_op(int offset) { static void emit_spill_load(scc_x86_64_isel_t *isel, int vreg, int slot) {
return (scc_mir_operand_t){.kind = SCC_MIR_OP_MEM, .stack_slot = offset}; scc_x86_operand_value_t dst = scc_x86_op_vreg(vreg);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, scc_x86_op_slot(slot));
} }
static void emit_spill_load(scc_x86_64_isel_t *isel, int vreg, int offset) { static void emit_spill_store(scc_x86_64_isel_t *isel, int vreg, int slot) {
scc_mir_operand_t dst = {.kind = SCC_MIR_OP_VREG, .vreg = vreg}; scc_x86_operand_value_t src = scc_x86_op_vreg(vreg);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, stack_slot_op(offset)); add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, scc_x86_op_slot(slot), src);
} }
static void emit_spill_store(scc_x86_64_isel_t *isel, int vreg, int offset) {
scc_mir_operand_t src = {.kind = SCC_MIR_OP_VREG, .vreg = vreg};
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, stack_slot_op(offset), src);
}
// static void emit_alloca(scc_x86_64_isel_t *isel, scc_mir_operand_t dst,
// i64 size) {
// scc_mir_operand_t imm = {.kind = SCC_MIR_OP_IMM, .imm = size};
// scc_mir_operand_t rsp = {.kind = SCC_MIR_OP_PREG, .preg =
// SCC_X86_REG_RSP}; add_instr_2(isel, SCC_X86_IFORM_SUB_GPRV_IMMZ, rsp,
// imm); scc_x86_emit_move(isel, dst, rsp, 8);
// }
static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
scc_mir_operand_t dst = scc_x86_lir_val_to_mir_op(isel, &instr->to); scc_x86_operand_value_t dst = scc_x86_lir_val_to_mir_op(isel, &instr->to);
scc_mir_operand_t src0 = scc_x86_lir_val_to_mir_op(isel, &instr->arg0); scc_x86_operand_value_t src0 =
scc_mir_operand_t src1 = scc_x86_lir_val_to_mir_op(isel, &instr->arg1); scc_x86_lir_val_to_mir_op(isel, &instr->arg0);
scc_x86_operand_value_t src1 =
scc_x86_lir_val_to_mir_op(isel, &instr->arg1);
u8 size = instr->size; u8 size = instr->size;
switch (instr->op) { switch (instr->op) {
@@ -241,23 +240,19 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
case SCC_LIR_MOV: case SCC_LIR_MOV:
scc_x86_emit_move(isel, dst, src0, size); scc_x86_emit_move(isel, dst, src0, size);
break; break;
case SCC_LIR_LOAD: case SCC_LIR_LOAD:
// 从 [addr] 加载到 vregaddr 通常为 vreg scc_x86_emit_move(isel, dst, src0, size);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src0); break;
case SCC_LIR_STORE:
scc_x86_emit_move(isel, src1, src0, size);
break; break;
case SCC_LIR_STORE_ADDR: case SCC_LIR_STORE_ADDR:
TODO(); TODO();
break; break;
case SCC_LIR_STORE:
// 将 src0 存入 [src1]
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, src1, src0);
break;
case SCC_LIR_LEA: case SCC_LIR_LEA:
case SCC_LIR_LOAD_ADDR: case SCC_LIR_LOAD_ADDR:
// 地址计算src0 是复杂地址LIR 的 MEM 类型)
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0); add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0);
break; break;
@@ -279,18 +274,21 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
break; break;
case SCC_LIR_MUL: case SCC_LIR_MUL:
// imul dst, src0, src1 → 需要 mov + imul
emit_copy_if_needed(isel, dst, src0, size); emit_copy_if_needed(isel, dst, src0, size);
if (src1.kind == SCC_X86_OPR_IMM) {
scc_x86_operand_value_t op = new_vreg_temp(isel);
scc_x86_emit_move(isel, op, src1, size);
src1 = op;
}
add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1); add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1);
break; break;
case SCC_LIR_SHL: case SCC_LIR_SHL:
case SCC_LIR_SHR: case SCC_LIR_SHR:
case SCC_LIR_SAR: { case SCC_LIR_SAR: {
// 双地址dst = dst op count
emit_copy_if_needed(isel, dst, src0, size); emit_copy_if_needed(isel, dst, src0, size);
if (src1.kind == SCC_MIR_OP_IMM) { if (src1.kind == SCC_X86_OPR_IMM) {
scc_x86_iform_t iform; scc_x86_iform_t iform;
switch (instr->op) { switch (instr->op) {
case SCC_LIR_SHL: case SCC_LIR_SHL:
@@ -307,10 +305,8 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
} }
add_instr_2(isel, iform, dst, src1); add_instr_2(isel, iform, dst, src1);
} else { } else {
// 移位量在 CL需要先 mov cl, src1 scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL);
scc_mir_operand_t cl = {.kind = SCC_MIR_OP_PREG, scc_x86_emit_move(isel, cl, src1, 1);
.preg = SCC_X86_REG_CL};
scc_x86_emit_move(isel, cl, src1, 1); // CL 是 8 位
scc_x86_iform_t iform; scc_x86_iform_t iform;
switch (instr->op) { switch (instr->op) {
case SCC_LIR_SHL: case SCC_LIR_SHL:
@@ -334,19 +330,15 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
case SCC_LIR_DIV_U: case SCC_LIR_DIV_U:
case SCC_LIR_REM_S: case SCC_LIR_REM_S:
case SCC_LIR_REM_U: { case SCC_LIR_REM_U: {
scc_mir_operand_t rax = {.kind = SCC_MIR_OP_PREG, scc_x86_operand_value_t rax = scc_x86_op_preg(SCC_X86_REG_RAX);
.preg = SCC_X86_REG_RAX}; scc_x86_operand_value_t rdx = scc_x86_op_preg(SCC_X86_REG_RDX);
scc_mir_operand_t rdx = {.kind = SCC_MIR_OP_PREG,
.preg = SCC_X86_REG_RDX};
scc_x86_emit_move(isel, rax, src0, size); scc_x86_emit_move(isel, rax, src0, size);
if (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) { if (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) {
// 有符号扩展cqo / cdq根据 size 选择,这里简化为 64 位 cqo
add_instr_0(isel, SCC_X86_IFORM_CQO); add_instr_0(isel, SCC_X86_IFORM_CQO);
} else { } else {
// 无符号xor edx, edx scc_x86_operand_value_t zero = scc_x86_op_imm(0);
scc_mir_operand_t zero = {.kind = SCC_MIR_OP_IMM, .imm = 0};
scc_x86_emit_move(isel, rdx, zero, size); scc_x86_emit_move(isel, rdx, zero, size);
} }
@@ -356,7 +348,6 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
: SCC_X86_IFORM_DIV_GPRV; : SCC_X86_IFORM_DIV_GPRV;
add_instr_1(isel, div_if, src1); add_instr_1(isel, div_if, src1);
// 结果:商在 RAX余数在 RDX
if (instr->op == SCC_LIR_REM_S || instr->op == SCC_LIR_REM_U) if (instr->op == SCC_LIR_REM_S || instr->op == SCC_LIR_REM_U)
scc_x86_emit_move(isel, dst, rdx, size); scc_x86_emit_move(isel, dst, rdx, size);
else else
@@ -365,66 +356,57 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
/* ---- 比较指令 ---- */ /* ---- 比较指令 ---- */
case SCC_LIR_CMP: { case SCC_LIR_CMP: {
// 1. 比较并设置标志位 if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM)
if (src0.kind == SCC_MIR_OP_VREG && src1.kind == SCC_MIR_OP_IMM)
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1); add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1);
else if (src0.kind == SCC_MIR_OP_VREG && src1.kind == SCC_MIR_OP_VREG) else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1))
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_39, src0, src1); add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1);
else else
UNREACHABLE(); UNREACHABLE();
// 2. 标志位 -> 布尔值 (写入 dst)
scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond); scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond);
add_instr_1(isel, setcc, dst); // 注意 setcc 只写低 8 位 add_instr_1(isel, setcc, dst);
// 若需 32/64 位布尔值,可再 movzx dst, dst
if (size > 1) { if (size > 1) {
// movzx dst, dst (假设 MOVZX_GPRV_GPR8 存在;这里临时用 and 模拟) scc_x86_operand_value_t one = scc_x86_op_imm(1);
// 简单处理:用 and dst, 1 清理高位
scc_mir_operand_t one = {.kind = SCC_MIR_OP_IMM, .imm = 1};
add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one); add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one);
} }
} break; } break;
/* ---- 条件分支 ---- */ /* ---- 条件分支 ---- */
case SCC_LIR_BR: { case SCC_LIR_BR: {
// arg0 是 CMP 产生的布尔值 (0 或 1) scc_x86_operand_value_t true_bb =
// test src0, src0 ; jnz true_bb ; jmp false_bb scc_x86_op_block(instr->metadata.br.true_target);
scc_mir_operand_t true_bb = {.kind = SCC_MIR_OP_BLOCK, scc_x86_operand_value_t false_bb =
.block_id = scc_x86_op_block(instr->metadata.br.false_target);
instr->metadata.br.true_target};
scc_mir_operand_t false_bb = {.kind = SCC_MIR_OP_BLOCK,
.block_id =
instr->metadata.br.false_target};
// test src0, src0
add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0); add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0);
// jnz true
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb); add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb);
// jmp false
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb); add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb);
} break; } break;
case SCC_LIR_JMP: { case SCC_LIR_JMP: {
add_instr_1( scc_x86_operand_value_t jmp_bb =
isel, SCC_X86_IFORM_JMP_RELBRZ, scc_x86_op_block(instr->metadata.jmp_target);
(scc_mir_operand_t){.kind = SCC_MIR_OP_BLOCK, add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb);
.block_id = instr->metadata.jmp_target});
} break; } break;
/* ---- 栈分配 ---- */ /* ---- 栈分配 ---- */
case SCC_LIR_ALLOCA: case SCC_LIR_ALLOCA: {
// emit_alloca(isel, dst, instr->metadata.alloca.size_bytes); scc_x86_operand_value_t op =
scc_mir_operand_t op = scc_x86_lir_val_to_mir_op(isel, &instr->to); scc_x86_lir_val_to_mir_op(isel, &instr->to);
add_instr_2(isel, (scc_x86_iform_t)SCC_MIR_PSUEDO_ALLOCA, op, scc_mir_x86_instr_t x86instr;
(scc_mir_operand_t){ x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA;
.kind = SCC_MIR_OP_IMM, Assert(op.kind == SCC_X86_OPR_REG);
.imm = instr->size, x86instr.instr.data.alloc.vreg = op.reg;
}); x86instr.instr.data.alloc.size = instr->size;
Assert(op.kind == SCC_MIR_OP_VREG); x86instr.instr.data.alloc.align = 0;
scc_vec_push(isel->instrs, x86instr);
scc_mir_vreg_map2slot(isel->func, instr->to.data.reg, instr->size, 0);
break; break;
}
/* ---- 其他(占位) ---- */ /* ---- 其他(占位) ---- */
case SCC_LIR_NOP: case SCC_LIR_NOP:
add_instr_0(isel, SCC_X86_IFORM_NOP_90);
break; break;
/* ---- 调用与返回 ---- */ /* ---- 调用与返回 ---- */
@@ -465,6 +447,7 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module,
const scc_lir_module_t *lir_module, const scc_lir_module_t *lir_module,
scc_x86_64_isel_t *isel) { scc_x86_64_isel_t *isel) {
mir_module->instr_size = sizeof(scc_mir_x86_instr_t);
scc_vec_foreach(lir_module->cfg_module.funcs, i) { scc_vec_foreach(lir_module->cfg_module.funcs, i) {
if (i == 0) if (i == 0)
continue; continue;
@@ -474,7 +457,6 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module,
scc_malloc(sizeof(scc_mir_func_meta_t)); scc_malloc(sizeof(scc_mir_func_meta_t));
Assert(func_meta != nullptr); Assert(func_meta != nullptr);
scc_mir_func_meta_init(func_meta); scc_mir_func_meta_init(func_meta);
// FIXME
func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count; func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count;
func->meta = func_meta; func->meta = func_meta;

View File

@@ -0,0 +1,201 @@
#include <arch/scc_x86_isel.h>
#include <arch/scc_x86_mir.h>
#include <arch/scc_x86_reg_alloc.h>
#include <x86/scc_x86_iform.h>
#include <x86/scc_x86_reg.h>
/* ========== 指令访问回调 ========== */
static int instr_opcode(const void *instr) {
return ((const scc_mir_x86_instr_t *)instr)->x86_instr.opcode;
}
static int instr_num_operands(const void *instr) {
return ((const scc_mir_x86_instr_t *)instr)->x86_instr.num_operands;
}
static bool op_is_vreg(const void *instr, int idx) {
return scc_x86_op_is_vreg(
&((const scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx]);
}
static int op_get_vreg(const void *instr, int idx) {
return scc_x86_op_get_vreg(
&((const scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx]);
}
static void op_set_preg(void *instr, int idx, int preg) {
scc_x86_op_set_preg(
&((scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx],
(scc_x86_reg_t)preg);
}
static void op_set_slot(void *instr, int idx, int slot) {
((scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx] =
scc_x86_op_slot(slot);
}
/* ========== 伪指令处理 ========== */
static bool is_pseudo(const void *instr) {
return ((const scc_mir_x86_instr_t *)instr)->x86_instr.opcode < 0;
}
static void handle_pseudo(scc_mir_func_t *func, void *instr, void *out) {
scc_mir_x86_instr_t *ins = instr;
scc_mir_x86_instr_vec_t *out_vec = out;
if (ins->x86_instr.opcode == SCC_MIR_PSEUDO_ALLOCA) {
// // 指令选择时已分配 slot直接替换为 slot 操作数
// if (scc_x86_op_is_vreg(&ins->x86_instr.operands[0])) {
// int vreg = scc_x86_op_get_vreg(&ins->x86_instr.operands[0]);
// int slot = scc_mir_vreg_map2slot(func, vreg, 8, 8);
// ins->x86_instr.operands[0] = scc_x86_op_slot(slot);
// }
// scc_vec_push(*out_vec, *ins);
} else {
scc_vec_push(*out_vec, *ins);
}
}
/* ========== Spill / Reload / Copy ========== */
static void emit_spill(void *out, int preg, int slot) {
scc_mir_x86_instr_vec_t *vec = out;
scc_mir_x86_instr_t ins = {
.x86_instr.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV,
.x86_instr.num_operands = 2,
.x86_instr.operands = {scc_x86_op_slot(slot), scc_x86_op_preg(preg)}};
scc_vec_push(*vec, ins);
}
static void emit_reload(void *out, int preg, int slot) {
scc_mir_x86_instr_vec_t *vec = out;
scc_mir_x86_instr_t ins = {
.x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV,
.x86_instr.num_operands = 2,
.x86_instr.operands = {scc_x86_op_preg(preg), scc_x86_op_slot(slot)}};
scc_vec_push(*vec, ins);
}
static void emit_copy(void *out, int dst_preg, int src_preg, int size) {
(void)size;
scc_mir_x86_instr_vec_t *vec = out;
scc_mir_x86_instr_t ins = {
.x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_GPRV_8B,
.x86_instr.num_operands = 2,
.x86_instr.operands = {scc_x86_op_preg(dst_preg),
scc_x86_op_preg(src_preg)}};
scc_vec_push(*vec, ins);
}
/* ========== 操作数读写属性 ========== */
static scc_reg_op_access_t get_operand_access(void *ctx, int opcode,
int op_idx) {
(void)ctx;
if (opcode >= 0 && opcode < SCC_X86_IFORM_COUNT) {
const scc_x86_iform_info_t *info = &scc_x86_iform_table[opcode];
if (op_idx >= info->num_ops || op_idx < 0)
return SCC_REG_ALLOC_OP_ACCESS_READWRITE;
if (info->ops[op_idx].rw[0] == 'r')
return info->ops[op_idx].rw[1] == 'w'
? SCC_REG_ALLOC_OP_ACCESS_READWRITE
: SCC_REG_ALLOC_OP_ACCESS_READ;
else if (info->ops[op_idx].rw[0] == 'w')
return SCC_REG_ALLOC_OP_ACCESS_WRITE;
}
return SCC_REG_ALLOC_OP_ACCESS_READWRITE;
}
/* ========== 隐式寄存器 ========== */
static void get_implicit_regs(void *ctx, int opcode, const int **uses,
const int **defs) {
(void)ctx;
static const int empty[] = {-1};
static const int rax[] = {SCC_X86_REG_RAX, -1};
static const int rdx[] = {SCC_X86_REG_RDX, -1};
static const int rax_rdx[] = {SCC_X86_REG_RAX, SCC_X86_REG_RDX, -1};
static const int cl[] = {SCC_X86_REG_CL, -1};
switch (opcode) {
case SCC_X86_IFORM_IDIV_GPRV:
case SCC_X86_IFORM_DIV_GPRV:
*uses = rax_rdx;
*defs = rax_rdx;
break;
case SCC_X86_IFORM_CQO:
*uses = rax;
*defs = rax_rdx;
break;
case SCC_X86_IFORM_SAR_GPRV_CL:
*uses = cl;
*defs = empty;
break;
default:
*uses = empty;
*defs = empty;
break;
}
}
/* ========== 寄存器池 ========== */
static const int reg_pool[] = {
SCC_X86_REG_R8, SCC_X86_REG_R9, SCC_X86_REG_R10, SCC_X86_REG_R11,
SCC_X86_REG_R12, SCC_X86_REG_R13, SCC_X86_REG_R14, SCC_X86_REG_R15};
static uint32_t reg_mask = 0;
static int acquire_reg(void *ctx) {
(void)ctx;
for (int i = 0; i < SCC_ARRLEN(reg_pool); i++)
if (!(reg_mask & (1u << i))) {
reg_mask |= (1u << i);
return reg_pool[i];
}
UNREACHABLE();
}
static void release_reg(void *ctx, int preg) {
(void)ctx;
for (int i = 0; i < SCC_ARRLEN(reg_pool); i++)
if (reg_pool[i] == preg) {
reg_mask &= ~(1u << i);
return;
}
}
static void mark_reg_used(void *ctx, int preg) {
(void)ctx;
for (int i = 0; i < SCC_ARRLEN(reg_pool); i++)
if (reg_pool[i] == preg) {
reg_mask |= (1u << i);
return;
}
}
static void clean_mark_regs(void *ctx) {
(void)ctx;
reg_mask = 0;
}
/* ========== 注册全部 x86 回调 ========== */
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
ops->acquire_reg = acquire_reg;
ops->release_reg = release_reg;
ops->mark_reg_used = mark_reg_used;
ops->clean_mark_regs = clean_mark_regs;
ops->instr_opcode = instr_opcode;
ops->instr_num_operands = instr_num_operands;
ops->op_is_vreg = op_is_vreg;
ops->op_get_vreg = op_get_vreg;
ops->op_set_preg = op_set_preg;
ops->op_set_slot = op_set_slot;
ops->get_operand_access = get_operand_access;
ops->get_implicit_regs = get_implicit_regs;
ops->is_pseudo = is_pseudo;
ops->handle_pseudo = handle_pseudo;
ops->emit_spill = emit_spill;
ops->emit_reload = emit_reload;
ops->emit_copy = emit_copy;
}

View File

@@ -1,83 +0,0 @@
#include <arch/x86_64_isel.h>
#include <arch/x86_64_reg_alloc.h>
static void x86_emit_spill(scc_mir_instr_vec_t *ctx, int preg, int slot) {
scc_mir_instr_t ins = {
.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV,
.num_operands = 2,
.operands = {{.kind = SCC_MIR_OP_MEM, .stack_slot = slot},
{.kind = SCC_MIR_OP_PREG, .preg = preg}}};
scc_vec_push(*ctx, ins);
}
static void x86_emit_reload(scc_mir_instr_vec_t *ctx, int preg, int slot) {
scc_mir_instr_t ins = {
.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV,
.num_operands = 2,
.operands = {{.kind = SCC_MIR_OP_PREG, .preg = preg},
{.kind = SCC_MIR_OP_MEM, .stack_slot = slot}}};
scc_vec_push(*ctx, ins);
}
static void x86_emit_copy(scc_mir_instr_vec_t *ctx, int dst_preg, int src_preg,
int size) {
scc_mir_instr_t ins = {
.opcode = SCC_X86_IFORM_MOV_GPRV_GPRV_89,
.num_operands = 2,
.operands = {{.kind = SCC_MIR_OP_PREG, .preg = dst_preg},
{.kind = SCC_MIR_OP_PREG, .preg = src_preg}}};
scc_vec_push(*ctx, ins);
}
/* ---- 临时寄存器 ---- */
static int x86_acquire_temp_reg(void *vctx) { return SCC_X86_REG_R11; }
static void x86_release_temp_reg(void *vctx, int preg) { /* 简单模式无需操作 */
}
/* ---- 操作数读写属性 ---- */
static scc_op_access_t x86_get_operand_access(void *vctx, int opcode,
int op_idx) {
switch (opcode) {
default:
return SCC_REG_ALLOC_OP_ACCESS_READWRITE; // 保守
}
}
/* ---- 隐式寄存器 ---- */
static void x86_get_implicit_regs(void *vctx, int opcode, const int **uses,
const int **defs) {
static const int empty[] = {-1};
static const int rax[] = {SCC_X86_REG_RAX, -1};
static const int rdx[] = {SCC_X86_REG_RDX, -1};
static const int rax_rdx[] = {SCC_X86_REG_RAX, SCC_X86_REG_RDX, -1};
static const int cl[] = {SCC_X86_REG_CL, -1};
switch (opcode) {
case SCC_X86_IFORM_IDIV_GPRV:
case SCC_X86_IFORM_DIV_GPRV:
*uses = rax_rdx;
*defs = rax_rdx;
break;
case SCC_X86_IFORM_CQO:
*uses = rax;
*defs = rax_rdx;
break;
case SCC_X86_IFORM_SAR_GPRV_CL:
*uses = cl;
*defs = empty;
break;
default:
*uses = empty;
*defs = empty;
break;
}
}
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
ops->emit_spill = x86_emit_spill;
ops->emit_reload = x86_emit_reload;
ops->emit_copy = x86_emit_copy;
ops->get_operand_access = x86_get_operand_access;
ops->get_implicit_regs = x86_get_implicit_regs;
}

View File

@@ -1,3 +0,0 @@
#include <core_pass/scc_frame_layout.h>
void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module) {}

View File

@@ -1,174 +1,76 @@
#include <core_pass/scc_reg_alloc.h> #include <core_pass/scc_reg_alloc.h>
#include <scc_hashtable.h>
#include <scc_mir_module.h> #include <scc_mir_module.h>
// static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
// scc_mir_instr_vec_t *instr_vec,
// scc_mir_instr_t *instr) {
// const scc_reg_alloc_op_t *ops = &ctx->ops;
// scc_mir_instr_vec_t before, after;
// scc_vec_init(before);
// scc_vec_init(after);
// // 1. 标记隐式寄存器为占用
// const int *implicit_uses, *implicit_defs;
// ops->get_implicit_regs(ctx, instr->opcode, &implicit_uses,
// &implicit_defs); for (const int *p = implicit_uses; *p != -1; p++)
// ops->mark_reg_used(ctx, *p);
// for (const int *p = implicit_defs; *p != -1; p++)
// ops->mark_reg_used(ctx, *p);
// SCC_VEC(int) preg_vec;
// scc_vec_init(preg_vec);
// for (int i = 0; i < instr->num_operands; i++) {
// if (instr->operands[i].kind != SCC_MIR_OP_VREG)
// continue;
// int vreg = instr->operands[i].vreg;
// scc_mir_vreg_op(ctx->func, vreg, &instr->operands[i]);
// if (instr->operands[i].kind != SCC_MIR_OP_VREG)
// continue;
// // FIXME size alian
// int slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8);
// int preg = -1;
// // if (implicit_uses && implicit_uses[0] != -1)
// // preg = implicit_uses[0];
// // else
// preg = ops->acquire_reg(ctx);
// scc_vec_push(preg_vec, preg);
// // 根据操作数读写属性决定是否需要 reload
// scc_op_access_t acc = ops->get_operand_access(ctx, instr->opcode, i);
// if (acc == SCC_REG_ALLOC_OP_ACCESS_READ ||
// acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) {
// ops->emit_reload(&before, preg, slot);
// }
// if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE ||
// acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) {
// ops->emit_spill(&after, preg, slot);
// }
// // 替换操作数为物理寄存器
// instr->operands[i].kind = SCC_MIR_OP_PREG;
// instr->operands[i].preg = preg;
// }
// scc_vec_foreach(preg_vec, i) {
// int preg = scc_vec_at(preg_vec, i);
// ops->release_reg(ctx, preg);
// }
// scc_vec_foreach(before, i) scc_vec_push(*instr_vec, scc_vec_at(before,
// i)); scc_vec_push(*instr_vec, *instr); scc_vec_foreach(after, i)
// scc_vec_push(*instr_vec, scc_vec_at(after, i));
// // 7. 取消隐式寄存器的占用标记
// Assert(ops->mark_reg_used != nullptr);
// for (const int *p = implicit_defs; *p != -1; p++)
// ops->mark_reg_used(ctx, *p);
// for (const int *p = implicit_uses; *p != -1; p++)
// ops->release_reg(ctx, *p);
// scc_vec_free(before);
// scc_vec_free(after);
// }
static void alloc_instr(scc_reg_alloc_ctx_t *ctx, static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
scc_mir_instr_vec_t *instr_vec, scc_mir_instr_vec_t *instr_vec,
scc_mir_instr_t *instr) { scc_mir_instr_t *instr) {
const scc_reg_alloc_op_t *ops = &ctx->ops; const scc_reg_alloc_op_t *ops = &ctx->ops;
usize instr_size = ctx->module->instr_size;
if (ops->is_pseudo(instr)) {
ops->handle_pseudo(ctx->func, (void *)instr, instr_vec);
return;
}
scc_mir_instr_vec_t before, after; scc_mir_instr_vec_t before, after;
scc_vec_init(before); scc_vec_init(before);
scc_vec_init(after); scc_vec_init(after);
SCC_VEC(int) allocated;
scc_vec_init(allocated);
// 隐式寄存器标记 int opcode = ops->instr_opcode(instr);
// 标记隐式寄存器
const int *implicit_uses, *implicit_defs; const int *implicit_uses, *implicit_defs;
ops->get_implicit_regs(ctx, instr->opcode, &implicit_uses, &implicit_defs); ops->get_implicit_regs(ctx, opcode, &implicit_uses, &implicit_defs);
for (const int *p = implicit_uses; *p != -1; p++) for (const int *p = implicit_uses; *p != -1; p++)
ops->mark_reg_used(ctx, *p); ops->mark_reg_used(ctx, *p);
for (const int *p = implicit_defs; *p != -1; p++) for (const int *p = implicit_defs; *p != -1; p++)
ops->mark_reg_used(ctx, *p); ops->mark_reg_used(ctx, *p);
// 指令内 vreg→preg 的简单映射(操作数不超过 8 个) int num_ops = ops->instr_num_operands(instr);
int local_vreg[8], local_preg[8]; for (int op_i = 0; op_i < num_ops; op_i++) {
int local_cnt = 0; if (!ops->op_is_vreg(instr, op_i))
SCC_VEC(int) allocated_pregs;
scc_vec_init(allocated_pregs);
for (int i = 0; i < instr->num_operands; i++) {
scc_mir_operand_t *op = &instr->operands[i];
// 只处理 vreg
if (op->kind != SCC_MIR_OP_VREG)
continue; continue;
int vreg = op->vreg; int vreg = ops->op_get_vreg(instr, op_i);
int id = 0;
int mapping = scc_mir_vreg_lookup(ctx->func, vreg, &id);
int preg = id, slot = id;
// 查询当前 vreg 的映射(可能已经被之前的分配改为 MEM 等,但我们只需要 if (mapping == 1) {
// slot // 已预着色
scc_mir_vreg_op(ctx->func, vreg, op); ops->mark_reg_used(ctx, preg);
int slot; ops->op_set_preg(instr, op_i, preg);
if (op->kind == SCC_MIR_OP_VREG) { continue;
// 还没有 slot → 分配一个 }
if (mapping == 0)
slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8); slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8);
} else {
// 已经是 MEM直接用它的 slot
Assert(op->kind == SCC_MIR_OP_MEM);
slot = op->stack_slot;
}
// 在本指令内查找是否已为这个 vreg 分配了 preg
int preg = -1;
for (int k = 0; k < local_cnt; k++) {
if (local_vreg[k] == vreg) {
preg = local_preg[k];
break;
}
}
if (preg == -1) {
// 新分配
preg = ops->acquire_reg(ctx); preg = ops->acquire_reg(ctx);
scc_vec_push(allocated_pregs, preg); scc_vec_push(allocated, preg);
local_vreg[local_cnt] = vreg;
local_preg[local_cnt] = preg;
local_cnt++;
}
// 读写属性 scc_reg_op_access_t acc = ops->get_operand_access(ctx, opcode, op_i);
scc_op_access_t acc = ops->get_operand_access(ctx, instr->opcode, i);
// reload: slot → preg
if (acc == SCC_REG_ALLOC_OP_ACCESS_READ || if (acc == SCC_REG_ALLOC_OP_ACCESS_READ ||
acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
ops->emit_reload(&before, preg, slot); ops->emit_reload(&before, preg, slot);
}
// spill: preg → slot
if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE || if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE ||
acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
ops->emit_spill(&after, preg, slot); ops->emit_spill(&after, preg, slot);
}
// 替换操作数 ops->op_set_preg(instr, op_i, preg);
op->kind = SCC_MIR_OP_PREG;
op->preg = preg;
} }
// 释放本指令分配的临时寄存器
scc_vec_foreach(allocated_pregs, i)
ops->release_reg(ctx, scc_vec_at(allocated_pregs, i));
// 合并指令流 // 合并指令流
scc_vec_foreach(before, i) scc_vec_push(*instr_vec, scc_vec_at(before, i)); scc_vec_foreach(before, i) scc_vec_sized_push(
scc_vec_push(*instr_vec, *instr); *instr_vec, instr_size, scc_vec_sized_at_ptr(before, instr_size, i),
scc_vec_foreach(after, i) scc_vec_push(*instr_vec, scc_vec_at(after, i)); instr_size);
scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size);
scc_vec_foreach(after, i) scc_vec_sized_push(
*instr_vec, instr_size, scc_vec_sized_at_ptr(after, instr_size, i),
instr_size);
// 隐式寄存器清理 // 清理隐式寄存器
for (const int *p = implicit_defs; *p != -1; p++) for (const int *p = implicit_defs; *p != -1; p++)
ops->mark_reg_used(ctx, *p); ops->mark_reg_used(ctx, *p);
for (const int *p = implicit_uses; *p != -1; p++) for (const int *p = implicit_uses; *p != -1; p++)
@@ -176,58 +78,40 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
scc_vec_free(before); scc_vec_free(before);
scc_vec_free(after); scc_vec_free(after);
scc_vec_free(allocated_pregs); scc_vec_foreach(allocated, l)
ops->release_reg(ctx, scc_vec_at(allocated, l));
scc_vec_free(allocated);
} }
/* 对一个基本块执行分配 */ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) {
static void alloc_bb(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module, const scc_reg_alloc_op_t *ops = &ctx->ops;
scc_cfg_bblock_id_t bb_id) { ctx->module = module;
scc_vec_foreach(module->cfg_module.funcs, i) {
if (i == 0)
continue;
scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i);
ops->clean_mark_regs(ctx);
ctx->func = func;
scc_vec_foreach(func->bblocks, j) {
scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, j);
scc_cfg_bblock_t *bb = scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id); scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id);
Assert(bb != nullptr);
scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES(bb);
scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
scc_mir_instr_vec_t new_instrs; scc_mir_instr_vec_t new_instrs;
scc_vec_init(new_instrs); scc_vec_init(new_instrs);
scc_vec_foreach(*old_instrs, i) { scc_vec_foreach(*old_instrs, k) {
scc_mir_instr_t ins = scc_vec_at(*old_instrs, i); scc_mir_instr_t *instr = scc_vec_sized_at_ptr(
alloc_instr(ctx, &new_instrs, &ins); *old_instrs, ctx->module->instr_size, k);
alloc_instr(ctx, &new_instrs, instr);
} }
scc_vec_free(*old_instrs); scc_vec_free(*old_instrs);
*old_instrs = new_instrs; *old_instrs = new_instrs;
} }
/* 对一个函数运行分配 */
static void alloc_func(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module,
scc_mir_func_t *func) {
ctx->ops.clean_mark_regs(ctx);
ctx->func = func;
scc_vec_foreach(func->bblocks, i) {
scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, i);
alloc_bb(ctx, module, bb_id);
}
}
/* 公开入口 */
void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) {
Assert(ctx != nullptr && module != nullptr);
Assert(ctx->ops.acquire_reg != nullptr);
Assert(ctx->ops.clean_mark_regs != nullptr);
Assert(ctx->ops.emit_copy != nullptr);
Assert(ctx->ops.emit_reload != nullptr);
Assert(ctx->ops.emit_spill != nullptr);
Assert(ctx->ops.get_implicit_regs != nullptr);
Assert(ctx->ops.get_operand_access != nullptr);
Assert(ctx->ops.mark_reg_used != nullptr);
Assert(ctx->ops.release_reg != nullptr);
scc_vec_foreach(module->cfg_module.funcs, i) {
if (i == 0)
continue;
alloc_func(ctx, module, &scc_vec_at(module->cfg_module.funcs, i));
} }
} }

View File

@@ -1,10 +1,10 @@
#include <arch/x86_64_isel.h> #include <arch/scc_x86_isel.h>
#include <scc_lir2mir.h> #include <scc_lir2mir.h>
#include <target/scc_win64.h> #include <target/scc_win64.h>
void scc_lir2mir(scc_mir_module_t *mir_module, void scc_lir2mir(scc_mir_module_t *mir_module,
const scc_lir_module_t *lir_module) { const scc_lir_module_t *lir_module) {
// FIXME hack cfg module // Move
mir_module->cfg_module = lir_module->cfg_module; mir_module->cfg_module = lir_module->cfg_module;
scc_x86_64_isel_t isel; scc_x86_64_isel_t isel;

View File

@@ -1,9 +1,11 @@
#include <scc_mir.h> #include <scc_mir.h>
void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta) { void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta) {
func_meta->need_va_args = false;
func_meta->frame_size = 0; func_meta->frame_size = 0;
func_meta->stack_alignment = 0; func_meta->stack_alignment = 0;
func_meta->vregs_count = 0; func_meta->vregs_count = 0;
func_meta->target_data = nullptr;
scc_vec_init(func_meta->stack_slots); scc_vec_init(func_meta->stack_slots);
// For null stack slot // For null stack slot
@@ -16,24 +18,6 @@ int scc_mir_alloc_vreg(scc_mir_func_t *func) {
return meta->vregs_count++; return meta->vregs_count++;
} }
void scc_mir_vreg_op(const scc_mir_func_t *func, int vreg,
scc_mir_operand_t *out) {
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
isize idx =
(isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg);
if (idx == 0) {
out->kind = SCC_MIR_OP_VREG;
out->vreg = vreg;
} else if (idx < 0) {
out->kind = SCC_MIR_OP_PREG;
out->preg = (int)-idx;
} else {
out->kind = SCC_MIR_OP_MEM;
Assert(idx < scc_vec_size(meta->stack_slots));
out->stack_slot = (int)(usize)idx;
}
}
void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg) { void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg) {
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
isize val = isize val =

View File

@@ -1,49 +1,34 @@
#include <arch/scc_x86_mir.h>
#include <scc_mir_dump.h> #include <scc_mir_dump.h>
void scc_x86_instr_dump(scc_tree_dump_t *dump, const scc_mir_instr_t *instr); void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr);
void scc_mir_dump_instr(scc_mir_dump_ctx_t *ctx, const scc_mir_instr_t *ins) {
scc_tree_dump_t *td = ctx->dump_ctx;
scc_tree_dump_begin_line(td);
if (ins->opcode >= 0) {
scc_x86_instr_dump(td, ins);
return;
}
switch (ins->opcode) {
case SCC_MIR_PSUEDO_ALLOCA:
scc_tree_dump_node(td, " @alloca");
scc_tree_dump_append_fmt(td, "(%d)", ins->operands[1].imm);
if (ins->operands[0].kind == SCC_MIR_OP_VREG) {
scc_tree_dump_append_fmt(td, " %%%d", ins->operands[0].vreg);
} else if (ins->operands[0].kind == SCC_MIR_OP_MEM) {
scc_tree_dump_append_fmt(td, " [%d]", ins->operands[0].stack_slot);
} else {
scc_tree_dump_append(td, "<alloced>");
}
break;
default:
break;
}
}
void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) { void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) {
Assert(ctx != nullptr && bb != nullptr); Assert(ctx != nullptr && bb != nullptr);
scc_tree_dump_t *td = ctx->dump_ctx; scc_tree_dump_t *td = ctx->dump_ctx;
// 基本块头部
scc_tree_dump_begin_line(td); scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "#BB%zu", bb->id); scc_tree_dump_branch(td, "#BB%zu", bb->id);
if (bb->name) { if (bb->name) {
scc_tree_dump_append_fmt(td, " (%s)", bb->name); scc_tree_dump_append_fmt(td, " (%s)", bb->name);
} }
scc_tree_dump_append(td, ":"); scc_tree_dump_append(td, ":");
// 输出每条指令 for (int i = 0; i < scc_vec_size(bb->values); i += 1) {
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); scc_tree_dump_begin_line(td);
scc_vec_foreach(*instrs, i) { scc_mir_instr_t *instr =
const scc_mir_instr_t *ins = &scc_vec_at(*instrs, i); scc_vec_sized_at_ptr(bb->values, ctx->mir_module->instr_size, i);
scc_mir_dump_instr(ctx, ins); if (instr->opcode < 0) {
switch (instr->opcode) {
case SCC_MIR_PSEUDO_ALLOCA:
scc_tree_dump_append_fmt(td, " alloca(%d)",
instr->data.alloc.size);
break;
default:
break;
}
} else {
scc_x86_instr_dump(td, (void *)instr);
}
} }
} }
@@ -52,11 +37,9 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) {
scc_tree_dump_t *td = ctx->dump_ctx; scc_tree_dump_t *td = ctx->dump_ctx;
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
// 函数头部
scc_tree_dump_begin_line(td); scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "func @%s", func->name ? func->name : "<anon>"); scc_tree_dump_node(td, "func @%s", func->name ? func->name : "<anon>");
// 输出所有基本块
scc_vec_foreach(func->bblocks, i) { scc_vec_foreach(func->bblocks, i) {
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
const scc_cfg_bblock_t *bb = const scc_cfg_bblock_t *bb =
@@ -67,7 +50,6 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) {
void scc_mir_dump_module(scc_mir_dump_ctx_t *ctx) { void scc_mir_dump_module(scc_mir_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->mir_module->cfg_module.symbols, i) { scc_vec_foreach(ctx->mir_module->cfg_module.symbols, i) {
// FIXME 0 is null
if (i == 0) if (i == 0)
continue; continue;
scc_cfg_symbol_t *sym = scc_cfg_symbol_t *sym =

View File

@@ -1,6 +1,8 @@
#include "scc_mir_module.h" #include "scc_mir_module.h"
void scc_mir_module_init(scc_mir_module_t *mir_module) { void scc_mir_module_init(scc_mir_module_t *mir_module) {
mir_module->instr_size = 0;
mir_module->cfg_module = (scc_cfg_module_t){0};
scc_vec_init(mir_module->func_metas); scc_vec_init(mir_module->func_metas);
scc_vec_init(mir_module->symbol_metas); scc_vec_init(mir_module->symbol_metas);
} }

View File

@@ -1,27 +1,80 @@
#include <arch/x86_64_reg_alloc.h> #include <arch/scc_x86_mir.h>
#include <arch/scc_x86_reg_alloc.h>
#include <target/scc_win64.h> #include <target/scc_win64.h>
#include <core_pass/scc_frame_layout.h> // #include <core_pass/scc_frame_layout.h>
#include <core_pass/scc_reg_alloc.h> // #include <core_pass/scc_prolog_epilog.h>
// #include <core_pass/scc_reg_alloc.h>
#include <scc_mir_module.h> #include <scc_mir_module.h>
#include <scc_mir_pass.h> #include <scc_mir_pass.h>
void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module) {
Assert(ctx && ctx->impl_fn && module);
scc_vec_foreach(module->cfg_module.funcs, i) {
if (i == 0)
continue;
ctx->impl_fn(ctx, module, &scc_vec_at(module->cfg_module.funcs, i));
}
}
void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) {
Assert(ctx && ctx->epilog && ctx->prolog && module);
scc_vec_foreach(module->cfg_module.funcs, i) {
if (i == 0)
continue;
scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i);
scc_vec_foreach(func->bblocks, i) {
scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, i);
scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id);
Assert(bb != nullptr);
scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
scc_mir_instr_vec_t new_instrs;
scc_vec_init(new_instrs);
if (i == 0) {
ctx->prolog(&new_instrs, func);
}
scc_vec_foreach(*old_instrs, i) {
scc_mir_instr_t *ins =
scc_vec_sized_at_ptr(*old_instrs, module->instr_size, i);
if (ins->opcode < 0) {
continue;
}
if (ctx->need_epilog(ins)) {
ctx->epilog(&new_instrs, func);
}
scc_vec_sized_push(new_instrs, module->instr_size, ins,
module->instr_size);
}
scc_vec_free(*old_instrs);
*old_instrs = new_instrs;
}
}
}
void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) { void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) {
scc_reg_alloc_ctx_t reg_alloc_ctx = { scc_reg_alloc_ctx_t reg_alloc_ctx = {.func = nullptr, .ops = {0}};
.func = nullptr, .instrs = nullptr, .ops = {0}};
scc_reg_alloc_fill_arch_x86(&reg_alloc_ctx.ops); scc_reg_alloc_fill_arch_x86(&reg_alloc_ctx.ops);
scc_reg_alloc_fill_win_x64(&reg_alloc_ctx.ops); scc_win_pc_x64_reg_alloc_fill(&reg_alloc_ctx.ops);
scc_reg_alloc(&reg_alloc_ctx, mir_module); scc_reg_alloc(&reg_alloc_ctx, mir_module);
if (stage == SCC_MIR_STAGE_REGALLOC) { if (stage == SCC_MIR_STAGE_REGALLOC) {
return; return;
} }
scc_frame_layout_t frame_layout_ctx = {0};
scc_win_pc_x64_frame_alloc_init(&frame_layout_ctx);
scc_frame_layout(&frame_layout_ctx, mir_module);
if (stage == SCC_MIR_STAGE_FRAME_LAYOUT) { if (stage == SCC_MIR_STAGE_FRAME_LAYOUT) {
return; return;
} }
scc_prolog_epilog_t prolog_epilog_ctx = {0};
scc_win_pc_x64_prolog_epilog_init(&prolog_epilog_ctx);
scc_prolog_epilog(&prolog_epilog_ctx, mir_module);
if (stage == SCC_MIR_STAGE_PROLOGUE_EPILOGUE) { if (stage == SCC_MIR_STAGE_PROLOGUE_EPILOGUE) {
return; return;
} }

View File

@@ -1,60 +1,59 @@
#include <scc_mir_module.h> #include <scc_mir_module.h>
#include <x86/scc_x86_iform.h> #include <x86/scc_x86_iform.h>
#include <arch/x86_64_isel.h> #include <arch/scc_x86_isel.h>
#include <core_pass/scc_abi_lowering.h>
#include <core_pass/scc_prolog_epilog.h> #include <core_pass/scc_prolog_epilog.h>
#include <target/scc_win64.h> #include <target/scc_win64.h>
static const int WIN64_DEFAULT_ALIGN = 8;
static const int WIN64_STACK_ALIGN = 16; static const int WIN64_STACK_ALIGN = 16;
typedef struct { static void frame_alloc_impl(scc_frame_layout_t *ctx,
scc_hashtable_t *vreg2slot;
int offset;
} frame_layout_ctx_t;
static void transit_vreg(scc_mir_func_meta_t *func, scc_mir_operand_t *op) {
Assert(op->kind == SCC_MIR_OP_VREG);
}
static void frame_alloc_impl(frame_layout_ctx_t *ctx,
scc_mir_module_t *mir_module, scc_mir_module_t *mir_module,
scc_mir_func_t *mir_func) { scc_mir_func_t *mir_func) {
/* ctx->offset = 8;
WIN ABI
*/
ctx->offset = 8; // called ret address
scc_mir_func_meta_t *func_meta = SCC_MIR_FUNC_META(mir_func); scc_mir_func_meta_t *func_meta = SCC_MIR_FUNC_META(mir_func);
scc_vec_foreach(mir_func->bblocks, i) { scc_vec_foreach(mir_func->bblocks, i) {
scc_cfg_bblock_id_t id = scc_vec_at(mir_func->bblocks, i); scc_cfg_bblock_id_t id = scc_vec_at(mir_func->bblocks, i);
scc_cfg_bblock_t *bb = scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id); scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); scc_mir_x86_instr_vec_t *instrs = SCC_MIR_X86_BBLOCK_INSTRS(bb);
scc_vec_foreach(*instrs, j) { scc_vec_foreach(*instrs, j) {
scc_mir_instr_t *ins = &scc_vec_at(*instrs, j); scc_mir_x86_instr_t *ins = &scc_vec_at(*instrs, j);
for (int k = 0; k < ins->num_operands; k += 1) { for (int k = 0; k < ins->x86_instr.num_operands; k++) {
if (ins->operands[k].kind == SCC_MIR_OP_VREG) { scc_x86_operand_value_t *op = &ins->x86_instr.operands[k];
transit_vreg(func_meta, &ins->operands[k]); if (scc_x86_op_is_slot(op)) {
int slot_id = scc_x86_op_slot_id(op);
scc_mir_stack_slot_t *slot =
scc_mir_unsafe_slot(mir_func, slot_id);
if (slot->offset == 0) {
ctx->offset += slot->size;
slot->offset = ctx->offset;
}
op->mem.base = SCC_X86_REG_RSP;
op->mem.disp = -slot->offset;
} }
} }
} }
} }
// Windows shadow space int total_size = ctx->offset + 32; // shadow space
int total_size = ctx->offset + 32; // 加上影子空间
// 16 字节栈对齐
ctx->offset = ctx->offset =
(total_size + WIN64_STACK_ALIGN - 1) & ~(WIN64_STACK_ALIGN - 1); (total_size + WIN64_STACK_ALIGN - 1) & ~(WIN64_STACK_ALIGN - 1);
func_meta->frame_size = ctx->offset;
}
void scc_win_pc_x64_frame_alloc_init(scc_frame_layout_t *ctx) {
ctx->impl_fn = frame_alloc_impl;
} }
/* /*
windows x86 prolog epilog windows x86 prolog epilog
https://learn.microsoft.com/zh-cn/cpp/build/prolog-and-epilog?view=msvc-180 https://learn.microsoft.com/zh-cn/cpp/build/prolog-and-epilog?view=msvc-180
*/ */
static void prologue(void *userdata, const scc_mir_func_t *func) { static void prologue(scc_mir_instr_vec_t *userdata,
scc_x86_64_isel_t *isel = userdata; const scc_mir_func_t *func) {
scc_mir_x86_instr_vec_t *instrs = (void *)userdata;
scc_mir_x86_instr_t instr;
/* /*
mov [RSP + 8], RCX mov [RSP + 8], RCX
push R15 push R15
@@ -65,25 +64,26 @@ static void prologue(void *userdata, const scc_mir_func_t *func) {
... ...
*/ */
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
int frame_size = meta->frame_size; // 之前计算好的 int frame_size = meta->frame_size;
// 1. push rbp // va_arg
add_instr_1(isel, SCC_X86_IFORM_PUSH_GPRV_50, reg_operand(SCC_X86_REG_RBP)); if (meta->need_va_args) {
/// FILL to shadow space
}
// 2. mov rbp, rsp // sub rsp, frame_size
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89,
reg_operand(SCC_X86_REG_RBP), reg_operand(SCC_X86_REG_RSP));
// 3. sub rsp, frame_size
if (frame_size > 0) { if (frame_size > 0) {
scc_mir_operand_t imm = {.kind = SCC_MIR_OP_IMM, .imm = frame_size}; scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_SUB_GPRV_IMMZ,
add_instr_2(isel, SCC_X86_IFORM_SUB_GPRV_IMMZ, scc_x86_op_preg(SCC_X86_REG_RSP),
reg_operand(SCC_X86_REG_RSP), imm); scc_x86_op_imm(frame_size), scc_pos_create());
scc_vec_push(*instrs, instr);
} }
} }
static void epilogue(void *userdata, const scc_mir_func_t *func) { static void epilogue(scc_mir_instr_vec_t *userdata,
scc_x86_64_isel_t *isel = userdata; const scc_mir_func_t *func) {
scc_mir_x86_instr_vec_t *instrs = (void *)userdata;
scc_mir_x86_instr_t instr;
/* /*
add RSP, fixed-allocation-size add RSP, fixed-allocation-size
pop R13 pop R13
@@ -91,91 +91,99 @@ static void epilogue(void *userdata, const scc_mir_func_t *func) {
pop R15 pop R15
ret ret
*/ */
// 1. mov rsp, rbp scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89, int frame_size = meta->frame_size;
reg_operand(SCC_X86_REG_RSP), reg_operand(SCC_X86_REG_RBP));
// 2. pop rbp // add rsp, frame_size
add_instr_1(isel, SCC_X86_IFORM_POP_GPRV_58, reg_operand(SCC_X86_REG_RBP)); if (frame_size > 0) {
scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_ADD_GPRV_IMMZ,
scc_x86_op_preg(SCC_X86_REG_RSP),
scc_x86_op_imm(frame_size), scc_pos_create());
scc_vec_push(*instrs, instr);
}
}
static int need_epilog(const scc_mir_instr_t *instr) {
scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)instr;
switch (ins->x86_instr.opcode) {
case SCC_X86_IFORM_RET_FAR:
case SCC_X86_IFORM_RET_NEAR:
case SCC_X86_IFORM_RET_FAR_IMMW:
case SCC_X86_IFORM_RET_NEAR_IMMW:
return true;
default:
break;
}
return false;
}
void scc_win_pc_x64_prolog_epilog_init(scc_prolog_epilog_t *ctx) {
ctx->prolog = prologue;
ctx->epilog = epilogue;
ctx->need_epilog = need_epilog;
} }
static void lower_call(void *userdata, const scc_lir_instr_t *instr) { static void lower_call(void *userdata, const scc_lir_instr_t *instr) {
scc_x86_64_isel_t *isel = userdata; scc_x86_64_isel_t *isel = userdata;
/*
Windows x64 parameter passing
https://learn.microsoft.com/zh-cn/cpp/build/x64-calling-convention?view=msvc-180#parameter-passing
eg.
func1(int a, int b, int c, int d, int e, int f);
// a in RCX, b in RDX, c in R8, d in R9, f then e passed on stack
func2(float a, double b, float c, double d, float e, float f);
// a in XMM0, b in XMM1, c in XMM2, d in XMM3, f then e passed on stack
func3(int a, double b, int c, float d, int e, float f);
// a in RCX, b in XMM1, c in R8, d in XMM3, f then e passed on stack
func4(__m64 a, __m128 b, struct c, float d, __m128 e, __m128 f);
// a in RCX, ptr to b in RDX, ptr to c in R8, d in XMM3,
// ptr to f passed on stack, then ptr to e passed on stack
*/
for (int i = instr->metadata.call.arg_count - 1; i >= 0; i -= 1) { for (int i = instr->metadata.call.arg_count - 1; i >= 0; i -= 1) {
scc_lir_val_t *args = &instr->metadata.call.args[i]; scc_lir_val_t *args = &instr->metadata.call.args[i];
switch (i) { switch (i) {
case 0: case 0:
scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_RCX), scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX),
scc_x86_lir_val_to_mir_op(isel, args), 8); scc_x86_lir_val_to_mir_op(isel, args), 8);
break; break;
case 1: case 1:
scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_RDX), scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDX),
scc_x86_lir_val_to_mir_op(isel, args), 8); scc_x86_lir_val_to_mir_op(isel, args), 8);
break; break;
case 2: case 2:
scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_R8), scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R8),
scc_x86_lir_val_to_mir_op(isel, args), 8); scc_x86_lir_val_to_mir_op(isel, args), 8);
break; break;
case 3: case 3:
scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_R9), scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R9),
scc_x86_lir_val_to_mir_op(isel, args), 8); scc_x86_lir_val_to_mir_op(isel, args), 8);
break; break;
default: default:
// Using stack scc_x86_operand_value_t op = scc_x86_lir_val_to_mir_op(isel, args);
scc_mir_operand_t op = scc_x86_lir_val_to_mir_op(isel, args);
add_instr_1(isel, add_instr_1(isel,
op.kind == SCC_MIR_OP_PREG || op.kind == SCC_MIR_OP_VREG op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50
? SCC_X86_IFORM_PUSH_GPRV_50
: SCC_X86_IFORM_PUSH_IMMZ, : SCC_X86_IFORM_PUSH_IMMZ,
op); op);
break; break;
} }
} }
emit_call(isel, instr->metadata.call.callee); emit_direct_call(isel, instr->metadata.call.callee);
scc_mir_operand_t ret_reg = scc_x86_lir_val_to_mir_op(isel, &instr->to); scc_x86_operand_value_t ret_reg =
if (ret_reg.kind == SCC_MIR_OP_VREG) { scc_x86_lir_val_to_mir_op(isel, &instr->to);
scc_x86_emit_move(isel, ret_reg, reg_operand(SCC_X86_REG_RAX), 8); if (ret_reg.kind != SCC_X86_OPR_NONE) {
} else { scc_x86_emit_move(isel, ret_reg, scc_x86_op_preg(SCC_X86_REG_RAX), 8);
TODO();
} }
} }
static scc_mir_operand_t lower_param(void *userdata, const scc_lir_val_t *val) { static void lower_param(void *userdata, const scc_lir_val_t *val,
scc_x86_64_isel_t *isel = userdata; void *out_op) {
scc_x86_operand_value_t *out = out_op;
Assert(val->kind == SCC_LIR_INSTR_KIND_ARG); Assert(val->kind == SCC_LIR_INSTR_KIND_ARG);
switch (val->data.arg) { switch (val->data.arg) {
case 0: case 0:
return reg_operand(SCC_X86_REG_RCX); *out = scc_x86_op_preg(SCC_X86_REG_RCX);
break;
case 1: case 1:
return reg_operand(SCC_X86_REG_RDX); *out = scc_x86_op_preg(SCC_X86_REG_RDX);
break;
case 2: case 2:
return reg_operand(SCC_X86_REG_R8); *out = scc_x86_op_preg(SCC_X86_REG_R8);
break;
case 3: case 3:
return reg_operand(SCC_X86_REG_R9); *out = scc_x86_op_preg(SCC_X86_REG_R9);
break;
default: default:
return (scc_mir_operand_t){.kind = SCC_MIR_OP_MEM, *out = scc_x86_op_slot(-val->data.arg);
.stack_slot = -val->data.arg}; break;
} }
} }
@@ -183,7 +191,7 @@ static void lower_ret(void *userdata, const scc_lir_instr_t *instr) {
scc_x86_64_isel_t *isel = userdata; scc_x86_64_isel_t *isel = userdata;
scc_lir_val_t ret_val = instr->metadata.ret_val; scc_lir_val_t ret_val = instr->metadata.ret_val;
if (ret_val.kind != SCC_LIR_INSTR_KIND_NONE) { if (ret_val.kind != SCC_LIR_INSTR_KIND_NONE) {
scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_RAX), scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RAX),
scc_x86_lir_val_to_mir_op(isel, &ret_val), 8); scc_x86_lir_val_to_mir_op(isel, &ret_val), 8);
} }
emit_ret(isel); emit_ret(isel);
@@ -200,45 +208,7 @@ void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t *abi_lowering) {
abi_lowering->lower_va_end = nullptr; abi_lowering->lower_va_end = nullptr;
} }
static const int reg_pool[] = { void scc_win_pc_x64_reg_alloc_fill(scc_reg_alloc_op_t *ops) {
SCC_X86_REG_R8, SCC_X86_REG_R9, SCC_X86_REG_R10, SCC_X86_REG_R11, (void)ops;
SCC_X86_REG_R12, SCC_X86_REG_R13, SCC_X86_REG_R14, SCC_X86_REG_R15}; // 寄存器池已在 scc_reg_alloc_fill_arch_x86 中注册
static uint32_t reg_mask = 0; // 1 表示已占用
static int acquire_reg(void *ctx) {
for (int i = 0; i < SCC_ARRLEN(reg_pool); i++)
if (!(reg_mask & (1u << i))) {
reg_mask |= (1u << i);
return reg_pool[i];
}
UNREACHABLE(); // 可改为溢出逻辑
}
static void release_reg(void *ctx, int preg) {
for (int i = 0; i < SCC_ARRLEN(reg_pool); i++)
if (reg_pool[i] == preg) {
reg_mask &= ~(1u << i);
return;
}
}
static void mark_reg_used(void *ctx, int preg) {
for (int i = 0; i < SCC_ARRLEN(reg_pool); i++)
if (reg_pool[i] == preg) {
reg_mask |= (1u << i);
return;
}
}
static void clean_mark_regs(void *ctx) { reg_mask = 0; }
void scc_reg_alloc_fill_win_x64(scc_reg_alloc_op_t *ops) {
ops->acquire_reg = acquire_reg;
ops->release_reg = release_reg;
ops->mark_reg_used = mark_reg_used;
ops->clean_mark_regs = clean_mark_regs;
}
void scc_win_pc_x64_prolog_epilog(scc_prolog_epilog_t *prolog_epilog) {
prolog_epilog->prolog = prologue;
prolog_epilog->epilog = epilogue;
} }

View File

@@ -2,44 +2,30 @@
#include <scc_mcode.h> #include <scc_mcode.h>
#include <scc_mir_module.h> #include <scc_mir_module.h>
#include <arch/scc_x86_mir.h>
#include <x86/scc_x86_encode.h> #include <x86/scc_x86_encode.h>
#include <x86/scc_x86_iform.h> #include <x86/scc_x86_iform.h>
#include <x86/scc_x86_reg.h> #include <x86/scc_x86_reg.h>
void mir_x86_to_mcode(scc_mcode_t *mcode, const scc_mir_instr_t *ins) { void mir_x86_to_mcode(scc_mcode_t *mcode, const scc_mir_x86_instr_t *_ins) {
scc_x86_instr_t *ins = (void *)_ins;
if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) {
return;
}
scc_x86_operand_value_t ops[8] = {0}; scc_x86_operand_value_t ops[8] = {0};
for (int i = 0; i < ins->num_operands; i += 1) { for (int i = 0; i < ins->num_operands; i++) {
switch (ins->operands[i].kind) { if (scc_x86_op_is_vreg(&ins->operands[i]))
case SCC_MIR_OP_VREG:
Panic("can't convert vreg to mcode"); Panic("can't convert vreg to mcode");
break; if (scc_x86_op_is_slot(&ins->operands[i]))
case SCC_MIR_OP_PREG: Panic("can't convert unresolved slot to mcode");
ops[i].kind = SCC_X86_OPR_REG; ops[i] = ins->operands[i];
ops[i].reg = ins->operands[i].preg;
break;
case SCC_MIR_OP_MEM:
Panic("can't convert mem to mcode");
break;
case SCC_MIR_OP_IMM:
ops[i].kind = SCC_X86_OPR_IMM;
ops[i].imm = ins->operands[i].imm;
break;
case SCC_MIR_OP_SYMBOL:
case SCC_MIR_OP_BLOCK:
ops[i].kind = SCC_X86_OPR_RELBR;
ops[i].imm = 0;
break;
default:
Panic("unsupported operand kind");
};
} }
scc_x86_encode_inst(mcode, ins->opcode, ops); scc_x86_encode_inst(mcode, ins->opcode, ops);
} }
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode, void scc_ir2mcode_emit_instr(scc_mcode_t *mcode,
const scc_mir_instr_t *mir_instr) { const scc_mir_instr_t *mir_instr) {
// TODO mir_x86_to_mcode(mcode, (const scc_mir_x86_instr_t *)mir_instr);
mir_x86_to_mcode(mcode, mir_instr);
} }
void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) { void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
@@ -51,9 +37,11 @@ void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
const scc_cfg_bblock_t *bb = const scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id); scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); const scc_mir_x86_instr_vec_t *instrs =
SCC_MIR_BBLOCK_VALUES_PTR(bb);
scc_vec_foreach(*instrs, i) { scc_vec_foreach(*instrs, i) {
const scc_mir_instr_t *ins = &scc_vec_at(*instrs, i); const scc_mir_instr_t *ins =
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
scc_ir2mcode_emit_instr(mcode, ins); scc_ir2mcode_emit_instr(mcode, ins);
} }
} }

View File

@@ -5,12 +5,15 @@ static inline void scc_ir_sym_to_sccf_sym(const scc_cfg_symbol_t *symbol,
switch (symbol->kind) { switch (symbol->kind) {
case SCC_CFG_SYMBOL_KIND_DATA: case SCC_CFG_SYMBOL_KIND_DATA:
sym->sccf_sym_type = SCCF_SYM_TYPE_DATA; sym->sccf_sym_type = SCCF_SYM_TYPE_DATA;
sym->sccf_sect_type = SCCF_SECT_DATA;
break; break;
case SCC_CFG_SYMBOL_KIND_FUNC: case SCC_CFG_SYMBOL_KIND_FUNC:
sym->sccf_sym_type = SCCF_SYM_TYPE_FUNC; sym->sccf_sym_type = SCCF_SYM_TYPE_FUNC;
sym->sccf_sect_type = SCCF_SECT_CODE;
break; break;
case SCC_CFG_SYMBOL_KIND_EXTERN: case SCC_CFG_SYMBOL_KIND_EXTERN:
sym->sccf_sym_type = SCCF_SYM_TYPE_EXTERN; sym->sccf_sym_type = SCCF_SYM_TYPE_EXTERN;
sym->sccf_sect_type = SCCF_SECT_NONE;
break; break;
} }
@@ -42,6 +45,11 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
scc_vec_init(sect_data); scc_vec_init(sect_data);
scc_vec_foreach(mir_module->cfg_module.symbols, i) { scc_vec_foreach(mir_module->cfg_module.symbols, i) {
if (i == 0) {
// FIXME
continue;
}
scc_cfg_symbol_t *symbol = scc_cfg_symbol_t *symbol =
&scc_vec_at(mir_module->cfg_module.symbols, i); &scc_vec_at(mir_module->cfg_module.symbols, i);
@@ -80,9 +88,10 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
const scc_cfg_bblock_t *bb = const scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id); scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
scc_vec_foreach(*instrs, i) { scc_vec_foreach(*instrs, i) {
const scc_mir_instr_t *ins = &scc_vec_at(*instrs, i); const scc_mir_instr_t *ins =
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
// FIXME reloc symbol needed // FIXME reloc symbol needed
scc_ir2mcode_emit_instr(&mcode, ins); scc_ir2mcode_emit_instr(&mcode, ins);
} }

View File

@@ -0,0 +1,28 @@
#ifndef __SCC_X86_ENCODE_H__
#define __SCC_X86_ENCODE_H__
#include "../scc_mcode.h"
#include "scc_x86_iform.h"
#include "scc_x86_reg.h"
typedef struct {
scc_x86_reg_t base;
scc_x86_reg_t index;
u8 scale; /* 1,2,4,8 */
i32 disp;
} scc_x86_mem_t;
typedef struct {
scc_x86_operand_kind_t kind;
union {
scc_x86_reg_t reg;
i64 imm;
scc_x86_mem_t mem;
};
} scc_x86_operand_value_t;
/* 按 iform 发射一条指令ops 数组长度需与 iform 定义的操作数数目一致 */
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
const scc_x86_operand_value_t *ops);
#endif /* __SCC_X86_ENCODE_H__ */

View File

@@ -0,0 +1,449 @@
#include <assert.h>
#include <string.h>
#include <x86/scc_x86_encode.h>
#include <x86/scc_x86_iform.h>
#include <x86/scc_x86_reg.h>
/* ---------- 内部辅助 ---------- */
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
scc_mcode_add_u8(m, v);
}
static inline void emit_u16(scc_mcode_t *m, uint16_t v) {
scc_mcode_add_u16(m, v);
}
static inline void emit_u32(scc_mcode_t *m, uint32_t v) {
scc_mcode_add_u32(m, v);
}
static inline void emit_u64(scc_mcode_t *m, uint64_t v) {
scc_mcode_add_u64(m, v);
}
/* ---------- 寄存器查询 ---------- */
static inline uint16_t scc_reg_width(scc_x86_reg_t reg) {
if (reg >= SCC_X86_REG_COUNT || reg == SCC_X86_REG_INVALID)
return 0;
return scc_x86_reg_table[reg].width;
}
static inline int scc_reg_ordinal(scc_x86_reg_t reg) {
if (reg >= SCC_X86_REG_COUNT || reg == SCC_X86_REG_INVALID)
return 0;
return scc_x86_reg_table[reg].ordinal;
}
static int reg_low3(scc_x86_reg_t reg) {
if (reg == SCC_X86_REG_INVALID)
return 0;
return scc_reg_ordinal(reg) & 7;
}
static int reg_rex_bit(scc_x86_reg_t reg) {
if (reg == SCC_X86_REG_INVALID)
return 0;
if (reg >= SCC_X86_REG_AH && reg <= SCC_X86_REG_DH)
return 0;
return (scc_reg_ordinal(reg) >= 8) ? 1 : 0;
}
/* ---------- 操作数宽度推导 ---------- */
static int infer_operand_width(const scc_x86_iform_info_t *info,
const scc_x86_operand_value_t ops[]) {
for (int i = 0; i < info->num_explicit_ops; i++) {
if (ops[i].kind == SCC_X86_OPR_REG && !info->ops[i].is_implicit) {
uint16_t w = scc_reg_width(ops[i].reg);
if (w > 0)
return w;
}
}
const char *eosz = info->encode.eosz;
int default_64 = info->encode.default_64b;
if (!strcmp(eosz, "o16"))
return 16;
if (!strcmp(eosz, "o32"))
return 32;
if (!strcmp(eosz, "o64"))
return 64;
if (!strcmp(eosz, "oszall") || !strcmp(eosz, "osznot16"))
return default_64 ? 64 : 32;
return 32;
}
/* ---------- 前缀决策 ---------- */
static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
scc_x86_reg_t rm_op, scc_x86_reg_t base,
scc_x86_reg_t idx) {
/* 强制要求 / 明确禁止 优先级最高 */
if (enc->rex_w == 1)
return 1;
if (enc->rex_w == 0)
return 0;
/* 指令已隐含 64 位语义(如 PUSH/POP但仍可能被 64 位操作数需要 W例如
* PUSH r64 不需要 W但 PUSH r/m64 也不需要。总之 default_64b
* 时一般无需额外 W但若操作数明确是 64 位且模板没有禁止,我们仍加上以兼容
* movabs 等 */
int has_64bit_op = 0;
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 64)
has_64bit_op = 1;
if (rm_op != SCC_X86_REG_INVALID && scc_reg_width(rm_op) == 64)
has_64bit_op = 1;
if (base != SCC_X86_REG_INVALID && scc_reg_width(base) == 64)
has_64bit_op = 1;
if (idx != SCC_X86_REG_INVALID && scc_reg_width(idx) == 64)
has_64bit_op = 1;
if (enc->default_64b) {
/* 对于默认 64 位的指令(如 CALL, JMP有些仍需要 REX.W
* 访问扩展寄存器,但若 reg/rm 本身是 64 位且需要 REX.B/R 则一并设置 W
* 来保证编码正确?这里简单处理:只要访问扩展寄存器就加 W */
return (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) ||
(rm_op != SCC_X86_REG_INVALID && reg_rex_bit(rm_op)) ||
(base != SCC_X86_REG_INVALID && reg_rex_bit(base)) ||
(idx != SCC_X86_REG_INVALID && reg_rex_bit(idx))
? 1
: 0;
}
/* 普通指令:有 64 位操作数即加 W */
return has_64bit_op;
}
static int need_66_prefix(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
scc_x86_reg_t rm_op) {
if (enc->osz_required)
return 1;
// 如果强制指定了操作大小不自动加66
if (!strcmp(enc->eosz, "o32") || !strcmp(enc->eosz, "o64"))
return 0;
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 16)
return 1;
if (rm_op != SCC_X86_REG_INVALID && scc_reg_width(rm_op) == 16)
return 1;
return 0;
}
static int need_67_prefix(const scc_x86_encoding_t *enc, scc_x86_reg_t base,
scc_x86_reg_t idx) {
(void)enc;
(void)base;
(void)idx;
return 0;
}
static void emit_legacy_prefixes(scc_mcode_t *m, const scc_x86_encoding_t *enc,
scc_x86_reg_t reg_op, scc_x86_reg_t rm_op,
scc_x86_reg_t base, scc_x86_reg_t idx) {
if (enc->has_lock)
emit_u8(m, 0xF0);
if (enc->f2_required)
emit_u8(m, 0xF2);
if (enc->f3_required)
emit_u8(m, 0xF3);
if (need_66_prefix(enc, reg_op, rm_op))
emit_u8(m, 0x66);
if (need_67_prefix(enc, base, idx))
emit_u8(m, 0x67);
}
static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc,
scc_x86_reg_t reg_op, scc_x86_reg_t rm_op,
scc_x86_reg_t base, scc_x86_reg_t idx) {
int rex = 0x40;
if (need_rexw(enc, reg_op, rm_op, base, idx))
rex |= 8;
if (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op))
rex |= 4;
if (idx != SCC_X86_REG_INVALID && reg_rex_bit(idx))
rex |= 2;
scc_x86_reg_t b = (rm_op != SCC_X86_REG_INVALID) ? rm_op : base;
if (b != SCC_X86_REG_INVALID && reg_rex_bit(b))
rex |= 1;
if (rex != 0x40) {
LOG_INFO("[REX] emit 0x%02x", (uint8_t)rex);
emit_u8(m, (uint8_t)rex);
}
}
static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) {
if (enc->map == 1) {
emit_u8(m, 0x0F);
} else if (enc->map == 2) {
emit_u8(m, 0x0F);
emit_u8(m, 0x38);
} else if (enc->map == 3) {
emit_u8(m, 0x0F);
emit_u8(m, 0x3A);
}
}
static void emit_opcode(scc_mcode_t *m, const scc_x86_encoding_t *enc,
scc_x86_reg_t rm_reg, scc_x86_reg_t base_reg) {
for (int i = 0; i < enc->opcode_len; i++) {
uint8_t byte = enc->opcode[i];
if (enc->partial_opcode && i == enc->opcode_len - 1) {
scc_x86_reg_t target =
(rm_reg != SCC_X86_REG_INVALID) ? rm_reg : base_reg;
if (target != SCC_X86_REG_INVALID)
byte |= (reg_low3(target) & 7);
}
emit_u8(m, byte);
}
}
static int scale_to_enc(uint8_t scale) {
switch (scale) {
case 1:
return 0;
case 2:
return 1;
case 4:
return 2;
case 8:
return 3;
default:
return -1;
}
}
static int disp_size(int32_t disp, scc_x86_reg_t base) {
if (disp == 0 && base != SCC_X86_REG_RBP && base != SCC_X86_REG_R13)
return 0;
if (disp >= -128 && disp <= 127)
return 8;
return 32;
}
/* ---------- 立即数发射(独立函数) ---------- */
static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc,
const scc_x86_operand_t *tmpl, int imm_idx,
int64_t imm_val, int op_width) {
const char *oc2 = tmpl[imm_idx].oc2;
int imm_size = enc->imm_size;
if (!strcmp(oc2, "b"))
imm_size = 1;
else if (!strcmp(oc2, "w"))
imm_size = 2;
else if (!strcmp(oc2, "z"))
imm_size = (op_width <= 16) ? op_width / 8 : (op_width <= 32 ? 4 : 4);
else if (!strcmp(oc2, "v"))
imm_size = op_width / 8;
else if (!strcmp(oc2, "d") || !strcmp(oc2, "ss"))
imm_size = 4;
else if (!strcmp(oc2, "q"))
imm_size = 8;
LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size);
switch (imm_size) {
case 1:
emit_u8(m, (uint8_t)imm_val);
break;
case 2:
emit_u16(m, (uint16_t)imm_val);
break;
case 4:
emit_u32(m, (uint32_t)imm_val);
break;
case 8:
emit_u64(m, (uint64_t)imm_val);
break;
default:
break;
}
}
/* ---------- ModR/M + SIB + 位移 + 立即数 ---------- */
static void emit_modrm_sib_disp(scc_mcode_t *m,
const scc_x86_iform_info_t *info,
const scc_x86_operand_value_t ops[],
int op_width) {
const scc_x86_encoding_t *enc = &info->encode;
const scc_x86_operand_t *tmpl = info->ops;
int num_ops = info->num_explicit_ops;
scc_x86_reg_t reg_r = SCC_X86_REG_INVALID;
scc_x86_reg_t reg_b = SCC_X86_REG_INVALID;
int has_mem = 0;
scc_x86_mem_t memdesc = {0};
int64_t imm_val = 0;
int imm_idx = -1;
for (int i = 0; i < num_ops; i++) {
const char *tname = tmpl[i].name;
if (ops[i].kind == SCC_X86_OPR_REG) {
LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
ops[i].reg);
if (strncmp(tname, "REG0", 4) == 0)
reg_r = ops[i].reg;
else if (strncmp(tname, "REG1", 4) == 0)
reg_b = ops[i].reg;
else {
if (reg_r == SCC_X86_REG_INVALID)
reg_r = ops[i].reg;
else if (reg_b == SCC_X86_REG_INVALID)
reg_b = ops[i].reg;
}
} else if (ops[i].kind == SCC_X86_OPR_MEM) {
has_mem = 1;
memdesc = ops[i].mem;
} else if (ops[i].kind == SCC_X86_OPR_IMM) {
imm_val = ops[i].imm;
imm_idx = i;
}
}
LOG_INFO("[MODRM] reg_r=%d (ord=%d) reg_b=%d (ord=%d)", reg_r,
scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b));
uint8_t modrm = 0;
if (has_mem) {
if (reg_r != SCC_X86_REG_INVALID)
modrm |= (reg_low3(reg_r) & 7) << 3;
else if (enc->modrm_reg_fix >= 0)
modrm |= (enc->modrm_reg_fix & 7) << 3;
int32_t disp = memdesc.disp;
int dsize = disp_size(disp, memdesc.base);
modrm |= (dsize == 0) ? 0 : (dsize == 8) ? 0x40 : 0x80;
if (memdesc.index != SCC_X86_REG_INVALID) {
modrm |= 4;
int idx_ord = scc_reg_ordinal(memdesc.index);
int base_ord = scc_reg_ordinal(memdesc.base);
int scale_enc = scale_to_enc(memdesc.scale);
if (scale_enc < 0)
return;
uint8_t sib = (uint8_t)((scale_enc << 6) | ((idx_ord & 7) << 3) |
(base_ord & 7));
emit_u8(m, modrm);
emit_u8(m, sib);
if (dsize == 8)
emit_u8(m, (uint8_t)disp);
else if (dsize == 32)
emit_u32(m, (uint32_t)disp);
} else if (memdesc.base == SCC_X86_REG_INVALID) {
modrm |= 5;
emit_u8(m, modrm);
emit_u32(m, (uint32_t)disp);
} else {
int base_ord = scc_reg_ordinal(memdesc.base);
if (memdesc.base == SCC_X86_REG_RSP ||
memdesc.base == SCC_X86_REG_R12) {
modrm |= 4;
uint8_t sib = (uint8_t)((base_ord & 7) | (4 << 3));
emit_u8(m, modrm);
emit_u8(m, sib);
if (dsize == 8)
emit_u8(m, (uint8_t)disp);
else if (dsize == 32)
emit_u32(m, (uint32_t)disp);
} else {
modrm |= (base_ord & 7);
emit_u8(m, modrm);
if (dsize == 8)
emit_u8(m, (uint8_t)disp);
else if (dsize == 32)
emit_u32(m, (uint32_t)disp);
}
}
} else {
modrm = 0xC0;
if (enc->modrm_reg_fix >= 0)
modrm |= (enc->modrm_reg_fix & 7) << 3;
else if (reg_r != SCC_X86_REG_INVALID)
modrm |= (reg_low3(reg_r) & 7) << 3;
if (enc->modrm_rm_fix >= 0) {
modrm |= enc->modrm_rm_fix & 7;
} else if (reg_b != SCC_X86_REG_INVALID) {
modrm |= reg_low3(reg_b) & 7;
} else if (enc->modrm_reg_fix >= 0 && reg_r != SCC_X86_REG_INVALID) {
modrm |= reg_low3(reg_r) & 7;
} else if (reg_r != SCC_X86_REG_INVALID) {
modrm |= reg_low3(reg_r) & 7;
}
emit_u8(m, modrm);
}
LOG_INFO("[MODRM] emit byte 0x%02x", modrm);
/* 立即数在 ModRM 后发射 */
if (imm_idx >= 0) {
emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width);
}
}
/* ---------- 主编码入口 ---------- */
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
const scc_x86_operand_value_t *ops) {
if (!mcode || !ops)
return -1;
if (iform >= SCC_X86_IFORM_COUNT || iform < 0)
Panic("invalid iform %d", iform);
const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform];
const scc_x86_encoding_t *enc = &info->encode;
const scc_x86_operand_t *tmpl = info->ops;
int num_ops = info->num_explicit_ops;
LOG_INFO("[IFORM] %s, explicit_ops=%d (total=%d)", info->iform_name,
num_ops, info->num_ops);
scc_x86_reg_t reg_field = SCC_X86_REG_INVALID;
scc_x86_reg_t rm_field = SCC_X86_REG_INVALID;
scc_x86_reg_t base_reg = SCC_X86_REG_INVALID;
scc_x86_reg_t idx_reg = SCC_X86_REG_INVALID;
/* ---------- 收集立即数信息(用于无 ModRM 指令) ---------- */
int64_t imm_val = 0;
int imm_idx = -1;
for (int i = 0; i < num_ops; i++) {
const char *tname = tmpl[i].name;
if (ops[i].kind == SCC_X86_OPR_REG) {
if (strncmp(tname, "REG0", 4) == 0) {
if (enc->modrm_reg_fix >= 0)
rm_field = ops[i].reg; // reg固定 → REG0为rm
else
reg_field = ops[i].reg; // 否则为reg
} else if (strncmp(tname, "REG1", 4) == 0) {
if (enc->modrm_rm_fix >= 0)
reg_field = ops[i].reg; // rm固定 → REG1为reg
else
rm_field = ops[i].reg; // 否则为rm
} else {
// 未命名的寄存器,按先 reg 后 rm 填充
if (reg_field == SCC_X86_REG_INVALID)
reg_field = ops[i].reg;
else if (rm_field == SCC_X86_REG_INVALID)
rm_field = ops[i].reg;
}
} else if (ops[i].kind == SCC_X86_OPR_MEM) {
base_reg = ops[i].mem.base;
idx_reg = ops[i].mem.index;
} else if (ops[i].kind == SCC_X86_OPR_IMM ||
ops[i].kind == SCC_X86_OPR_RELBR) {
imm_val = ops[i].imm;
imm_idx = i;
}
}
int op_width = infer_operand_width(info, ops);
LOG_INFO("[OPWIDTH] %d bits", op_width);
// +++ 新增:无 ModRM 时,寄存器用 REX.B 扩展 +++
if (!enc->has_modrm) {
rm_field = reg_field;
reg_field = SCC_X86_REG_INVALID;
}
emit_legacy_prefixes(mcode, enc, reg_field, rm_field, base_reg, idx_reg);
emit_rex(mcode, enc, reg_field, rm_field, base_reg, idx_reg);
emit_escape_map(mcode, enc);
if (enc->has_modrm) {
emit_opcode(mcode, enc, rm_field, base_reg);
emit_modrm_sib_disp(mcode, info, ops, op_width);
} else {
// 无 ModRMopcode 中的寄存器来自 rm_field
emit_opcode(mcode, enc, rm_field, base_reg);
if (imm_idx >= 0) {
emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width);
}
}
return 0;
}

View File

@@ -2,6 +2,7 @@
#define __SCC_SEMA_H__ #define __SCC_SEMA_H__
#include <scc_ast.h> #include <scc_ast.h>
#include <scc_utils.h>
typedef struct scc_sema_ctx scc_sema_ctx_t; typedef struct scc_sema_ctx scc_sema_ctx_t;
/** /**
@@ -13,6 +14,12 @@ typedef void (*scc_sema_callback_t)(scc_sema_ctx_t *context,
typedef scc_ast_qual_type_t *(*scc_sema_got_type_t)(scc_sema_ctx_t *context, typedef scc_ast_qual_type_t *(*scc_sema_got_type_t)(scc_sema_ctx_t *context,
const char *name); const char *name);
typedef struct scc_label_scope {
int function_scope_depth;
scc_hashtable_t labels; // 标签名 -> scc_ast_stmt_t* (LABEL节点)
scc_ast_stmt_vec_t pending_gotos; // 尚未找到目标的goto语句
} scc_sema_label_scope_t;
/** /**
* @brief 语义分析回调集合 * @brief 语义分析回调集合
*/ */
@@ -26,6 +33,7 @@ struct scc_sema_ctx {
scc_ast_stmt_vec_t break_stack; scc_ast_stmt_vec_t break_stack;
scc_ast_stmt_vec_t continue_stack; scc_ast_stmt_vec_t continue_stack;
scc_sema_label_scope_t label_scope;
void *context; void *context;
}; };

View File

@@ -290,7 +290,10 @@ CONTINUE:
decl->var.init = scc_parse_initializer(parser, lvalue); decl->var.init = scc_parse_initializer(parser, lvalue);
} else if (tok_ptr->type == SCC_TOK_L_BRACE) { } else if (tok_ptr->type == SCC_TOK_L_BRACE) {
scc_parse_decl_sema(parser, decl); scc_parse_decl_sema(parser, decl);
scc_sema_decl(parser, scc_ast_decl_t_BEGIN, nullptr);
// 进入函数作用域(用于参数和标签)
scc_sema_decl(parser, scc_ast_decl_t_BEGIN, decl);
// FIXME hack struct // FIXME hack struct
scc_vec_foreach(decl->func.type->type->function.params, i) { scc_vec_foreach(decl->func.type->type->function.params, i) {
scc_ast_decl_t *param = scc_ast_decl_t *param =
@@ -299,7 +302,10 @@ CONTINUE:
scc_parse_decl_sema(parser, param); scc_parse_decl_sema(parser, param);
} }
scc_ast_stmt_t *body = scc_parse_statement(parser); scc_ast_stmt_t *body = scc_parse_statement(parser);
scc_sema_decl(parser, scc_ast_decl_t_END, nullptr);
// 退出函数作用域
scc_sema_decl(parser, scc_ast_decl_t_END, decl);
Assert(decl->base.type == SCC_AST_DECL_FUNC); Assert(decl->base.type == SCC_AST_DECL_FUNC);
decl->func.body = body; decl->func.body = body;
Assert(decl->func.type != nullptr); Assert(decl->func.type != nullptr);

View File

@@ -73,6 +73,7 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
if (decl != nullptr) { if (decl != nullptr) {
scc_vec_push(unit->declarations, decl); scc_vec_push(unit->declarations, decl);
} else { } else {
parser->errcode = 1;
break; break;
} }
if (parser->errcode != 0) { // FIXME errcode if (parser->errcode != 0) { // FIXME errcode

View File

@@ -133,37 +133,72 @@ static void stmt_callback(scc_sema_ctx_t *sema_ctx,
} }
scc_ast_stmt_t *stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node); scc_ast_stmt_t *stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node);
switch (stmt->base.type) { switch (stmt->base.type) {
case SCC_AST_STMT_BREAK: case SCC_AST_STMT_BREAK: {
if (scc_vec_size(sema_ctx->break_stack) == 0) if (scc_vec_size(sema_ctx->break_stack) == 0)
SCC_ERROR(stmt->base.loc, "break not in loop/switch"); SCC_ERROR(stmt->base.loc, "break not in loop/switch");
else else
stmt->jump._target = scc_vec_at( stmt->jump._target = scc_vec_at(
sema_ctx->break_stack, scc_vec_size(sema_ctx->break_stack) - 1); sema_ctx->break_stack, scc_vec_size(sema_ctx->break_stack) - 1);
break; } break;
case SCC_AST_STMT_CONTINUE: case SCC_AST_STMT_CONTINUE: {
if (scc_vec_size(sema_ctx->continue_stack) == 0) if (scc_vec_size(sema_ctx->continue_stack) == 0)
SCC_ERROR(stmt->base.loc, "continue not in loop"); SCC_ERROR(stmt->base.loc, "continue not in loop");
else else
stmt->jump._target = stmt->jump._target =
scc_vec_at(sema_ctx->continue_stack, scc_vec_at(sema_ctx->continue_stack,
scc_vec_size(sema_ctx->continue_stack) - 1); scc_vec_size(sema_ctx->continue_stack) - 1);
case SCC_AST_STMT_GOTO: } break;
scc_ast_node_t *target_node = case SCC_AST_STMT_GOTO: {
scc_sema_symtab_lookup_symbol(sema_symtab, stmt->goto_stmt.label); scc_ast_stmt_t *goto_stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node);
if (target_node == nullptr) { scc_sema_label_scope_t *scope = &sema_ctx->label_scope;
SCC_ERROR(stmt->base.loc, ""); if (scope->function_scope_depth != 1) {
SCC_ERROR(goto_stmt->base.loc, "goto not inside any function");
break; break;
} }
if (!SCC_AST_IS_A(scc_ast_stmt_t, target_node)) {
SCC_ERROR(stmt->base.loc, ""); // 尝试直接查找标签
scc_ast_node_t *target =
scc_hashtable_get(&scope->labels, goto_stmt->goto_stmt.label);
if (target) {
goto_stmt->goto_stmt._target =
SCC_AST_CAST_TO(scc_ast_stmt_t, target);
} else {
// 未找到则加入待处理列表
scc_vec_push(scope->pending_gotos, goto_stmt);
}
} break;
case SCC_AST_STMT_LABEL: {
scc_ast_stmt_t *label_stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node);
scc_sema_label_scope_t *scope = &sema_ctx->label_scope;
// 获取当前函数标签作用域
if (scope->function_scope_depth != 1) {
SCC_ERROR(label_stmt->base.loc, "label not inside any function");
break; break;
} }
stmt->goto_stmt._target = SCC_AST_CAST_TO(scc_ast_stmt_t, target_node);
break; // 检查重复定义
case SCC_AST_STMT_LABEL: if (scc_hashtable_get(&scope->labels, label_stmt->label_stmt.label)) {
scc_sema_symtab_add_symbol(sema_symtab, stmt->label_stmt.label, SCC_ERROR(label_stmt->base.loc, "duplicate label '%s'",
&stmt->base); label_stmt->label_stmt.label);
break; break;
}
// 添加标签
scc_hashtable_set(&scope->labels, label_stmt->label_stmt.label,
&label_stmt->base);
// 检查是否有等待该标签的 goto
scc_vec_foreach(scope->pending_gotos, i) {
scc_ast_stmt_t *goto_stmt = scc_vec_at(scope->pending_gotos, i);
if (goto_stmt == nullptr)
continue;
if (scc_strcmp(goto_stmt->goto_stmt.label,
label_stmt->label_stmt.label) == 0) {
goto_stmt->goto_stmt._target = label_stmt;
scc_vec_at(scope->pending_gotos, i) = nullptr;
}
}
} break;
default: default:
break; break;
} }
@@ -175,10 +210,37 @@ static void decl_callback(scc_sema_ctx_t *sema_ctx,
scc_sema_symtab_t *sema_symtab = sema_ctx->context; scc_sema_symtab_t *sema_symtab = sema_ctx->context;
// Function declaration scope // Function declaration scope
// FIXME 使用 node_type 区分其他未来的scope
if (node_type == scc_ast_decl_t_BEGIN) { if (node_type == scc_ast_decl_t_BEGIN) {
// 创建标签作用域
scc_sema_label_scope_t *scope = &sema_ctx->label_scope;
scope->function_scope_depth += 1;
scc_hashtable_cstr_init(&scope->labels);
scc_vec_init(scope->pending_gotos);
// 进入普通符号表作用域(用于参数和局部变量)
scc_sema_symtab_enter_scope(sema_symtab); scc_sema_symtab_enter_scope(sema_symtab);
return; return;
} else if (node_type == scc_ast_decl_t_END) { } else if (node_type == scc_ast_decl_t_END) {
scc_sema_label_scope_t *scope = &sema_ctx->label_scope;
scope->function_scope_depth -= 1;
// 处理尚未绑定的 goto
scc_vec_foreach(scope->pending_gotos, i) {
scc_ast_stmt_t *goto_stmt = scc_vec_at(scope->pending_gotos, i);
if (goto_stmt == nullptr) {
continue;
}
// 标签未定义 -> 报错
SCC_ERROR(goto_stmt->base.loc, "label '%s' used but not defined",
goto_stmt->goto_stmt.label);
}
// 清理
scc_hashtable_drop(&scope->labels);
scc_vec_free(scope->pending_gotos);
// 退出普通符号表作用域
scc_sema_symtab_leave_scope(sema_symtab); scc_sema_symtab_leave_scope(sema_symtab);
return; return;
} }
@@ -242,6 +304,7 @@ void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx) {
sema_ctx->on_stmt = stmt_callback; sema_ctx->on_stmt = stmt_callback;
sema_ctx->on_type = type_callback; sema_ctx->on_type = type_callback;
sema_ctx->got_type = got_type_callback; sema_ctx->got_type = got_type_callback;
sema_ctx->label_scope = (scc_sema_label_scope_t){0};
scc_sema_symtab_init(sema_symtab); scc_sema_symtab_init(sema_symtab);

View File

@@ -99,11 +99,11 @@ void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok,
for (int i = 1; i < len - 1; i++) { for (int i = 1; i < len - 1; i++) {
scc_str_append_ch(&fname, includename[i]); scc_str_append_ch(&fname, includename[i]);
} }
scc_str_drop(&line);
int is_system = includename[0] == '<'; int is_system = includename[0] == '<';
if (switch_file_stack(pp, &fname, &pos, is_system)) { if (switch_file_stack(pp, &fname, &pos, is_system)) {
// LOG_ERROR() // LOG_ERROR()
} }
scc_str_drop(&line);
scc_str_drop(&fname); scc_str_drop(&fname);
return; return;
ERROR: ERROR:

View File

@@ -71,20 +71,17 @@ void scc_tree_dump_append(scc_tree_dump_t *td, const char *s);
*/ */
void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...); void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...);
/**
* @brief 追加带节点颜色的文本
*/
#define scc_tree_dump_node(td, fmt, ...) \ #define scc_tree_dump_node(td, fmt, ...) \
scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->node_color, \ scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->node_color, \
##__VA_ARGS__, (td)->reset_color) ##__VA_ARGS__, (td)->reset_color)
/**
* @brief 追加带值颜色的格式化文本
*/
#define scc_tree_dump_value(td, fmt, ...) \ #define scc_tree_dump_value(td, fmt, ...) \
scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->value_color, \ scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->value_color, \
##__VA_ARGS__, (td)->reset_color) ##__VA_ARGS__, (td)->reset_color)
#define scc_tree_dump_branch(td, fmt, ...) \
scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->branch_color, \
##__VA_ARGS__, (td)->reset_color)
/** /**
* @brief 推入新层级 * @brief 推入新层级
* @param is_last 该层级是否是父节点的最后一个子节点 * @param is_last 该层级是否是父节点的最后一个子节点

View File

@@ -4,10 +4,10 @@
#define DEFAULT_BRANCH "|-" #define DEFAULT_BRANCH "|-"
#define DEFAULT_LAST_BRANCH "`-" #define DEFAULT_LAST_BRANCH "`-"
#define DEFAULT_SPACE " " #define DEFAULT_SPACE " "
#define NODE_COLOR "\033[34m" #define NODE_COLOR ANSI_FG_GREEN
#define VALUE_COLOR "\033[32m" #define VALUE_COLOR ANSI_FG_YELLOW
#define BRANCH_COLOR "\033[33m" #define BRANCH_COLOR ANSI_FG_CYAN
#define RESET_COLOR "\033[0m" #define RESET_COLOR ANSI_NONE
void scc_tree_dump_init(scc_tree_dump_t *td, cbool use_color) { void scc_tree_dump_init(scc_tree_dump_t *td, cbool use_color) {
scc_str_init(&td->buf); scc_str_init(&td->buf);

View File

@@ -4,7 +4,7 @@
* @brief Arbitrary Precision Library * @brief Arbitrary Precision Library
* *
*/ */
#ifdef __AP_SCC__ #ifdef __SCC__
#include <scc_core.h> #include <scc_core.h>
#define SCC_AP_DIGIT u64 #define SCC_AP_DIGIT u64
#define SCC_AP_PANIC Panic #define SCC_AP_PANIC Panic

View File

@@ -21,7 +21,7 @@
#define __scc_log_unreachable() (__builtin_unreachable()) #define __scc_log_unreachable() (__builtin_unreachable())
#elif defined _MSC_VER // MSVC #elif defined _MSC_VER // MSVC
#define __scc_log_unreachable() (__assume(false)) #define __scc_log_unreachable() (__assume(false))
#elif defined __SCC_BUILTIN__ // The SCC Compiler (my compiler) #elif defined __SCC_BUILTIN_UNREACHEABLE__ // The SCC Compiler (my compiler)
#define __scc_log_unreachable() (__scc_builtin_unreachable()) #define __scc_log_unreachable() (__scc_builtin_unreachable())
#else #else
#define __scc_log_unreachable() ((void)0) #define __scc_log_unreachable() ((void)0)
@@ -184,7 +184,7 @@ void log_set_handler(logger_t *logger, log_handler handler);
* 或使用 _Static_assert (C11) * 或使用 _Static_assert (C11)
*/ */
#if __STDC_VERSION__ >= 201112L #if __STDC_VERSION__ >= 201112L
#define StaticAssert static_assert #define StaticAssert _Static_assert
#else #else
#define StaticAssert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1] #define StaticAssert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1]
#endif #endif

View File

@@ -13,4 +13,14 @@
#define scc_min(a, b) ((a) < (b) ? (a) : (b)) #define scc_min(a, b) ((a) < (b) ? (a) : (b))
#define scc_max(a, b) ((a) > (b) ? (a) : (b)) #define scc_max(a, b) ((a) > (b) ? (a) : (b))
#ifdef __GNUC__
#define SCC_MAYBE_UNUSED __attribute__((unused))
#elif defined(_MSC_VER)
#define SCC_MAYBE_UNUSED __pragma(warning(suppress : 4100))
#elif defined(__clang__)
#define SCC_MAYBE_UNUSED __attribute__((unused))
#else
#define SCC_MAYBE_UNUSED
#endif
#endif // __SCC_CORE_MACRO_H__ #endif // __SCC_CORE_MACRO_H__

View File

@@ -15,13 +15,16 @@
#include "scc_core_type.h" #include "scc_core_type.h"
#define __scc_vec_realloc scc_realloc #define __scc_vec_realloc scc_realloc
#define __scc_vec_free scc_free #define __scc_vec_free scc_free
#define __scc_vec_memcpy scc_memcpy
#else #else
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
typedef size_t usize; typedef size_t usize;
#define __scc_vec_realloc realloc #define __scc_vec_realloc realloc
#define __scc_vec_free free #define __scc_vec_free free
#define __scc_vec_memcpy memcpy
#ifndef LOG_FATAL #ifndef LOG_FATAL
#include <stdio.h> #include <stdio.h>
@@ -169,4 +172,86 @@ typedef size_t usize;
(vec).data = array; \ (vec).data = array; \
} while (0) } while (0)
/**
* @def scc_vec_sized_realloc(vec, elem_size, new_cap)
* @brief 内部宏:按 elem_size 重新分配内存
*/
#define scc_vec_sized_realloc(vec, elem_size, new_cap) \
do { \
void *new_data = \
__scc_vec_realloc((vec).data, (new_cap) * (elem_size)); \
if (!new_data) \
LOG_FATAL("scc_vec_sized_realloc: failed\n"); \
(vec).data = new_data; \
(vec).cap = new_cap; \
} while (0)
/**
* @def scc_vec_sized_push(vec, elem_size, src_ptr)
* @brief 添加一个元素(从 src_ptr 拷贝 elem_size 字节)
* @param vec SCC_VEC(type) 定义的向量变量type 可为 char 或 void
* @param elem_size 每个元素占用的字节数
* @param src_ptr 源数据的指针
* @param copy_size 要拷贝的字节数
*
* @note 使用前需确保 vec.data 类型与 src_ptr 无关,内部会按字节拷贝。
* 推荐声明时为 `SCC_VEC(char)` 或 `SCC_VEC(unsigned char)`。
*/
#define scc_vec_sized_push(vec, elem_size, src_ptr, copy_size) \
do { \
if ((vec).size >= (vec).cap) { \
usize new_cap = (vec).cap ? (vec).cap * 2 : 4; \
scc_vec_sized_realloc(vec, elem_size, new_cap); \
} \
char *slot = (char *)(vec).data + (vec).size * (elem_size); \
__scc_vec_memcpy(slot, (src_ptr), (copy_size)); \
(vec).size++; \
} while (0)
/**
* @def scc_vec_sized_at_ptr(vec, elem_size, idx)
* @brief 获取第 idx 个元素的指针void*
* @return 指向元素的指针,需转换为具体类型使用
*/
#define scc_vec_sized_at_ptr(vec, elem_size, idx) \
((void *)((char *)(vec).data + (idx) * (elem_size)))
/**
* @def scc_vec_sized_foreach(vec, elem_size, elem_ptr_var, block)
* @brief 遍历所有元素
* @param elem_ptr_var 循环内的变量名void* 类型)
* @param block 循环体语句块
*/
#define scc_vec_sized_foreach(vec, elem_size, elem_ptr_var, block) \
do { \
for (usize __i = 0; __i < (vec).size; ++__i) { \
void *elem_ptr_var = scc_vec_sized_at_ptr(vec, elem_size, __i); \
block; \
} \
} while (0)
/**
* @def scc_vec_sized_pop(vec, elem_size)
* @brief 弹出最后一个元素(仅减小 size不返回数据
*/
#define scc_vec_sized_pop(vec, elem_size) \
do { \
if ((vec).size == 0) \
LOG_FATAL("scc_vec_sized_pop: empty\n"); \
(vec).size--; \
} while (0)
/**
* @def scc_vec_sized_clear(vec)
* @brief 清空向量(重置 size = 0不释放内存
*/
#define scc_vec_sized_clear(vec) ((vec).size = 0)
/**
* @def scc_vec_sized_free(vec)
* @brief 释放向量内存(与原始 scc_vec_free 相同,可复用)
* @note 注意:如果元素内部有堆资源,需在释放前自行遍历调用析构函数。
*/
#define scc_vec_sized_free(vec) scc_vec_free(vec)
#endif /* __SCC_CORE_VEC_H__ */ #endif /* __SCC_CORE_VEC_H__ */

View File

@@ -39,8 +39,15 @@ usize scc_fread(scc_file_t file, void *buffer, usize size) {
return scc_pal_fread(file, buffer, size); return scc_pal_fread(file, buffer, size);
} }
usize scc_fwrite(scc_file_t file, const void *buffer, usize size) { usize scc_fwrite(scc_file_t file, const void *buf, usize size) {
return scc_pal_fwrite(file, buffer, size); if (file == scc_stdout) {
scc_pal_write(buf, size);
} else if (file == scc_stderr) {
scc_pal_ewrite(buf, size);
} else {
return scc_pal_fwrite(file, buf, size);
}
return 0;
} }
cbool scc_fexists(const char *path) { cbool scc_fexists(const char *path) {

View File

@@ -155,7 +155,6 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
static const char *emit_stages[] = { static const char *emit_stages[] = {
[SCC_EMIT_STAGE_LEX] = "lex", [SCC_EMIT_STAGE_LEX] = "lex",
[SCC_EMIT_STAGE_PP] = "pp", [SCC_EMIT_STAGE_PP] = "pp",
[SCC_EMIT_STAGE_AST] = "ast", // -T [SCC_EMIT_STAGE_AST] = "ast", // -T
[SCC_EMIT_STAGE_HIR] = "hir", // -H [SCC_EMIT_STAGE_HIR] = "hir", // -H
[SCC_EMIT_STAGE_LIR] = "lir", // -L [SCC_EMIT_STAGE_LIR] = "lir", // -L

View File

@@ -18,6 +18,8 @@
#include <sccf2pe.h> #include <sccf2pe.h>
#include "config.h" #include "config.h"
void init_platform(void);
#define GET_VALID_FP(fp) (fp == nullptr ? scc_stdout : fp)
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};
@@ -66,10 +68,21 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) {
static void tree_dump_output(const char *str, usize len, void *user) { static void tree_dump_output(const char *str, usize len, void *user) {
scc_fprintf(user, "%.*s", (int)len, str); scc_fprintf(user, "%.*s", (int)len, str);
} }
static inline int mir_dump(scc_file_t fp, scc_mir_module_t *mir_module) {
scc_tree_dump_t tree_dump;
scc_mir_dump_ctx_t mir_dump_ctx;
if (fp == nullptr) {
scc_tree_dump_init(&tree_dump, true);
} else {
scc_tree_dump_init(&tree_dump, false);
}
scc_mir_dump_init(&mir_dump_ctx, &tree_dump, mir_module);
scc_mir_dump_module(&mir_dump_ctx);
void init_platform(void); scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
scc_tree_dump_drop(&tree_dump);
#define GET_VALID_FP(fp) (fp == nullptr ? scc_stdout : fp) return 0;
}
int main(int argc, const char **argv, const char **envp) { int main(int argc, const char **argv, const char **envp) {
init_platform(); init_platform();
@@ -276,36 +289,20 @@ sstream_drop:
switch (config.emit_stage) { switch (config.emit_stage) {
case SCC_EMIT_STAGE_MIR: case SCC_EMIT_STAGE_MIR:
goto mir_dump; return mir_dump(fp, &mir_module);
case SCC_EMIT_STAGE_MIR_PASS_REG_ALLOC: case SCC_EMIT_STAGE_MIR_PASS_REG_ALLOC:
scc_mir_pass(&mir_module, SCC_MIR_STAGE_REGALLOC); scc_mir_pass(&mir_module, SCC_MIR_STAGE_REGALLOC);
goto mir_dump; return mir_dump(fp, &mir_module);
case SCC_EMIT_STAGE_MIR_PASS_FLAME_LAYOUT: case SCC_EMIT_STAGE_MIR_PASS_FLAME_LAYOUT:
scc_mir_pass(&mir_module, SCC_MIR_STAGE_FRAME_LAYOUT); scc_mir_pass(&mir_module, SCC_MIR_STAGE_FRAME_LAYOUT);
goto mir_dump; return mir_dump(fp, &mir_module);
case SCC_EMIT_STAGE_MIR_PASS_PROLOG_EPILOG: case SCC_EMIT_STAGE_MIR_PASS_PROLOG_EPILOG:
scc_mir_pass(&mir_module, SCC_MIR_STAGE_PROLOGUE_EPILOGUE); scc_mir_pass(&mir_module, SCC_MIR_STAGE_PROLOGUE_EPILOGUE);
goto mir_dump; return mir_dump(fp, &mir_module);
break;
default: default:
scc_mir_pass(&mir_module, SCC_MIR_STAGE_ANY);
break; break;
} }
do {
mir_dump:
scc_mir_dump_ctx_t mir_dump_ctx;
scc_tree_dump_t tree_dump;
if (fp == nullptr) {
scc_tree_dump_init(&tree_dump, true);
} else {
scc_tree_dump_init(&tree_dump, false);
}
scc_mir_dump_init(&mir_dump_ctx, &tree_dump, &mir_module);
scc_mir_dump_module(&mir_dump_ctx);
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
scc_tree_dump_drop(&tree_dump);
return 0;
} while (0);
if (config.emit_stage == SCC_EMIT_STAGE_FLATBIN) { if (config.emit_stage == SCC_EMIT_STAGE_FLATBIN) {
scc_mcode_t mcode = {0}; scc_mcode_t mcode = {0};