Compare commits
2 Commits
aa4292a30e
...
d78b91894e
| Author | SHA1 | Date | |
|---|---|---|---|
| d78b91894e | |||
| 41d060d7e7 |
@@ -19,6 +19,10 @@ typedef struct {
|
|||||||
scc_ast_ctx_t *ast_ctx;
|
scc_ast_ctx_t *ast_ctx;
|
||||||
} scc_ast2ir_ctx_t;
|
} scc_ast2ir_ctx_t;
|
||||||
|
|
||||||
|
static inline scc_hir_module_t *scc_ast2ir_mir_module(scc_ast2ir_ctx_t *ctx) {
|
||||||
|
return &ctx->builder.cprog->module;
|
||||||
|
}
|
||||||
|
|
||||||
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
||||||
scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog);
|
scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog);
|
||||||
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx);
|
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ static void emit_array_initialization(scc_ast2ir_ctx_t *ctx,
|
|||||||
Assert(array_type->tag == SCC_HIR_TYPE_ARRAY);
|
Assert(array_type->tag == SCC_HIR_TYPE_ARRAY);
|
||||||
scc_hir_type_ref_t elem_type_ref = array_type->data.array.base;
|
scc_hir_type_ref_t elem_type_ref = array_type->data.array.base;
|
||||||
const scc_hir_type_t *elem_type =
|
const scc_hir_type_t *elem_type =
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module, elem_type_ref);
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), elem_type_ref);
|
||||||
usize array_len = array_type->data.array.len;
|
usize array_len = array_type->data.array.len;
|
||||||
|
|
||||||
// 字符串字面量初始化:直接 memcpy
|
// 字符串字面量初始化:直接 memcpy
|
||||||
@@ -124,8 +124,8 @@ static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx,
|
|||||||
scc_vec_at(init_expr->compound.rhs_exprs, i);
|
scc_vec_at(init_expr->compound.rhs_exprs, i);
|
||||||
scc_hir_type_ref_t field_type_ref =
|
scc_hir_type_ref_t field_type_ref =
|
||||||
scc_vec_at(type->data.aggregate.fields, idx);
|
scc_vec_at(type->data.aggregate.fields, idx);
|
||||||
const scc_hir_type_t *field_type = scc_hir_module_get_type(
|
const scc_hir_type_t *field_type =
|
||||||
&ctx->builder.cprog->module, field_type_ref);
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), field_type_ref);
|
||||||
|
|
||||||
scc_ap_t idx_ap;
|
scc_ap_t idx_ap;
|
||||||
scc_ap_set_int(&idx_ap, idx);
|
scc_ap_set_int(&idx_ap, idx);
|
||||||
@@ -149,68 +149,6 @@ static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
// static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {}
|
// 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: {
|
|
||||||
// 目标指针大小,可以定义为 8(64位)或从 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)
|
// 辅助函数:计算数组实际长度(如果原长度为0)
|
||||||
static void resolve_array_length(scc_ast2ir_ctx_t *ctx,
|
static void resolve_array_length(scc_ast2ir_ctx_t *ctx,
|
||||||
const scc_hir_type_t *orig_array_type,
|
const scc_hir_type_t *orig_array_type,
|
||||||
@@ -334,7 +272,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
|||||||
// === 3. 直接添加到模块,不经过 builder 的 uniquing ===
|
// === 3. 直接添加到模块,不经过 builder 的 uniquing ===
|
||||||
// 因为此时我们不需要类型去重,只需要一个确定不移的引用
|
// 因为此时我们不需要类型去重,只需要一个确定不移的引用
|
||||||
scc_hir_type_ref_t place_ref =
|
scc_hir_type_ref_t place_ref =
|
||||||
scc_hir_module_add_type(&ctx->builder.cprog->module, &placeholder);
|
scc_hir_module_add_type(scc_ast2ir_mir_module(ctx), &placeholder);
|
||||||
|
|
||||||
// === 4. 将映射写入缓存(关键!必须在递归前) ===
|
// === 4. 将映射写入缓存(关键!必须在递归前) ===
|
||||||
scc_hashtable_set(&ctx->type_cache, canon, (void *)(usize)place_ref);
|
scc_hashtable_set(&ctx->type_cache, canon, (void *)(usize)place_ref);
|
||||||
@@ -357,7 +295,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
|||||||
|
|
||||||
// === 6. 将字段填入占位类型 ===
|
// === 6. 将字段填入占位类型 ===
|
||||||
scc_hir_type_t *place_type =
|
scc_hir_type_t *place_type =
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module, place_ref);
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), place_ref);
|
||||||
// 注意:scc_hir_type_init 已经为 struct/union 初始化了 fields 空向量
|
// 注意:scc_hir_type_init 已经为 struct/union 初始化了 fields 空向量
|
||||||
// 这里直接 push 即可(也可以先 scc_vec_free 再 init,看需要)
|
// 这里直接 push 即可(也可以先 scc_vec_free 再 init,看需要)
|
||||||
scc_vec_foreach(fields, i) {
|
scc_vec_foreach(fields, i) {
|
||||||
@@ -895,13 +833,15 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
// 3. 确定转换模式(SEXT / ZEXT / TRUNC)
|
// 3. 确定转换模式(SEXT / ZEXT / TRUNC)
|
||||||
// 这里用简单的启发式:根据大小变化决定
|
// 这里用简单的启发式:根据大小变化决定
|
||||||
scc_hir_type_t *src_type = scc_hir_module_get_type_by_value(
|
scc_hir_type_t *src_type = scc_hir_module_get_type_by_value(
|
||||||
&ctx->builder.cprog->module, operand);
|
scc_ast2ir_mir_module(ctx), operand);
|
||||||
scc_hir_type_t *dst_type =
|
scc_hir_type_t *dst_type =
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module, target_type);
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), target_type);
|
||||||
|
|
||||||
usize src_size =
|
usize src_size = scc_hir_module_type_size(
|
||||||
scc_hir_type_size(ctx, src_type); // 你可能有这个函数,否则自行计算
|
scc_ast2ir_mir_module(ctx),
|
||||||
usize dst_size = scc_hir_type_size(ctx, dst_type);
|
src_type); // 你可能有这个函数,否则自行计算
|
||||||
|
usize dst_size =
|
||||||
|
scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), dst_type);
|
||||||
|
|
||||||
int conv_kind;
|
int conv_kind;
|
||||||
if (dst_size > src_size) {
|
if (dst_size > src_size) {
|
||||||
@@ -923,8 +863,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
.data.conv.target_type = target_type,
|
.data.conv.target_type = target_type,
|
||||||
.data.conv.conv_type = conv_kind,
|
.data.conv.conv_type = conv_kind,
|
||||||
};
|
};
|
||||||
return scc_hir_module_add_value(&ctx->builder.cprog->module,
|
return scc_hir_module_add_value(scc_ast2ir_mir_module(ctx), &conv_node);
|
||||||
&conv_node);
|
|
||||||
}
|
}
|
||||||
case SCC_AST_EXPR_SIZE_OF: {
|
case SCC_AST_EXPR_SIZE_OF: {
|
||||||
// 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型
|
// 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型
|
||||||
@@ -939,7 +878,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
scc_hir_value_ref_t dummy =
|
scc_hir_value_ref_t dummy =
|
||||||
scc_ast2ir_expr(ctx, expr->attr_of.expr, false);
|
scc_ast2ir_expr(ctx, expr->attr_of.expr, false);
|
||||||
hir_type =
|
hir_type =
|
||||||
scc_hir_module_get_value(&ctx->builder.cprog->module, dummy)
|
scc_hir_module_get_value(scc_ast2ir_mir_module(ctx), dummy)
|
||||||
->type;
|
->type;
|
||||||
} else {
|
} else {
|
||||||
scc_ap_t val;
|
scc_ap_t val;
|
||||||
@@ -951,8 +890,9 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
|
|
||||||
// 2. 计算大小
|
// 2. 计算大小
|
||||||
const scc_hir_type_t *type =
|
const scc_hir_type_t *type =
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module, hir_type);
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), hir_type);
|
||||||
usize dst_size = scc_hir_type_size(ctx, type);
|
usize dst_size =
|
||||||
|
scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), type);
|
||||||
|
|
||||||
scc_ap_t val;
|
scc_ap_t val;
|
||||||
val.data.digit = dst_size;
|
val.data.digit = dst_size;
|
||||||
@@ -971,7 +911,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
scc_ast_qual_type_t *ast_type = expr->compound.base->lvalue.type;
|
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);
|
scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, ast_type);
|
||||||
const scc_hir_type_t *type =
|
const scc_hir_type_t *type =
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module, type_ref);
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), type_ref);
|
||||||
|
|
||||||
// 2. 分配栈上临时存储
|
// 2. 分配栈上临时存储
|
||||||
scc_hir_value_ref_t storage =
|
scc_hir_value_ref_t storage =
|
||||||
@@ -1073,10 +1013,10 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
} else {
|
} else {
|
||||||
// 右值:如果是数组类型,退化为指针(返回地址)
|
// 右值:如果是数组类型,退化为指针(返回地址)
|
||||||
scc_hir_type_t *ir_type = scc_hir_module_get_type_by_value(
|
scc_hir_type_t *ir_type = scc_hir_module_get_type_by_value(
|
||||||
&ctx->builder.cprog->module, in);
|
scc_ast2ir_mir_module(ctx), in);
|
||||||
if (ir_type->tag == SCC_HIR_TYPE_PTR) {
|
if (ir_type->tag == SCC_HIR_TYPE_PTR) {
|
||||||
scc_hir_type_t *target_type = scc_hir_module_get_type(
|
scc_hir_type_t *target_type = scc_hir_module_get_type(
|
||||||
&ctx->builder.cprog->module, ir_type->data.pointer.base);
|
scc_ast2ir_mir_module(ctx), ir_type->data.pointer.base);
|
||||||
if (target_type->tag == SCC_HIR_TYPE_ARRAY) {
|
if (target_type->tag == SCC_HIR_TYPE_ARRAY) {
|
||||||
// 生成 getptr 获取数组首地址
|
// 生成 getptr 获取数组首地址
|
||||||
return scc_hir_builder_get_elem_ptr(&ctx->builder, in,
|
return scc_hir_builder_get_elem_ptr(&ctx->builder, in,
|
||||||
@@ -1344,8 +1284,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
const scc_hir_type_t *orig_type;
|
const scc_hir_type_t *orig_type;
|
||||||
SCC_HIR_BUILDER_BEGIN_BORROW(
|
SCC_HIR_BUILDER_BEGIN_BORROW(
|
||||||
&ctx->builder, orig_type,
|
&ctx->builder, orig_type,
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module,
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), orig_type_ref));
|
||||||
orig_type_ref));
|
|
||||||
scc_hir_type_t final_type_desc = *orig_type;
|
scc_hir_type_t final_type_desc = *orig_type;
|
||||||
SCC_HIR_BUILDER_END_BORROW(&ctx->builder);
|
SCC_HIR_BUILDER_END_BORROW(&ctx->builder);
|
||||||
|
|
||||||
@@ -1384,7 +1323,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
const scc_hir_type_t *final_type;
|
const scc_hir_type_t *final_type;
|
||||||
SCC_HIR_BUILDER_BEGIN_BORROW(
|
SCC_HIR_BUILDER_BEGIN_BORROW(
|
||||||
&ctx->builder, final_type,
|
&ctx->builder, final_type,
|
||||||
scc_hir_module_get_type(&ctx->builder.cprog->module,
|
scc_hir_module_get_type(scc_ast2ir_mir_module(ctx),
|
||||||
final_type_ref));
|
final_type_ref));
|
||||||
scc_hir_type_t type = *final_type;
|
scc_hir_type_t type = *final_type;
|
||||||
SCC_HIR_BUILDER_END_BORROW(&ctx->builder);
|
SCC_HIR_BUILDER_END_BORROW(&ctx->builder);
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ scc_hir_value_ref_t scc_hir_builder_builtin_memcpy(scc_hir_builder_t *builder,
|
|||||||
static inline scc_hir_value_ref_t
|
static inline scc_hir_value_ref_t
|
||||||
scc_hir_builder_integer(scc_hir_builder_t *builder, scc_hir_type_ref_t type,
|
scc_hir_builder_integer(scc_hir_builder_t *builder, scc_hir_type_ref_t type,
|
||||||
scc_ap_t *val) {
|
scc_ap_t *val) {
|
||||||
|
Assert(builder != nullptr && val != nullptr);
|
||||||
scc_hir_value_t value;
|
scc_hir_value_t value;
|
||||||
scc_hir_value_init(&value, nullptr, SCC_HIR_VALUE_TAG_INTEGER);
|
scc_hir_value_init(&value, nullptr, SCC_HIR_VALUE_TAG_INTEGER);
|
||||||
// FIXME assign
|
// FIXME assign
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ scc_hir_bblock_t *scc_hir_module_get_bblock(scc_hir_module_t *ctx,
|
|||||||
scc_hir_bblock_ref_t ref);
|
scc_hir_bblock_ref_t ref);
|
||||||
scc_hir_func_t *scc_hir_module_get_func(scc_hir_module_t *ctx,
|
scc_hir_func_t *scc_hir_module_get_func(scc_hir_module_t *ctx,
|
||||||
scc_hir_func_ref_t ref);
|
scc_hir_func_ref_t ref);
|
||||||
|
usize scc_hir_module_type_size(scc_hir_module_t *ctx, scc_hir_type_t *type);
|
||||||
|
|
||||||
static inline scc_hir_type_t *
|
static inline scc_hir_type_t *
|
||||||
scc_hir_module_get_type_by_value(scc_hir_module_t *ctx,
|
scc_hir_module_get_type_by_value(scc_hir_module_t *ctx,
|
||||||
|
|||||||
@@ -287,14 +287,8 @@ scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder,
|
|||||||
scc_hir_builder_global_alloca(builder, array_type_ref, const_array_ref);
|
scc_hir_builder_global_alloca(builder, array_type_ref, const_array_ref);
|
||||||
// scc_hashtable_insert(builder);
|
// scc_hashtable_insert(builder);
|
||||||
|
|
||||||
scc_hir_value_ref_t pointer_to_global_value = scc_hir_module_add_value(
|
scc_hir_value_ref_t pointer_to_global_value = scc_hir_builder_get_elem_ptr(
|
||||||
GET_MODULE(builder),
|
builder, global_value_ref, SCC_HIR_VALUE_TAG_NULLPTR);
|
||||||
&(scc_hir_value_t){
|
|
||||||
.tag = SCC_HIR_VALUE_TAG_GET_ELEM_PTR,
|
|
||||||
.data.get_elem_ptr.src_addr = global_value_ref,
|
|
||||||
.data.get_elem_ptr.index = SCC_HIR_VALUE_TAG_NULLPTR,
|
|
||||||
});
|
|
||||||
scc_hir_builder_add_instr(builder, pointer_to_global_value);
|
|
||||||
return pointer_to_global_value;
|
return pointer_to_global_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,12 +400,18 @@ scc_hir_value_ref_t scc_hir_builder_global_alloca(scc_hir_builder_t *builder,
|
|||||||
scc_hir_type_ref_t type,
|
scc_hir_type_ref_t type,
|
||||||
scc_hir_value_ref_t value) {
|
scc_hir_value_ref_t value) {
|
||||||
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
|
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
|
||||||
|
// 全局变量的实际类型是指向 type 的指针
|
||||||
|
scc_hir_type_t ptr_type = {.tag = SCC_HIR_TYPE_PTR,
|
||||||
|
.data.pointer.base = type};
|
||||||
|
scc_hir_type_ref_t ptr_type_ref = scc_hir_builder_type(builder, &ptr_type);
|
||||||
|
|
||||||
|
// FIXME
|
||||||
char *name = scc_malloc(32);
|
char *name = scc_malloc(32);
|
||||||
scc_hir_value_ref_t global_value_ref = scc_hir_module_add_value(
|
scc_hir_value_ref_t global_value_ref = scc_hir_module_add_value(
|
||||||
GET_MODULE(builder), &(scc_hir_value_t){
|
GET_MODULE(builder), &(scc_hir_value_t){
|
||||||
.name = name,
|
.name = name,
|
||||||
.tag = SCC_HIR_VALUE_TAG_GLOBAL_ALLOC,
|
.tag = SCC_HIR_VALUE_TAG_GLOBAL_ALLOC,
|
||||||
.type = type,
|
.type = ptr_type_ref, // 类型是指针
|
||||||
.data.global_alloc.value = value,
|
.data.global_alloc.value = value,
|
||||||
});
|
});
|
||||||
scc_snprintf(name, 32, "$G%u", global_value_ref);
|
scc_snprintf(name, 32, "$G%u", global_value_ref);
|
||||||
@@ -506,6 +506,12 @@ scc_hir_value_ref_t scc_hir_builder_get_elem_ptr(scc_hir_builder_t *builder,
|
|||||||
scc_hir_value_t get_ptr_node = {0};
|
scc_hir_value_t get_ptr_node = {0};
|
||||||
get_ptr_node.tag = SCC_HIR_VALUE_TAG_GET_ELEM_PTR;
|
get_ptr_node.tag = SCC_HIR_VALUE_TAG_GET_ELEM_PTR;
|
||||||
get_ptr_node.data.get_elem_ptr.src_addr = target;
|
get_ptr_node.data.get_elem_ptr.src_addr = target;
|
||||||
|
if (index == SCC_HIR_REF_nullptr) {
|
||||||
|
scc_ap_t ap = {.capacity = -1, .len = 0, .data.digit = 0};
|
||||||
|
index = scc_hir_builder_integer(builder,
|
||||||
|
scc_hir_builder_type_u8(builder), &ap);
|
||||||
|
}
|
||||||
|
Assert(target != SCC_HIR_REF_nullptr && index != SCC_HIR_REF_nullptr);
|
||||||
get_ptr_node.data.get_elem_ptr.index = index;
|
get_ptr_node.data.get_elem_ptr.index = index;
|
||||||
|
|
||||||
// 借用类型信息
|
// 借用类型信息
|
||||||
|
|||||||
@@ -126,3 +126,46 @@ scc_hir_func_t *scc_hir_module_get_func(scc_hir_module_t *ctx,
|
|||||||
scc_hir_func_ref_t ref) {
|
scc_hir_func_ref_t ref) {
|
||||||
return scc_cfg_module_unsafe_get_func(&ctx->cfg_module, ref);
|
return scc_cfg_module_unsafe_get_func(&ctx->cfg_module, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usize scc_hir_module_type_size(scc_hir_module_t *ctx, scc_hir_type_t *type) {
|
||||||
|
Assert(type != nullptr);
|
||||||
|
switch (type->tag) {
|
||||||
|
case SCC_HIR_TYPE_unknown:
|
||||||
|
case SCC_HIR_TYPE_void:
|
||||||
|
return 0;
|
||||||
|
case SCC_HIR_TYPE_i8:
|
||||||
|
case SCC_HIR_TYPE_u8:
|
||||||
|
return 1;
|
||||||
|
case SCC_HIR_TYPE_i16:
|
||||||
|
case SCC_HIR_TYPE_u16:
|
||||||
|
return 2;
|
||||||
|
case SCC_HIR_TYPE_f32:
|
||||||
|
case SCC_HIR_TYPE_i32:
|
||||||
|
case SCC_HIR_TYPE_u32:
|
||||||
|
return 4;
|
||||||
|
case SCC_HIR_TYPE_f64:
|
||||||
|
case SCC_HIR_TYPE_i64:
|
||||||
|
case SCC_HIR_TYPE_u64:
|
||||||
|
return 8;
|
||||||
|
case SCC_HIR_TYPE_FUNC:
|
||||||
|
case SCC_HIR_TYPE_PTR: {
|
||||||
|
// TODO
|
||||||
|
// 目标指针大小,可以定义为 8(64位)或从 ABI 获取
|
||||||
|
// 假设你的目标架构是 64 位
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
case SCC_HIR_TYPE_ARRAY: {
|
||||||
|
usize elem_size = scc_hir_module_type_size(
|
||||||
|
ctx, scc_hir_module_get_type(ctx, type->data.array.base));
|
||||||
|
return elem_size * type->data.array.len;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,6 @@
|
|||||||
#include "scc_lir_module.h"
|
#include "scc_lir_module.h"
|
||||||
#include <scc_hir.h>
|
#include <scc_hir.h>
|
||||||
|
|
||||||
void scc_hir2lir(scc_lir_module_t *module, const scc_hir_cprog_t *cprog);
|
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog);
|
||||||
|
|
||||||
#endif /* __SCC_IR2LIR_H__ */
|
#endif /* __SCC_IR2LIR_H__ */
|
||||||
|
|||||||
@@ -41,17 +41,6 @@ typedef enum {
|
|||||||
SCC_LIR_INSTR_KIND_MEM, // 复杂地址表达式 (base + index*scale + offset)
|
SCC_LIR_INSTR_KIND_MEM, // 复杂地址表达式 (base + index*scale + offset)
|
||||||
} scc_lir_instr_kind_t;
|
} scc_lir_instr_kind_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 复杂地址表达式
|
|
||||||
* base + index * scale + offset
|
|
||||||
*/
|
|
||||||
typedef struct scc_lir_addr {
|
|
||||||
int base; // 基址寄存器,-1 表示无
|
|
||||||
int index; // 索引寄存器,-1 表示无
|
|
||||||
int scale; // 比例因子 (1, 2, 4, 8)
|
|
||||||
i64 offset; // 常量偏移
|
|
||||||
} scc_lir_addr_t;
|
|
||||||
|
|
||||||
typedef struct scc_lir_instr {
|
typedef struct scc_lir_instr {
|
||||||
scc_lir_instr_kind_t kind;
|
scc_lir_instr_kind_t kind;
|
||||||
union {
|
union {
|
||||||
@@ -60,7 +49,6 @@ typedef struct scc_lir_instr {
|
|||||||
scc_ap_t imm; // 整型立即数
|
scc_ap_t imm; // 整型立即数
|
||||||
f64 fimm; // 浮点立即数
|
f64 fimm; // 浮点立即数
|
||||||
const char *symbol; // 符号名 (生命周期由前端管理)
|
const char *symbol; // 符号名 (生命周期由前端管理)
|
||||||
scc_lir_addr_t addr; // 复杂地址
|
|
||||||
} data;
|
} data;
|
||||||
} scc_lir_val_t;
|
} scc_lir_val_t;
|
||||||
|
|
||||||
@@ -74,8 +62,6 @@ typedef struct scc_lir_instr {
|
|||||||
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_FIMM, .data.fimm = (v)})
|
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_FIMM, .data.fimm = (v)})
|
||||||
#define SCC_LIR_SYMBOL(s) \
|
#define SCC_LIR_SYMBOL(s) \
|
||||||
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_SYMBOL, .data.symbol = (s)})
|
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_SYMBOL, .data.symbol = (s)})
|
||||||
#define SCC_LIR_ADDR(b, i, s, o) \
|
|
||||||
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_MEM, .data.addr = {b, i, s, o}})
|
|
||||||
#define SCC_LIR_ARG(n) \
|
#define SCC_LIR_ARG(n) \
|
||||||
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_ARG, .data.arg = (n)})
|
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_ARG, .data.arg = (n)})
|
||||||
|
|
||||||
@@ -97,8 +83,6 @@ typedef enum {
|
|||||||
SCC_LIR_LOAD,
|
SCC_LIR_LOAD,
|
||||||
SCC_LIR_LOAD_ADDR,
|
SCC_LIR_LOAD_ADDR,
|
||||||
SCC_LIR_STORE,
|
SCC_LIR_STORE,
|
||||||
SCC_LIR_STORE_ADDR,
|
|
||||||
SCC_LIR_LEA,
|
|
||||||
|
|
||||||
/* 整数算术 */
|
/* 整数算术 */
|
||||||
SCC_LIR_ADD,
|
SCC_LIR_ADD,
|
||||||
@@ -144,6 +128,9 @@ typedef enum {
|
|||||||
SCC_LIR_VA_ARG,
|
SCC_LIR_VA_ARG,
|
||||||
SCC_LIR_VA_END,
|
SCC_LIR_VA_END,
|
||||||
SCC_LIR_VA_COPY,
|
SCC_LIR_VA_COPY,
|
||||||
|
/* 内置方法 */
|
||||||
|
SCC_LIR_MEMCPY,
|
||||||
|
SCC_LIR_MEMSET,
|
||||||
|
|
||||||
/* 栈管理 */
|
/* 栈管理 */
|
||||||
SCC_LIR_ALLOCA,
|
SCC_LIR_ALLOCA,
|
||||||
@@ -184,6 +171,12 @@ typedef struct scc_lir_ins {
|
|||||||
union {
|
union {
|
||||||
scc_lir_cond_t cond;
|
scc_lir_cond_t cond;
|
||||||
|
|
||||||
|
// base + index * scale + offset
|
||||||
|
struct scc_lir_addr {
|
||||||
|
int scale; // 比例因子 (1, 2, 4, 8)
|
||||||
|
i64 offset; // 常量偏移
|
||||||
|
} addr;
|
||||||
|
|
||||||
struct scc_lir_br {
|
struct scc_lir_br {
|
||||||
scc_lir_bblock_id_t true_target;
|
scc_lir_bblock_id_t true_target;
|
||||||
scc_lir_bblock_id_t false_target;
|
scc_lir_bblock_id_t false_target;
|
||||||
@@ -241,6 +234,18 @@ typedef struct scc_lir_ins {
|
|||||||
scc_lir_val_t dest;
|
scc_lir_val_t dest;
|
||||||
scc_lir_val_t src;
|
scc_lir_val_t src;
|
||||||
} va_copy;
|
} va_copy;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
scc_lir_val_t dest;
|
||||||
|
scc_lir_val_t src;
|
||||||
|
scc_lir_val_t size;
|
||||||
|
} memcpy;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
scc_lir_val_t dest;
|
||||||
|
scc_lir_val_t value;
|
||||||
|
scc_lir_val_t size;
|
||||||
|
} memset;
|
||||||
} metadata;
|
} metadata;
|
||||||
} scc_lir_instr_t;
|
} scc_lir_instr_t;
|
||||||
|
|
||||||
@@ -253,14 +258,14 @@ typedef scc_cfg_func_t scc_lir_func_t;
|
|||||||
typedef struct scc_lir_func_meta {
|
typedef struct scc_lir_func_meta {
|
||||||
int vregs_count;
|
int vregs_count;
|
||||||
int frame_size;
|
int frame_size;
|
||||||
|
int is_va_arg;
|
||||||
scc_lir_attr_t attr;
|
scc_lir_attr_t attr;
|
||||||
} scc_lir_func_meta_t;
|
} scc_lir_func_meta_t;
|
||||||
#define SCC_LIR_FUNC_META(func) ((scc_lir_func_meta_t *)(func)->meta)
|
#define SCC_LIR_FUNC_META(func) ((scc_lir_func_meta_t *)(func)->meta)
|
||||||
|
|
||||||
typedef scc_cfg_symbol_id_t scc_lir_symbol_id_t;
|
typedef scc_cfg_symbol_id_t scc_lir_symbol_id_t;
|
||||||
typedef scc_cfg_symbol_t scc_lir_symbol_t;
|
typedef scc_cfg_symbol_t scc_lir_symbol_t;
|
||||||
typedef struct scc_lir_symbol_meta {
|
typedef union scc_lir_symbol_meta {
|
||||||
union {
|
|
||||||
struct {
|
struct {
|
||||||
scc_lir_func_t *func; // 指向函数体(若为定义)
|
scc_lir_func_t *func; // 指向函数体(若为定义)
|
||||||
} func;
|
} func;
|
||||||
@@ -269,7 +274,6 @@ typedef struct scc_lir_symbol_meta {
|
|||||||
usize size; // 数据大小(字节)
|
usize size; // 数据大小(字节)
|
||||||
int align; // 对齐要求
|
int align; // 对齐要求
|
||||||
} data;
|
} data;
|
||||||
};
|
|
||||||
} scc_lir_symbol_meta_t;
|
} scc_lir_symbol_meta_t;
|
||||||
#define SCC_LIR_SYMBOL_META(symbol) ((scc_lir_symbol_meta_t *)(symbol)->meta)
|
#define SCC_LIR_SYMBOL_META(symbol) ((scc_lir_symbol_meta_t *)(symbol)->meta)
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ static void ir_type_to_lir_size_ext(scc_hir_type_t *type, u8 *out_size,
|
|||||||
*out_size = SCC_LIR_SIZE_64;
|
*out_size = SCC_LIR_SIZE_64;
|
||||||
*out_ext = SCC_LIR_EXT_FLOAT;
|
*out_ext = SCC_LIR_EXT_FLOAT;
|
||||||
break;
|
break;
|
||||||
|
case SCC_HIR_TYPE_ARRAY:
|
||||||
case SCC_HIR_TYPE_PTR:
|
case SCC_HIR_TYPE_PTR:
|
||||||
*out_size = SCC_LIR_SIZE_64;
|
*out_size = SCC_LIR_SIZE_64;
|
||||||
*out_ext = SCC_LIR_EXT_NONE;
|
*out_ext = SCC_LIR_EXT_NONE;
|
||||||
@@ -126,9 +127,7 @@ static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC: {
|
case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC: {
|
||||||
// 全局变量地址作为符号
|
// 全局变量地址作为符号
|
||||||
scc_hir_value_t *global_val = scc_hir_module_get_value(
|
return SCC_LIR_SYMBOL(val->name);
|
||||||
ctx->hir_module, val->data.global_alloc.value);
|
|
||||||
return SCC_LIR_SYMBOL(global_val->name);
|
|
||||||
}
|
}
|
||||||
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF: {
|
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF: {
|
||||||
// 函数参数:预先已分配 vreg
|
// 函数参数:预先已分配 vreg
|
||||||
@@ -234,12 +233,30 @@ static scc_lir_op_t map_binop(scc_hir_op_type_t op, cbool is_float) {
|
|||||||
case SCC_HIR_OP_SAR:
|
case SCC_HIR_OP_SAR:
|
||||||
return SCC_LIR_SAR;
|
return SCC_LIR_SAR;
|
||||||
default:
|
default:
|
||||||
return map_cmp_cond(op, is_float);
|
return SCC_LIR_CMP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SCC_LIR_NOP;
|
return SCC_LIR_NOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保操作数是一个虚拟寄存器,如果不是则生成 MOV 并返回新 VREG 编号
|
||||||
|
static int ensure_vreg(ir2lir_ctx_t *ctx, scc_lir_val_t *val) {
|
||||||
|
if (val->kind == SCC_LIR_INSTR_KIND_VREG) {
|
||||||
|
return val->data.reg;
|
||||||
|
}
|
||||||
|
// 分配新的虚拟寄存器
|
||||||
|
int new_vreg = ++(SCC_LIR_FUNC_META(ctx->current_func)->vregs_count);
|
||||||
|
scc_lir_instr_t mov = {.op = SCC_LIR_MOV,
|
||||||
|
.size = SCC_LIR_SIZE_64, // 地址宽度
|
||||||
|
.to = SCC_LIR_VREG(new_vreg),
|
||||||
|
.arg0 = *val};
|
||||||
|
scc_lir_builder_add_instr(ctx, &mov);
|
||||||
|
// 将原操作数替换为 VREG,避免重复转换
|
||||||
|
val->kind = SCC_LIR_INSTR_KIND_VREG;
|
||||||
|
val->data.reg = new_vreg;
|
||||||
|
return new_vreg;
|
||||||
|
}
|
||||||
|
|
||||||
static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||||
scc_hir_value_ref_t value_ref) {
|
scc_hir_value_ref_t value_ref) {
|
||||||
// 防止重复翻译
|
// 防止重复翻译
|
||||||
@@ -254,8 +271,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
}
|
}
|
||||||
bool is_float = (ext == SCC_LIR_EXT_FLOAT);
|
bool is_float = (ext == SCC_LIR_EXT_FLOAT);
|
||||||
|
|
||||||
// 为当前指令分配目标虚拟寄存器
|
int dst_vreg = get_vreg_for_value(ctx, value_ref);
|
||||||
unsigned int dst_vreg = get_vreg_for_value(ctx, value_ref);
|
|
||||||
|
|
||||||
switch (value->tag) {
|
switch (value->tag) {
|
||||||
case SCC_HIR_VALUE_TAG_OP: {
|
case SCC_HIR_VALUE_TAG_OP: {
|
||||||
@@ -263,15 +279,19 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
scc_lir_val_t rhs = ir_value_to_lir_operand(ctx, value->data.op.rhs);
|
scc_lir_val_t rhs = ir_value_to_lir_operand(ctx, value->data.op.rhs);
|
||||||
scc_lir_op_t op = map_binop(value->data.op.op, is_float);
|
scc_lir_op_t op = map_binop(value->data.op.op, is_float);
|
||||||
|
|
||||||
scc_lir_instr_t instr = {.op = op,
|
scc_lir_instr_t instr = {
|
||||||
|
.op = op,
|
||||||
.size = size,
|
.size = size,
|
||||||
.ext = ext,
|
.ext = ext,
|
||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = lhs,
|
.arg0 = lhs,
|
||||||
.arg1 = rhs};
|
.arg1 = rhs,
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
};
|
||||||
break;
|
if (op == SCC_LIR_CMP) {
|
||||||
|
instr.metadata.cond = map_cmp_cond(value->data.op.op, is_float);
|
||||||
}
|
}
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
} break;
|
||||||
case SCC_HIR_VALUE_TAG_LOAD: {
|
case SCC_HIR_VALUE_TAG_LOAD: {
|
||||||
scc_lir_val_t addr =
|
scc_lir_val_t addr =
|
||||||
ir_value_to_lir_operand(ctx, value->data.load.target);
|
ir_value_to_lir_operand(ctx, value->data.load.target);
|
||||||
@@ -281,82 +301,68 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = addr};
|
.arg0 = addr};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_STORE: {
|
case SCC_HIR_VALUE_TAG_STORE: {
|
||||||
scc_lir_val_t data =
|
scc_lir_val_t data =
|
||||||
ir_value_to_lir_operand(ctx, value->data.store.value);
|
ir_value_to_lir_operand(ctx, value->data.store.value);
|
||||||
scc_lir_val_t addr =
|
scc_lir_val_t addr =
|
||||||
ir_value_to_lir_operand(ctx, value->data.store.target);
|
ir_value_to_lir_operand(ctx, value->data.store.target);
|
||||||
scc_lir_instr_t instr = {
|
ty = scc_hir_module_get_type_by_value(ctx->hir_module,
|
||||||
.op = SCC_LIR_STORE, .size = size, .arg0 = data, .arg1 = addr};
|
value->data.store.value);
|
||||||
|
ir_type_to_lir_size_ext(ty, &size, &ext);
|
||||||
|
scc_lir_instr_t instr = {.op = SCC_LIR_STORE,
|
||||||
|
.ext = ext,
|
||||||
|
.size = size,
|
||||||
|
.arg0 = data,
|
||||||
|
.arg1 = addr};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
|
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
|
||||||
// 将指针运算转换为 LEA
|
// 1. 获取基址和索引的 LIR 操作数
|
||||||
scc_lir_val_t base =
|
scc_lir_val_t base =
|
||||||
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr);
|
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr);
|
||||||
scc_lir_val_t index = SCC_LIR_IMM(0);
|
scc_lir_val_t index =
|
||||||
if (value->data.get_elem_ptr.index)
|
|
||||||
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index);
|
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index);
|
||||||
|
|
||||||
// 计算元素大小
|
// 2. 获取元素类型和大小
|
||||||
scc_hir_type_t *ptr_ty = scc_hir_module_get_type_by_value(
|
scc_hir_type_t *ptr_type =
|
||||||
ctx->hir_module, value->data.get_elem_ptr.src_addr);
|
scc_hir_module_get_type(ctx->hir_module, value->type);
|
||||||
scc_hir_type_t *elem_ty = nullptr;
|
scc_hir_type_t *pointee = NULL;
|
||||||
if (ptr_ty->tag == SCC_HIR_TYPE_PTR) {
|
if (ptr_type->tag == SCC_HIR_TYPE_PTR) {
|
||||||
elem_ty = scc_hir_module_get_type(ctx->hir_module,
|
pointee = scc_hir_module_get_type(ctx->hir_module,
|
||||||
ptr_ty->data.pointer.base);
|
ptr_type->data.pointer.base);
|
||||||
} else if (ptr_ty->tag == SCC_HIR_TYPE_ARRAY) {
|
} else if (ptr_type->tag == SCC_HIR_TYPE_ARRAY) {
|
||||||
elem_ty = scc_hir_module_get_type(ctx->hir_module,
|
// 数组名退化为指针,元素类型为数组的元素类型
|
||||||
ptr_ty->data.array.base);
|
pointee = scc_hir_module_get_type(ctx->hir_module,
|
||||||
|
ptr_type->data.array.base);
|
||||||
|
} else {
|
||||||
|
Panic("GET_ELEM_PTR on non-pointer/array type");
|
||||||
}
|
}
|
||||||
Assert(elem_ty != nullptr);
|
int elem_size = scc_hir_module_type_size(ctx->hir_module, pointee);
|
||||||
int elem_size = 0;
|
|
||||||
// 简化:仅处理基本类型
|
|
||||||
if (elem_ty->tag == SCC_HIR_TYPE_i32 ||
|
|
||||||
elem_ty->tag == SCC_HIR_TYPE_u32)
|
|
||||||
elem_size = 4;
|
|
||||||
else if (elem_ty->tag == SCC_HIR_TYPE_i64 ||
|
|
||||||
elem_ty->tag == SCC_HIR_TYPE_u64)
|
|
||||||
elem_size = 8;
|
|
||||||
else if (elem_ty->tag == SCC_HIR_TYPE_i8 ||
|
|
||||||
elem_ty->tag == SCC_HIR_TYPE_u8)
|
|
||||||
elem_size = 1;
|
|
||||||
else if (elem_ty->tag == SCC_HIR_TYPE_ARRAY)
|
|
||||||
elem_size = 8; // FIXME ptr size
|
|
||||||
else
|
|
||||||
Panic("unsupported element type for getelemptr");
|
|
||||||
|
|
||||||
// 构造地址表达式:base + index * elem_size
|
int dst_vreg = get_vreg_for_value(ctx, value_ref);
|
||||||
scc_lir_val_t addr =
|
scc_lir_instr_t instr = {
|
||||||
SCC_LIR_ADDR(dst_vreg, -1, index.data.reg, elem_size);
|
.op = SCC_LIR_LOAD_ADDR,
|
||||||
// 更简单的做法:使用 LEA 指令,参数为 base 和 index,由后端展开
|
|
||||||
scc_lir_instr_t instr = {.op = SCC_LIR_LEA,
|
|
||||||
.size = SCC_LIR_SIZE_64,
|
.size = SCC_LIR_SIZE_64,
|
||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = base,
|
.arg0 = base,
|
||||||
.arg1 = index};
|
.arg1 = index,
|
||||||
// 实际需要将 index * elem_size 的信息编码,这里简化,假设后端处理
|
.metadata.addr.scale = elem_size,
|
||||||
|
.metadata.addr.offset = 0,
|
||||||
|
};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_ALLOC: {
|
case SCC_HIR_VALUE_TAG_ALLOC: {
|
||||||
// alloca 指令:分配栈空间
|
Assert(ty != nullptr);
|
||||||
scc_hir_type_t *alloc_ty =
|
scc_hir_type_t *alloc_ty =
|
||||||
scc_hir_module_get_type(ctx->hir_module, ty->data.pointer.base);
|
scc_hir_module_get_type(ctx->hir_module, ty->data.pointer.base);
|
||||||
// 计算大小和对齐(简化)
|
int alloc_size = scc_hir_module_type_size(ctx->hir_module, alloc_ty);
|
||||||
int alloc_size = 8; // 默认
|
|
||||||
if (alloc_ty->tag == SCC_HIR_TYPE_i32)
|
|
||||||
alloc_size = 4;
|
|
||||||
scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA,
|
scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA,
|
||||||
.size = SCC_LIR_SIZE_64,
|
.size = alloc_size,
|
||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.metadata.alloca = {alloc_size, alloc_size}};
|
.metadata.alloca = {alloc_size, 1}};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_CALL: {
|
case SCC_HIR_VALUE_TAG_CALL: {
|
||||||
scc_hir_func_t *callee = scc_hir_module_get_func(
|
scc_hir_func_t *callee = scc_hir_module_get_func(
|
||||||
ctx->hir_module, value->data.call.callee.func_ref);
|
ctx->hir_module, value->data.call.callee.func_ref);
|
||||||
@@ -381,8 +387,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
// metadata.call.args 指针仍指向 malloc 内存,
|
// metadata.call.args 指针仍指向 malloc 内存,
|
||||||
// 这会导致内存泄漏。实际实现中应使用 arena
|
// 这会导致内存泄漏。实际实现中应使用 arena
|
||||||
// 分配或随函数释放。此处为示例简化。
|
// 分配或随函数释放。此处为示例简化。
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_BRANCH: {
|
case SCC_HIR_VALUE_TAG_BRANCH: {
|
||||||
scc_lir_val_t cond =
|
scc_lir_val_t cond =
|
||||||
ir_value_to_lir_operand(ctx, value->data.branch.cond);
|
ir_value_to_lir_operand(ctx, value->data.branch.cond);
|
||||||
@@ -392,15 +397,13 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.metadata.br = {value->data.branch.true_bblock,
|
.metadata.br = {value->data.branch.true_bblock,
|
||||||
value->data.branch.false_bblock}};
|
value->data.branch.false_bblock}};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_JUMP: {
|
case SCC_HIR_VALUE_TAG_JUMP: {
|
||||||
scc_lir_instr_t instr = {.op = SCC_LIR_JMP,
|
scc_lir_instr_t instr = {.op = SCC_LIR_JMP,
|
||||||
.metadata.jmp_target =
|
.metadata.jmp_target =
|
||||||
value->data.jump.target_bblock};
|
value->data.jump.target_bblock};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_RET: {
|
case SCC_HIR_VALUE_TAG_RET: {
|
||||||
scc_lir_val_t ret_val;
|
scc_lir_val_t ret_val;
|
||||||
if (value->data.ret.ret_val != SCC_HIR_REF_nullptr) {
|
if (value->data.ret.ret_val != SCC_HIR_REF_nullptr) {
|
||||||
@@ -411,8 +414,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
scc_lir_instr_t instr = {.op = SCC_LIR_RET,
|
scc_lir_instr_t instr = {.op = SCC_LIR_RET,
|
||||||
.metadata.ret_val = ret_val};
|
.metadata.ret_val = ret_val};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_CONV: {
|
case SCC_HIR_VALUE_TAG_CONV: {
|
||||||
// 类型转换:使用 MOV 指令配合扩展/截断
|
// 类型转换:使用 MOV 指令配合扩展/截断
|
||||||
scc_lir_val_t src =
|
scc_lir_val_t src =
|
||||||
@@ -429,10 +431,91 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = src};
|
.arg0 = src};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
} break;
|
||||||
|
case SCC_HIR_VALUE_TAG_BUILTIN: {
|
||||||
|
scc_hir_builtin_t *b = &value->data.builtin;
|
||||||
|
switch (b->tag) {
|
||||||
|
case SCC_HIR_BUILTIN_TAG_MEMCPY: {
|
||||||
|
scc_lir_val_t dest =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.memcpy.dest);
|
||||||
|
scc_lir_val_t src =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.memcpy.src);
|
||||||
|
scc_lir_val_t len =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.memcpy.size);
|
||||||
|
scc_lir_instr_t instr = {.op = SCC_LIR_MEMCPY,
|
||||||
|
.metadata.memcpy = {dest, src, len}};
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCC_HIR_BUILTIN_TAG_MEMSET: {
|
||||||
|
scc_lir_val_t dest =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.memset.dest);
|
||||||
|
scc_lir_val_t val =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.memset.value);
|
||||||
|
scc_lir_val_t len =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.memset.size);
|
||||||
|
scc_lir_instr_t instr = {.op = SCC_LIR_MEMSET,
|
||||||
|
.metadata.memset = {dest, val, len}};
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCC_HIR_BUILTIN_TAG_VA_START: {
|
||||||
|
scc_lir_val_t ap =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.va_start.ap);
|
||||||
|
scc_lir_val_t last =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.va_start.last);
|
||||||
|
scc_lir_instr_t instr = {.op = SCC_LIR_VA_START,
|
||||||
|
.metadata.va_start = {ap, last}};
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCC_HIR_BUILTIN_TAG_VA_ARG: {
|
||||||
|
// 需要从类型中获取大小和对齐以及是否为浮点
|
||||||
|
scc_hir_type_t *ty =
|
||||||
|
scc_hir_module_get_type(ctx->hir_module, b->func.va_arg.type);
|
||||||
|
u8 size = 0;
|
||||||
|
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
||||||
|
ir_type_to_lir_size_ext(ty, &size, &ext);
|
||||||
|
bool is_float = (ext == SCC_LIR_EXT_FLOAT);
|
||||||
|
scc_lir_val_t ap = ir_value_to_lir_operand(ctx, b->func.va_arg.ap);
|
||||||
|
scc_lir_instr_t instr = {
|
||||||
|
.op = SCC_LIR_VA_ARG,
|
||||||
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
|
.metadata.va_arg = {.ap = ap,
|
||||||
|
.type_size = size,
|
||||||
|
.type_align =
|
||||||
|
size, // 简化,实际应查询 ABI 对齐
|
||||||
|
.is_float = is_float,
|
||||||
|
.to = SCC_LIR_VREG(dst_vreg)}};
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCC_HIR_BUILTIN_TAG_VA_END: {
|
||||||
|
scc_lir_val_t ap = ir_value_to_lir_operand(ctx, b->func.va_end.ap);
|
||||||
|
scc_lir_instr_t instr = {.op = SCC_LIR_VA_END,
|
||||||
|
.metadata.va_end = {ap}};
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCC_HIR_BUILTIN_TAG_VA_COPY: {
|
||||||
|
scc_lir_val_t dest =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.va_copy.dest);
|
||||||
|
scc_lir_val_t src =
|
||||||
|
ir_value_to_lir_operand(ctx, b->func.va_copy.src);
|
||||||
|
scc_lir_instr_t instr = {.op = SCC_LIR_VA_COPY,
|
||||||
|
.metadata.va_copy = {dest, src}};
|
||||||
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// 不生成指令的节点(如 CONST_INT, FUNC_ARG_REF)不会调用本函数
|
TODO();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF:
|
||||||
|
case SCC_HIR_VALUE_TAG_BLOCK_ARG_REF:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Panic("unsupported opcode %d", value->tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -447,6 +530,7 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
|||||||
.attr = SCC_LIR_ATTR_NONE,
|
.attr = SCC_LIR_ATTR_NONE,
|
||||||
.frame_size = 0,
|
.frame_size = 0,
|
||||||
.vregs_count = 0,
|
.vregs_count = 0,
|
||||||
|
.is_va_arg = false,
|
||||||
};
|
};
|
||||||
scc_vec_push(ctx->lir_module->func_metas, lir_func_meta);
|
scc_vec_push(ctx->lir_module->func_metas, lir_func_meta);
|
||||||
ctx->current_func = ir_func;
|
ctx->current_func = ir_func;
|
||||||
@@ -483,7 +567,7 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
|||||||
scc_hashtable_drop(&ctx->value_to_vreg);
|
scc_hashtable_drop(&ctx->value_to_vreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_hir2lir(scc_lir_module_t *module, const scc_hir_cprog_t *cprog) {
|
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
|
||||||
Assert(module != nullptr && cprog != nullptr);
|
Assert(module != nullptr && cprog != nullptr);
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|||||||
@@ -16,10 +16,8 @@ static const char *op_to_string(scc_lir_op_t op) {
|
|||||||
return "load.addr";
|
return "load.addr";
|
||||||
case SCC_LIR_STORE:
|
case SCC_LIR_STORE:
|
||||||
return "store";
|
return "store";
|
||||||
case SCC_LIR_STORE_ADDR:
|
// case SCC_LIR_STORE_ADDR:
|
||||||
return "store.addr";
|
// return "store.addr";
|
||||||
case SCC_LIR_LEA:
|
|
||||||
return "lea";
|
|
||||||
case SCC_LIR_ADD:
|
case SCC_LIR_ADD:
|
||||||
return "add";
|
return "add";
|
||||||
case SCC_LIR_SUB:
|
case SCC_LIR_SUB:
|
||||||
@@ -88,6 +86,11 @@ static const char *op_to_string(scc_lir_op_t op) {
|
|||||||
return "va_copy";
|
return "va_copy";
|
||||||
case SCC_LIR_ALLOCA:
|
case SCC_LIR_ALLOCA:
|
||||||
return "alloca";
|
return "alloca";
|
||||||
|
|
||||||
|
case SCC_LIR_MEMCPY:
|
||||||
|
return "memcpy";
|
||||||
|
case SCC_LIR_MEMSET:
|
||||||
|
return "memset";
|
||||||
case SCC_LIR_NOP:
|
case SCC_LIR_NOP:
|
||||||
return "nop";
|
return "nop";
|
||||||
default:
|
default:
|
||||||
@@ -162,29 +165,6 @@ static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) {
|
|||||||
scc_tree_dump_append_fmt(td, "@%s",
|
scc_tree_dump_append_fmt(td, "@%s",
|
||||||
op->data.symbol ? op->data.symbol : "<null>");
|
op->data.symbol ? op->data.symbol : "<null>");
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_INSTR_KIND_MEM: {
|
|
||||||
const scc_lir_addr_t *addr = &op->data.addr;
|
|
||||||
scc_tree_dump_append(td, "[");
|
|
||||||
if (addr->base != -1) {
|
|
||||||
scc_tree_dump_append_fmt(td, "%%%d", addr->base);
|
|
||||||
}
|
|
||||||
if (addr->index != -1) {
|
|
||||||
scc_tree_dump_append_fmt(td, " + %%%d * %d", addr->index,
|
|
||||||
addr->scale);
|
|
||||||
}
|
|
||||||
if (addr->offset != 0) {
|
|
||||||
if (addr->offset > 0)
|
|
||||||
scc_tree_dump_append_fmt(td, " + %lld",
|
|
||||||
(long long)addr->offset);
|
|
||||||
else
|
|
||||||
scc_tree_dump_append_fmt(td, " - %lld",
|
|
||||||
-(long long)addr->offset);
|
|
||||||
}
|
|
||||||
if (addr->base == -1 && addr->index == -1 && addr->offset == 0)
|
|
||||||
scc_tree_dump_append(td, "0");
|
|
||||||
scc_tree_dump_append(td, "]");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
scc_tree_dump_append(td, "<?>");
|
scc_tree_dump_append(td, "<?>");
|
||||||
}
|
}
|
||||||
@@ -201,6 +181,8 @@ static void dump_size_ext(scc_lir_dump_ctx_t *ctx, u8 size, scc_lir_ext_t ext) {
|
|||||||
size_str = "32";
|
size_str = "32";
|
||||||
else if (size == SCC_LIR_SIZE_64)
|
else if (size == SCC_LIR_SIZE_64)
|
||||||
size_str = "64";
|
size_str = "64";
|
||||||
|
else
|
||||||
|
size_str = "sz(?)";
|
||||||
|
|
||||||
const char *ext_str = "";
|
const char *ext_str = "";
|
||||||
if (ext == SCC_LIR_EXT_SEXT)
|
if (ext == SCC_LIR_EXT_SEXT)
|
||||||
@@ -231,32 +213,40 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
switch (ins->op) {
|
switch (ins->op) {
|
||||||
case SCC_LIR_MOV:
|
case SCC_LIR_MOV:
|
||||||
case SCC_LIR_LOAD:
|
case SCC_LIR_LOAD:
|
||||||
case SCC_LIR_LOAD_ADDR:
|
|
||||||
dump_operand(ctx, &ins->to);
|
dump_operand(ctx, &ins->to);
|
||||||
scc_tree_dump_append(td, " <- ");
|
scc_tree_dump_append(td, " <- ");
|
||||||
dump_operand(ctx, &ins->arg0);
|
dump_operand(ctx, &ins->arg0);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_LEA:
|
case SCC_LIR_LOAD_ADDR:
|
||||||
|
// base + index * scale + offset
|
||||||
|
dump_operand(ctx, &ins->to);
|
||||||
|
scc_tree_dump_append(td, " <- (");
|
||||||
|
dump_operand(ctx, &ins->arg0); // base
|
||||||
|
scc_tree_dump_append(td, " + ");
|
||||||
|
dump_operand(ctx, &ins->arg1); // index
|
||||||
|
scc_tree_dump_append_fmt(td, " * %d + %lld)", ins->metadata.addr.scale,
|
||||||
|
ins->metadata.addr.offset);
|
||||||
|
break;
|
||||||
case SCC_LIR_NEG:
|
case SCC_LIR_NEG:
|
||||||
case SCC_LIR_NOT:
|
case SCC_LIR_NOT:
|
||||||
case SCC_LIR_FNEG:
|
case SCC_LIR_FNEG:
|
||||||
case SCC_LIR_FCVT:
|
case SCC_LIR_FCVT:
|
||||||
case SCC_LIR_ALLOCA:
|
|
||||||
dump_operand(ctx, &ins->to);
|
dump_operand(ctx, &ins->to);
|
||||||
if (ins->op != SCC_LIR_ALLOCA) {
|
|
||||||
scc_tree_dump_append(td, ", ");
|
scc_tree_dump_append(td, ", ");
|
||||||
dump_operand(ctx, &ins->arg0);
|
dump_operand(ctx, &ins->arg0);
|
||||||
// alloca 额外信息在 metadata 中,但通常只关注 to
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
case SCC_LIR_ALLOCA:
|
||||||
|
scc_tree_dump_append_fmt(td, "(sz=%zd,al=%zd) => ",
|
||||||
|
ins->metadata.alloca.size_bytes,
|
||||||
|
ins->metadata.alloca.align_bytes);
|
||||||
|
dump_operand(ctx, &ins->to);
|
||||||
|
break;
|
||||||
|
// case SCC_LIR_STORE_ADDR:
|
||||||
case SCC_LIR_STORE:
|
case SCC_LIR_STORE:
|
||||||
case SCC_LIR_STORE_ADDR:
|
|
||||||
dump_operand(ctx, &ins->arg0);
|
dump_operand(ctx, &ins->arg0);
|
||||||
scc_tree_dump_append(td, " -> ");
|
scc_tree_dump_append(td, " -> ");
|
||||||
dump_operand(ctx, &ins->arg1);
|
dump_operand(ctx, &ins->arg1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_ADD:
|
case SCC_LIR_ADD:
|
||||||
case SCC_LIR_SUB:
|
case SCC_LIR_SUB:
|
||||||
case SCC_LIR_MUL:
|
case SCC_LIR_MUL:
|
||||||
@@ -280,7 +270,6 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
scc_tree_dump_append(td, ", ");
|
scc_tree_dump_append(td, ", ");
|
||||||
dump_operand(ctx, &ins->arg1);
|
dump_operand(ctx, &ins->arg1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_CMP:
|
case SCC_LIR_CMP:
|
||||||
dump_operand(ctx, &ins->to);
|
dump_operand(ctx, &ins->to);
|
||||||
scc_tree_dump_append_fmt(td, ", %s, ",
|
scc_tree_dump_append_fmt(td, ", %s, ",
|
||||||
@@ -289,22 +278,18 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
scc_tree_dump_append(td, ", ");
|
scc_tree_dump_append(td, ", ");
|
||||||
dump_operand(ctx, &ins->arg1);
|
dump_operand(ctx, &ins->arg1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_BR:
|
case SCC_LIR_BR:
|
||||||
dump_operand(ctx, &ins->arg0);
|
dump_operand(ctx, &ins->arg0);
|
||||||
scc_tree_dump_append_fmt(td, ", BB#%zu, BB#%zu",
|
scc_tree_dump_append_fmt(td, ", BB#%zu, BB#%zu",
|
||||||
ins->metadata.br.true_target,
|
ins->metadata.br.true_target,
|
||||||
ins->metadata.br.false_target);
|
ins->metadata.br.false_target);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_JMP:
|
case SCC_LIR_JMP:
|
||||||
scc_tree_dump_append_fmt(td, "#BB%d", ins->metadata.jmp_target);
|
scc_tree_dump_append_fmt(td, "#BB%d", ins->metadata.jmp_target);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_JMP_INDIRECT:
|
case SCC_LIR_JMP_INDIRECT:
|
||||||
dump_operand(ctx, &ins->arg0);
|
dump_operand(ctx, &ins->arg0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_CALL: {
|
case SCC_LIR_CALL: {
|
||||||
const struct scc_lir_call *c = &ins->metadata.call;
|
const struct scc_lir_call *c = &ins->metadata.call;
|
||||||
if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) {
|
if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) {
|
||||||
@@ -320,9 +305,7 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
}
|
}
|
||||||
scc_tree_dump_append_fmt(td, ") clobber=0x%llx",
|
scc_tree_dump_append_fmt(td, ") clobber=0x%llx",
|
||||||
(unsigned long long)c->clobber_mask);
|
(unsigned long long)c->clobber_mask);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
case SCC_LIR_CALL_INDIRECT: {
|
case SCC_LIR_CALL_INDIRECT: {
|
||||||
const struct scc_lir_call_indirect *c = &ins->metadata.call_indirect;
|
const struct scc_lir_call_indirect *c = &ins->metadata.call_indirect;
|
||||||
if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) {
|
if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) {
|
||||||
@@ -339,15 +322,12 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
}
|
}
|
||||||
scc_tree_dump_append_fmt(td, ") clobber=0x%llx",
|
scc_tree_dump_append_fmt(td, ") clobber=0x%llx",
|
||||||
(unsigned long long)c->clobber_mask);
|
(unsigned long long)c->clobber_mask);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
case SCC_LIR_RET:
|
case SCC_LIR_RET:
|
||||||
if (ins->metadata.ret_val.kind != SCC_LIR_INSTR_KIND_NONE) {
|
if (ins->metadata.ret_val.kind != SCC_LIR_INSTR_KIND_NONE) {
|
||||||
dump_operand(ctx, &ins->metadata.ret_val);
|
dump_operand(ctx, &ins->metadata.ret_val);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_PARALLEL_COPY: {
|
case SCC_LIR_PARALLEL_COPY: {
|
||||||
const struct scc_lir_parallel_copy *pc = &ins->metadata.parallel_copy;
|
const struct scc_lir_parallel_copy *pc = &ins->metadata.parallel_copy;
|
||||||
scc_tree_dump_append(td, "[");
|
scc_tree_dump_append(td, "[");
|
||||||
@@ -361,13 +341,11 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
scc_tree_dump_append(td, "]");
|
scc_tree_dump_append(td, "]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCC_LIR_VA_START:
|
case SCC_LIR_VA_START:
|
||||||
dump_operand(ctx, &ins->metadata.va_start.ap);
|
dump_operand(ctx, &ins->metadata.va_start.ap);
|
||||||
scc_tree_dump_append(td, ", ");
|
scc_tree_dump_append(td, ", ");
|
||||||
dump_operand(ctx, &ins->metadata.va_start.last);
|
dump_operand(ctx, &ins->metadata.va_start.last);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_VA_ARG:
|
case SCC_LIR_VA_ARG:
|
||||||
dump_operand(ctx, &ins->metadata.va_arg.to);
|
dump_operand(ctx, &ins->metadata.va_arg.to);
|
||||||
scc_tree_dump_append(td, " = va_arg ");
|
scc_tree_dump_append(td, " = va_arg ");
|
||||||
@@ -376,17 +354,28 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
td, ", size=%u, align=%u, float=%d", ins->metadata.va_arg.type_size,
|
td, ", size=%u, align=%u, float=%d", ins->metadata.va_arg.type_size,
|
||||||
ins->metadata.va_arg.type_align, ins->metadata.va_arg.is_float);
|
ins->metadata.va_arg.type_align, ins->metadata.va_arg.is_float);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_VA_END:
|
case SCC_LIR_VA_END:
|
||||||
dump_operand(ctx, &ins->metadata.va_end.ap);
|
dump_operand(ctx, &ins->metadata.va_end.ap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_VA_COPY:
|
case SCC_LIR_VA_COPY:
|
||||||
dump_operand(ctx, &ins->metadata.va_copy.dest);
|
dump_operand(ctx, &ins->metadata.va_copy.dest);
|
||||||
scc_tree_dump_append(td, ", ");
|
scc_tree_dump_append(td, ", ");
|
||||||
dump_operand(ctx, &ins->metadata.va_copy.src);
|
dump_operand(ctx, &ins->metadata.va_copy.src);
|
||||||
break;
|
break;
|
||||||
|
case SCC_LIR_MEMCPY:
|
||||||
|
dump_operand(ctx, &ins->metadata.memcpy.dest);
|
||||||
|
scc_tree_dump_append(td, ", ");
|
||||||
|
dump_operand(ctx, &ins->metadata.memcpy.src);
|
||||||
|
scc_tree_dump_append(td, ", ");
|
||||||
|
dump_operand(ctx, &ins->metadata.memcpy.size);
|
||||||
|
break;
|
||||||
|
case SCC_LIR_MEMSET:
|
||||||
|
dump_operand(ctx, &ins->metadata.memset.dest);
|
||||||
|
scc_tree_dump_append(td, ", ");
|
||||||
|
dump_operand(ctx, &ins->metadata.memset.value);
|
||||||
|
scc_tree_dump_append(td, ", ");
|
||||||
|
dump_operand(ctx, &ins->metadata.memset.size);
|
||||||
|
break;
|
||||||
case SCC_LIR_NOP:
|
case SCC_LIR_NOP:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -419,7 +408,8 @@ void scc_lir_dump_func(scc_lir_dump_ctx_t *ctx, const scc_lir_func_t *func) {
|
|||||||
scc_lir_func_meta_t *meta = SCC_LIR_FUNC_META(func);
|
scc_lir_func_meta_t *meta = SCC_LIR_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%s", func->name ? func->name : "<anon>",
|
||||||
|
meta->is_va_arg ? "(...)" : "()");
|
||||||
scc_tree_dump_append_fmt(td, " (vregs: %u, frame: %d)", meta->vregs_count,
|
scc_tree_dump_append_fmt(td, " (vregs: %u, frame: %d)", meta->vregs_count,
|
||||||
meta->frame_size);
|
meta->frame_size);
|
||||||
if (meta->attr != SCC_LIR_ATTR_NONE) {
|
if (meta->attr != SCC_LIR_ATTR_NONE) {
|
||||||
@@ -453,7 +443,12 @@ void scc_lir_dump_module(scc_lir_dump_ctx_t *ctx) {
|
|||||||
&scc_vec_at(ctx->lir_module->cfg_module.symbols, i);
|
&scc_vec_at(ctx->lir_module->cfg_module.symbols, i);
|
||||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||||
scc_tree_dump_node(ctx->dump_ctx, "symbol");
|
scc_tree_dump_node(ctx->dump_ctx, "symbol");
|
||||||
|
scc_lir_symbol_meta_t *meta = SCC_LIR_SYMBOL_META(sym);
|
||||||
scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name);
|
scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name);
|
||||||
|
if (sym->kind == SCC_CFG_SYMBOL_KIND_DATA) {
|
||||||
|
scc_tree_dump_append_fmt(ctx->dump_ctx, "(size=%zu)",
|
||||||
|
meta->data.size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scc_vec_foreach(ctx->lir_module->cfg_module.funcs, i) {
|
scc_vec_foreach(ctx->lir_module->cfg_module.funcs, i) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
|||||||
@@ -19,16 +19,20 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module,
|
|||||||
scc_x86_64_isel_t *isel);
|
scc_x86_64_isel_t *isel);
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg,
|
||||||
|
scc_x86_operand_value_t src, u8 size);
|
||||||
|
void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||||
|
scc_x86_operand_value_t src, u8 size);
|
||||||
|
void scc_x86_emit_store(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 src, u8 size);
|
||||||
scc_x86_operand_value_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);
|
||||||
static inline void emit_direct_call(scc_x86_64_isel_t *isel,
|
static inline void emit_direct_call(scc_x86_64_isel_t *isel,
|
||||||
const char *callee) {
|
const char *callee) {
|
||||||
(void)callee;
|
|
||||||
scc_mir_x86_instr_t instr = {0};
|
scc_mir_x86_instr_t instr = {0};
|
||||||
scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_RELBRZ,
|
scc_x86_operand_value_t op = scc_x86_op_reloc_global_relbr(callee, 0);
|
||||||
scc_x86_op_relbr(0), scc_pos_create());
|
scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_RELBRZ, op,
|
||||||
|
scc_pos_create());
|
||||||
scc_vec_push(isel->instrs, instr);
|
scc_vec_push(isel->instrs, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,16 +56,18 @@ static inline void emit_ret(scc_x86_64_isel_t *isel) {
|
|||||||
scc_vec_push((isel)->instrs, instr); \
|
scc_vec_push((isel)->instrs, instr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define add_instr_1(isel, iform, arg1) \
|
#define add_instr_1(isel, iform, arg1, _size) \
|
||||||
do { \
|
do { \
|
||||||
scc_mir_x86_instr_t instr; \
|
scc_mir_x86_instr_t instr; \
|
||||||
|
(arg1).size = (_size); \
|
||||||
scc_mir_x86_instr_1(&instr, (iform), (arg1), (isel)->pos); \
|
scc_mir_x86_instr_1(&instr, (iform), (arg1), (isel)->pos); \
|
||||||
scc_vec_push((isel)->instrs, instr); \
|
scc_vec_push((isel)->instrs, instr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define add_instr_2(isel, iform, arg1, arg2) \
|
#define add_instr_2(isel, iform, arg1, arg2, _size) \
|
||||||
do { \
|
do { \
|
||||||
scc_mir_x86_instr_t instr; \
|
scc_mir_x86_instr_t instr; \
|
||||||
|
(arg1).size = (_size); \
|
||||||
scc_mir_x86_instr_2(&instr, (iform), (arg1), (arg2), (isel)->pos); \
|
scc_mir_x86_instr_2(&instr, (iform), (arg1), (arg2), (isel)->pos); \
|
||||||
scc_vec_push((isel)->instrs, instr); \
|
scc_vec_push((isel)->instrs, instr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|||||||
@@ -9,8 +9,11 @@
|
|||||||
#include <x86/scc_x86_reg.h>
|
#include <x86/scc_x86_reg.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
union {
|
||||||
int opcode;
|
int opcode;
|
||||||
uint8_t num_operands;
|
scc_x86_iform_t iform;
|
||||||
|
};
|
||||||
|
u8 num_operands;
|
||||||
scc_x86_operand_value_t operands[6];
|
scc_x86_operand_value_t operands[6];
|
||||||
scc_pos_t src_loc;
|
scc_pos_t src_loc;
|
||||||
} scc_x86_instr_t;
|
} scc_x86_instr_t;
|
||||||
@@ -29,13 +32,17 @@ typedef SCC_VEC(scc_mir_x86_instr_t) scc_mir_x86_instr_vec_t;
|
|||||||
#define SCC_MIR_X86_BBLOCK_INSTRS_C(bb) \
|
#define SCC_MIR_X86_BBLOCK_INSTRS_C(bb) \
|
||||||
((const scc_mir_x86_instr_vec_t *)&bb->values)
|
((const scc_mir_x86_instr_vec_t *)&bb->values)
|
||||||
|
|
||||||
// ── vreg 编码 ──────────────────────────────────────────────────────────
|
static inline cbool scc_x86_reg_is_vreg(scc_x86_reg_t reg) {
|
||||||
static inline bool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) {
|
return reg >= SCC_X86_REG_COUNT;
|
||||||
return op->kind == SCC_X86_OPR_REG &&
|
}
|
||||||
(int)op->reg >= (int)SCC_X86_REG_COUNT;
|
static inline cbool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) {
|
||||||
|
return op->kind == SCC_X86_OPR_REG && scc_x86_reg_is_vreg(op->reg);
|
||||||
|
}
|
||||||
|
static inline int scc_x86_reg_get_vreg(scc_x86_reg_t reg) {
|
||||||
|
return (int)reg - (int)SCC_X86_REG_COUNT;
|
||||||
}
|
}
|
||||||
static inline int scc_x86_op_get_vreg(const scc_x86_operand_value_t *op) {
|
static inline int scc_x86_op_get_vreg(const scc_x86_operand_value_t *op) {
|
||||||
return (int)op->reg - (int)SCC_X86_REG_COUNT;
|
return scc_x86_reg_get_vreg(op->reg);
|
||||||
}
|
}
|
||||||
static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op,
|
static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op,
|
||||||
scc_x86_reg_t preg) {
|
scc_x86_reg_t preg) {
|
||||||
@@ -43,15 +50,24 @@ static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op,
|
|||||||
op->reg = preg;
|
op->reg = preg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 未解析栈槽编码 (base=INVALID, disp=slot_id) ──────────────────────
|
// 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.displacement = slot_id;
|
||||||
|
o.mem.disp.displacement_bits = 0;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) {
|
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;
|
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) {
|
static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) {
|
||||||
return op->mem.disp;
|
return op->mem.disp.displacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 指令构建辅助 ──────────────────────────────────────────────────────
|
|
||||||
static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int opcode,
|
static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int opcode,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
out->x86_instr.opcode = opcode;
|
out->x86_instr.opcode = opcode;
|
||||||
@@ -89,46 +105,4 @@ static inline void scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, int opcode,
|
|||||||
out->x86_instr.src_loc = pos;
|
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__ */
|
#endif /* __SCC_X86_MIR_H__ */
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ typedef enum {
|
|||||||
SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2,
|
SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2,
|
||||||
} scc_reg_op_access_t;
|
} scc_reg_op_access_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const scc_mir_instr_t *instr;
|
||||||
|
int op_idx;
|
||||||
|
int op_sub_idx;
|
||||||
|
} scc_reg_alloc_iter_t;
|
||||||
|
|
||||||
// 后端回调表 —— 框架通过回调获取/修改指令,不感知具体布局
|
// 后端回调表 —— 框架通过回调获取/修改指令,不感知具体布局
|
||||||
typedef struct scc_reg_alloc_op {
|
typedef struct scc_reg_alloc_op {
|
||||||
// ── 寄存器池 ──
|
// ── 寄存器池 ──
|
||||||
@@ -18,25 +24,21 @@ typedef struct scc_reg_alloc_op {
|
|||||||
void (*clean_mark_regs)(void *ctx);
|
void (*clean_mark_regs)(void *ctx);
|
||||||
|
|
||||||
// ── 指令信息 ──
|
// ── 指令信息 ──
|
||||||
int (*instr_opcode)(const void *instr);
|
scc_reg_alloc_iter_t iter;
|
||||||
int (*instr_num_operands)(const void *instr);
|
void (*alloc_iter_begin)(scc_reg_alloc_iter_t *iter);
|
||||||
bool (*op_is_vreg)(const void *instr, int idx);
|
cbool (*alloc_iter_next)(scc_reg_alloc_iter_t *iter, int *out_vreg,
|
||||||
int (*op_get_vreg)(const void *instr, int idx);
|
int *out_size, scc_reg_op_access_t *out_access);
|
||||||
void (*op_set_preg)(void *instr, int idx, int preg);
|
void (*alloc_iter_replace_preg)(scc_reg_alloc_iter_t *iter, int preg);
|
||||||
void (*op_set_slot)(void *instr, int idx, int slot);
|
void (*alloc_iter_replace_slot)(scc_reg_alloc_iter_t *iter, int slot);
|
||||||
|
void (*alloc_iter_end)(scc_reg_alloc_iter_t *iter);
|
||||||
|
|
||||||
// 读写属性与隐式寄存器
|
// 读写属性与隐式寄存器
|
||||||
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 向量) ──
|
// ── 溢出/重载(写入 out 向量) ──
|
||||||
void (*emit_spill)(void *out, int preg, int slot);
|
void (*emit_spill)(void *out, int preg, int slot, int size);
|
||||||
void (*emit_reload)(void *out, int preg, int slot);
|
void (*emit_reload)(void *out, int preg, int slot, int size);
|
||||||
void (*emit_copy)(void *out, int dst_preg, int src_preg, int size);
|
void (*emit_copy)(void *out, int dst_preg, int src_preg, int size);
|
||||||
} scc_reg_alloc_op_t;
|
} scc_reg_alloc_op_t;
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,8 @@
|
|||||||
#include <scc_lir_module.h>
|
#include <scc_lir_module.h>
|
||||||
|
|
||||||
typedef SCC_VEC(char) scc_mir_instr_vec_t;
|
typedef SCC_VEC(char) scc_mir_instr_vec_t;
|
||||||
|
typedef scc_lir_symbol_meta_t scc_mir_symbol_meta_t;
|
||||||
typedef struct {
|
#define SCC_MIR_SYMBOL_META(symbol) ((scc_mir_symbol_meta_t *)(symbol)->meta)
|
||||||
|
|
||||||
} 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;
|
||||||
|
|||||||
@@ -9,7 +9,16 @@ 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_x86_instr_t *instr) {
|
static inline void scc_x86_dump_reg(scc_tree_dump_t *td,
|
||||||
|
const scc_x86_reg_t reg) {
|
||||||
|
if (scc_x86_reg_is_vreg(reg))
|
||||||
|
scc_tree_dump_append_fmt(td, "%%%d", scc_x86_reg_get_vreg(reg));
|
||||||
|
else
|
||||||
|
scc_tree_dump_append_fmt(td, "$%s", preg_name(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func,
|
||||||
|
const scc_mir_x86_instr_t *instr) {
|
||||||
if (instr->x86_instr.opcode >= SCC_X86_IFORM_COUNT ||
|
if (instr->x86_instr.opcode >= SCC_X86_IFORM_COUNT ||
|
||||||
instr->x86_instr.opcode < 0) {
|
instr->x86_instr.opcode < 0) {
|
||||||
scc_tree_dump_append_fmt(td, " ???");
|
scc_tree_dump_append_fmt(td, " ???");
|
||||||
@@ -26,27 +35,65 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) {
|
|||||||
const scc_x86_operand_value_t *op = &instr->x86_instr.operands[i];
|
const scc_x86_operand_value_t *op = &instr->x86_instr.operands[i];
|
||||||
switch (op->kind) {
|
switch (op->kind) {
|
||||||
case SCC_X86_OPR_REG:
|
case SCC_X86_OPR_REG:
|
||||||
if (scc_x86_op_is_vreg(op))
|
scc_x86_dump_reg(td, op->reg);
|
||||||
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_X86_OPR_IMM:
|
case SCC_X86_OPR_IMM:
|
||||||
scc_tree_dump_append_fmt(td, "%ld", op->imm);
|
scc_tree_dump_append_fmt(td, "%ld", op->imm0);
|
||||||
break;
|
break;
|
||||||
case SCC_X86_OPR_MEM:
|
case SCC_X86_OPR_MEM:
|
||||||
if (scc_x86_op_is_slot(op))
|
if (scc_x86_op_is_slot(op)) {
|
||||||
scc_tree_dump_append_fmt(td, "[slot:%d]",
|
int slot_id = scc_x86_op_slot_id(op);
|
||||||
scc_x86_op_slot_id(op));
|
scc_mir_stack_slot_t *slot = scc_mir_unsafe_slot(func, slot_id);
|
||||||
else
|
if (slot == nullptr) {
|
||||||
scc_tree_dump_append_fmt(td, "[sp%+d]", op->mem.disp);
|
scc_tree_dump_append_fmt(td, "[slot:%d<null>]", slot_id);
|
||||||
|
} else {
|
||||||
|
scc_tree_dump_append_fmt(td, "[slot:%d(of=%d,sz=%d,al=%d)]",
|
||||||
|
slot_id, slot->offset, slot->size,
|
||||||
|
slot->alignment);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scc_tree_dump_append(td, "(");
|
||||||
|
scc_x86_dump_reg(td, op->mem.base);
|
||||||
|
if (op->mem.index != SCC_X86_REG_INVALID) {
|
||||||
|
scc_tree_dump_append(td, "[");
|
||||||
|
scc_x86_dump_reg(td, op->mem.index);
|
||||||
|
scc_tree_dump_append(td, "]");
|
||||||
|
}
|
||||||
|
if (op->mem.scale != 1) {
|
||||||
|
scc_tree_dump_append_fmt(td, "(x%d)", op->mem.scale);
|
||||||
|
}
|
||||||
|
if (op->mem.disp.displacement != 0) {
|
||||||
|
scc_tree_dump_append_fmt(
|
||||||
|
td, " %c %llu",
|
||||||
|
op->mem.disp.displacement >= 0 ? '+' : '-',
|
||||||
|
op->mem.disp.displacement < 0
|
||||||
|
? -op->mem.disp.displacement
|
||||||
|
: op->mem.disp.displacement);
|
||||||
|
}
|
||||||
|
scc_tree_dump_append(td, ")");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_X86_OPR_RELBR:
|
case SCC_X86_OPR_RELBR:
|
||||||
scc_tree_dump_append(td, "label");
|
scc_tree_dump_append(td, "<relbr>");
|
||||||
|
break;
|
||||||
|
case SCC_X86_OPR_RELOC:
|
||||||
|
switch (op->reloc.target) {
|
||||||
|
case SCC_X86_RELOC_TARGET_BBLOCK:
|
||||||
|
scc_tree_dump_append_fmt(td, "<#BB%d>", op->reloc.bblock_id);
|
||||||
|
break;
|
||||||
|
case SCC_X86_RELOC_TARGET_SYMBOL:
|
||||||
|
scc_tree_dump_append_fmt(td, "<%s>", op->reloc.global_name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
scc_tree_dump_append_fmt(td, "<reloc>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
scc_tree_dump_append(td, "<?>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scc_tree_dump_append_fmt(td, "(%zu)", op->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,70 +122,54 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
|
|||||||
op = scc_x86_op_imm(*(i64 *)&val->data.fimm);
|
op = scc_x86_op_imm(*(i64 *)&val->data.fimm);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_INSTR_KIND_SYMBOL:
|
case SCC_LIR_INSTR_KIND_SYMBOL:
|
||||||
op = scc_x86_op_symbol(val->data.symbol);
|
op = scc_x86_op_reloc_global_relrip(val->data.symbol, 0);
|
||||||
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);
|
||||||
isel->abi_lowering.lower_param(isel, val, &op);
|
isel->abi_lowering.lower_param(isel, val, &op);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
Panic("unsupported lir instr kind %d", val->kind);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static scc_x86_operand_value_t build_mem_op(scc_x86_64_isel_t *isel,
|
||||||
|
scc_x86_operand_value_t base,
|
||||||
|
scc_x86_operand_value_t index,
|
||||||
|
int scale, i64 offset) {
|
||||||
|
(void)isel;
|
||||||
|
scc_x86_operand_value_t mem_op;
|
||||||
|
mem_op.kind = SCC_X86_OPR_MEM;
|
||||||
|
// base 必须为寄存器
|
||||||
|
Assert(base.kind == SCC_X86_OPR_REG);
|
||||||
|
mem_op.mem.base = base.reg;
|
||||||
|
// index 可选
|
||||||
|
if (index.kind == SCC_X86_OPR_REG) {
|
||||||
|
mem_op.mem.index = index.reg;
|
||||||
|
mem_op.mem.scale = scale;
|
||||||
|
} else {
|
||||||
|
mem_op.mem.index = SCC_X86_REG_INVALID;
|
||||||
|
mem_op.mem.scale = 1;
|
||||||
|
}
|
||||||
|
mem_op.mem.disp.displacement = offset;
|
||||||
|
mem_op.mem.disp.displacement_bits = 0;
|
||||||
|
return mem_op;
|
||||||
|
}
|
||||||
|
|
||||||
// 虚拟临时寄存器分配(简单递增)
|
// 虚拟临时寄存器分配(简单递增)
|
||||||
static scc_x86_operand_value_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_x86_op_vreg(scc_mir_alloc_vreg(isel->func));
|
return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func));
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
if (dst.kind == SCC_X86_OPR_REG) {
|
|
||||||
if (src.kind == SCC_X86_OPR_REG) {
|
|
||||||
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,
|
|
||||||
(size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ
|
|
||||||
: SCC_X86_IFORM_MOV_GPRV_IMMV,
|
|
||||||
dst, src);
|
|
||||||
} else if (src.kind == SCC_X86_OPR_IMM && src.imm == 0) {
|
|
||||||
// 特殊:符号作为立即数地址
|
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src);
|
|
||||||
} else if (src.kind == SCC_X86_OPR_MEM) {
|
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src);
|
|
||||||
} else {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
} else if (dst.kind == SCC_X86_OPR_MEM) {
|
|
||||||
if (src.kind == SCC_X86_OPR_REG) {
|
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src);
|
|
||||||
} else if (src.kind == SCC_X86_OPR_IMM) {
|
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src);
|
|
||||||
} else if (src.kind == SCC_X86_OPR_IMM) {
|
|
||||||
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_MEMV_GPRV, dst, temp);
|
|
||||||
} else if (src.kind == SCC_X86_OPR_MEM) {
|
|
||||||
scc_x86_operand_value_t temp = new_vreg_temp(isel);
|
|
||||||
scc_x86_emit_move(isel, temp, src, size);
|
|
||||||
scc_x86_emit_move(isel, dst, temp, size);
|
|
||||||
} else {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_compare(scc_x86_64_isel_t *isel, scc_x86_operand_value_t op0,
|
static void emit_compare(scc_x86_64_isel_t *isel, scc_x86_operand_value_t op0,
|
||||||
scc_x86_operand_value_t op1, u8 size) {
|
scc_x86_operand_value_t op1, u8 size) {
|
||||||
(void)size;
|
(void)size;
|
||||||
if (scc_x86_op_is_vreg(&op0) && op1.kind == SCC_X86_OPR_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, size);
|
||||||
} else if (scc_x86_op_is_vreg(&op0) && scc_x86_op_is_vreg(&op1)) {
|
} else if (scc_x86_op_is_vreg(&op0) && scc_x86_op_is_vreg(&op1)) {
|
||||||
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1);
|
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1, size);
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@@ -187,6 +218,9 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
|
|||||||
scc_x86_operand_value_t src1, u8 size) {
|
scc_x86_operand_value_t src1, u8 size) {
|
||||||
(void)size;
|
(void)size;
|
||||||
emit_copy_if_needed(isel, dst, src0, size);
|
emit_copy_if_needed(isel, dst, src0, size);
|
||||||
|
dst.size = size;
|
||||||
|
src0.size = size;
|
||||||
|
src1.size = size;
|
||||||
|
|
||||||
bool is_imm = (src1.kind == SCC_X86_OPR_IMM);
|
bool is_imm = (src1.kind == SCC_X86_OPR_IMM);
|
||||||
scc_x86_iform_t iform;
|
scc_x86_iform_t iform;
|
||||||
@@ -214,17 +248,155 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
add_instr_2(isel, iform, dst, src1);
|
add_instr_2(isel, iform, dst, src1, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_spill_load(scc_x86_64_isel_t *isel, int vreg, int slot) {
|
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg,
|
||||||
scc_x86_operand_value_t dst = scc_x86_op_vreg(vreg);
|
scc_x86_operand_value_t src, u8 size) {
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, scc_x86_op_slot(slot));
|
if (size == 0) {
|
||||||
|
size = dst_reg.size;
|
||||||
|
}
|
||||||
|
if (dst_reg.size != src.size) {
|
||||||
|
LOG_WARN("Mismatched register sizes for move %d != %d", dst_reg.size,
|
||||||
|
src.size);
|
||||||
|
}
|
||||||
|
Assert(dst_reg.kind == SCC_X86_OPR_REG);
|
||||||
|
if (src.kind == SCC_X86_OPR_REG) {
|
||||||
|
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, dst_reg, src, size);
|
||||||
|
} else if (src.kind == SCC_X86_OPR_IMM) {
|
||||||
|
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMV, dst_reg, src, size);
|
||||||
|
} else if (src.kind == SCC_X86_OPR_MEM ||
|
||||||
|
(src.kind == SCC_X86_OPR_RELOC &&
|
||||||
|
src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) {
|
||||||
|
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst_reg, src, size);
|
||||||
|
} else {
|
||||||
|
Panic("emit_move: unsupported src kind %d", src.kind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_spill_store(scc_x86_64_isel_t *isel, int vreg, int slot) {
|
void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||||
scc_x86_operand_value_t src = scc_x86_op_vreg(vreg);
|
scc_x86_operand_value_t src, u8 size) {
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, scc_x86_op_slot(slot), src);
|
if (size == 0) {
|
||||||
|
size = dst.size;
|
||||||
|
}
|
||||||
|
if (dst.size != src.size) {
|
||||||
|
LOG_WARN("Mismatched register sizes for store %d != %d", dst.size,
|
||||||
|
src.size);
|
||||||
|
}
|
||||||
|
if (dst.kind != SCC_X86_OPR_REG) {
|
||||||
|
scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel);
|
||||||
|
scc_x86_emit_move(isel, tmp_reg, dst, size);
|
||||||
|
dst = tmp_reg;
|
||||||
|
}
|
||||||
|
scc_x86_operand_value_t mem_op;
|
||||||
|
if (src.kind == SCC_X86_OPR_REG) {
|
||||||
|
// 地址在寄存器中 -> 构造 [reg]
|
||||||
|
mem_op = (scc_x86_operand_value_t){
|
||||||
|
.kind = SCC_X86_OPR_MEM,
|
||||||
|
.mem = {.base = src.reg,
|
||||||
|
.index = SCC_X86_REG_INVALID,
|
||||||
|
.scale = 1,
|
||||||
|
.disp = {.displacement = 0, .displacement_bits = size * 8}},
|
||||||
|
};
|
||||||
|
} else if (src.kind == SCC_X86_OPR_MEM) {
|
||||||
|
mem_op = src;
|
||||||
|
} else {
|
||||||
|
Panic("emit_load: src must be REG or MEM");
|
||||||
|
}
|
||||||
|
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, mem_op, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||||
|
scc_x86_operand_value_t src, u8 size) {
|
||||||
|
if (size == 0) {
|
||||||
|
size = dst.size;
|
||||||
|
}
|
||||||
|
if (dst.size != src.size) {
|
||||||
|
LOG_WARN("Mismatched register sizes for store %d != %d", dst.size,
|
||||||
|
src.size);
|
||||||
|
}
|
||||||
|
if (src.kind != SCC_X86_OPR_REG) {
|
||||||
|
scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel);
|
||||||
|
scc_x86_emit_move(isel, tmp_reg, src, size);
|
||||||
|
src = tmp_reg;
|
||||||
|
}
|
||||||
|
scc_x86_operand_value_t mem_op;
|
||||||
|
if (dst.kind == SCC_X86_OPR_REG) {
|
||||||
|
mem_op = (scc_x86_operand_value_t){
|
||||||
|
.kind = SCC_X86_OPR_MEM,
|
||||||
|
.mem = {.base = dst.reg,
|
||||||
|
.index = SCC_X86_REG_INVALID,
|
||||||
|
.scale = 1,
|
||||||
|
.disp = {.displacement = 0, .displacement_bits = 0}}};
|
||||||
|
} else if (dst.kind == SCC_X86_OPR_MEM) {
|
||||||
|
mem_op = dst;
|
||||||
|
} else {
|
||||||
|
Panic("emit_store: dst_addr must be REG or MEM");
|
||||||
|
}
|
||||||
|
mem_op.size = size;
|
||||||
|
src.size = size;
|
||||||
|
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, mem_op, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||||
|
scc_x86_operand_value_t base,
|
||||||
|
scc_x86_operand_value_t index, int scale,
|
||||||
|
i64 offset) {
|
||||||
|
usize size = dst.size;
|
||||||
|
// 前置断言:dst 必须是寄存器
|
||||||
|
Assert(dst.kind == SCC_X86_OPR_REG);
|
||||||
|
// scale 必须是 1,2,4,8 之一
|
||||||
|
Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
|
||||||
|
|
||||||
|
// ---- 处理 base ----
|
||||||
|
scc_x86_operand_value_t base_reg = base;
|
||||||
|
if (base.kind != SCC_X86_OPR_REG) {
|
||||||
|
base_reg = new_vreg_temp(isel);
|
||||||
|
scc_x86_emit_move(isel, base_reg, base, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 处理 index * scale ----
|
||||||
|
scc_x86_operand_value_t scaled_index = index;
|
||||||
|
Assert(index.kind != SCC_X86_OPR_NONE);
|
||||||
|
// 确保 index 在寄存器中
|
||||||
|
if (index.kind != SCC_X86_OPR_REG) {
|
||||||
|
scc_x86_operand_value_t index_tmp = new_vreg_temp(isel);
|
||||||
|
scc_x86_emit_move(isel, index_tmp, index, 8);
|
||||||
|
index = index_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 计算 base + scaled_index ----
|
||||||
|
scc_x86_operand_value_t sum = base_reg;
|
||||||
|
if (base_reg.kind == SCC_X86_OPR_REG &&
|
||||||
|
scaled_index.kind == SCC_X86_OPR_REG) {
|
||||||
|
if (dst.reg != base_reg.reg) {
|
||||||
|
scc_x86_emit_move(isel, dst, base_reg, 8);
|
||||||
|
sum = dst;
|
||||||
|
}
|
||||||
|
add_instr_2(isel, SCC_X86_IFORM_ADD_GPRV_GPRV_03, sum, scaled_index,
|
||||||
|
size);
|
||||||
|
} else if (base_reg.kind == SCC_X86_OPR_REG) {
|
||||||
|
if (dst.reg != base_reg.reg)
|
||||||
|
scc_x86_emit_move(isel, dst, base_reg, 8);
|
||||||
|
sum = dst;
|
||||||
|
} else if (scaled_index.kind == SCC_X86_OPR_REG) {
|
||||||
|
scc_x86_emit_move(isel, dst, scaled_index, 8);
|
||||||
|
sum = dst;
|
||||||
|
} else {
|
||||||
|
// base 和 index 都无效 => 结果为 0
|
||||||
|
scc_x86_emit_move(isel, dst, scc_x86_op_imm(0), 8);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 加上 offset ----
|
||||||
|
if (offset != 0) {
|
||||||
|
scc_x86_operand_value_t mem_op = build_mem_op(
|
||||||
|
isel, sum, (scc_x86_operand_value_t){.kind = SCC_X86_OPR_NONE}, 1,
|
||||||
|
offset);
|
||||||
|
scc_x86_emit_move(isel, dst, mem_op, 8);
|
||||||
|
} else if (sum.reg != dst.reg) {
|
||||||
|
scc_x86_emit_move(isel, dst, sum, 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) {
|
||||||
@@ -237,33 +409,30 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
|
|
||||||
switch (instr->op) {
|
switch (instr->op) {
|
||||||
/* ---- 数据移动 ---- */
|
/* ---- 数据移动 ---- */
|
||||||
case SCC_LIR_MOV:
|
|
||||||
scc_x86_emit_move(isel, dst, src0, size);
|
|
||||||
break;
|
|
||||||
case SCC_LIR_LOAD:
|
case SCC_LIR_LOAD:
|
||||||
scc_x86_emit_move(isel, dst, src0, size);
|
// src0 是地址(可能是寄存器或内存操作数),dst 是寄存器
|
||||||
|
scc_x86_emit_load(isel, dst, src0, size);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_STORE:
|
case SCC_LIR_STORE:
|
||||||
scc_x86_emit_move(isel, src1, src0, size);
|
// src0 是要存储的值(寄存器),src1 是目标地址
|
||||||
|
scc_x86_emit_store(isel, src1, src0, size);
|
||||||
break;
|
break;
|
||||||
|
case SCC_LIR_MOV:
|
||||||
case SCC_LIR_STORE_ADDR:
|
// 纯粹的寄存器/立即数复制
|
||||||
TODO();
|
scc_x86_emit_move(isel, dst, src0, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_LEA:
|
|
||||||
case SCC_LIR_LOAD_ADDR:
|
case SCC_LIR_LOAD_ADDR:
|
||||||
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0);
|
// 计算地址,结果放入 dst(寄存器)
|
||||||
|
emit_load_addr(isel, dst, src0, src1, instr->metadata.addr.scale,
|
||||||
|
instr->metadata.addr.offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ---- 一元运算 ---- */
|
/* ---- 一元运算 ---- */
|
||||||
case SCC_LIR_NEG:
|
case SCC_LIR_NEG:
|
||||||
add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst);
|
add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst, size);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_NOT:
|
case SCC_LIR_NOT:
|
||||||
add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst);
|
add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ---- 算术/逻辑二元运算 ---- */
|
/* ---- 算术/逻辑二元运算 ---- */
|
||||||
case SCC_LIR_ADD:
|
case SCC_LIR_ADD:
|
||||||
case SCC_LIR_SUB:
|
case SCC_LIR_SUB:
|
||||||
@@ -280,7 +449,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
scc_x86_emit_move(isel, op, src1, size);
|
scc_x86_emit_move(isel, op, src1, size);
|
||||||
src1 = op;
|
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, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_SHL:
|
case SCC_LIR_SHL:
|
||||||
@@ -303,7 +472,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
add_instr_2(isel, iform, dst, src1);
|
add_instr_2(isel, iform, dst, src1, size);
|
||||||
} else {
|
} else {
|
||||||
scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL);
|
scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL);
|
||||||
scc_x86_emit_move(isel, cl, src1, 1);
|
scc_x86_emit_move(isel, cl, src1, 1);
|
||||||
@@ -321,7 +490,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
add_instr_2(isel, iform, dst, cl);
|
add_instr_2(isel, iform, dst, cl, size);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -346,7 +515,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
(instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S)
|
(instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S)
|
||||||
? SCC_X86_IFORM_IDIV_GPRV
|
? SCC_X86_IFORM_IDIV_GPRV
|
||||||
: SCC_X86_IFORM_DIV_GPRV;
|
: SCC_X86_IFORM_DIV_GPRV;
|
||||||
add_instr_1(isel, div_if, src1);
|
add_instr_1(isel, div_if, src1, size);
|
||||||
|
|
||||||
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);
|
||||||
@@ -357,36 +526,36 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
/* ---- 比较指令 ---- */
|
/* ---- 比较指令 ---- */
|
||||||
case SCC_LIR_CMP: {
|
case SCC_LIR_CMP: {
|
||||||
if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM)
|
if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_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, size);
|
||||||
else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1))
|
else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1))
|
||||||
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1);
|
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1, size);
|
||||||
else
|
else
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
|
||||||
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);
|
add_instr_1(isel, setcc, dst, size);
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
scc_x86_operand_value_t one = scc_x86_op_imm(1);
|
scc_x86_operand_value_t one = scc_x86_op_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, size);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* ---- 条件分支 ---- */
|
/* ---- 条件分支 ---- */
|
||||||
case SCC_LIR_BR: {
|
case SCC_LIR_BR: {
|
||||||
scc_x86_operand_value_t true_bb =
|
scc_x86_operand_value_t true_bb =
|
||||||
scc_x86_op_block(instr->metadata.br.true_target);
|
scc_x86_op_reloc_block(instr->metadata.br.true_target, 0);
|
||||||
scc_x86_operand_value_t false_bb =
|
scc_x86_operand_value_t false_bb =
|
||||||
scc_x86_op_block(instr->metadata.br.false_target);
|
scc_x86_op_reloc_block(instr->metadata.br.false_target, 0);
|
||||||
|
|
||||||
add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0);
|
add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0, size);
|
||||||
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb);
|
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb, size);
|
||||||
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb);
|
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb, size);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SCC_LIR_JMP: {
|
case SCC_LIR_JMP: {
|
||||||
scc_x86_operand_value_t jmp_bb =
|
scc_x86_operand_value_t jmp_bb =
|
||||||
scc_x86_op_block(instr->metadata.jmp_target);
|
scc_x86_op_reloc_block(instr->metadata.jmp_target, 0);
|
||||||
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb);
|
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb, size);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* ---- 栈分配 ---- */
|
/* ---- 栈分配 ---- */
|
||||||
@@ -397,10 +566,14 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA;
|
x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA;
|
||||||
Assert(op.kind == SCC_X86_OPR_REG);
|
Assert(op.kind == SCC_X86_OPR_REG);
|
||||||
x86instr.instr.data.alloc.vreg = op.reg;
|
x86instr.instr.data.alloc.vreg = op.reg;
|
||||||
x86instr.instr.data.alloc.size = instr->size;
|
x86instr.instr.data.alloc.size = instr->metadata.alloca.size_bytes;
|
||||||
x86instr.instr.data.alloc.align = 0;
|
x86instr.instr.data.alloc.align = instr->metadata.alloca.align_bytes;
|
||||||
scc_vec_push(isel->instrs, x86instr);
|
scc_vec_push(isel->instrs, x86instr);
|
||||||
scc_mir_vreg_map2slot(isel->func, instr->to.data.reg, instr->size, 0);
|
scc_mir_vreg_map2slot(isel->func, instr->to.data.reg,
|
||||||
|
instr->metadata.alloca.size_bytes,
|
||||||
|
instr->metadata.alloca.align_bytes
|
||||||
|
? instr->metadata.alloca.align_bytes
|
||||||
|
: 8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,12 +587,43 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
|||||||
Assert(isel->abi_lowering.lower_call);
|
Assert(isel->abi_lowering.lower_call);
|
||||||
isel->abi_lowering.lower_call(isel, instr);
|
isel->abi_lowering.lower_call(isel, instr);
|
||||||
} break;
|
} break;
|
||||||
|
case SCC_LIR_CALL_INDIRECT: {
|
||||||
|
TODO();
|
||||||
|
// 假设函数指针的 LIR 值在某个 vreg 中
|
||||||
|
// scc_x86_operand_value_t func_ptr_op =
|
||||||
|
// scc_x86_lir_val_to_mir_op(isel, &func_ptr_val);
|
||||||
|
// scc_x86_operand_value_t temp_reg = new_vreg_temp(isel);
|
||||||
|
// scc_x86_emit_lea(isel, temp_reg, func_ptr_op); // 确保得到地址
|
||||||
|
// emit_indirect_call(isel, temp_reg);
|
||||||
|
} break;
|
||||||
case SCC_LIR_RET: {
|
case SCC_LIR_RET: {
|
||||||
Assert(isel->abi_lowering.lower_ret);
|
Assert(isel->abi_lowering.lower_ret);
|
||||||
isel->abi_lowering.lower_ret(isel, instr);
|
isel->abi_lowering.lower_ret(isel, instr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case SCC_LIR_MEMCPY: {
|
||||||
|
scc_lir_val_t dest_val = instr->metadata.memcpy.dest;
|
||||||
|
scc_lir_val_t src_val = instr->metadata.memcpy.src;
|
||||||
|
|
||||||
|
// 将 dest 的地址放入 RDI
|
||||||
|
scc_x86_operand_value_t dest_op =
|
||||||
|
scc_x86_lir_val_to_mir_op(isel, &dest_val);
|
||||||
|
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI), dest_op, 8);
|
||||||
|
|
||||||
|
// 将 src 的地址放入 RSI
|
||||||
|
scc_x86_operand_value_t src_op =
|
||||||
|
scc_x86_lir_val_to_mir_op(isel, &src_val);
|
||||||
|
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI), src_op, 8);
|
||||||
|
|
||||||
|
// 长度处理保持不变...
|
||||||
|
scc_x86_operand_value_t len_op =
|
||||||
|
scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size);
|
||||||
|
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX), len_op, 8);
|
||||||
|
|
||||||
|
add_instr_0(isel, SCC_X86_IFORM_REP_MOVSB);
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
Panic("unsupported instruction %d", instr->op);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,6 +662,7 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module,
|
|||||||
Assert(func_meta != nullptr);
|
Assert(func_meta != nullptr);
|
||||||
scc_mir_func_meta_init(func_meta);
|
scc_mir_func_meta_init(func_meta);
|
||||||
func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count;
|
func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count;
|
||||||
|
func_meta->need_va_args = SCC_LIR_FUNC_META(func)->is_va_arg;
|
||||||
func->meta = func_meta;
|
func->meta = func_meta;
|
||||||
|
|
||||||
isel->func = func;
|
isel->func = func;
|
||||||
|
|||||||
161
libs/ir/mir/src/arch/scc_x86_peephole.c
Normal file
161
libs/ir/mir/src/arch/scc_x86_peephole.c
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#include <arch/scc_x86_mir.h>
|
||||||
|
#include <scc_mir_module.h>
|
||||||
|
|
||||||
|
static bool same_x86_operand(const scc_x86_operand_value_t *a,
|
||||||
|
const scc_x86_operand_value_t *b) {
|
||||||
|
if (a->kind != b->kind)
|
||||||
|
return false;
|
||||||
|
switch (a->kind) {
|
||||||
|
case SCC_X86_OPR_REG:
|
||||||
|
return a->reg == b->reg;
|
||||||
|
case SCC_X86_OPR_MEM:
|
||||||
|
return a->mem.base == b->mem.base && a->mem.index == b->mem.index &&
|
||||||
|
a->mem.scale == b->mem.scale &&
|
||||||
|
a->mem.disp.displacement == b->mem.disp.displacement;
|
||||||
|
case SCC_X86_OPR_IMM:
|
||||||
|
return a->imm0 == b->imm0;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_store_to_mem(const scc_mir_x86_instr_t *ins) {
|
||||||
|
int op = ins->x86_instr.opcode;
|
||||||
|
return op == SCC_X86_IFORM_MOV_MEMV_GPRV ||
|
||||||
|
op == SCC_X86_IFORM_MOV_MEMV_IMMZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_load_from_mem(const scc_mir_x86_instr_t *ins) {
|
||||||
|
int op = ins->x86_instr.opcode;
|
||||||
|
return op == SCC_X86_IFORM_MOV_GPRV_MEMV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_reg_reg_move(const scc_mir_x86_instr_t *ins) {
|
||||||
|
int op = ins->x86_instr.opcode;
|
||||||
|
return op == SCC_X86_IFORM_MOV_GPRV_GPRV_8B;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc_x86_peephole_optimize(scc_mir_module_t *module) {
|
||||||
|
Assert(module != nullptr);
|
||||||
|
usize instr_size = module->instr_size;
|
||||||
|
|
||||||
|
// 遍历函数
|
||||||
|
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, j) {
|
||||||
|
scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, j);
|
||||||
|
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_vec = SCC_MIR_BBLOCK_VALUES_PTR(bb);
|
||||||
|
if (scc_vec_size(*old_vec) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t old_count = scc_vec_size(*old_vec);
|
||||||
|
// 构建新向量
|
||||||
|
scc_mir_instr_vec_t new_vec;
|
||||||
|
scc_vec_init(new_vec);
|
||||||
|
|
||||||
|
for (size_t k = 0; k < old_count;) {
|
||||||
|
if (k + 1 >= old_count) {
|
||||||
|
// 剩余不足2条,直接复制
|
||||||
|
void *ins_ptr =
|
||||||
|
scc_vec_sized_at_ptr(*old_vec, instr_size, k);
|
||||||
|
scc_vec_sized_push(new_vec, instr_size, ins_ptr,
|
||||||
|
instr_size);
|
||||||
|
k++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_mir_x86_instr_t *i0 =
|
||||||
|
(scc_mir_x86_instr_t *)scc_vec_sized_at_ptr(*old_vec,
|
||||||
|
instr_size, k);
|
||||||
|
scc_mir_x86_instr_t *i1 =
|
||||||
|
(scc_mir_x86_instr_t *)scc_vec_sized_at_ptr(
|
||||||
|
*old_vec, instr_size, k + 1);
|
||||||
|
|
||||||
|
int op0 = i0->x86_instr.opcode;
|
||||||
|
int op1 = i1->x86_instr.opcode;
|
||||||
|
|
||||||
|
// 模式 A: store reg, mem 后紧跟 load mem, reg (同一 reg 和 mem)
|
||||||
|
if (is_store_to_mem(i0) && is_load_from_mem(i1) &&
|
||||||
|
i0->x86_instr.num_operands >= 2 &&
|
||||||
|
i1->x86_instr.num_operands >= 2) {
|
||||||
|
scc_x86_operand_value_t *store_dst =
|
||||||
|
&i0->x86_instr.operands[0]; // mem
|
||||||
|
scc_x86_operand_value_t *store_src =
|
||||||
|
&i0->x86_instr.operands[1]; // reg/imm
|
||||||
|
scc_x86_operand_value_t *load_dst =
|
||||||
|
&i1->x86_instr.operands[0]; // reg
|
||||||
|
scc_x86_operand_value_t *load_src =
|
||||||
|
&i1->x86_instr.operands[1]; // mem
|
||||||
|
|
||||||
|
if (store_src->kind == SCC_X86_OPR_REG &&
|
||||||
|
load_dst->kind == SCC_X86_OPR_REG &&
|
||||||
|
same_x86_operand(store_dst, load_src) &&
|
||||||
|
store_src->reg == load_dst->reg) {
|
||||||
|
// 两条指令相互抵消,都跳过
|
||||||
|
k += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模式 B: load mem, reg 后紧跟 store reg, mem (同一 reg 和 mem)
|
||||||
|
if (is_load_from_mem(i0) && is_store_to_mem(i1) &&
|
||||||
|
i0->x86_instr.num_operands >= 2 &&
|
||||||
|
i1->x86_instr.num_operands >= 2) {
|
||||||
|
scc_x86_operand_value_t *load_dst =
|
||||||
|
&i0->x86_instr.operands[0]; // reg
|
||||||
|
scc_x86_operand_value_t *load_src =
|
||||||
|
&i0->x86_instr.operands[1]; // mem
|
||||||
|
scc_x86_operand_value_t *store_dst =
|
||||||
|
&i1->x86_instr.operands[0]; // mem
|
||||||
|
scc_x86_operand_value_t *store_src =
|
||||||
|
&i1->x86_instr.operands[1]; // reg
|
||||||
|
|
||||||
|
if (store_src->kind == SCC_X86_OPR_REG &&
|
||||||
|
load_dst->kind == SCC_X86_OPR_REG &&
|
||||||
|
same_x86_operand(load_src, store_dst) &&
|
||||||
|
load_dst->reg == store_src->reg) {
|
||||||
|
k += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模式 C: mov r1, r2 后跟 mov r2, r1
|
||||||
|
if (is_reg_reg_move(i0) && is_reg_reg_move(i1) &&
|
||||||
|
i0->x86_instr.num_operands >= 2 &&
|
||||||
|
i1->x86_instr.num_operands >= 2) {
|
||||||
|
scc_x86_operand_value_t *dst0 = &i0->x86_instr.operands[0];
|
||||||
|
scc_x86_operand_value_t *src0 = &i0->x86_instr.operands[1];
|
||||||
|
scc_x86_operand_value_t *dst1 = &i1->x86_instr.operands[0];
|
||||||
|
scc_x86_operand_value_t *src1 = &i1->x86_instr.operands[1];
|
||||||
|
|
||||||
|
if (dst0->kind == SCC_X86_OPR_REG &&
|
||||||
|
src0->kind == SCC_X86_OPR_REG &&
|
||||||
|
dst1->kind == SCC_X86_OPR_REG &&
|
||||||
|
src1->kind == SCC_X86_OPR_REG &&
|
||||||
|
dst0->reg == src1->reg && src0->reg == dst1->reg) {
|
||||||
|
// 保留第一条,删除第二条
|
||||||
|
scc_vec_sized_push(new_vec, instr_size, i0, instr_size);
|
||||||
|
k += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未匹配,保留当前指令
|
||||||
|
scc_vec_sized_push(new_vec, instr_size, i0, instr_size);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换基本块的指令向量
|
||||||
|
scc_vec_free(*old_vec);
|
||||||
|
*old_vec = new_vec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,71 +4,29 @@
|
|||||||
#include <x86/scc_x86_iform.h>
|
#include <x86/scc_x86_iform.h>
|
||||||
#include <x86/scc_x86_reg.h>
|
#include <x86/scc_x86_reg.h>
|
||||||
|
|
||||||
/* ========== 指令访问回调 ========== */
|
static void emit_spill(void *out, int preg, int slot, int size) {
|
||||||
|
|
||||||
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_vec_t *vec = out;
|
||||||
|
scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot);
|
||||||
|
scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg);
|
||||||
|
val_slot.size = size;
|
||||||
|
val_preg.size = size;
|
||||||
scc_mir_x86_instr_t ins = {
|
scc_mir_x86_instr_t ins = {
|
||||||
.x86_instr.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV,
|
.x86_instr.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV,
|
||||||
.x86_instr.num_operands = 2,
|
.x86_instr.num_operands = 2,
|
||||||
.x86_instr.operands = {scc_x86_op_slot(slot), scc_x86_op_preg(preg)}};
|
.x86_instr.operands = {val_slot, val_preg},
|
||||||
|
};
|
||||||
scc_vec_push(*vec, ins);
|
scc_vec_push(*vec, ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_reload(void *out, int preg, int slot) {
|
static void emit_reload(void *out, int preg, int slot, int size) {
|
||||||
|
scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot);
|
||||||
|
scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg);
|
||||||
|
val_slot.size = size;
|
||||||
|
val_preg.size = size;
|
||||||
scc_mir_x86_instr_vec_t *vec = out;
|
scc_mir_x86_instr_vec_t *vec = out;
|
||||||
scc_mir_x86_instr_t ins = {
|
scc_mir_x86_instr_t ins = {.x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV,
|
||||||
.x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV,
|
|
||||||
.x86_instr.num_operands = 2,
|
.x86_instr.num_operands = 2,
|
||||||
.x86_instr.operands = {scc_x86_op_preg(preg), scc_x86_op_slot(slot)}};
|
.x86_instr.operands = {val_preg, val_slot}};
|
||||||
scc_vec_push(*vec, ins);
|
scc_vec_push(*vec, ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,11 +41,7 @@ static void emit_copy(void *out, int dst_preg, int src_preg, int size) {
|
|||||||
scc_vec_push(*vec, ins);
|
scc_vec_push(*vec, ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========== 操作数读写属性 ========== */
|
static scc_reg_op_access_t get_operand_access(int opcode, int op_idx) {
|
||||||
|
|
||||||
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) {
|
if (opcode >= 0 && opcode < SCC_X86_IFORM_COUNT) {
|
||||||
const scc_x86_iform_info_t *info = &scc_x86_iform_table[opcode];
|
const scc_x86_iform_info_t *info = &scc_x86_iform_table[opcode];
|
||||||
if (op_idx >= info->num_ops || op_idx < 0)
|
if (op_idx >= info->num_ops || op_idx < 0)
|
||||||
@@ -174,7 +128,111 @@ static void clean_mark_regs(void *ctx) {
|
|||||||
reg_mask = 0;
|
reg_mask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========== 注册全部 x86 回调 ========== */
|
static void x86_alloc_iter_begin(scc_reg_alloc_iter_t *iter) {
|
||||||
|
iter->op_idx = 0;
|
||||||
|
iter->op_sub_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg,
|
||||||
|
int *out_size,
|
||||||
|
scc_reg_op_access_t *out_access) {
|
||||||
|
const scc_mir_x86_instr_t *ins = (const scc_mir_x86_instr_t *)iter->instr;
|
||||||
|
int opcode = ins->x86_instr.opcode;
|
||||||
|
int num_ops = ins->x86_instr.num_operands;
|
||||||
|
|
||||||
|
while (iter->op_idx < num_ops) {
|
||||||
|
const scc_x86_operand_value_t *op =
|
||||||
|
&ins->x86_instr.operands[iter->op_idx];
|
||||||
|
scc_reg_op_access_t base_access =
|
||||||
|
get_operand_access(opcode, iter->op_idx);
|
||||||
|
|
||||||
|
*out_size = op->size;
|
||||||
|
if (op->kind == SCC_X86_OPR_REG) {
|
||||||
|
if (iter->op_sub_idx == 0 && scc_x86_op_is_vreg(op)) {
|
||||||
|
*out_vreg = scc_x86_op_get_vreg(op);
|
||||||
|
*out_access = base_access;
|
||||||
|
iter->op_sub_idx++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
iter->op_idx++;
|
||||||
|
iter->op_sub_idx = 0;
|
||||||
|
continue;
|
||||||
|
} else if (op->kind == SCC_X86_OPR_MEM) {
|
||||||
|
const scc_x86_mem_t *mem = &op->mem;
|
||||||
|
// 子索引 0: 基址寄存器
|
||||||
|
if (iter->op_sub_idx == 0) {
|
||||||
|
if (mem->base != SCC_X86_REG_INVALID &&
|
||||||
|
scc_x86_reg_is_vreg(mem->base)) {
|
||||||
|
*out_vreg = scc_x86_reg_get_vreg(mem->base);
|
||||||
|
*out_access =
|
||||||
|
SCC_REG_ALLOC_OP_ACCESS_READ; // 地址寄存器只读
|
||||||
|
iter->op_sub_idx++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
iter->op_sub_idx++;
|
||||||
|
}
|
||||||
|
// 子索引 1: 索引寄存器
|
||||||
|
if (iter->op_sub_idx == 1) {
|
||||||
|
if (mem->index != SCC_X86_REG_INVALID &&
|
||||||
|
scc_x86_reg_is_vreg(mem->index)) {
|
||||||
|
*out_vreg = scc_x86_reg_get_vreg(mem->index);
|
||||||
|
*out_access = SCC_REG_ALLOC_OP_ACCESS_READ;
|
||||||
|
iter->op_sub_idx++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
iter->op_sub_idx++;
|
||||||
|
}
|
||||||
|
// 没有更多子部分
|
||||||
|
iter->op_idx++;
|
||||||
|
iter->op_sub_idx = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他操作数类型(立即数、slot 等)直接跳过
|
||||||
|
iter->op_idx++;
|
||||||
|
iter->op_sub_idx = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x86_alloc_iter_replace_preg(scc_reg_alloc_iter_t *iter, int preg) {
|
||||||
|
scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)iter->instr;
|
||||||
|
int op_idx = iter->op_idx;
|
||||||
|
int sub_idx = iter->op_sub_idx;
|
||||||
|
|
||||||
|
if (op_idx >= ins->x86_instr.num_operands)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scc_x86_operand_value_t *op = &ins->x86_instr.operands[op_idx];
|
||||||
|
|
||||||
|
if (op->kind == SCC_X86_OPR_REG) {
|
||||||
|
// 普通寄存器操作数
|
||||||
|
scc_x86_op_set_preg(op, (scc_x86_reg_t)preg);
|
||||||
|
} else if (op->kind == SCC_X86_OPR_MEM) {
|
||||||
|
scc_x86_mem_t *mem = &op->mem;
|
||||||
|
if (sub_idx == 1) {
|
||||||
|
// 基址寄存器
|
||||||
|
mem->base = (scc_x86_reg_t)preg;
|
||||||
|
} else if (sub_idx == 2) {
|
||||||
|
// 索引寄存器
|
||||||
|
mem->index = (scc_x86_reg_t)preg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x86_alloc_iter_replace_slot(scc_reg_alloc_iter_t *iter, int slot) {
|
||||||
|
scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)iter->instr;
|
||||||
|
int op_idx = iter->op_idx;
|
||||||
|
if (op_idx < ins->x86_instr.num_operands && iter->op_sub_idx == 0) {
|
||||||
|
ins->x86_instr.operands[op_idx] = scc_x86_op_slot(slot);
|
||||||
|
} else {
|
||||||
|
Panic("x86_alloc_iter_replace_slot: invalid op_idx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x86_alloc_iter_end(scc_reg_alloc_iter_t *iter) {
|
||||||
|
(void)iter; // 无需清理
|
||||||
|
}
|
||||||
|
|
||||||
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
|
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
|
||||||
ops->acquire_reg = acquire_reg;
|
ops->acquire_reg = acquire_reg;
|
||||||
@@ -182,19 +240,13 @@ void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
|
|||||||
ops->mark_reg_used = mark_reg_used;
|
ops->mark_reg_used = mark_reg_used;
|
||||||
ops->clean_mark_regs = clean_mark_regs;
|
ops->clean_mark_regs = clean_mark_regs;
|
||||||
|
|
||||||
ops->instr_opcode = instr_opcode;
|
ops->alloc_iter_begin = x86_alloc_iter_begin;
|
||||||
ops->instr_num_operands = instr_num_operands;
|
ops->alloc_iter_next = x86_alloc_iter_next;
|
||||||
ops->op_is_vreg = op_is_vreg;
|
ops->alloc_iter_replace_preg = x86_alloc_iter_replace_preg;
|
||||||
ops->op_get_vreg = op_get_vreg;
|
ops->alloc_iter_replace_slot = x86_alloc_iter_replace_slot;
|
||||||
ops->op_set_preg = op_set_preg;
|
ops->alloc_iter_end = x86_alloc_iter_end;
|
||||||
ops->op_set_slot = op_set_slot;
|
|
||||||
|
|
||||||
ops->get_operand_access = get_operand_access;
|
|
||||||
ops->get_implicit_regs = get_implicit_regs;
|
ops->get_implicit_regs = get_implicit_regs;
|
||||||
|
|
||||||
ops->is_pseudo = is_pseudo;
|
|
||||||
ops->handle_pseudo = handle_pseudo;
|
|
||||||
|
|
||||||
ops->emit_spill = emit_spill;
|
ops->emit_spill = emit_spill;
|
||||||
ops->emit_reload = emit_reload;
|
ops->emit_reload = emit_reload;
|
||||||
ops->emit_copy = emit_copy;
|
ops->emit_copy = emit_copy;
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
|
|||||||
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;
|
usize instr_size = ctx->module->instr_size;
|
||||||
if (ops->is_pseudo(instr)) {
|
|
||||||
ops->handle_pseudo(ctx->func, (void *)instr, instr_vec);
|
if (instr->opcode < 0) {
|
||||||
|
if (instr->opcode != SCC_MIR_PSEUDO_ALLOCA) {
|
||||||
|
scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,69 +20,69 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
|
|||||||
SCC_VEC(int) allocated;
|
SCC_VEC(int) allocated;
|
||||||
scc_vec_init(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, opcode, &implicit_uses, &implicit_defs);
|
ops->get_implicit_regs(ctx, instr->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);
|
||||||
|
|
||||||
int num_ops = ops->instr_num_operands(instr);
|
// 初始化迭代器
|
||||||
for (int op_i = 0; op_i < num_ops; op_i++) {
|
scc_reg_alloc_iter_t iter;
|
||||||
if (!ops->op_is_vreg(instr, op_i))
|
iter.instr = instr;
|
||||||
continue;
|
ops->alloc_iter_begin(&iter);
|
||||||
|
|
||||||
int vreg = ops->op_get_vreg(instr, op_i);
|
int vreg;
|
||||||
|
int size;
|
||||||
|
scc_reg_op_access_t access;
|
||||||
|
while (ops->alloc_iter_next(&iter, &vreg, &size, &access)) {
|
||||||
int id = 0;
|
int id = 0;
|
||||||
int mapping = scc_mir_vreg_lookup(ctx->func, vreg, &id);
|
int mapping = scc_mir_vreg_lookup(ctx->func, vreg, &id);
|
||||||
int preg = id, slot = id;
|
int preg = id, slot = id;
|
||||||
|
|
||||||
if (mapping == 1) {
|
if (mapping == 1) {
|
||||||
// 已预着色
|
|
||||||
ops->mark_reg_used(ctx, preg);
|
ops->mark_reg_used(ctx, preg);
|
||||||
ops->op_set_preg(instr, op_i, preg);
|
ops->alloc_iter_replace_preg(&iter, preg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapping == 0)
|
if (mapping == 0)
|
||||||
slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8);
|
slot = scc_mir_vreg_map2slot(ctx->func, vreg, size, 8);
|
||||||
|
|
||||||
preg = ops->acquire_reg(ctx);
|
preg = ops->acquire_reg(ctx);
|
||||||
scc_vec_push(allocated, preg);
|
scc_vec_push(allocated, preg);
|
||||||
|
|
||||||
scc_reg_op_access_t acc = ops->get_operand_access(ctx, opcode, op_i);
|
if (access == SCC_REG_ALLOC_OP_ACCESS_READ ||
|
||||||
if (acc == SCC_REG_ALLOC_OP_ACCESS_READ ||
|
access == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
|
||||||
acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
|
ops->emit_reload(&before, preg, slot, size);
|
||||||
ops->emit_reload(&before, preg, slot);
|
if (access == SCC_REG_ALLOC_OP_ACCESS_WRITE ||
|
||||||
if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE ||
|
access == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
|
||||||
acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
|
ops->emit_spill(&after, preg, slot, size);
|
||||||
ops->emit_spill(&after, preg, slot);
|
|
||||||
|
|
||||||
ops->op_set_preg(instr, op_i, preg);
|
ops->alloc_iter_replace_preg(&iter, preg);
|
||||||
|
}
|
||||||
|
ops->alloc_iter_end(&iter);
|
||||||
|
|
||||||
|
// 合并 before / instr / after
|
||||||
|
for (size_t i = 0; i < scc_vec_size(before); i++) {
|
||||||
|
void *p = scc_vec_sized_at_ptr(before, instr_size, i);
|
||||||
|
scc_vec_sized_push(*instr_vec, instr_size, p, instr_size);
|
||||||
|
}
|
||||||
|
scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size);
|
||||||
|
for (size_t i = 0; i < scc_vec_size(after); i++) {
|
||||||
|
void *p = scc_vec_sized_at_ptr(after, instr_size, i);
|
||||||
|
scc_vec_sized_push(*instr_vec, instr_size, p, instr_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 合并指令流
|
// 释放隐式寄存器
|
||||||
scc_vec_foreach(before, i) scc_vec_sized_push(
|
|
||||||
*instr_vec, instr_size, scc_vec_sized_at_ptr(before, instr_size, 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->release_reg(ctx, *p);
|
||||||
for (const int *p = implicit_uses; *p != -1; p++)
|
for (const int *p = implicit_uses; *p != -1; p++)
|
||||||
ops->release_reg(ctx, *p);
|
ops->release_reg(ctx, *p);
|
||||||
|
|
||||||
scc_vec_free(before);
|
scc_vec_free(before);
|
||||||
scc_vec_free(after);
|
scc_vec_free(after);
|
||||||
scc_vec_foreach(allocated, l)
|
for (size_t i = 0; i < scc_vec_size(allocated); i++)
|
||||||
ops->release_reg(ctx, scc_vec_at(allocated, l));
|
ops->release_reg(ctx, scc_vec_at(allocated, i));
|
||||||
scc_vec_free(allocated);
|
scc_vec_free(allocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +102,6 @@ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) {
|
|||||||
scc_cfg_bblock_id_t bb_id = scc_vec_at(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);
|
||||||
|
|
||||||
scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES_PTR(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);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include <arch/scc_x86_mir.h>
|
#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 *td, const scc_mir_x86_instr_t *instr);
|
void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func,
|
||||||
void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) {
|
const scc_mir_x86_instr_t *instr);
|
||||||
|
void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func,
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scc_x86_instr_dump(td, (void *)instr);
|
scc_x86_instr_dump(td, func, (void *)instr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,7 +46,7 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) {
|
|||||||
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(&ctx->mir_module->cfg_module, id);
|
scc_cfg_module_unsafe_get_bblock(&ctx->mir_module->cfg_module, id);
|
||||||
scc_mir_dump_bblock(ctx, bb);
|
scc_mir_dump_bblock(ctx, func, bb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scc_x86_peephole_optimize(scc_mir_module_t * module);
|
||||||
|
// scc_x86_peephole_optimize(mir_module);
|
||||||
|
|
||||||
scc_frame_layout_t frame_layout_ctx = {0};
|
scc_frame_layout_t frame_layout_ctx = {0};
|
||||||
scc_win_pc_x64_frame_alloc_init(&frame_layout_ctx);
|
scc_win_pc_x64_frame_alloc_init(&frame_layout_ctx);
|
||||||
scc_frame_layout(&frame_layout_ctx, mir_module);
|
scc_frame_layout(&frame_layout_ctx, mir_module);
|
||||||
|
|||||||
@@ -29,8 +29,13 @@ static void frame_alloc_impl(scc_frame_layout_t *ctx,
|
|||||||
ctx->offset += slot->size;
|
ctx->offset += slot->size;
|
||||||
slot->offset = ctx->offset;
|
slot->offset = ctx->offset;
|
||||||
}
|
}
|
||||||
op->mem.base = SCC_X86_REG_RSP;
|
*op = scc_x86_op_mem((scc_x86_mem_t){
|
||||||
op->mem.disp = -slot->offset;
|
.seg = SCC_X86_REG_INVALID,
|
||||||
|
.base = SCC_X86_REG_RSP,
|
||||||
|
.disp = {.displacement = -slot->offset},
|
||||||
|
.index = SCC_X86_REG_INVALID,
|
||||||
|
.scale = 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +155,7 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) {
|
|||||||
add_instr_1(isel,
|
add_instr_1(isel,
|
||||||
op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50
|
op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50
|
||||||
: SCC_X86_IFORM_PUSH_IMMZ,
|
: SCC_X86_IFORM_PUSH_IMMZ,
|
||||||
op);
|
op, 8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,30 @@
|
|||||||
|
|
||||||
#include <scc_mcode.h>
|
#include <scc_mcode.h>
|
||||||
#include <scc_mir_module.h>
|
#include <scc_mir_module.h>
|
||||||
|
|
||||||
|
typedef struct scc_reloc {
|
||||||
|
usize offset; // 占位位置
|
||||||
|
u8 size; // 占位字节数(可选,用于校验)
|
||||||
|
int arch_type; // 架构相关的重定位类型(由后端解释)
|
||||||
|
enum {
|
||||||
|
SCC_RELOC_TARGET_NONE,
|
||||||
|
SCC_RELOC_TARGET_SYMBOL,
|
||||||
|
SCC_RELOC_TARGET_BBLOCK,
|
||||||
|
} target_kind;
|
||||||
|
union {
|
||||||
|
const char *symbol;
|
||||||
|
int bblock_id;
|
||||||
|
};
|
||||||
|
i64 addend;
|
||||||
|
} scc_reloc_t;
|
||||||
|
|
||||||
|
typedef SCC_VEC(scc_reloc_t) scc_reloc_vec_t;
|
||||||
|
|
||||||
// FIXME target choice
|
// FIXME target choice
|
||||||
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode,
|
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
const scc_mir_instr_t *mir_instr);
|
const scc_mir_instr_t *mir_instr);
|
||||||
void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module);
|
void scc_ir2mcode_patch(scc_mcode_t *mcode, scc_reloc_t *reloc, i64 value);
|
||||||
|
void scc_ir2mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
|
const scc_mir_module_t *mir_module);
|
||||||
|
|
||||||
#endif /* __SCC_IR2MCODE_H__ */
|
#endif /* __SCC_IR2MCODE_H__ */
|
||||||
|
|||||||
@@ -5,30 +5,117 @@
|
|||||||
#include <arch/scc_x86_mir.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_patch.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_x86_instr_t *_ins) {
|
scc_x86_reg_t mir_x86_trans_gpr(scc_x86_reg_t reg, u8 size) {
|
||||||
|
size *= 8;
|
||||||
|
if (size == 0) {
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
for (scc_x86_reg_t i = 0; i < SCC_X86_REG_COUNT; i += 1) {
|
||||||
|
if (scc_x86_reg_table[i].max_enclosing == reg &&
|
||||||
|
scc_x86_reg_table[i].width == size) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
|
const scc_mir_x86_instr_t *_ins) {
|
||||||
|
Assert(mcode != nullptr && _ins != nullptr);
|
||||||
|
int skip_reloc = relocs == nullptr;
|
||||||
scc_x86_instr_t *ins = (void *)_ins;
|
scc_x86_instr_t *ins = (void *)_ins;
|
||||||
if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) {
|
if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scc_x86_operand_value_t ops[8] = {0};
|
scc_x86_operand_value_t ops[8] = {0};
|
||||||
|
scc_reloc_t reloc = {0};
|
||||||
for (int i = 0; i < ins->num_operands; i++) {
|
for (int i = 0; i < ins->num_operands; i++) {
|
||||||
if (scc_x86_op_is_vreg(&ins->operands[i]))
|
scc_x86_operand_value_t *op_ptr = &ins->operands[i];
|
||||||
|
if (scc_x86_op_is_vreg(op_ptr))
|
||||||
Panic("can't convert vreg to mcode");
|
Panic("can't convert vreg to mcode");
|
||||||
if (scc_x86_op_is_slot(&ins->operands[i]))
|
if (scc_x86_op_is_slot(op_ptr))
|
||||||
Panic("can't convert unresolved slot to mcode");
|
Panic("can't convert unresolved slot to mcode");
|
||||||
ops[i] = ins->operands[i];
|
if (op_ptr->kind == SCC_X86_OPR_RELOC) {
|
||||||
|
ops[i].kind = op_ptr->reloc.kind;
|
||||||
|
switch (op_ptr->reloc.kind) {
|
||||||
|
case SCC_X86_OPR_RELBR:
|
||||||
|
ops[i].brdisp = 0;
|
||||||
|
break;
|
||||||
|
case SCC_X86_OPR_MEM:
|
||||||
|
ops[i].mem.base = SCC_X86_REG_RIP;
|
||||||
|
ops[i].mem.index = SCC_X86_REG_INVALID;
|
||||||
|
ops[i].mem.scale = 1;
|
||||||
|
ops[i].mem.disp.displacement = 0;
|
||||||
|
ops[i].mem.disp.displacement_bits = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Panic("unsupported reloc type %d", op_ptr->reloc.kind);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (skip_reloc) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (skip_reloc != SCC_RELOC_TARGET_NONE) {
|
||||||
|
LOG_FATAL("can't using twice reloc in one instr");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
reloc.addend = op_ptr->reloc.addend;
|
||||||
|
reloc.arch_type = (int)op_ptr->reloc.kind;
|
||||||
|
reloc.size = 0;
|
||||||
|
reloc.offset = scc_mcode_size(mcode);
|
||||||
|
if (op_ptr->reloc.target == SCC_X86_RELOC_TARGET_SYMBOL) {
|
||||||
|
reloc.target_kind = SCC_RELOC_TARGET_SYMBOL;
|
||||||
|
reloc.symbol = op_ptr->reloc.global_name;
|
||||||
|
} else if (op_ptr->reloc.target == SCC_X86_RELOC_TARGET_BBLOCK) {
|
||||||
|
reloc.target_kind = SCC_RELOC_TARGET_BBLOCK;
|
||||||
|
reloc.bblock_id = op_ptr->reloc.bblock_id;
|
||||||
|
} else {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
} else if (op_ptr->kind == SCC_X86_OPR_REG) {
|
||||||
|
ops[i].kind = SCC_X86_OPR_REG;
|
||||||
|
ops[i].reg = mir_x86_trans_gpr(op_ptr->reg, op_ptr->size);
|
||||||
|
} else {
|
||||||
|
ops[i] = *op_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scc_x86_encode_inst(mcode, ins->opcode, ops);
|
scc_x86_encode_inst(mcode, ins->opcode, ops);
|
||||||
|
if (!skip_reloc && reloc.target_kind != SCC_RELOC_TARGET_NONE) {
|
||||||
|
reloc.offset = scc_mcode_size(mcode);
|
||||||
|
scc_vec_push(*relocs, reloc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode,
|
void mir_x86_patch(scc_mcode_t *mcode, scc_reloc_t *reloc, i64 value) {
|
||||||
|
// return;
|
||||||
|
scc_x86_patch_type_t patch_type = SCC_X86_PATCH_NONE;
|
||||||
|
switch (reloc->arch_type) {
|
||||||
|
case SCC_X86_OPR_RELBR:
|
||||||
|
patch_type = SCC_X86_PATCH_PC32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Panic("unsupported reloc type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scc_x86_patch(mcode, patch_type, reloc->offset + reloc->addend, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
const scc_mir_instr_t *mir_instr) {
|
const scc_mir_instr_t *mir_instr) {
|
||||||
mir_x86_to_mcode(mcode, (const scc_mir_x86_instr_t *)mir_instr);
|
mir_x86_to_mcode(mcode, relocs, (const scc_mir_x86_instr_t *)mir_instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
|
void scc_ir2mcode_patch(scc_mcode_t *mcode, scc_reloc_t *reloc, i64 value) {
|
||||||
|
mir_x86_patch(mcode, reloc, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc_ir2mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
|
const scc_mir_module_t *mir_module) {
|
||||||
|
Assert(mir_module != nullptr && mcode != nullptr);
|
||||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -42,7 +129,7 @@ void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
|
|||||||
scc_vec_foreach(*instrs, i) {
|
scc_vec_foreach(*instrs, i) {
|
||||||
const scc_mir_instr_t *ins =
|
const scc_mir_instr_t *ins =
|
||||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
||||||
scc_ir2mcode_emit_instr(mcode, ins);
|
scc_ir2mcode_emit_instr(mcode, relocs, ins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,82 @@ static inline void scc_ir_sym_to_sccf_sym(const scc_cfg_symbol_t *symbol,
|
|||||||
|
|
||||||
static inline void scc_ir_symbol_to_sect_data(const scc_cfg_symbol_t *symbol,
|
static inline void scc_ir_symbol_to_sect_data(const scc_cfg_symbol_t *symbol,
|
||||||
sccf_sect_data_t *sect_data) {
|
sccf_sect_data_t *sect_data) {
|
||||||
// scc_vec_foreach(value->data.const_array.fields, j) {
|
if (symbol->kind != SCC_CFG_SYMBOL_KIND_DATA) {
|
||||||
// scc_vec_push(ctx->sect_data,
|
return;
|
||||||
// scc_vec_at(value->data.const_array.fields, j));
|
}
|
||||||
// }
|
scc_mir_symbol_meta_t *meta = SCC_MIR_SYMBOL_META(symbol);
|
||||||
|
for (usize i = 0; i < meta->data.size; i += 1) {
|
||||||
|
scc_vec_push(*sect_data, meta->data.init_data[i]);
|
||||||
|
}
|
||||||
|
// struct {
|
||||||
|
// u8 *init_data; // 初始化数据(若为 NULL 则零初始化)
|
||||||
|
// usize size; // 数据大小(字节)
|
||||||
|
// int align; // 对齐要求
|
||||||
|
// } data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode,
|
||||||
|
scc_mir_module_t *mir_module) {
|
||||||
|
|
||||||
|
scc_hashtable_t bblock_offset;
|
||||||
|
|
||||||
|
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||||
|
if (i == 0)
|
||||||
|
continue;
|
||||||
|
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
||||||
|
|
||||||
|
sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, func->name);
|
||||||
|
Assert(sym != nullptr);
|
||||||
|
sym->sccf_sect_offset = scc_mcode_size(mcode);
|
||||||
|
|
||||||
|
scc_hashtable_usize_init(&bblock_offset);
|
||||||
|
scc_reloc_vec_t relocs;
|
||||||
|
scc_vec_init(relocs);
|
||||||
|
scc_vec_foreach(func->bblocks, i) {
|
||||||
|
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
||||||
|
const scc_cfg_bblock_t *bb =
|
||||||
|
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
|
||||||
|
|
||||||
|
// 插入bblock的offset
|
||||||
|
scc_hashtable_set(&bblock_offset, (void *)(usize)id,
|
||||||
|
(void *)scc_mcode_size(mcode));
|
||||||
|
|
||||||
|
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
|
||||||
|
scc_vec_foreach(*instrs, i) {
|
||||||
|
const scc_mir_instr_t *ins =
|
||||||
|
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
||||||
|
// FIXME reloc symbol needed
|
||||||
|
scc_ir2mcode_emit_instr(mcode, &relocs, ins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_vec_foreach(relocs, i) {
|
||||||
|
scc_reloc_t *reloc = &scc_vec_at(relocs, i);
|
||||||
|
if (reloc->target_kind == SCC_RELOC_TARGET_BBLOCK) {
|
||||||
|
reloc->target_kind = SCC_RELOC_TARGET_NONE;
|
||||||
|
usize addr = (usize)scc_hashtable_get(
|
||||||
|
&bblock_offset, (void *)(usize)reloc->bblock_id);
|
||||||
|
scc_ir2mcode_patch(mcode, reloc, addr);
|
||||||
|
} else if (reloc->target_kind == SCC_RELOC_TARGET_SYMBOL) {
|
||||||
|
usize sym_idx =
|
||||||
|
sccf_builder_get_symbol_idx(builder, reloc->symbol);
|
||||||
|
Assert(sym_idx != 0);
|
||||||
|
sccf_builder_add_reloc(builder,
|
||||||
|
(sccf_reloc_t){
|
||||||
|
.addend = reloc->addend,
|
||||||
|
.offset = reloc->offset,
|
||||||
|
.reloc_type = reloc->arch_type,
|
||||||
|
.sect_type = SCCF_SECT_CODE,
|
||||||
|
.sym_idx = sym_idx,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scc_vec_free(relocs);
|
||||||
|
// 重定向bblock的reloc
|
||||||
|
scc_hashtable_drop(&bblock_offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
||||||
@@ -58,14 +130,16 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sccf_sym_t sym = (sccf_sym_t){
|
sccf_sym_t sym = {0};
|
||||||
.sccf_sect_offset = scc_vec_size(sect_data),
|
|
||||||
.sccf_sym_size =
|
|
||||||
4, // FIXME on windows using rel32, on linux using ?
|
|
||||||
};
|
|
||||||
|
|
||||||
scc_ir_sym_to_sccf_sym(symbol, &sym);
|
scc_ir_sym_to_sccf_sym(symbol, &sym);
|
||||||
|
|
||||||
|
// FIXME 区分只读
|
||||||
|
if (sym.sccf_sect_type == SCCF_SECT_DATA ||
|
||||||
|
sym.sccf_sect_type == SCCF_SECT_RODATA) {
|
||||||
|
sym.sccf_sect_offset = scc_vec_size(sect_data);
|
||||||
scc_ir_symbol_to_sect_data(symbol, §_data);
|
scc_ir_symbol_to_sect_data(symbol, §_data);
|
||||||
|
sym.sccf_sym_size = scc_vec_size(sect_data) - sym.sccf_sect_offset;
|
||||||
|
}
|
||||||
|
|
||||||
usize sym_idx = sccf_builder_add_symbol(builder, symbol->name, &sym);
|
usize sym_idx = sccf_builder_add_symbol(builder, symbol->name, &sym);
|
||||||
Assert(sym_idx != 0);
|
Assert(sym_idx != 0);
|
||||||
@@ -74,54 +148,36 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
|||||||
sccf_sect_data_t sect_code = {0};
|
sccf_sect_data_t sect_code = {0};
|
||||||
scc_vec_init(sect_code);
|
scc_vec_init(sect_code);
|
||||||
scc_mcode_t mcode = {0};
|
scc_mcode_t mcode = {0};
|
||||||
|
// TODO choice arch
|
||||||
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
emit_mir_module(builder, &mcode, mir_module);
|
||||||
if (i == 0)
|
scc_vec_unsafe_from_buffer(sect_code, (u8 *)scc_mcode_unsafe_data(&mcode),
|
||||||
continue;
|
scc_mcode_size(&mcode));
|
||||||
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
|
||||||
|
|
||||||
sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, func->name);
|
scc_vec_foreach(builder->relocs, i) {
|
||||||
Assert(sym != nullptr);
|
sccf_reloc_t *reloc = &scc_vec_at(builder->relocs, i);
|
||||||
sym->sccf_sect_offset = scc_vec_size(mcode.mcode);
|
if (reloc->sym_idx == 0) {
|
||||||
|
Panic("relocate to an invalid symbol");
|
||||||
|
}
|
||||||
|
sccf_sym_t *sym = &scc_vec_at(builder->symtab, reloc->sym_idx);
|
||||||
|
if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
|
||||||
|
|
||||||
scc_vec_foreach(func->bblocks, i) {
|
if (sym->sccf_sect_type == SCCF_SECT_CODE &&
|
||||||
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
|
||||||
const scc_cfg_bblock_t *bb =
|
i64 target_off = sym->sccf_sect_offset;
|
||||||
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
|
|
||||||
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
|
scc_ir2mcode_patch(&mcode,
|
||||||
scc_vec_foreach(*instrs, i) {
|
&(scc_reloc_t){
|
||||||
const scc_mir_instr_t *ins =
|
.target_kind = SCC_RELOC_TARGET_SYMBOL,
|
||||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
.arch_type = reloc->reloc_type,
|
||||||
// FIXME reloc symbol needed
|
.offset = reloc->offset,
|
||||||
scc_ir2mcode_emit_instr(&mcode, ins);
|
.addend = reloc->addend,
|
||||||
|
},
|
||||||
|
target_off);
|
||||||
|
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scc_vec_unsafe_from_buffer(sect_code, scc_vec_unsafe_get_data(mcode.mcode),
|
|
||||||
scc_vec_size(mcode.mcode));
|
|
||||||
|
|
||||||
// u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode);
|
|
||||||
// scc_vec_foreach(ctx->builder->relocs, i) {
|
|
||||||
// sccf_reloc_t *reloc = &scc_vec_at(ctx->builder->relocs, i);
|
|
||||||
// if (reloc->sym_idx == 0) {
|
|
||||||
// Panic("relocate to an invalid symbol");
|
|
||||||
// }
|
|
||||||
// sccf_sym_t *sym = &scc_vec_at(ctx->builder->symtab, reloc->sym_idx);
|
|
||||||
// if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
|
|
||||||
// Assert(reloc->reloc_type == SCCF_RELOC_TYPE_REL);
|
|
||||||
|
|
||||||
// if (sym->sccf_sect_type == SCCF_SECT_CODE &&
|
|
||||||
// sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
|
|
||||||
// i64 target_off = sym->sccf_sect_offset;
|
|
||||||
// i64 next_off = reloc->offset + reloc->addend;
|
|
||||||
// i32 rel = (i32)(target_off - next_off);
|
|
||||||
// // FIXME 写入到指令的偏移字段(小端)
|
|
||||||
// *(i32 *)(&buf[reloc->offset]) = rel;
|
|
||||||
|
|
||||||
// reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
sccf_builder_add_text_section(builder, §_code);
|
sccf_builder_add_text_section(builder, §_code);
|
||||||
sccf_builder_add_data_section(builder, §_data);
|
sccf_builder_add_data_section(builder, §_data);
|
||||||
|
|||||||
2
libs/mcode/.gitignore
vendored
Normal file
2
libs/mcode/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
*.json
|
||||||
@@ -12,76 +12,76 @@ typedef SCC_VEC(u8) scc_mcode_buff_t;
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
cbool is_littel_endian;
|
cbool is_littel_endian;
|
||||||
scc_mcode_arch_t arch;
|
scc_mcode_arch_t arch;
|
||||||
scc_mcode_buff_t mcode;
|
scc_mcode_buff_t code;
|
||||||
} scc_mcode_t;
|
} scc_mcode_t;
|
||||||
|
|
||||||
static inline void scc_mcode_init(scc_mcode_t *mcode, scc_mcode_arch_t arch) {
|
static inline void scc_mcode_init(scc_mcode_t *mcode, scc_mcode_arch_t arch) {
|
||||||
scc_vec_init(mcode->mcode);
|
scc_vec_init(mcode->code);
|
||||||
mcode->arch = arch;
|
mcode->arch = arch;
|
||||||
mcode->is_littel_endian = true;
|
mcode->is_littel_endian = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *scc_mcode_unsafe_data(scc_mcode_t *mcode) {
|
static inline char *scc_mcode_unsafe_data(scc_mcode_t *mcode) {
|
||||||
return (char *)scc_vec_unsafe_get_data(mcode->mcode);
|
return (char *)scc_vec_unsafe_get_data(mcode->code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline usize scc_mcode_size(scc_mcode_t *mcode) {
|
static inline usize scc_mcode_size(scc_mcode_t *mcode) {
|
||||||
return scc_vec_size(mcode->mcode);
|
return scc_vec_size(mcode->code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_mcode_drop(scc_mcode_t *mcode) {
|
static inline void scc_mcode_drop(scc_mcode_t *mcode) {
|
||||||
scc_vec_free(mcode->mcode);
|
scc_vec_free(mcode->code);
|
||||||
mcode->arch = SCC_MCODE_ARCH_NONE;
|
mcode->arch = SCC_MCODE_ARCH_NONE;
|
||||||
mcode->is_littel_endian = true;
|
mcode->is_littel_endian = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) {
|
static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) {
|
||||||
scc_vec_push(mcode->mcode, data);
|
scc_vec_push(mcode->code, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_mcode_add_u16(scc_mcode_t *mcode, u16 data) {
|
static inline void scc_mcode_add_u16(scc_mcode_t *mcode, u16 data) {
|
||||||
if (mcode->is_littel_endian) {
|
if (mcode->is_littel_endian) {
|
||||||
scc_vec_push(mcode->mcode, (u8)(data & 0xFF));
|
scc_vec_push(mcode->code, (u8)(data & 0xFF));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 8));
|
scc_vec_push(mcode->code, (u8)(data >> 8));
|
||||||
} else {
|
} else {
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 8));
|
scc_vec_push(mcode->code, (u8)(data >> 8));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data & 0xFF));
|
scc_vec_push(mcode->code, (u8)(data & 0xFF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_mcode_add_u32(scc_mcode_t *mcode, u32 data) {
|
static inline void scc_mcode_add_u32(scc_mcode_t *mcode, u32 data) {
|
||||||
if (mcode->is_littel_endian) {
|
if (mcode->is_littel_endian) {
|
||||||
scc_vec_push(mcode->mcode, (u8)(data & 0xFF));
|
scc_vec_push(mcode->code, (u8)(data & 0xFF));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 8));
|
scc_vec_push(mcode->code, (u8)(data >> 8));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 16));
|
scc_vec_push(mcode->code, (u8)(data >> 16));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 24));
|
scc_vec_push(mcode->code, (u8)(data >> 24));
|
||||||
} else {
|
} else {
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 24));
|
scc_vec_push(mcode->code, (u8)(data >> 24));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 16));
|
scc_vec_push(mcode->code, (u8)(data >> 16));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 8));
|
scc_vec_push(mcode->code, (u8)(data >> 8));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data & 0xFF));
|
scc_vec_push(mcode->code, (u8)(data & 0xFF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_mcode_add_u64(scc_mcode_t *mcode, uint64_t data) {
|
static inline void scc_mcode_add_u64(scc_mcode_t *mcode, uint64_t data) {
|
||||||
if (mcode->is_littel_endian) {
|
if (mcode->is_littel_endian) {
|
||||||
scc_vec_push(mcode->mcode, (u8)(data & 0xFF));
|
scc_vec_push(mcode->code, (u8)(data & 0xFF));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 8));
|
scc_vec_push(mcode->code, (u8)(data >> 8));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 16));
|
scc_vec_push(mcode->code, (u8)(data >> 16));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 24));
|
scc_vec_push(mcode->code, (u8)(data >> 24));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 32));
|
scc_vec_push(mcode->code, (u8)(data >> 32));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 40));
|
scc_vec_push(mcode->code, (u8)(data >> 40));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 48));
|
scc_vec_push(mcode->code, (u8)(data >> 48));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 56));
|
scc_vec_push(mcode->code, (u8)(data >> 56));
|
||||||
} else {
|
} else {
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 56));
|
scc_vec_push(mcode->code, (u8)(data >> 56));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 48));
|
scc_vec_push(mcode->code, (u8)(data >> 48));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 40));
|
scc_vec_push(mcode->code, (u8)(data >> 40));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 32));
|
scc_vec_push(mcode->code, (u8)(data >> 32));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 24));
|
scc_vec_push(mcode->code, (u8)(data >> 24));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 16));
|
scc_vec_push(mcode->code, (u8)(data >> 16));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data >> 8));
|
scc_vec_push(mcode->code, (u8)(data >> 8));
|
||||||
scc_vec_push(mcode->mcode, (u8)(data & 0xFF));
|
scc_vec_push(mcode->code, (u8)(data & 0xFF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,131 @@
|
|||||||
#include "scc_x86_reg.h"
|
#include "scc_x86_reg.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
i64 displacement;
|
||||||
|
u32 displacement_bits;
|
||||||
|
} scc_x86_disp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
scc_x86_reg_t seg;
|
||||||
scc_x86_reg_t base;
|
scc_x86_reg_t base;
|
||||||
scc_x86_reg_t index;
|
scc_x86_reg_t index;
|
||||||
u8 scale; /* 1,2,4,8 */
|
u32 scale;
|
||||||
i32 disp;
|
scc_x86_disp_t disp;
|
||||||
} scc_x86_mem_t;
|
} scc_x86_mem_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SCC_X86_RELOC_TARGET_SYMBOL,
|
||||||
|
SCC_X86_RELOC_TARGET_BBLOCK,
|
||||||
|
} scc_x86_reloc_target_t;
|
||||||
|
|
||||||
|
typedef struct scc_x86_reloc_op {
|
||||||
|
scc_x86_operand_kind_t kind; // 原始操作数类型
|
||||||
|
scc_x86_reloc_target_t target;
|
||||||
|
union {
|
||||||
|
i64 imm;
|
||||||
|
int bblock_id; // 如果 kind == RELBR
|
||||||
|
const char *global_name; // 如果 kind == SYMBOL
|
||||||
|
};
|
||||||
|
i64 addend; // 额外常量偏移,用于 sym+addend
|
||||||
|
} scc_x86_reloc_op_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_x86_operand_kind_t kind;
|
scc_x86_operand_kind_t kind;
|
||||||
union {
|
union {
|
||||||
scc_x86_reg_t reg;
|
scc_x86_reg_t reg;
|
||||||
i64 imm;
|
i32 brdisp;
|
||||||
|
i64 simm0;
|
||||||
|
u64 imm0;
|
||||||
|
u8 imm1;
|
||||||
scc_x86_mem_t mem;
|
scc_x86_mem_t mem;
|
||||||
|
scc_x86_reloc_op_t reloc;
|
||||||
};
|
};
|
||||||
|
usize size;
|
||||||
} scc_x86_operand_value_t;
|
} scc_x86_operand_value_t;
|
||||||
|
|
||||||
|
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_reg_t scc_x86_op_vreg_reg(int vreg) {
|
||||||
|
return (int)SCC_X86_REG_COUNT + vreg;
|
||||||
|
}
|
||||||
|
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_op_vreg_reg(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, .brdisp = 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, .simm0 = imm};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_mem(scc_x86_mem_t mem) {
|
||||||
|
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM, .mem = mem};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 全局符号重定位(绝对地址加载:MOV reg, imm32/64)
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_imm(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_IMM;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_relrip(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_MEM;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 全局符号重定位(相对跳转/调用:CALL/JMP rel32)
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_relbr(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_RELBR;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 基本块重定位(相对跳转)
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_reloc_block(int bid,
|
||||||
|
i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_RELBR;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_BBLOCK;
|
||||||
|
op.reloc.bblock_id = bid;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 如果需要支持符号的内存寻址(如 [RIP + sym]),可扩展 kind =
|
||||||
|
// SCC_X86_OPR_MEM
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_mem(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_MEM;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
// 编码时需生成 RIP 相对寻址的 ModRM/SIB
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
/* 按 iform 发射一条指令,ops 数组长度需与 iform 定义的操作数数目一致 */
|
/* 按 iform 发射一条指令,ops 数组长度需与 iform 定义的操作数数目一致 */
|
||||||
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
||||||
const scc_x86_operand_value_t *ops);
|
const scc_x86_operand_value_t *ops);
|
||||||
|
|||||||
135
libs/mcode/include/x86/scc_x86_patch.h
Normal file
135
libs/mcode/include/x86/scc_x86_patch.h
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#ifndef __SCC_X86_PATCH_H__
|
||||||
|
#define __SCC_X86_PATCH_H__
|
||||||
|
#include "scc_x86_encode.h"
|
||||||
|
|
||||||
|
// x86-64 重定位类型(由底层 patch 函数处理)
|
||||||
|
typedef enum {
|
||||||
|
SCC_X86_PATCH_NONE,
|
||||||
|
SCC_X86_PATCH_PC32, // 32 位 PC 相对偏移(CALL/JMP/Jcc)
|
||||||
|
SCC_X86_PATCH_ABS64, // 64 位绝对地址(MOV reg, imm64)
|
||||||
|
SCC_X86_PATCH_ABS32, // 32 位绝对地址(MOV reg, imm32)
|
||||||
|
SCC_X86_PATCH_DISP8, // 8 位内存位移([RIP+disp8] 或 [base+disp8])
|
||||||
|
SCC_X86_PATCH_DISP32, // 32 位内存位移([RIP+disp32])
|
||||||
|
} scc_x86_patch_type_t;
|
||||||
|
|
||||||
|
static inline void patch_bytes(scc_mcode_t *mcode, usize offset,
|
||||||
|
const void *data, usize size) {
|
||||||
|
u8 *buf = (u8 *)scc_mcode_unsafe_data(mcode);
|
||||||
|
usize total = scc_mcode_size(mcode);
|
||||||
|
if (offset + size > total) {
|
||||||
|
Panic("patch offset out of range: offset=%zu size=%zu total=%zu",
|
||||||
|
offset, size, total);
|
||||||
|
}
|
||||||
|
scc_memcpy(buf + offset, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int scc_x86_patch_disp(scc_mcode_t *mcode, usize offset,
|
||||||
|
scc_x86_disp_t disp) {
|
||||||
|
if (!mcode || disp.displacement_bits == 0)
|
||||||
|
return -1;
|
||||||
|
usize bytes = disp.displacement_bits / 8;
|
||||||
|
if (bytes == 0) {
|
||||||
|
bytes = 4; // RELBR 32
|
||||||
|
}
|
||||||
|
if (bytes != 1 && bytes != 2 && bytes != 4 && bytes != 8) {
|
||||||
|
Panic("invalid displacement bits: %u", disp.displacement_bits);
|
||||||
|
}
|
||||||
|
// 将 displacement 截断到对应宽度(小端写入)
|
||||||
|
i64 val = disp.displacement;
|
||||||
|
switch (bytes) {
|
||||||
|
case 1: {
|
||||||
|
u8 v = (u8)val;
|
||||||
|
patch_bytes(mcode, offset, &v, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
u16 v = (u16)val;
|
||||||
|
patch_bytes(mcode, offset, &v, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
u32 v = (u32)val;
|
||||||
|
patch_bytes(mcode, offset, &v, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
patch_bytes(mcode, offset, &val, 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int scc_x86_patch_brdisp(scc_mcode_t *mcode, usize offset,
|
||||||
|
scc_x86_operand_value_t disp) {
|
||||||
|
if (disp.kind != SCC_X86_OPR_RELBR && disp.kind != SCC_X86_OPR_RELOC) {
|
||||||
|
Panic("patch_brdisp called with non-branch operand kind %d", disp.kind);
|
||||||
|
}
|
||||||
|
i32 brdisp;
|
||||||
|
if (disp.kind == SCC_X86_OPR_RELBR)
|
||||||
|
brdisp = disp.brdisp;
|
||||||
|
else
|
||||||
|
brdisp = (i32)disp.reloc.imm; // 从重定位占位中获取值(上层会先填好)
|
||||||
|
patch_bytes(mcode, offset, &brdisp, 4);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int scc_x86_patch_imm0(scc_mcode_t *mcode, usize offset,
|
||||||
|
scc_x86_operand_value_t imm0) {
|
||||||
|
// 注意:原声明未提供大小参数,我们假定调用者保证了正确的宽度。
|
||||||
|
// 此处默认写入 8 字节(最常用)。若需要其他宽度,请使用扩展版本。
|
||||||
|
if (imm0.kind != SCC_X86_OPR_IMM && imm0.kind != SCC_X86_OPR_RELOC) {
|
||||||
|
Panic("patch_imm0 called with non-immediate operand kind %d",
|
||||||
|
imm0.kind);
|
||||||
|
}
|
||||||
|
u64 val;
|
||||||
|
if (imm0.kind == SCC_X86_OPR_IMM)
|
||||||
|
val = imm0.imm0;
|
||||||
|
else
|
||||||
|
val = (u64)imm0.reloc.imm; // 从重定位占位中获取
|
||||||
|
patch_bytes(mcode, offset, &val, 8);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 扩展:带大小的立即数 patch(推荐上层使用) ---------- */
|
||||||
|
static inline int scc_x86_patch_imm0_ex(scc_mcode_t *mcode, usize offset,
|
||||||
|
u64 value, usize size) {
|
||||||
|
if (size != 1 && size != 2 && size != 4 && size != 8)
|
||||||
|
return -1;
|
||||||
|
switch (size) {
|
||||||
|
case 1: {
|
||||||
|
u8 v = (u8)value;
|
||||||
|
patch_bytes(mcode, offset, &v, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
u16 v = (u16)value;
|
||||||
|
patch_bytes(mcode, offset, &v, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
u32 v = (u32)value;
|
||||||
|
patch_bytes(mcode, offset, &v, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
patch_bytes(mcode, offset, &value, 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void scc_x86_patch(scc_mcode_t *mcode,
|
||||||
|
scc_x86_patch_type_t patch_type, u64 offset,
|
||||||
|
i64 value) {
|
||||||
|
switch (patch_type) {
|
||||||
|
case SCC_X86_PATCH_PC32:
|
||||||
|
scc_x86_patch_brdisp(mcode, offset - 4,
|
||||||
|
scc_x86_op_relbr(value - offset));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TODO();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SCC_X86_PATCH_H__ */
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <string.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>
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#ifdef LOG_INFO
|
||||||
|
#undef LOG_INFO
|
||||||
|
#endif
|
||||||
|
#define LOG_INFO(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------- 内部辅助 ---------- */
|
/* ---------- 内部辅助 ---------- */
|
||||||
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
|
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
|
||||||
scc_mcode_add_u8(m, v);
|
scc_mcode_add_u8(m, v);
|
||||||
@@ -32,11 +37,19 @@ static inline int scc_reg_ordinal(scc_x86_reg_t reg) {
|
|||||||
static int reg_low3(scc_x86_reg_t reg) {
|
static int reg_low3(scc_x86_reg_t reg) {
|
||||||
if (reg == SCC_X86_REG_INVALID)
|
if (reg == SCC_X86_REG_INVALID)
|
||||||
return 0;
|
return 0;
|
||||||
|
// RIP/EIP/IP 必须返回 5,否则无法编码 RIP 相对寻址
|
||||||
|
if (reg == SCC_X86_REG_RIP || reg == SCC_X86_REG_EIP ||
|
||||||
|
reg == SCC_X86_REG_IP)
|
||||||
|
return 5;
|
||||||
return scc_reg_ordinal(reg) & 7;
|
return scc_reg_ordinal(reg) & 7;
|
||||||
}
|
}
|
||||||
static int reg_rex_bit(scc_x86_reg_t reg) {
|
static int reg_rex_bit(scc_x86_reg_t reg) {
|
||||||
if (reg == SCC_X86_REG_INVALID)
|
if (reg == SCC_X86_REG_INVALID)
|
||||||
return 0;
|
return 0;
|
||||||
|
// RIP 不需要 REX 扩展
|
||||||
|
if (reg == SCC_X86_REG_RIP || reg == SCC_X86_REG_EIP ||
|
||||||
|
reg == SCC_X86_REG_IP)
|
||||||
|
return 0;
|
||||||
if (reg >= SCC_X86_REG_AH && reg <= SCC_X86_REG_DH)
|
if (reg >= SCC_X86_REG_AH && reg <= SCC_X86_REG_DH)
|
||||||
return 0;
|
return 0;
|
||||||
return (scc_reg_ordinal(reg) >= 8) ? 1 : 0;
|
return (scc_reg_ordinal(reg) >= 8) ? 1 : 0;
|
||||||
@@ -54,13 +67,13 @@ static int infer_operand_width(const scc_x86_iform_info_t *info,
|
|||||||
}
|
}
|
||||||
const char *eosz = info->encode.eosz;
|
const char *eosz = info->encode.eosz;
|
||||||
int default_64 = info->encode.default_64b;
|
int default_64 = info->encode.default_64b;
|
||||||
if (!strcmp(eosz, "o16"))
|
if (!scc_strcmp(eosz, "o16"))
|
||||||
return 16;
|
return 16;
|
||||||
if (!strcmp(eosz, "o32"))
|
if (!scc_strcmp(eosz, "o32"))
|
||||||
return 32;
|
return 32;
|
||||||
if (!strcmp(eosz, "o64"))
|
if (!scc_strcmp(eosz, "o64"))
|
||||||
return 64;
|
return 64;
|
||||||
if (!strcmp(eosz, "oszall") || !strcmp(eosz, "osznot16"))
|
if (!scc_strcmp(eosz, "oszall") || !scc_strcmp(eosz, "osznot16"))
|
||||||
return default_64 ? 64 : 32;
|
return default_64 ? 64 : 32;
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
@@ -69,16 +82,11 @@ static int infer_operand_width(const scc_x86_iform_info_t *info,
|
|||||||
static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
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 rm_op, scc_x86_reg_t base,
|
||||||
scc_x86_reg_t idx) {
|
scc_x86_reg_t idx) {
|
||||||
/* 强制要求 / 明确禁止 优先级最高 */
|
|
||||||
if (enc->rex_w == 1)
|
if (enc->rex_w == 1)
|
||||||
return 1;
|
return 1;
|
||||||
if (enc->rex_w == 0)
|
if (enc->rex_w == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* 指令已隐含 64 位语义(如 PUSH/POP),但仍可能被 64 位操作数需要 W?例如
|
|
||||||
* PUSH r64 不需要 W,但 PUSH r/m64 也不需要。总之 default_64b
|
|
||||||
* 时一般无需额外 W,但若操作数明确是 64 位且模板没有禁止,我们仍加上以兼容
|
|
||||||
* movabs 等 */
|
|
||||||
int has_64bit_op = 0;
|
int has_64bit_op = 0;
|
||||||
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 64)
|
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 64)
|
||||||
has_64bit_op = 1;
|
has_64bit_op = 1;
|
||||||
@@ -90,9 +98,6 @@ static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
|||||||
has_64bit_op = 1;
|
has_64bit_op = 1;
|
||||||
|
|
||||||
if (enc->default_64b) {
|
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)) ||
|
return (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) ||
|
||||||
(rm_op != SCC_X86_REG_INVALID && reg_rex_bit(rm_op)) ||
|
(rm_op != SCC_X86_REG_INVALID && reg_rex_bit(rm_op)) ||
|
||||||
(base != SCC_X86_REG_INVALID && reg_rex_bit(base)) ||
|
(base != SCC_X86_REG_INVALID && reg_rex_bit(base)) ||
|
||||||
@@ -101,7 +106,6 @@ static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 普通指令:有 64 位操作数即加 W */
|
|
||||||
return has_64bit_op;
|
return has_64bit_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,8 +113,7 @@ static int need_66_prefix(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
|||||||
scc_x86_reg_t rm_op) {
|
scc_x86_reg_t rm_op) {
|
||||||
if (enc->osz_required)
|
if (enc->osz_required)
|
||||||
return 1;
|
return 1;
|
||||||
// 如果强制指定了操作大小,不自动加66
|
if (!scc_strcmp(enc->eosz, "o32") || !scc_strcmp(enc->eosz, "o64"))
|
||||||
if (!strcmp(enc->eosz, "o32") || !strcmp(enc->eosz, "o64"))
|
|
||||||
return 0;
|
return 0;
|
||||||
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 16)
|
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 16)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -143,9 +146,11 @@ static void emit_legacy_prefixes(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
|||||||
|
|
||||||
static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
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 reg_op, scc_x86_reg_t rm_op,
|
||||||
scc_x86_reg_t base, scc_x86_reg_t idx) {
|
scc_x86_reg_t base, scc_x86_reg_t idx,
|
||||||
|
int op_width) { // 新增 op_width 参数
|
||||||
int rex = 0x40;
|
int rex = 0x40;
|
||||||
if (need_rexw(enc, reg_op, rm_op, base, idx))
|
// 仅当 op_width == 64 时才考虑 REX.W
|
||||||
|
if (op_width == 64 && need_rexw(enc, reg_op, rm_op, base, idx))
|
||||||
rex |= 8;
|
rex |= 8;
|
||||||
if (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op))
|
if (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op))
|
||||||
rex |= 4;
|
rex |= 4;
|
||||||
@@ -159,7 +164,6 @@ static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
|||||||
emit_u8(m, (uint8_t)rex);
|
emit_u8(m, (uint8_t)rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) {
|
static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) {
|
||||||
if (enc->map == 1) {
|
if (enc->map == 1) {
|
||||||
emit_u8(m, 0x0F);
|
emit_u8(m, 0x0F);
|
||||||
@@ -201,31 +205,33 @@ static int scale_to_enc(uint8_t scale) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 修正:位移大小只由数值范围决定,与基址寄存器无关 */
|
||||||
static int disp_size(int32_t disp, scc_x86_reg_t base) {
|
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)
|
(void)base;
|
||||||
|
if (disp == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (disp >= -128 && disp <= 127)
|
if (disp >= -128 && disp <= 127)
|
||||||
return 8;
|
return 8;
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- 立即数发射(独立函数) ---------- */
|
/* ---------- 立即数发射 ---------- */
|
||||||
static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
||||||
const scc_x86_operand_t *tmpl, int imm_idx,
|
const scc_x86_operand_t *tmpl, int imm_idx,
|
||||||
int64_t imm_val, int op_width) {
|
int64_t imm_val, int op_width) {
|
||||||
const char *oc2 = tmpl[imm_idx].oc2;
|
const char *oc2 = tmpl[imm_idx].oc2;
|
||||||
int imm_size = enc->imm_size;
|
int imm_size = enc->imm_size;
|
||||||
if (!strcmp(oc2, "b"))
|
if (!scc_strcmp(oc2, "b"))
|
||||||
imm_size = 1;
|
imm_size = 1;
|
||||||
else if (!strcmp(oc2, "w"))
|
else if (!scc_strcmp(oc2, "w"))
|
||||||
imm_size = 2;
|
imm_size = 2;
|
||||||
else if (!strcmp(oc2, "z"))
|
else if (!scc_strcmp(oc2, "z"))
|
||||||
imm_size = (op_width <= 16) ? op_width / 8 : (op_width <= 32 ? 4 : 4);
|
imm_size = (op_width <= 16) ? op_width / 8 : (op_width <= 32 ? 4 : 4);
|
||||||
else if (!strcmp(oc2, "v"))
|
else if (!scc_strcmp(oc2, "v"))
|
||||||
imm_size = op_width / 8;
|
imm_size = op_width / 8;
|
||||||
else if (!strcmp(oc2, "d") || !strcmp(oc2, "ss"))
|
else if (!scc_strcmp(oc2, "d") || !scc_strcmp(oc2, "ss"))
|
||||||
imm_size = 4;
|
imm_size = 4;
|
||||||
else if (!strcmp(oc2, "q"))
|
else if (!scc_strcmp(oc2, "q"))
|
||||||
imm_size = 8;
|
imm_size = 8;
|
||||||
|
|
||||||
LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size);
|
LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size);
|
||||||
@@ -268,9 +274,9 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
if (ops[i].kind == SCC_X86_OPR_REG) {
|
if (ops[i].kind == SCC_X86_OPR_REG) {
|
||||||
LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
|
LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
|
||||||
ops[i].reg);
|
ops[i].reg);
|
||||||
if (strncmp(tname, "REG0", 4) == 0)
|
if (scc_strcmp(tname, "REG0") == 0)
|
||||||
reg_r = ops[i].reg;
|
reg_r = ops[i].reg;
|
||||||
else if (strncmp(tname, "REG1", 4) == 0)
|
else if (scc_strcmp(tname, "REG1") == 0)
|
||||||
reg_b = ops[i].reg;
|
reg_b = ops[i].reg;
|
||||||
else {
|
else {
|
||||||
if (reg_r == SCC_X86_REG_INVALID)
|
if (reg_r == SCC_X86_REG_INVALID)
|
||||||
@@ -282,7 +288,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
has_mem = 1;
|
has_mem = 1;
|
||||||
memdesc = ops[i].mem;
|
memdesc = ops[i].mem;
|
||||||
} else if (ops[i].kind == SCC_X86_OPR_IMM) {
|
} else if (ops[i].kind == SCC_X86_OPR_IMM) {
|
||||||
imm_val = ops[i].imm;
|
imm_val = ops[i].imm0;
|
||||||
imm_idx = i;
|
imm_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,17 +296,58 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b));
|
scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b));
|
||||||
|
|
||||||
uint8_t modrm = 0;
|
uint8_t modrm = 0;
|
||||||
|
|
||||||
if (has_mem) {
|
if (has_mem) {
|
||||||
|
// ========== RIP 相对寻址特殊处理 ==========
|
||||||
|
if (memdesc.base == SCC_X86_REG_RIP &&
|
||||||
|
memdesc.index == SCC_X86_REG_INVALID) {
|
||||||
|
// RIP 相对:mod=00, r/m=101,位移固定 32 位
|
||||||
|
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;
|
||||||
|
modrm |= 0x05; // r/m = 101
|
||||||
|
emit_u8(m, modrm);
|
||||||
|
// 写入 32 位位移(小端)
|
||||||
|
int32_t disp32 = (int32_t)memdesc.disp.displacement;
|
||||||
|
emit_u32(m, (uint32_t)disp32);
|
||||||
|
// 处理立即数(如果有)
|
||||||
|
if (imm_idx >= 0) {
|
||||||
|
emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width);
|
||||||
|
}
|
||||||
|
return; // 已处理完,跳过后续 SIB/位移逻辑
|
||||||
|
}
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
if (reg_r != SCC_X86_REG_INVALID)
|
if (reg_r != SCC_X86_REG_INVALID)
|
||||||
modrm |= (reg_low3(reg_r) & 7) << 3;
|
modrm |= (reg_low3(reg_r) & 7) << 3;
|
||||||
else if (enc->modrm_reg_fix >= 0)
|
else if (enc->modrm_reg_fix >= 0)
|
||||||
modrm |= (enc->modrm_reg_fix & 7) << 3;
|
modrm |= (enc->modrm_reg_fix & 7) << 3;
|
||||||
|
|
||||||
int32_t disp = memdesc.disp;
|
int32_t disp = memdesc.disp.displacement;
|
||||||
int dsize = disp_size(disp, memdesc.base);
|
// 优先使用用户指定的 displacement_bits,转换为字节数
|
||||||
modrm |= (dsize == 0) ? 0 : (dsize == 8) ? 0x40 : 0x80;
|
int dsize = 0;
|
||||||
|
if (memdesc.disp.displacement_bits != 0) {
|
||||||
|
dsize = memdesc.disp.displacement_bits / 8;
|
||||||
|
if (dsize != 1 && dsize != 2 && dsize != 4 && dsize != 8)
|
||||||
|
dsize = 0; // 无效则回退
|
||||||
|
}
|
||||||
|
if (dsize == 0) {
|
||||||
|
// 使用自动计算:disp_size 返回位数,除以 8 得字节数
|
||||||
|
int bits = disp_size(disp, memdesc.base);
|
||||||
|
dsize = bits / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置 ModRM 的 mod 字段
|
||||||
|
if (dsize == 0)
|
||||||
|
modrm |= 0x00;
|
||||||
|
else if (dsize == 1)
|
||||||
|
modrm |= 0x40;
|
||||||
|
else if (dsize == 2 || dsize == 4 || dsize == 8)
|
||||||
|
modrm |= 0x80; // 2/4/8 字节位移均使用 mod=10b
|
||||||
|
|
||||||
if (memdesc.index != SCC_X86_REG_INVALID) {
|
if (memdesc.index != SCC_X86_REG_INVALID) {
|
||||||
|
// SIB 寻址
|
||||||
modrm |= 4;
|
modrm |= 4;
|
||||||
int idx_ord = scc_reg_ordinal(memdesc.index);
|
int idx_ord = scc_reg_ordinal(memdesc.index);
|
||||||
int base_ord = scc_reg_ordinal(memdesc.base);
|
int base_ord = scc_reg_ordinal(memdesc.base);
|
||||||
@@ -311,35 +358,61 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
(base_ord & 7));
|
(base_ord & 7));
|
||||||
emit_u8(m, modrm);
|
emit_u8(m, modrm);
|
||||||
emit_u8(m, sib);
|
emit_u8(m, sib);
|
||||||
if (dsize == 8)
|
if (dsize == 1)
|
||||||
emit_u8(m, (uint8_t)disp);
|
emit_u8(m, (uint8_t)disp);
|
||||||
else if (dsize == 32)
|
else if (dsize == 2)
|
||||||
|
emit_u16(m, (uint16_t)disp);
|
||||||
|
else if (dsize == 4)
|
||||||
emit_u32(m, (uint32_t)disp);
|
emit_u32(m, (uint32_t)disp);
|
||||||
|
else if (dsize == 8)
|
||||||
|
emit_u64(m, (uint64_t)disp);
|
||||||
} else if (memdesc.base == SCC_X86_REG_INVALID) {
|
} else if (memdesc.base == SCC_X86_REG_INVALID) {
|
||||||
|
// 绝对地址:mod=00, r/m=101,位移 32 位
|
||||||
modrm |= 5;
|
modrm |= 5;
|
||||||
emit_u8(m, modrm);
|
emit_u8(m, modrm);
|
||||||
emit_u32(m, (uint32_t)disp);
|
emit_u32(m, (uint32_t)disp);
|
||||||
} else {
|
} else {
|
||||||
|
// 一般基址寻址
|
||||||
int base_ord = scc_reg_ordinal(memdesc.base);
|
int base_ord = scc_reg_ordinal(memdesc.base);
|
||||||
if (memdesc.base == SCC_X86_REG_RSP ||
|
if (memdesc.base == SCC_X86_REG_RSP ||
|
||||||
memdesc.base == SCC_X86_REG_R12) {
|
memdesc.base == SCC_X86_REG_R12) {
|
||||||
|
// 需要 SIB(基址为 RSP/R12 时强制)
|
||||||
modrm |= 4;
|
modrm |= 4;
|
||||||
uint8_t sib = (uint8_t)((base_ord & 7) | (4 << 3));
|
uint8_t sib = (uint8_t)((base_ord & 7) | (4 << 3));
|
||||||
emit_u8(m, modrm);
|
emit_u8(m, modrm);
|
||||||
emit_u8(m, sib);
|
emit_u8(m, sib);
|
||||||
if (dsize == 8)
|
if (dsize == 1)
|
||||||
emit_u8(m, (uint8_t)disp);
|
emit_u8(m, (uint8_t)disp);
|
||||||
else if (dsize == 32)
|
else if (dsize == 2)
|
||||||
|
emit_u16(m, (uint16_t)disp);
|
||||||
|
else if (dsize == 4)
|
||||||
emit_u32(m, (uint32_t)disp);
|
emit_u32(m, (uint32_t)disp);
|
||||||
|
else if (dsize == 8)
|
||||||
|
emit_u64(m, (uint64_t)disp);
|
||||||
} else {
|
} else {
|
||||||
modrm |= (base_ord & 7);
|
modrm |= (base_ord & 7);
|
||||||
emit_u8(m, modrm);
|
emit_u8(m, modrm);
|
||||||
if (dsize == 8)
|
if (dsize == 1)
|
||||||
emit_u8(m, (uint8_t)disp);
|
emit_u8(m, (uint8_t)disp);
|
||||||
else if (dsize == 32)
|
else if (dsize == 2)
|
||||||
|
emit_u16(m, (uint16_t)disp);
|
||||||
|
else if (dsize == 4)
|
||||||
emit_u32(m, (uint32_t)disp);
|
emit_u32(m, (uint32_t)disp);
|
||||||
|
else if (dsize == 8)
|
||||||
|
emit_u64(m, (uint64_t)disp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 没有内存操作数:寄存器-寄存器或单个寄存器
|
||||||
|
int is_single_reg_op =
|
||||||
|
(info->num_explicit_ops == 1 && enc->modrm_reg_fix == -1 &&
|
||||||
|
enc->modrm_rm_fix == -1 && enc->mod_fix == 3);
|
||||||
|
if (is_single_reg_op && reg_r != SCC_X86_REG_INVALID &&
|
||||||
|
reg_b == SCC_X86_REG_INVALID) {
|
||||||
|
modrm = 0xC0 | (reg_low3(reg_r) & 7);
|
||||||
|
emit_u8(m, modrm);
|
||||||
|
LOG_INFO("[MODRM] single reg operand treated as rm, emit 0x%02x",
|
||||||
|
modrm);
|
||||||
} else {
|
} else {
|
||||||
modrm = 0xC0;
|
modrm = 0xC0;
|
||||||
if (enc->modrm_reg_fix >= 0)
|
if (enc->modrm_reg_fix >= 0)
|
||||||
@@ -351,35 +424,135 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
modrm |= enc->modrm_rm_fix & 7;
|
modrm |= enc->modrm_rm_fix & 7;
|
||||||
} else if (reg_b != SCC_X86_REG_INVALID) {
|
} else if (reg_b != SCC_X86_REG_INVALID) {
|
||||||
modrm |= reg_low3(reg_b) & 7;
|
modrm |= reg_low3(reg_b) & 7;
|
||||||
} else if (enc->modrm_reg_fix >= 0 && reg_r != SCC_X86_REG_INVALID) {
|
} else if (enc->modrm_reg_fix >= 0 &&
|
||||||
|
reg_r != SCC_X86_REG_INVALID) {
|
||||||
modrm |= reg_low3(reg_r) & 7;
|
modrm |= reg_low3(reg_r) & 7;
|
||||||
} else if (reg_r != SCC_X86_REG_INVALID) {
|
} else if (reg_r != SCC_X86_REG_INVALID) {
|
||||||
modrm |= reg_low3(reg_r) & 7;
|
modrm |= reg_low3(reg_r) & 7;
|
||||||
}
|
}
|
||||||
emit_u8(m, modrm);
|
emit_u8(m, modrm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_INFO("[MODRM] emit byte 0x%02x", modrm);
|
LOG_INFO("[MODRM] emit byte 0x%02x", modrm);
|
||||||
|
|
||||||
/* 立即数在 ModRM 后发射 */
|
// 立即数在 ModRM 后发射
|
||||||
if (imm_idx >= 0) {
|
if (imm_idx >= 0) {
|
||||||
emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width);
|
emit_immediate(m, enc, tmpl, imm_idx, imm_val, op_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static scc_x86_iform_t adapt_iform_to_8bit(scc_x86_iform_t iform,
|
||||||
|
const scc_x86_operand_value_t *ops,
|
||||||
|
int num_ops) {
|
||||||
|
// 只处理第一个操作数是 8
|
||||||
|
// 位寄存器的情况(大多数指令的目标或源是第一个寄存器)
|
||||||
|
if (num_ops > 0 && ops[0].kind == SCC_X86_OPR_REG &&
|
||||||
|
scc_reg_width(ops[0].reg) == 8) {
|
||||||
|
switch (iform) {
|
||||||
|
// ---- MOV 类 ----
|
||||||
|
case SCC_X86_IFORM_MOV_GPRV_IMMV:
|
||||||
|
case SCC_X86_IFORM_MOV_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_MOV_GPR8_IMMB_B0;
|
||||||
|
case SCC_X86_IFORM_MOV_GPRV_GPRV_89: // mov r/m, r
|
||||||
|
return SCC_X86_IFORM_MOV_GPR8_GPR8_88;
|
||||||
|
case SCC_X86_IFORM_MOV_GPRV_GPRV_8B: // mov r, r/m
|
||||||
|
return SCC_X86_IFORM_MOV_GPR8_GPR8_8A;
|
||||||
|
case SCC_X86_IFORM_MOV_GPRV_MEMV: // mov r, mem
|
||||||
|
return SCC_X86_IFORM_MOV_GPR8_MEMB;
|
||||||
|
case SCC_X86_IFORM_MOV_MEMV_GPRV: // mov mem, r
|
||||||
|
return SCC_X86_IFORM_MOV_MEMB_GPR8;
|
||||||
|
// ---- ADD ----
|
||||||
|
case SCC_X86_IFORM_ADD_GPRV_IMMB:
|
||||||
|
case SCC_X86_IFORM_ADD_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_ADD_GPR8_IMMB_80R0;
|
||||||
|
case SCC_X86_IFORM_ADD_GPRV_GPRV_01: // add r/m, r
|
||||||
|
return SCC_X86_IFORM_ADD_GPR8_GPR8_00;
|
||||||
|
case SCC_X86_IFORM_ADD_GPRV_GPRV_03: // add r, r/m
|
||||||
|
return SCC_X86_IFORM_ADD_GPR8_GPR8_02;
|
||||||
|
// ---- SUB ----
|
||||||
|
case SCC_X86_IFORM_SUB_GPRV_IMMB:
|
||||||
|
case SCC_X86_IFORM_SUB_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_SUB_GPR8_IMMB_80R5;
|
||||||
|
case SCC_X86_IFORM_SUB_GPRV_GPRV_29:
|
||||||
|
return SCC_X86_IFORM_SUB_GPR8_GPR8_28;
|
||||||
|
case SCC_X86_IFORM_SUB_GPRV_GPRV_2B:
|
||||||
|
return SCC_X86_IFORM_SUB_GPR8_GPR8_2A;
|
||||||
|
// ---- CMP ----
|
||||||
|
case SCC_X86_IFORM_CMP_GPRV_IMMB:
|
||||||
|
case SCC_X86_IFORM_CMP_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_CMP_GPR8_IMMB_80R7;
|
||||||
|
case SCC_X86_IFORM_CMP_GPRV_GPRV_39:
|
||||||
|
return SCC_X86_IFORM_CMP_GPR8_GPR8_38;
|
||||||
|
case SCC_X86_IFORM_CMP_GPRV_GPRV_3B:
|
||||||
|
return SCC_X86_IFORM_CMP_GPR8_GPR8_3A;
|
||||||
|
// ---- AND ----
|
||||||
|
case SCC_X86_IFORM_AND_GPRV_IMMB:
|
||||||
|
case SCC_X86_IFORM_AND_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_AND_GPR8_IMMB_80R4;
|
||||||
|
case SCC_X86_IFORM_AND_GPRV_GPRV_21:
|
||||||
|
return SCC_X86_IFORM_AND_GPR8_GPR8_20;
|
||||||
|
// ---- OR ----
|
||||||
|
case SCC_X86_IFORM_OR_GPRV_IMMB:
|
||||||
|
case SCC_X86_IFORM_OR_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_OR_GPR8_IMMB_80R1;
|
||||||
|
case SCC_X86_IFORM_OR_GPRV_GPRV_09:
|
||||||
|
return SCC_X86_IFORM_OR_GPR8_GPR8_08;
|
||||||
|
// ---- XOR ----
|
||||||
|
case SCC_X86_IFORM_XOR_GPRV_IMMB:
|
||||||
|
case SCC_X86_IFORM_XOR_GPRV_IMMZ:
|
||||||
|
return SCC_X86_IFORM_XOR_GPR8_IMMB_80R6;
|
||||||
|
case SCC_X86_IFORM_XOR_GPRV_GPRV_31:
|
||||||
|
return SCC_X86_IFORM_XOR_GPR8_GPR8_30;
|
||||||
|
// ---- TEST ----
|
||||||
|
case SCC_X86_IFORM_TEST_GPRV_GPRV:
|
||||||
|
return SCC_X86_IFORM_TEST_GPR8_GPR8;
|
||||||
|
case SCC_X86_IFORM_TEST_GPRV_IMMZ_F7R0:
|
||||||
|
return SCC_X86_IFORM_TEST_GPR8_IMMB_F6R0;
|
||||||
|
// ---- INC/DEC ----
|
||||||
|
case SCC_X86_IFORM_INC_GPRV_40:
|
||||||
|
case SCC_X86_IFORM_INC_GPRV_FFR0:
|
||||||
|
return SCC_X86_IFORM_INC_GPR8;
|
||||||
|
case SCC_X86_IFORM_DEC_GPRV_48:
|
||||||
|
case SCC_X86_IFORM_DEC_GPRV_FFR1:
|
||||||
|
return SCC_X86_IFORM_DEC_GPR8;
|
||||||
|
// ---- NEG/NOT ----
|
||||||
|
case SCC_X86_IFORM_NEG_GPRV:
|
||||||
|
return SCC_X86_IFORM_NEG_GPR8;
|
||||||
|
case SCC_X86_IFORM_NOT_GPRV:
|
||||||
|
return SCC_X86_IFORM_NOT_GPR8;
|
||||||
|
// ---- 移位操作 ----
|
||||||
|
case SCC_X86_IFORM_SHL_GPRV_ONE_D1R4:
|
||||||
|
return SCC_X86_IFORM_SHL_GPR8_ONE_D0R4;
|
||||||
|
case SCC_X86_IFORM_SHR_GPRV_ONE:
|
||||||
|
return SCC_X86_IFORM_SHR_GPR8_ONE;
|
||||||
|
case SCC_X86_IFORM_SAR_GPRV_ONE:
|
||||||
|
return SCC_X86_IFORM_SAR_GPR8_ONE;
|
||||||
|
// ---- 其他(根据需求继续添加)----
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return iform;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------- 主编码入口 ---------- */
|
/* ---------- 主编码入口 ---------- */
|
||||||
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
||||||
const scc_x86_operand_value_t *ops) {
|
const scc_x86_operand_value_t *ops) {
|
||||||
if (!mcode || !ops)
|
if (!mcode || !ops)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (iform >= SCC_X86_IFORM_COUNT)
|
||||||
if (iform >= SCC_X86_IFORM_COUNT || iform < 0)
|
|
||||||
Panic("invalid iform %d", iform);
|
Panic("invalid iform %d", iform);
|
||||||
|
|
||||||
const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform];
|
const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform];
|
||||||
|
int num_ops = info->num_explicit_ops;
|
||||||
|
// FIXME 自动适配 8 位操作数
|
||||||
|
iform = adapt_iform_to_8bit(iform, ops, num_ops);
|
||||||
|
// FIXME 重新获取 info 因为 iform 可能变了
|
||||||
|
info = &scc_x86_iform_table[iform];
|
||||||
|
|
||||||
const scc_x86_encoding_t *enc = &info->encode;
|
const scc_x86_encoding_t *enc = &info->encode;
|
||||||
const scc_x86_operand_t *tmpl = info->ops;
|
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,
|
LOG_INFO("[IFORM] %s, explicit_ops=%d (total=%d)", info->iform_name,
|
||||||
num_ops, info->num_ops);
|
num_ops, info->num_ops);
|
||||||
|
|
||||||
@@ -388,24 +561,22 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
scc_x86_reg_t base_reg = SCC_X86_REG_INVALID;
|
scc_x86_reg_t base_reg = SCC_X86_REG_INVALID;
|
||||||
scc_x86_reg_t idx_reg = SCC_X86_REG_INVALID;
|
scc_x86_reg_t idx_reg = SCC_X86_REG_INVALID;
|
||||||
|
|
||||||
/* ---------- 收集立即数信息(用于无 ModRM 指令) ---------- */
|
|
||||||
int64_t imm_val = 0;
|
int64_t imm_val = 0;
|
||||||
int imm_idx = -1;
|
int imm_idx = -1;
|
||||||
for (int i = 0; i < num_ops; i++) {
|
for (int i = 0; i < num_ops; i++) {
|
||||||
const char *tname = tmpl[i].name;
|
const char *tname = tmpl[i].name;
|
||||||
if (ops[i].kind == SCC_X86_OPR_REG) {
|
if (ops[i].kind == SCC_X86_OPR_REG) {
|
||||||
if (strncmp(tname, "REG0", 4) == 0) {
|
if (scc_strcmp(tname, "REG0") == 0) {
|
||||||
if (enc->modrm_reg_fix >= 0)
|
if (enc->modrm_reg_fix >= 0)
|
||||||
rm_field = ops[i].reg; // reg固定 → REG0为rm
|
rm_field = ops[i].reg;
|
||||||
else
|
else
|
||||||
reg_field = ops[i].reg; // 否则为reg
|
reg_field = ops[i].reg;
|
||||||
} else if (strncmp(tname, "REG1", 4) == 0) {
|
} else if (scc_strcmp(tname, "REG1") == 0) {
|
||||||
if (enc->modrm_rm_fix >= 0)
|
if (enc->modrm_rm_fix >= 0)
|
||||||
reg_field = ops[i].reg; // rm固定 → REG1为reg
|
reg_field = ops[i].reg;
|
||||||
else
|
else
|
||||||
rm_field = ops[i].reg; // 否则为rm
|
rm_field = ops[i].reg;
|
||||||
} else {
|
} else {
|
||||||
// 未命名的寄存器,按先 reg 后 rm 填充
|
|
||||||
if (reg_field == SCC_X86_REG_INVALID)
|
if (reg_field == SCC_X86_REG_INVALID)
|
||||||
reg_field = ops[i].reg;
|
reg_field = ops[i].reg;
|
||||||
else if (rm_field == SCC_X86_REG_INVALID)
|
else if (rm_field == SCC_X86_REG_INVALID)
|
||||||
@@ -416,29 +587,38 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
idx_reg = ops[i].mem.index;
|
idx_reg = ops[i].mem.index;
|
||||||
} else if (ops[i].kind == SCC_X86_OPR_IMM ||
|
} else if (ops[i].kind == SCC_X86_OPR_IMM ||
|
||||||
ops[i].kind == SCC_X86_OPR_RELBR) {
|
ops[i].kind == SCC_X86_OPR_RELBR) {
|
||||||
imm_val = ops[i].imm;
|
imm_val = ops[i].imm0;
|
||||||
imm_idx = i;
|
imm_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 特殊处理 SETZ 等单寄存器指令
|
||||||
|
if (enc->has_modrm && info->num_explicit_ops == 1 &&
|
||||||
|
enc->modrm_reg_fix == -1 && enc->modrm_rm_fix == -1 &&
|
||||||
|
enc->mod_fix == 3) {
|
||||||
|
if (reg_field != SCC_X86_REG_INVALID &&
|
||||||
|
rm_field == SCC_X86_REG_INVALID) {
|
||||||
|
rm_field = reg_field;
|
||||||
|
reg_field = SCC_X86_REG_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int op_width = infer_operand_width(info, ops);
|
int op_width = infer_operand_width(info, ops);
|
||||||
LOG_INFO("[OPWIDTH] %d bits", op_width);
|
LOG_INFO("[OPWIDTH] %d bits", op_width);
|
||||||
|
|
||||||
// +++ 新增:无 ModRM 时,寄存器用 REX.B 扩展 +++
|
|
||||||
if (!enc->has_modrm) {
|
if (!enc->has_modrm) {
|
||||||
rm_field = reg_field;
|
rm_field = reg_field;
|
||||||
reg_field = SCC_X86_REG_INVALID;
|
reg_field = SCC_X86_REG_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_legacy_prefixes(mcode, enc, reg_field, rm_field, base_reg, idx_reg);
|
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_rex(mcode, enc, reg_field, rm_field, base_reg, idx_reg, op_width);
|
||||||
emit_escape_map(mcode, enc);
|
emit_escape_map(mcode, enc);
|
||||||
|
|
||||||
if (enc->has_modrm) {
|
if (enc->has_modrm) {
|
||||||
emit_opcode(mcode, enc, rm_field, base_reg);
|
emit_opcode(mcode, enc, rm_field, base_reg);
|
||||||
emit_modrm_sib_disp(mcode, info, ops, op_width);
|
emit_modrm_sib_disp(mcode, info, ops, op_width);
|
||||||
} else {
|
} else {
|
||||||
// 无 ModRM:opcode 中的寄存器来自 rm_field
|
|
||||||
emit_opcode(mcode, enc, rm_field, base_reg);
|
emit_opcode(mcode, enc, rm_field, base_reg);
|
||||||
if (imm_idx >= 0) {
|
if (imm_idx >= 0) {
|
||||||
emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width);
|
emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width);
|
||||||
|
|||||||
@@ -72,11 +72,12 @@ typedef enum {
|
|||||||
SCCF_SECT_RELOCS = 7, ///< 重定位表
|
SCCF_SECT_RELOCS = 7, ///< 重定位表
|
||||||
} sccf_sect_type_t;
|
} sccf_sect_type_t;
|
||||||
|
|
||||||
/** 重定位类型 */
|
/** 重定位类型 (可以被platform任意修改)在此只提供一个样例模板占位符 */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SCCF_RELOC_TYPE_EMPTY = 0, ///< 空展位符
|
SCCF_RELOC_TYPE_EMPTY = 0, ///< 空展位符
|
||||||
SCCF_RELOC_TYPE_ABS = 1, ///< 绝对地址
|
SCCF_RELOC_TYPE_ABS = 1, ///< 绝对地址
|
||||||
SCCF_RELOC_TYPE_REL = 2, ///< 相对地址
|
SCCF_RELOC_TYPE_REL = 2, ///< 相对地址
|
||||||
|
SCCF_RELOC_TYPE_COUNT = 3, ///< 重定位类型数量
|
||||||
} sccf_reloc_type_t;
|
} sccf_reloc_type_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
#ifndef __SCCF2PE_H__
|
||||||
|
#define __SCCF2PE_H__
|
||||||
|
|
||||||
#include <scc_pe_builder.h>
|
#include <scc_pe_builder.h>
|
||||||
#include <sccf_builder.h>
|
#include <sccf_builder.h>
|
||||||
|
|
||||||
void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf);
|
void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf);
|
||||||
|
|
||||||
|
#endif /* __SCCF2PE_H__ */
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <scc_pe_idata.h>
|
#include <scc_pe_idata.h>
|
||||||
#include <sccf2pe.h>
|
#include <sccf2pe.h>
|
||||||
#include <sccf_utils.h>
|
#include <sccf_utils.h>
|
||||||
|
#include <x86/scc_x86_patch.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_hashtable_t str2libsym;
|
scc_hashtable_t str2libsym;
|
||||||
@@ -199,6 +200,10 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
|||||||
.size_of_heap_commit = 0x1000,
|
.size_of_heap_commit = 0x1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scc_mcode_t mcode;
|
||||||
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
|
// FIXME hack
|
||||||
|
mcode.code = *(scc_mcode_buff_t *)code_data;
|
||||||
scc_vec_foreach(relocs, i) {
|
scc_vec_foreach(relocs, i) {
|
||||||
sccf_reloc_t *reloc = &scc_vec_at(relocs, i);
|
sccf_reloc_t *reloc = &scc_vec_at(relocs, i);
|
||||||
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
|
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
|
||||||
@@ -220,14 +225,15 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(rva != 0);
|
Assert(rva != 0);
|
||||||
if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) {
|
|
||||||
TODO();
|
|
||||||
}
|
|
||||||
rva -= code_range.virual_address + reloc->offset + reloc->addend;
|
|
||||||
Assert(code_data != nullptr);
|
Assert(code_data != nullptr);
|
||||||
// FIXME 需要确保宿主机与目标机器大小端一致
|
// FIXME patch type
|
||||||
*(u32 *)(scc_vec_unsafe_get_data(*code_data) + reloc->offset) = rva;
|
// if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) {
|
||||||
|
// TODO();
|
||||||
|
// }
|
||||||
|
scc_x86_patch(&mcode, SCC_X86_PATCH_PC32, reloc->offset + reloc->addend,
|
||||||
|
(i64)rva - (i64)code_range.virual_address);
|
||||||
}
|
}
|
||||||
|
*(scc_mcode_buff_t *)code_data = mcode.code;
|
||||||
|
|
||||||
scc_pe_write_header(builder, &config);
|
scc_pe_write_header(builder, &config);
|
||||||
if (code_data != nullptr) {
|
if (code_data != nullptr) {
|
||||||
|
|||||||
10
src/main.c
10
src/main.c
@@ -307,16 +307,16 @@ sstream_drop:
|
|||||||
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};
|
||||||
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
scc_ir2mcode(&mcode, &mir_module);
|
scc_ir2mcode(&mcode, nullptr, &mir_module);
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
LOG_WARN("emit flatbin can't write to stdout");
|
LOG_WARN("emit flatbin can't write to stdout");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usize ret = scc_fwrite(fp, scc_vec_unsafe_get_data(mcode.mcode),
|
usize mcode_size = scc_mcode_size(&mcode);
|
||||||
scc_vec_size(mcode.mcode));
|
usize ret = scc_fwrite(fp, scc_mcode_unsafe_data(&mcode), mcode_size);
|
||||||
if (ret != scc_vec_size(mcode.mcode)) {
|
if (ret != mcode_size) {
|
||||||
LOG_ERROR("write flatbin failed, write %zu but need write %zu\n",
|
LOG_ERROR("write flatbin failed, write %zu but need write %zu\n",
|
||||||
ret, scc_vec_size(mcode.mcode));
|
ret, mcode_size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user