feat(ast2ir): 实现C11类型提升系统并重构HIR基本块管理

- 新增 scc_ast2ir_promote.c 实现整数提升(6.3.1.1)和寻常算术转换(6.3.1.8)
- 重构 HIR Builder: bblock → create_bblock + append_bblock,引入BBList链表管理
- AST2IR 全面集成类型提升:二元运算、赋值、函数调用参数、自增/自减操作符
- 变参函数支持:跳过 ... 假参数,实现默认参数提升(float→double等)
- 简化 HIR Dump 实现
- MIR: Win64 ABI改进、x86指令选择优化
- 新增 printf 测试用例
This commit is contained in:
zzy
2026-05-24 15:46:22 +08:00
parent ea553718f0
commit cec96333e7
27 changed files with 1223 additions and 740 deletions

View File

@@ -135,6 +135,9 @@ typedef enum {
/* 栈管理 */
SCC_LIR_ALLOCA,
/* 类型扩展 */
SCC_LIR_EXTEND,
SCC_LIR_NOP
} scc_lir_op_t;
@@ -208,6 +211,10 @@ typedef struct scc_lir_ins {
int align_bytes;
} alloca;
struct scc_lir_extend {
int from_size; // 源类型宽度(字节)
} extend;
struct {
scc_lir_val_t ap;
scc_lir_val_t last;

View File

@@ -428,21 +428,37 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_CONV: {
// 类型转换:使用 MOV 指令配合扩展/截断
// 类型转换:使用 LIR_EXTEND 指令实现符号/零扩展
scc_lir_val_t src =
ir_value_to_lir_operand(ctx, value->data.conv.operand);
scc_lir_ext_t conv_ext = SCC_LIR_EXT_NONE;
if (value->data.conv.conv_type == CONV_SEXT)
if (value->data.conv.conv_type == SCC_HIR_CONV_SEXT)
conv_ext = SCC_LIR_EXT_SEXT;
else if (value->data.conv.conv_type == CONV_ZEXT)
else if (value->data.conv.conv_type == SCC_HIR_CONV_ZEXT)
conv_ext = SCC_LIR_EXT_ZEXT;
// TRUNC 用 NONE 即可(MOV 截断
scc_lir_instr_t instr = {.op = SCC_LIR_MOV,
.size = size,
.ext = conv_ext,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = src};
scc_lir_builder_add_instr(ctx, &instr);
// TRUNC 用 SCC_LIR_MOV 截断
if (value->data.conv.conv_type == SCC_HIR_CONV_TRUNC) {
scc_lir_instr_t instr = {.op = SCC_LIR_MOV,
.size = size,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = src};
scc_lir_builder_add_instr(ctx, &instr);
} else {
// 计算源类型宽度
scc_hir_type_t *src_type = scc_hir_module_get_type(
ctx->hir_module,
scc_hir_module_get_value(ctx->hir_module,
value->data.conv.operand)
->type);
int from_size = scc_hir_module_type_size(ctx->hir_module, src_type);
scc_lir_instr_t instr = {.op = SCC_LIR_EXTEND,
.size = size,
.ext = conv_ext,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = src,
.metadata.extend.from_size = from_size};
scc_lir_builder_add_instr(ctx, &instr);
}
} break;
case SCC_HIR_VALUE_TAG_BUILTIN: {
scc_hir_builtin_t *b = &value->data.builtin;
@@ -542,7 +558,7 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
.attr = SCC_LIR_ATTR_NONE,
.frame_size = 0,
.vregs_count = 0,
.is_va_arg = false,
.is_va_arg = func_meta->is_variadic,
};
scc_vec_push(ctx->lir_module->func_metas, lir_func_meta);
ctx->current_func = ir_func;

View File

@@ -7,134 +7,65 @@
#include <scc_core.h>
static const char *op_to_string(scc_lir_op_t op) {
switch (op) {
case SCC_LIR_MOV:
return "mov";
case SCC_LIR_LOAD:
return "load";
case SCC_LIR_LOAD_ADDR:
return "load.addr";
case SCC_LIR_STORE:
return "store";
// case SCC_LIR_STORE_ADDR:
// return "store.addr";
case SCC_LIR_ADD:
return "add";
case SCC_LIR_SUB:
return "sub";
case SCC_LIR_MUL:
return "mul";
case SCC_LIR_DIV_S:
return "div.s";
case SCC_LIR_DIV_U:
return "div.u";
case SCC_LIR_REM_S:
return "rem.s";
case SCC_LIR_REM_U:
return "rem.u";
case SCC_LIR_AND:
return "and";
case SCC_LIR_OR:
return "or";
case SCC_LIR_XOR:
return "xor";
case SCC_LIR_SHL:
return "shl";
case SCC_LIR_SHR:
return "shr";
case SCC_LIR_SAR:
return "sar";
case SCC_LIR_NEG:
return "neg";
case SCC_LIR_NOT:
return "not";
case SCC_LIR_FADD:
return "fadd";
case SCC_LIR_FSUB:
return "fsub";
case SCC_LIR_FMUL:
return "fmul";
case SCC_LIR_FDIV:
return "fdiv";
case SCC_LIR_FNEG:
return "fneg";
case SCC_LIR_FCVT:
return "fcvt";
case SCC_LIR_CMP:
return "cmp";
case SCC_LIR_BR:
return "br";
case SCC_LIR_JMP:
return "jmp";
case SCC_LIR_JMP_INDIRECT:
return "jmp.indirect";
case SCC_LIR_CALL:
return "call";
case SCC_LIR_CALL_INDIRECT:
return "call.indirect";
case SCC_LIR_RET:
return "ret";
case SCC_LIR_PARALLEL_COPY:
return "parallel_copy";
case SCC_LIR_VA_START:
return "va_start";
case SCC_LIR_VA_ARG:
return "va_arg";
case SCC_LIR_VA_END:
return "va_end";
case SCC_LIR_VA_COPY:
return "va_copy";
case SCC_LIR_ALLOCA:
return "alloca";
case SCC_LIR_MEMCPY:
return "memcpy";
case SCC_LIR_MEMSET:
return "memset";
case SCC_LIR_NOP:
return "nop";
default:
return "???";
}
static const char *op_names[] = {
[SCC_LIR_MOV] = "mov",
[SCC_LIR_LOAD] = "load",
[SCC_LIR_LOAD_ADDR] = "load.addr",
[SCC_LIR_STORE] = "store",
[SCC_LIR_ADD] = "add",
[SCC_LIR_SUB] = "sub",
[SCC_LIR_MUL] = "mul",
[SCC_LIR_DIV_S] = "div.s",
[SCC_LIR_DIV_U] = "div.u",
[SCC_LIR_REM_S] = "rem.s",
[SCC_LIR_REM_U] = "rem.u",
[SCC_LIR_AND] = "and",
[SCC_LIR_OR] = "or",
[SCC_LIR_XOR] = "xor",
[SCC_LIR_SHL] = "shl",
[SCC_LIR_SHR] = "shr",
[SCC_LIR_SAR] = "sar",
[SCC_LIR_NEG] = "neg",
[SCC_LIR_NOT] = "not",
[SCC_LIR_FADD] = "fadd",
[SCC_LIR_FSUB] = "fsub",
[SCC_LIR_FMUL] = "fmul",
[SCC_LIR_FDIV] = "fdiv",
[SCC_LIR_FNEG] = "fneg",
[SCC_LIR_FCVT] = "fcvt",
[SCC_LIR_CMP] = "cmp",
[SCC_LIR_BR] = "br",
[SCC_LIR_JMP] = "jmp",
[SCC_LIR_JMP_INDIRECT] = "jmp.indirect",
[SCC_LIR_CALL] = "call",
[SCC_LIR_CALL_INDIRECT] = "call.indirect",
[SCC_LIR_RET] = "ret",
[SCC_LIR_PARALLEL_COPY] = "parallel_copy",
[SCC_LIR_VA_START] = "va_start",
[SCC_LIR_VA_ARG] = "va_arg",
[SCC_LIR_VA_END] = "va_end",
[SCC_LIR_VA_COPY] = "va_copy",
[SCC_LIR_ALLOCA] = "alloca",
[SCC_LIR_EXTEND] = "extend",
[SCC_LIR_MEMCPY] = "memcpy",
[SCC_LIR_MEMSET] = "memset",
[SCC_LIR_NOP] = "nop",
};
return op_names[op];
}
static const char *cond_to_string(scc_lir_cond_t cond) {
switch (cond) {
case SCC_LIR_COND_EQ:
return "eq";
case SCC_LIR_COND_NE:
return "ne";
case SCC_LIR_COND_SLT:
return "slt";
case SCC_LIR_COND_SLE:
return "sle";
case SCC_LIR_COND_SGT:
return "sgt";
case SCC_LIR_COND_SGE:
return "sge";
case SCC_LIR_COND_ULT:
return "ult";
case SCC_LIR_COND_ULE:
return "ule";
case SCC_LIR_COND_UGT:
return "ugt";
case SCC_LIR_COND_UGE:
return "uge";
case SCC_LIR_COND_FEQ:
return "feq";
case SCC_LIR_COND_FNE:
return "fne";
case SCC_LIR_COND_FLT:
return "flt";
case SCC_LIR_COND_FLE:
return "fle";
case SCC_LIR_COND_FGT:
return "fgt";
case SCC_LIR_COND_FGE:
return "fge";
default:
return "???";
}
static const char *names[] = {
[SCC_LIR_COND_EQ] = "eq", [SCC_LIR_COND_NE] = "ne",
[SCC_LIR_COND_SLT] = "slt", [SCC_LIR_COND_SLE] = "sle",
[SCC_LIR_COND_SGT] = "sgt", [SCC_LIR_COND_SGE] = "sge",
[SCC_LIR_COND_ULT] = "ult", [SCC_LIR_COND_ULE] = "ule",
[SCC_LIR_COND_UGT] = "ugt", [SCC_LIR_COND_UGE] = "uge",
[SCC_LIR_COND_FEQ] = "feq", [SCC_LIR_COND_FNE] = "fne",
[SCC_LIR_COND_FLT] = "flt", [SCC_LIR_COND_FLE] = "fle",
[SCC_LIR_COND_FGT] = "fgt", [SCC_LIR_COND_FGE] = "fge",
};
return names[cond];
}
static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) {
@@ -150,9 +81,6 @@ static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) {
case SCC_LIR_INSTR_KIND_VREG:
scc_tree_dump_append_fmt(td, "%%%u", op->data.reg);
break;
// case SCC_LIR_INSTR_KIND_PREG:
// scc_tree_dump_append_fmt(td, "Phy%u", op->data.reg);
// break;
case SCC_LIR_INSTR_KIND_IMM:
// TODO hack ap
scc_tree_dump_append_fmt(td, "%lld", op->data.imm.data.digit);
@@ -241,6 +169,26 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
ins->metadata.alloca.align_bytes);
dump_operand(ctx, &ins->to);
break;
case SCC_LIR_EXTEND: {
const char *ext_name = "";
switch (ins->ext) {
case SCC_LIR_EXT_ZEXT:
ext_name = "zext";
break;
case SCC_LIR_EXT_SEXT:
ext_name = "sext";
break;
default:
ext_name = "ext";
break;
}
scc_tree_dump_append_fmt(td, "%s(%d<-%d) ", ext_name, ins->size * 8,
ins->metadata.extend.from_size * 8);
dump_operand(ctx, &ins->to);
scc_tree_dump_append(td, " <- ");
dump_operand(ctx, &ins->arg0);
break;
}
// case SCC_LIR_STORE_ADDR:
case SCC_LIR_STORE:
dump_operand(ctx, &ins->arg0);