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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user