refactor(ast2ir): 重构ABI类型系统并修复union结构问题
- 将scc_ast_def.h中的attr_of从union改为struct以修复结构定义问题 - 添加type_abi依赖到ast2ir模块的cbuild.toml配置文件中 - 重命名scc_ast2ir.h中的abi字段为type_abi,并更新相关初始化函数签名 - 移除废弃的scc_abi_type.h和相关平台ABI头文件 - 添加辅助函数is_variadic_marker和fixed_param_count用于处理可变参数 - 添加数组和聚合类型初始化的辅助函数
This commit is contained in:
@@ -8,6 +8,7 @@ dependencies = [
|
||||
{ name = "scc_cfg", path = "../cfg" },
|
||||
{ name = "scc_utils", path = "../../../runtime/scc_utils" },
|
||||
{ name = "tree_dump", path = "../../tree_dump" },
|
||||
{ name = "type_abi", path = "../../target/type_abi" },
|
||||
]
|
||||
# dependencies = []
|
||||
# features = {}
|
||||
|
||||
39
libs/ir/hir/include/scc_hir_layout.h
Normal file
39
libs/ir/hir/include/scc_hir_layout.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __SCC_HIR_LAYOUT_H__
|
||||
#define __SCC_HIR_LAYOUT_H__
|
||||
|
||||
#include <scc_hir_module.h>
|
||||
#include <scc_type_abi.h>
|
||||
|
||||
#define SCC_ALIGN_UP(x, align) (((x) + (align)-1) & ~((align)-1))
|
||||
|
||||
/// 结构体/联合体字段布局
|
||||
typedef struct scc_hir_field_layout {
|
||||
int offset;
|
||||
int size;
|
||||
int align;
|
||||
} scc_hir_field_layout_t;
|
||||
|
||||
/// 聚合体布局结果 (FLEX)
|
||||
typedef struct scc_hir_aggregate_layout {
|
||||
int size;
|
||||
int align;
|
||||
int field_count;
|
||||
scc_hir_field_layout_t fields[];
|
||||
} scc_hir_aggregate_layout_t;
|
||||
|
||||
int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t type,
|
||||
const scc_type_abi_t *abi);
|
||||
|
||||
int scc_hir_type_align(scc_hir_module_t *mod, scc_hir_type_ref_t type,
|
||||
const scc_type_abi_t *abi);
|
||||
|
||||
int scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t type,
|
||||
int field_idx, const scc_type_abi_t *abi);
|
||||
|
||||
scc_hir_aggregate_layout_t *
|
||||
scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t type,
|
||||
const scc_type_abi_t *abi);
|
||||
|
||||
void scc_hir_aggregate_layout_free(scc_hir_aggregate_layout_t *layout);
|
||||
|
||||
#endif /* __SCC_HIR_LAYOUT_H__ */
|
||||
@@ -334,6 +334,9 @@ scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder,
|
||||
case '"':
|
||||
scc_str_append_ch(&buf, '"');
|
||||
break;
|
||||
case '0':
|
||||
scc_str_append_ch(&buf, '\0');
|
||||
break;
|
||||
default:
|
||||
LOG_WARN("Unknown escape sequence: \\%c", str[i]);
|
||||
scc_str_append_ch(&buf, str[i]);
|
||||
|
||||
249
libs/ir/hir/src/scc_hir_layout.c
Normal file
249
libs/ir/hir/src/scc_hir_layout.c
Normal file
@@ -0,0 +1,249 @@
|
||||
#include <scc_hir_layout.h>
|
||||
|
||||
int scc_hir_type_align(scc_hir_module_t *mod, scc_hir_type_ref_t ref,
|
||||
const scc_type_abi_t *abi) {
|
||||
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
||||
if (!type)
|
||||
return 0;
|
||||
|
||||
switch (type->tag) {
|
||||
case SCC_HIR_TYPE_void:
|
||||
case SCC_HIR_TYPE_FUNC:
|
||||
case SCC_HIR_TYPE_unknown:
|
||||
return 1; // void/func 不占空间, 对齐为 1
|
||||
|
||||
case SCC_HIR_TYPE_i8:
|
||||
case SCC_HIR_TYPE_u8:
|
||||
return scc_type_abi_get_type_align(abi, 1) * 8;
|
||||
case SCC_HIR_TYPE_i16:
|
||||
case SCC_HIR_TYPE_u16:
|
||||
case SCC_HIR_TYPE_f16:
|
||||
return scc_type_abi_get_type_align(abi, 2) * 8;
|
||||
case SCC_HIR_TYPE_i32:
|
||||
case SCC_HIR_TYPE_u32:
|
||||
case SCC_HIR_TYPE_f32:
|
||||
return scc_type_abi_get_type_align(abi, 4) * 8;
|
||||
case SCC_HIR_TYPE_i64:
|
||||
case SCC_HIR_TYPE_u64:
|
||||
case SCC_HIR_TYPE_f64:
|
||||
return scc_type_abi_get_type_align(abi, 8) * 8;
|
||||
case SCC_HIR_TYPE_i128:
|
||||
case SCC_HIR_TYPE_u128:
|
||||
case SCC_HIR_TYPE_f128:
|
||||
return scc_type_abi_get_type_align(abi, 16) * 8;
|
||||
|
||||
case SCC_HIR_TYPE_PTR:
|
||||
return abi->ptr_align * 8;
|
||||
|
||||
case SCC_HIR_TYPE_ARRAY: {
|
||||
return scc_hir_type_align(mod, type->data.array.base, abi);
|
||||
}
|
||||
|
||||
case SCC_HIR_TYPE_STRUCT: {
|
||||
int max_align_bits = 0;
|
||||
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
|
||||
scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8;
|
||||
if (fa2_bits > max_align_bits)
|
||||
max_align_bits = fa2_bits;
|
||||
}
|
||||
return scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8;
|
||||
}
|
||||
|
||||
case SCC_HIR_TYPE_UNION: {
|
||||
int max_align_bits = 0;
|
||||
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
|
||||
scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
(void)fs_bits;
|
||||
if (fa_bits > max_align_bits)
|
||||
max_align_bits = fa_bits;
|
||||
}
|
||||
return scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8;
|
||||
}
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t ref,
|
||||
const scc_type_abi_t *abi) {
|
||||
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
||||
if (!type)
|
||||
return 0;
|
||||
|
||||
switch (type->tag) {
|
||||
case SCC_HIR_TYPE_void:
|
||||
case SCC_HIR_TYPE_FUNC:
|
||||
case SCC_HIR_TYPE_unknown:
|
||||
return 0;
|
||||
|
||||
case SCC_HIR_TYPE_i8:
|
||||
case SCC_HIR_TYPE_u8:
|
||||
return 8;
|
||||
case SCC_HIR_TYPE_i16:
|
||||
case SCC_HIR_TYPE_u16:
|
||||
case SCC_HIR_TYPE_f16:
|
||||
return 16;
|
||||
case SCC_HIR_TYPE_i32:
|
||||
case SCC_HIR_TYPE_u32:
|
||||
case SCC_HIR_TYPE_f32:
|
||||
return 32;
|
||||
case SCC_HIR_TYPE_i64:
|
||||
case SCC_HIR_TYPE_u64:
|
||||
case SCC_HIR_TYPE_f64:
|
||||
return 64;
|
||||
case SCC_HIR_TYPE_i128:
|
||||
case SCC_HIR_TYPE_u128:
|
||||
case SCC_HIR_TYPE_f128:
|
||||
return 128;
|
||||
|
||||
case SCC_HIR_TYPE_PTR:
|
||||
return abi->ptr_size * 8;
|
||||
|
||||
case SCC_HIR_TYPE_ARRAY: {
|
||||
int es_bits = scc_hir_type_size(mod, type->data.array.base, abi);
|
||||
return es_bits * (int)type->data.array.len;
|
||||
}
|
||||
|
||||
case SCC_HIR_TYPE_STRUCT: {
|
||||
int offset_bits = 0, max_align_bits = 0;
|
||||
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
|
||||
scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8;
|
||||
offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits);
|
||||
offset_bits += fs_bits;
|
||||
if (fa2_bits > max_align_bits)
|
||||
max_align_bits = fa2_bits;
|
||||
}
|
||||
return SCC_ALIGN_UP(offset_bits,
|
||||
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
||||
}
|
||||
|
||||
case SCC_HIR_TYPE_UNION: {
|
||||
int max_size_bits = 0, max_align_bits = 0;
|
||||
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
|
||||
scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
if (fs_bits > max_size_bits)
|
||||
max_size_bits = fs_bits;
|
||||
if (fa_bits > max_align_bits)
|
||||
max_align_bits = fa_bits;
|
||||
}
|
||||
return SCC_ALIGN_UP(max_size_bits,
|
||||
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t ref,
|
||||
int field_idx, const scc_type_abi_t *abi) {
|
||||
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
||||
if (!type || (type->tag != SCC_HIR_TYPE_STRUCT &&
|
||||
type->tag != SCC_HIR_TYPE_UNION))
|
||||
return 0;
|
||||
|
||||
if (type->tag == SCC_HIR_TYPE_UNION)
|
||||
return 0; // union 所有字段偏移为 0
|
||||
|
||||
int offset_bits = 0;
|
||||
int count = (int)scc_vec_size(type->data.aggregate.fields);
|
||||
if (field_idx >= count)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, (usize)i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8;
|
||||
offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits);
|
||||
if (i == field_idx)
|
||||
return offset_bits;
|
||||
offset_bits += fs_bits;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
scc_hir_aggregate_layout_t *
|
||||
scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t ref,
|
||||
const scc_type_abi_t *abi) {
|
||||
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
||||
if (!type || (type->tag != SCC_HIR_TYPE_STRUCT &&
|
||||
type->tag != SCC_HIR_TYPE_UNION))
|
||||
return NULL;
|
||||
|
||||
int fc = (int)scc_vec_size(type->data.aggregate.fields);
|
||||
|
||||
if (type->tag == SCC_HIR_TYPE_UNION) {
|
||||
int max_size_bits = 0, max_align_bits = 0;
|
||||
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
|
||||
scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
if (fs_bits > max_size_bits)
|
||||
max_size_bits = fs_bits;
|
||||
if (fa_bits > max_align_bits)
|
||||
max_align_bits = fa_bits;
|
||||
}
|
||||
|
||||
scc_hir_aggregate_layout_t *al =
|
||||
scc_malloc(sizeof(scc_hir_aggregate_layout_t) +
|
||||
(usize)fc * sizeof(scc_hir_field_layout_t));
|
||||
al->size = SCC_ALIGN_UP(max_size_bits, max_align_bits);
|
||||
al->align = max_align_bits;
|
||||
al->field_count = fc;
|
||||
for (int i = 0; i < fc; i++) {
|
||||
scc_hir_type_ref_t fr =
|
||||
scc_vec_at(type->data.aggregate.fields, (usize)i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
al->fields[i].offset = 0;
|
||||
al->fields[i].size = fs_bits;
|
||||
al->fields[i].align = fa_bits;
|
||||
}
|
||||
return al;
|
||||
}
|
||||
|
||||
// STRUCT
|
||||
scc_hir_aggregate_layout_t *al =
|
||||
scc_malloc(sizeof(scc_hir_aggregate_layout_t) +
|
||||
(usize)fc * sizeof(scc_hir_field_layout_t));
|
||||
al->field_count = fc;
|
||||
|
||||
int offset_bits = 0, max_align_bits = 0;
|
||||
for (int i = 0; i < fc; i++) {
|
||||
scc_hir_type_ref_t fr =
|
||||
scc_vec_at(type->data.aggregate.fields, (usize)i);
|
||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||
int fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||
int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8;
|
||||
offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits);
|
||||
|
||||
al->fields[i].offset = offset_bits;
|
||||
al->fields[i].size = fs_bits;
|
||||
al->fields[i].align = fa_bits;
|
||||
|
||||
offset_bits += fs_bits;
|
||||
if (fa2_bits > max_align_bits)
|
||||
max_align_bits = fa2_bits;
|
||||
}
|
||||
|
||||
al->size = SCC_ALIGN_UP(offset_bits,
|
||||
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
||||
al->align = scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8;
|
||||
return al;
|
||||
}
|
||||
|
||||
void scc_hir_aggregate_layout_free(scc_hir_aggregate_layout_t *layout) {
|
||||
scc_free(layout);
|
||||
}
|
||||
@@ -134,24 +134,24 @@ usize scc_hir_module_type_size(scc_hir_module_t *ctx, scc_hir_type_t *type) {
|
||||
return 0;
|
||||
case SCC_HIR_TYPE_i8:
|
||||
case SCC_HIR_TYPE_u8:
|
||||
return 1;
|
||||
return 8;
|
||||
case SCC_HIR_TYPE_i16:
|
||||
case SCC_HIR_TYPE_u16:
|
||||
return 2;
|
||||
return 16;
|
||||
case SCC_HIR_TYPE_f32:
|
||||
case SCC_HIR_TYPE_i32:
|
||||
case SCC_HIR_TYPE_u32:
|
||||
return 4;
|
||||
return 32;
|
||||
case SCC_HIR_TYPE_f64:
|
||||
case SCC_HIR_TYPE_i64:
|
||||
case SCC_HIR_TYPE_u64:
|
||||
return 8;
|
||||
return 64;
|
||||
case SCC_HIR_TYPE_FUNC:
|
||||
case SCC_HIR_TYPE_PTR: {
|
||||
// TODO
|
||||
// 目标指针大小,可以定义为 8(64位)或从 ABI 获取
|
||||
// 目标指针大小,可以定义为 64(64位)或从 ABI 获取
|
||||
// 假设你的目标架构是 64 位
|
||||
return 8;
|
||||
return 64;
|
||||
}
|
||||
case SCC_HIR_TYPE_ARRAY: {
|
||||
usize elem_size = scc_hir_module_type_size(
|
||||
|
||||
@@ -65,10 +65,10 @@ typedef struct scc_lir_instr {
|
||||
#define SCC_LIR_ARG(n) \
|
||||
((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_ARG, .data.arg = (n)})
|
||||
|
||||
#define SCC_LIR_SIZE_8 1
|
||||
#define SCC_LIR_SIZE_16 2
|
||||
#define SCC_LIR_SIZE_32 4
|
||||
#define SCC_LIR_SIZE_64 8
|
||||
#define SCC_LIR_SIZE_8 8
|
||||
#define SCC_LIR_SIZE_16 16
|
||||
#define SCC_LIR_SIZE_32 32
|
||||
#define SCC_LIR_SIZE_64 64
|
||||
|
||||
typedef enum {
|
||||
SCC_LIR_EXT_NONE,
|
||||
@@ -163,7 +163,7 @@ typedef enum {
|
||||
typedef scc_cfg_bblock_id_t scc_lir_bblock_id_t;
|
||||
typedef struct scc_lir_ins {
|
||||
scc_lir_op_t op;
|
||||
u8 size;
|
||||
u8 size_bits;
|
||||
scc_lir_ext_t ext;
|
||||
scc_lir_val_t to;
|
||||
scc_lir_val_t arg0;
|
||||
@@ -207,12 +207,12 @@ typedef struct scc_lir_ins {
|
||||
} parallel_copy;
|
||||
|
||||
struct scc_lir_alloca {
|
||||
int size_bytes;
|
||||
int align_bytes;
|
||||
int size_bits;
|
||||
int align_bits;
|
||||
} alloca;
|
||||
|
||||
struct scc_lir_extend {
|
||||
int from_size; // 源类型宽度(字节)
|
||||
int from_size_bits; // 源类型宽度(位)
|
||||
} extend;
|
||||
|
||||
struct {
|
||||
|
||||
@@ -294,7 +294,7 @@ static int ensure_vreg(ir2lir_ctx_t *ctx, scc_lir_val_t *val) {
|
||||
// 分配新的虚拟寄存器
|
||||
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, // 地址宽度
|
||||
.size_bits = SCC_LIR_SIZE_64, // 地址宽度
|
||||
.to = SCC_LIR_VREG(new_vreg),
|
||||
.arg0 = *val};
|
||||
scc_lir_builder_add_instr(ctx, &mov);
|
||||
@@ -311,10 +311,10 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
return;
|
||||
|
||||
scc_hir_type_t *ty = scc_hir_module_get_type(ctx->hir_module, value->type);
|
||||
u8 size = 0;
|
||||
u8 size_bits = 0;
|
||||
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
||||
if (ty != nullptr) {
|
||||
ir_type_to_lir_size_ext(ty, &size, &ext);
|
||||
ir_type_to_lir_size_ext(ty, &size_bits, &ext);
|
||||
}
|
||||
bool is_float = (ext == SCC_LIR_EXT_FLOAT);
|
||||
|
||||
@@ -331,7 +331,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
|
||||
scc_lir_instr_t instr = {
|
||||
.op = op,
|
||||
.size = size,
|
||||
.size_bits = size_bits,
|
||||
.ext = ext,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.arg0 = lhs,
|
||||
@@ -346,7 +346,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
scc_lir_val_t addr =
|
||||
ir_value_to_lir_operand(ctx, value->data.load.target);
|
||||
scc_lir_instr_t instr = {.op = SCC_LIR_LOAD,
|
||||
.size = size,
|
||||
.size_bits = size_bits,
|
||||
.ext = ext,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.arg0 = addr};
|
||||
@@ -363,15 +363,15 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
if (ptr_type && ptr_type->tag == SCC_HIR_TYPE_PTR) {
|
||||
scc_hir_type_t *elem_type = scc_hir_module_get_type(
|
||||
ctx->hir_module, ptr_type->data.pointer.base);
|
||||
ir_type_to_lir_size_ext(elem_type, &size, &ext);
|
||||
ir_type_to_lir_size_ext(elem_type, &size_bits, &ext);
|
||||
} else {
|
||||
ty = scc_hir_module_get_type_by_value(ctx->hir_module,
|
||||
value->data.store.value);
|
||||
ir_type_to_lir_size_ext(ty, &size, &ext);
|
||||
ir_type_to_lir_size_ext(ty, &size_bits, &ext);
|
||||
}
|
||||
scc_lir_instr_t instr = {.op = SCC_LIR_STORE,
|
||||
.ext = ext,
|
||||
.size = size,
|
||||
.size_bits = size_bits,
|
||||
.arg0 = data,
|
||||
.arg1 = addr};
|
||||
scc_lir_builder_add_instr(ctx, &instr);
|
||||
@@ -397,16 +397,17 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
} else {
|
||||
Panic("GET_ELEM_PTR on non-pointer/array type");
|
||||
}
|
||||
int elem_size = scc_hir_module_type_size(ctx->hir_module, pointee);
|
||||
int elem_size_bits = scc_hir_module_type_size(ctx->hir_module, pointee);
|
||||
|
||||
int dst_vreg = get_vreg_for_value(ctx, value_ref);
|
||||
scc_lir_instr_t instr = {
|
||||
.op = SCC_LIR_LOAD_ADDR,
|
||||
.size = SCC_LIR_SIZE_64,
|
||||
.size_bits = SCC_LIR_SIZE_64,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.arg0 = base,
|
||||
.arg1 = index,
|
||||
.metadata.addr.scale = elem_size,
|
||||
// FIXME
|
||||
.metadata.addr.scale = elem_size_bits / 8,
|
||||
.metadata.addr.offset = 0,
|
||||
};
|
||||
scc_lir_builder_add_instr(ctx, &instr);
|
||||
@@ -415,11 +416,13 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
Assert(ty != nullptr);
|
||||
scc_hir_type_t *alloc_ty =
|
||||
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_bits =
|
||||
scc_hir_module_type_size(ctx->hir_module, alloc_ty);
|
||||
scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA,
|
||||
.size = alloc_size,
|
||||
.size_bits = SCC_LIR_SIZE_64,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.metadata.alloca = {alloc_size, 1}};
|
||||
// FIXME
|
||||
.metadata.alloca = {alloc_size_bits, 8}};
|
||||
scc_lir_builder_add_instr(ctx, &instr);
|
||||
} break;
|
||||
case SCC_HIR_VALUE_TAG_CALL: {
|
||||
@@ -440,7 +443,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
int is_direct_call = sym->kind == SCC_CFG_SYMBOL_KIND_FUNC;
|
||||
scc_lir_instr_t instr = (scc_lir_instr_t){
|
||||
.op = is_direct_call ? SCC_LIR_CALL : SCC_LIR_CALL_INDIRECT,
|
||||
.size = size,
|
||||
.size_bits = size_bits,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.metadata.call = {.args = lir_args,
|
||||
.arg_count = arg_count,
|
||||
@@ -497,7 +500,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
// TRUNC 用 SCC_LIR_MOV 截断
|
||||
if (value->data.conv.conv_type == SCC_HIR_CONV_TRUNC) {
|
||||
scc_lir_instr_t instr = {.op = SCC_LIR_MOV,
|
||||
.size = size,
|
||||
.size_bits = size_bits,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.arg0 = src};
|
||||
scc_lir_builder_add_instr(ctx, &instr);
|
||||
@@ -507,13 +510,15 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||
ctx->hir_module, scc_hir_module_get_value(
|
||||
ctx->hir_module, value->data.conv.operand)
|
||||
->type);
|
||||
int from_size = scc_hir_module_type_size(ctx->hir_module, src_type);
|
||||
int from_size_bits =
|
||||
scc_hir_module_type_size(ctx->hir_module, src_type);
|
||||
scc_lir_instr_t instr = {.op = SCC_LIR_EXTEND,
|
||||
.size = size,
|
||||
.size_bits = size_bits,
|
||||
.ext = conv_ext,
|
||||
.to = SCC_LIR_VREG(dst_vreg),
|
||||
.arg0 = src,
|
||||
.metadata.extend.from_size = from_size};
|
||||
.metadata.extend.from_size_bits =
|
||||
from_size_bits};
|
||||
scc_lir_builder_add_instr(ctx, &instr);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -135,7 +135,7 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
||||
scc_tree_dump_node(td, "%s", op_to_string(ins->op));
|
||||
|
||||
// 输出宽度和扩展标志
|
||||
dump_size_ext(ctx, ins->size, ins->ext);
|
||||
dump_size_ext(ctx, ins->size_bits, ins->ext);
|
||||
scc_tree_dump_append(td, " ");
|
||||
|
||||
switch (ins->op) {
|
||||
@@ -165,8 +165,8 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
||||
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);
|
||||
ins->metadata.alloca.size_bits,
|
||||
ins->metadata.alloca.align_bits);
|
||||
dump_operand(ctx, &ins->to);
|
||||
break;
|
||||
case SCC_LIR_EXTEND: {
|
||||
@@ -182,8 +182,8 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
||||
ext_name = "ext";
|
||||
break;
|
||||
}
|
||||
scc_tree_dump_append_fmt(td, "%s(%d<-%d) ", ext_name, ins->size * 8,
|
||||
ins->metadata.extend.from_size * 8);
|
||||
scc_tree_dump_append_fmt(td, "%s(%d<-%d) ", ext_name, ins->size_bits,
|
||||
ins->metadata.extend.from_size_bits);
|
||||
dump_operand(ctx, &ins->to);
|
||||
scc_tree_dump_append(td, " <- ");
|
||||
dump_operand(ctx, &ins->arg0);
|
||||
|
||||
@@ -52,7 +52,7 @@ static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id, u8 size) {
|
||||
o.mem.scale = 1;
|
||||
o.mem.disp.displacement = slot_id;
|
||||
o.mem.disp.displacement_bits = 0;
|
||||
o.size = size;
|
||||
o.size_bits = size;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ typedef struct scc_mir_instr {
|
||||
int opcode;
|
||||
union {
|
||||
struct {
|
||||
int size;
|
||||
int align;
|
||||
int size_bits;
|
||||
int align_bits;
|
||||
int vreg;
|
||||
} alloc;
|
||||
} data;
|
||||
|
||||
@@ -98,34 +98,34 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func,
|
||||
scc_tree_dump_append(td, "<?>");
|
||||
break;
|
||||
}
|
||||
scc_tree_dump_append_fmt(td, ".(%zu)", op->size);
|
||||
scc_tree_dump_append_fmt(td, ".(%zu)", op->size_bits);
|
||||
}
|
||||
}
|
||||
|
||||
// 将 LIR 值转换为 x86 操作数
|
||||
scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
|
||||
const scc_lir_val_t *val,
|
||||
u8 size) {
|
||||
u8 size_bits) {
|
||||
scc_x86_operand_value_t op = {0};
|
||||
switch (val->kind) {
|
||||
case SCC_LIR_INSTR_KIND_NONE:
|
||||
op.kind = SCC_X86_OPR_NONE;
|
||||
break;
|
||||
case SCC_LIR_INSTR_KIND_VREG:
|
||||
op = scc_x86_op_vreg(val->data.reg, size);
|
||||
op = scc_x86_op_vreg(val->data.reg, size_bits);
|
||||
int id = 0;
|
||||
int ret = scc_mir_vreg_lookup(isel->func, val->data.reg, &id);
|
||||
if (ret > 0) {
|
||||
op = scc_x86_op_preg(id, size);
|
||||
op = scc_x86_op_preg(id, size_bits);
|
||||
} else if (ret < 0) {
|
||||
op = scc_x86_op_slot(id, size);
|
||||
op = scc_x86_op_slot(id, size_bits);
|
||||
}
|
||||
break;
|
||||
case SCC_LIR_INSTR_KIND_IMM:
|
||||
op = scc_x86_op_imm(val->data.imm.data.digit, size);
|
||||
op = scc_x86_op_imm(val->data.imm.data.digit, size_bits);
|
||||
break;
|
||||
case SCC_LIR_INSTR_KIND_FIMM:
|
||||
op = scc_x86_op_imm(*(i64 *)&val->data.fimm, size);
|
||||
op = scc_x86_op_imm(*(i64 *)&val->data.fimm, size_bits);
|
||||
break;
|
||||
case SCC_LIR_INSTR_KIND_SYMBOL:
|
||||
op = scc_x86_op_reloc_global_relrip(val->data.symbol, 0);
|
||||
@@ -133,7 +133,7 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
|
||||
case SCC_LIR_INSTR_KIND_ARG:
|
||||
Assert(isel->abi_lowering.lower_param);
|
||||
isel->abi_lowering.lower_param(isel, val, &op);
|
||||
op.size = size;
|
||||
op.size_bits = size_bits;
|
||||
break;
|
||||
default:
|
||||
Panic("unsupported lir instr kind %d", val->kind);
|
||||
@@ -144,15 +144,15 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
|
||||
|
||||
// 虚拟临时寄存器分配(简单递增)
|
||||
static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel,
|
||||
int size) {
|
||||
return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func), size);
|
||||
int size_bits) {
|
||||
return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func), size_bits);
|
||||
}
|
||||
|
||||
/* 确保操作数为寄存器: IMM → 加载到临时虚拟寄存器 */
|
||||
static scc_x86_operand_value_t ensure_reg(scc_x86_64_isel_t *isel,
|
||||
scc_x86_operand_value_t op) {
|
||||
if (op.kind == SCC_X86_OPR_IMM) {
|
||||
scc_x86_operand_value_t tmp = new_vreg_temp(isel, op.size);
|
||||
scc_x86_operand_value_t tmp = new_vreg_temp(isel, op.size_bits);
|
||||
scc_x86_emit_move(isel, tmp, op);
|
||||
return tmp;
|
||||
}
|
||||
@@ -202,8 +202,8 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
|
||||
scc_x86_operand_value_t src1) {
|
||||
emit_copy_if_needed(isel, dst, src0);
|
||||
|
||||
Assert(src0.size == src1.size);
|
||||
int is_8b = src0.size == 1;
|
||||
Assert(src0.size_bits == src1.size_bits);
|
||||
// int is_8b = src0.size_bits == 8;
|
||||
int is_imm = src1.kind == SCC_X86_OPR_IMM;
|
||||
scc_x86_iform_t opcode;
|
||||
switch (op) {
|
||||
@@ -242,7 +242,7 @@ 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_operand_value_t tmp_reg = dst;
|
||||
if (dst.kind != SCC_X86_OPR_REG) {
|
||||
tmp_reg = new_vreg_temp(isel, src.size);
|
||||
tmp_reg = new_vreg_temp(isel, src.size_bits);
|
||||
}
|
||||
scc_x86_emit_load_to_vec(&isel->instrs, tmp_reg, src);
|
||||
if (dst.kind != SCC_X86_OPR_REG) {
|
||||
@@ -253,7 +253,7 @@ void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||
void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||
scc_x86_operand_value_t src) {
|
||||
if (src.kind == SCC_X86_OPR_MEM) {
|
||||
scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src.size);
|
||||
scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src.size_bits);
|
||||
scc_x86_emit_load(isel, tmp_reg, src);
|
||||
src = tmp_reg;
|
||||
}
|
||||
@@ -264,8 +264,8 @@ 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;
|
||||
Assert(size == 8);
|
||||
usize size_bits = dst.size_bits;
|
||||
Assert(size_bits == 64);
|
||||
// 前置断言:dst 必须是寄存器
|
||||
Assert(dst.kind == SCC_X86_OPR_REG);
|
||||
// scale 必须是 1,2,4,8 之一
|
||||
@@ -279,11 +279,11 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||
} break;
|
||||
case SCC_X86_OPR_RELOC: {
|
||||
Assert(base.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL);
|
||||
base_reg = new_vreg_temp(isel, 8);
|
||||
base_reg = new_vreg_temp(isel, 64);
|
||||
scc_x86_emit_move(isel, base_reg, base);
|
||||
} break;
|
||||
case SCC_X86_OPR_MEM: {
|
||||
base_reg = new_vreg_temp(isel, 8);
|
||||
base_reg = new_vreg_temp(isel, 64);
|
||||
scc_x86_emit_move(isel, base_reg, base);
|
||||
} break;
|
||||
default: {
|
||||
@@ -298,15 +298,15 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||
} break;
|
||||
case SCC_X86_OPR_RELOC: {
|
||||
Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL);
|
||||
index_reg = new_vreg_temp(isel, 8);
|
||||
index_reg = new_vreg_temp(isel, 64);
|
||||
scc_x86_emit_move(isel, index_reg, index);
|
||||
} break;
|
||||
case SCC_X86_OPR_MEM: {
|
||||
index_reg = new_vreg_temp(isel, 8);
|
||||
index_reg = new_vreg_temp(isel, 64);
|
||||
scc_x86_emit_move(isel, index_reg, index);
|
||||
} break;
|
||||
case SCC_X86_OPR_IMM: {
|
||||
index_reg = new_vreg_temp(isel, index.size);
|
||||
index_reg = new_vreg_temp(isel, index.size_bits);
|
||||
scc_x86_emit_move(isel, index_reg, index);
|
||||
} break;
|
||||
default: {
|
||||
@@ -320,18 +320,18 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
||||
.scale = scale,
|
||||
.disp.displacement = offset,
|
||||
.disp.displacement_bits = 8},
|
||||
size);
|
||||
size_bits);
|
||||
scc_x86_emit_move(isel, dst, mem_op);
|
||||
}
|
||||
|
||||
static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
u8 size = instr->size;
|
||||
u8 size_bits = instr->size_bits;
|
||||
scc_x86_operand_value_t dst =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->to, size);
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->to, size_bits);
|
||||
scc_x86_operand_value_t src0 =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->arg0, size);
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->arg0, size_bits);
|
||||
scc_x86_operand_value_t src1 =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->arg1, size);
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->arg1, size_bits);
|
||||
|
||||
switch (instr->op) {
|
||||
/* ---- 数据移动 ---- */
|
||||
@@ -373,7 +373,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
case SCC_LIR_MUL:
|
||||
emit_copy_if_needed(isel, dst, src0);
|
||||
if (src1.kind == SCC_X86_OPR_IMM) {
|
||||
scc_x86_operand_value_t op = new_vreg_temp(isel, size);
|
||||
scc_x86_operand_value_t op = new_vreg_temp(isel, size_bits);
|
||||
scc_x86_emit_move(isel, op, src1);
|
||||
src1 = op;
|
||||
}
|
||||
@@ -401,7 +401,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
}
|
||||
add_instr_2(isel, iform, dst, src1);
|
||||
} else {
|
||||
scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL, 1);
|
||||
scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL, 8);
|
||||
scc_x86_emit_move(isel, cl, src1);
|
||||
scc_x86_iform_t iform;
|
||||
switch (instr->op) {
|
||||
@@ -426,14 +426,16 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
case SCC_LIR_DIV_U:
|
||||
case SCC_LIR_REM_S:
|
||||
case SCC_LIR_REM_U: {
|
||||
scc_x86_operand_value_t rax = scc_x86_op_preg(SCC_X86_REG_RAX, size);
|
||||
scc_x86_operand_value_t rdx = scc_x86_op_preg(SCC_X86_REG_RDX, size);
|
||||
scc_x86_operand_value_t rax =
|
||||
scc_x86_op_preg(SCC_X86_REG_RAX, size_bits);
|
||||
scc_x86_operand_value_t rdx =
|
||||
scc_x86_op_preg(SCC_X86_REG_RDX, size_bits);
|
||||
|
||||
if (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) {
|
||||
if (size < 8) {
|
||||
if (size_bits < 64) {
|
||||
// TODO 可能需要在lir进行size对齐
|
||||
scc_x86_operand_value_t rax64 =
|
||||
scc_x86_op_preg(SCC_X86_REG_RAX, 8);
|
||||
scc_x86_op_preg(SCC_X86_REG_RAX, 64);
|
||||
add_instr_2(isel, SCC_X86_IFORM_MOVSXD_GPRV_GPRZ, rax64, src0);
|
||||
} else {
|
||||
scc_x86_emit_move(isel, rax, src0);
|
||||
@@ -441,7 +443,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
add_instr_0(isel, SCC_X86_IFORM_CQO);
|
||||
} else {
|
||||
scc_x86_emit_move(isel, rax, src0);
|
||||
scc_x86_operand_value_t zero = scc_x86_op_imm(0, size);
|
||||
scc_x86_operand_value_t zero = scc_x86_op_imm(0, size_bits);
|
||||
scc_x86_emit_move(isel, rdx, zero);
|
||||
}
|
||||
|
||||
@@ -451,7 +453,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
: SCC_X86_IFORM_DIV_GPRV;
|
||||
scc_x86_operand_value_t divisor = src1;
|
||||
if (src1.kind == SCC_X86_OPR_IMM) {
|
||||
divisor = new_vreg_temp(isel, size);
|
||||
divisor = new_vreg_temp(isel, size_bits);
|
||||
scc_x86_emit_move(isel, divisor, src1);
|
||||
}
|
||||
add_instr_1(isel, div_if, divisor);
|
||||
@@ -464,33 +466,34 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
|
||||
/* ---- 比较指令 ---- */
|
||||
case SCC_LIR_CMP: {
|
||||
Assert(src0.size == src1.size);
|
||||
Assert(src0.size_bits == src1.size_bits);
|
||||
if (src0.kind == SCC_X86_OPR_IMM) {
|
||||
scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src0.size);
|
||||
scc_x86_operand_value_t tmp_reg =
|
||||
new_vreg_temp(isel, src0.size_bits);
|
||||
scc_x86_emit_move(isel, tmp_reg, src0);
|
||||
src0 = tmp_reg;
|
||||
}
|
||||
if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM)
|
||||
// SCC_X86_IFORM_CMP_GPR8_IMMB_82R7 历史遗留指令在amd64中已不再使用
|
||||
add_instr_2(isel,
|
||||
src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_IMMB_80R7
|
||||
: SCC_X86_IFORM_CMP_GPRV_IMMZ,
|
||||
src0.size_bits == 8 ? SCC_X86_IFORM_CMP_GPR8_IMMB_80R7
|
||||
: SCC_X86_IFORM_CMP_GPRV_IMMZ,
|
||||
src0, src1);
|
||||
else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1))
|
||||
add_instr_2(isel,
|
||||
src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_GPR8_3A
|
||||
: SCC_X86_IFORM_CMP_GPRV_GPRV_3B,
|
||||
src0.size_bits == 8 ? SCC_X86_IFORM_CMP_GPR8_GPR8_3A
|
||||
: SCC_X86_IFORM_CMP_GPRV_GPRV_3B,
|
||||
src0, src1);
|
||||
else
|
||||
UNREACHABLE();
|
||||
|
||||
scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond);
|
||||
add_instr_1(isel, setcc, dst);
|
||||
if (size > 1) {
|
||||
scc_x86_operand_value_t one = scc_x86_op_imm(1, size);
|
||||
if (size_bits > 8) {
|
||||
scc_x86_operand_value_t one = scc_x86_op_imm(1, size_bits);
|
||||
add_instr_2(isel,
|
||||
src1.size == 1 ? SCC_X86_IFORM_AND_GPR8_IMMB_82R4
|
||||
: SCC_X86_IFORM_AND_GPRV_IMMZ,
|
||||
src1.size_bits == 8 ? SCC_X86_IFORM_AND_GPR8_IMMB_82R4
|
||||
: SCC_X86_IFORM_AND_GPRV_IMMZ,
|
||||
dst, one);
|
||||
}
|
||||
} break;
|
||||
@@ -501,11 +504,11 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
scc_x86_op_reloc_block(instr->metadata.br.true_target, 0);
|
||||
scc_x86_operand_value_t false_bb =
|
||||
scc_x86_op_reloc_block(instr->metadata.br.false_target, 0);
|
||||
true_bb.size = instr->size;
|
||||
false_bb.size = instr->size;
|
||||
true_bb.size_bits = instr->size_bits;
|
||||
false_bb.size_bits = instr->size_bits;
|
||||
add_instr_2(isel,
|
||||
src0.size == 1 ? SCC_X86_IFORM_TEST_GPR8_GPR8
|
||||
: SCC_X86_IFORM_TEST_GPRV_GPRV,
|
||||
src0.size_bits == 8 ? SCC_X86_IFORM_TEST_GPR8_GPR8
|
||||
: SCC_X86_IFORM_TEST_GPRV_GPRV,
|
||||
src0, src0);
|
||||
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb);
|
||||
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb);
|
||||
@@ -520,49 +523,50 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
/* ---- 栈分配 ---- */
|
||||
case SCC_LIR_ALLOCA: {
|
||||
scc_x86_operand_value_t op =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->to, instr->size);
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->to, instr->size_bits);
|
||||
scc_mir_x86_instr_t x86instr;
|
||||
x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA;
|
||||
Assert(op.kind == SCC_X86_OPR_REG);
|
||||
x86instr.instr.data.alloc.vreg = op.reg;
|
||||
x86instr.instr.data.alloc.size = instr->metadata.alloca.size_bytes;
|
||||
x86instr.instr.data.alloc.align = instr->metadata.alloca.align_bytes;
|
||||
x86instr.instr.data.alloc.size_bits = instr->metadata.alloca.size_bits;
|
||||
x86instr.instr.data.alloc.align_bits =
|
||||
instr->metadata.alloca.align_bits;
|
||||
scc_vec_push(isel->instrs, x86instr);
|
||||
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
|
||||
instr->metadata.alloca.size_bits,
|
||||
instr->metadata.alloca.align_bits
|
||||
? instr->metadata.alloca.align_bits
|
||||
: 8);
|
||||
break;
|
||||
}
|
||||
|
||||
/* ---- 类型扩展 ---- */
|
||||
case SCC_LIR_EXTEND: {
|
||||
int from_size = instr->metadata.extend.from_size;
|
||||
int from_size_bits = instr->metadata.extend.from_size_bits;
|
||||
scc_x86_operand_value_t ext_src =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->arg0, from_size);
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->arg0, from_size_bits);
|
||||
ext_src = ensure_reg(isel, ext_src);
|
||||
|
||||
if (instr->ext == SCC_LIR_EXT_ZEXT) {
|
||||
if (from_size == 4) {
|
||||
if (from_size_bits == 32) {
|
||||
// 32→64: x86-64 写32位寄存器自动零扩展到64位
|
||||
scc_x86_emit_move(isel, dst, ext_src);
|
||||
} else {
|
||||
scc_x86_iform_t iform = (from_size == 1)
|
||||
scc_x86_iform_t iform = (from_size_bits == 8)
|
||||
? SCC_X86_IFORM_MOVZX_GPRV_GPR8
|
||||
: SCC_X86_IFORM_MOVZX_GPRV_GPR16;
|
||||
add_instr_2(isel, iform, dst, ext_src);
|
||||
}
|
||||
} else if (instr->ext == SCC_LIR_EXT_SEXT) {
|
||||
scc_x86_iform_t iform;
|
||||
switch (from_size) {
|
||||
case 1:
|
||||
switch (from_size_bits) {
|
||||
case 8:
|
||||
iform = SCC_X86_IFORM_MOVSX_GPRV_GPR8;
|
||||
break;
|
||||
case 2:
|
||||
case 16:
|
||||
iform = SCC_X86_IFORM_MOVSX_GPRV_GPR16;
|
||||
break;
|
||||
case 4:
|
||||
case 32:
|
||||
iform = SCC_X86_IFORM_MOVSXD_GPRV_GPRZ;
|
||||
break;
|
||||
default:
|
||||
@@ -600,18 +604,18 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
|
||||
|
||||
// 将 dest 的地址放入 RDI
|
||||
scc_x86_operand_value_t dest_op =
|
||||
scc_x86_lir_val_to_mir_op(isel, &dest_val, 8);
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI, 8), dest_op);
|
||||
scc_x86_lir_val_to_mir_op(isel, &dest_val, 64);
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI, 64), dest_op);
|
||||
|
||||
// 将 src 的地址放入 RSI
|
||||
scc_x86_operand_value_t src_op =
|
||||
scc_x86_lir_val_to_mir_op(isel, &src_val, 8);
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI, 8), src_op);
|
||||
scc_x86_lir_val_to_mir_op(isel, &src_val, 64);
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI, 64), src_op);
|
||||
|
||||
// 长度处理保持不变...
|
||||
scc_x86_operand_value_t len_op =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size, 8);
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX, 8), len_op);
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size, 64);
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX, 64), len_op);
|
||||
|
||||
add_instr_0(isel, SCC_X86_IFORM_REP_MOVSB);
|
||||
} break;
|
||||
@@ -632,9 +636,9 @@ static void sel_func(const scc_lir_module_t *lir_module,
|
||||
scc_lir_instr_vec_t *instrs = SCC_LIR_BBLOCK_VALUES(bb);
|
||||
scc_vec_foreach(*instrs, i) {
|
||||
scc_lir_instr_t *ins = &scc_vec_at(*instrs, i);
|
||||
// HACK BR size
|
||||
// HACK BR size_bits
|
||||
if (ins->op == SCC_LIR_BR) {
|
||||
ins->size = scc_vec_at(*instrs, i - 1).size;
|
||||
ins->size_bits = scc_vec_at(*instrs, i - 1).size_bits;
|
||||
}
|
||||
sel_mir(isel, ins);
|
||||
}
|
||||
|
||||
@@ -3,63 +3,64 @@
|
||||
static inline scc_x86_iform_t
|
||||
scc_mir_x86_mov_reg_mem(scc_x86_operand_value_t op0,
|
||||
scc_x86_operand_value_t op1) {
|
||||
Assert(op0.size == op1.size);
|
||||
Assert(op0.size_bits == op1.size_bits);
|
||||
Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_MEM);
|
||||
return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_MEMB
|
||||
: SCC_X86_IFORM_MOV_GPRV_MEMV;
|
||||
return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_GPR8_MEMB
|
||||
: SCC_X86_IFORM_MOV_GPRV_MEMV;
|
||||
}
|
||||
static inline scc_x86_iform_t
|
||||
scc_mir_x86_mov_reg_reg(scc_x86_operand_value_t op0,
|
||||
scc_x86_operand_value_t op1) {
|
||||
Assert(op0.size == op1.size);
|
||||
Assert(op0.size_bits == op1.size_bits);
|
||||
Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_REG);
|
||||
return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A
|
||||
: SCC_X86_IFORM_MOV_GPRV_GPRV_8B;
|
||||
return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A
|
||||
: SCC_X86_IFORM_MOV_GPRV_GPRV_8B;
|
||||
}
|
||||
|
||||
static inline scc_x86_iform_t
|
||||
scc_mir_x86_mov_reg_imm(scc_x86_operand_value_t op0,
|
||||
scc_x86_operand_value_t op1) {
|
||||
Assert(op0.size == op1.size);
|
||||
Assert(op0.size_bits == op1.size_bits);
|
||||
Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_IMM);
|
||||
return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0
|
||||
: SCC_X86_IFORM_MOV_GPRV_IMMV;
|
||||
return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0
|
||||
: SCC_X86_IFORM_MOV_GPRV_IMMV;
|
||||
}
|
||||
static inline scc_x86_iform_t
|
||||
scc_mir_x86_mov_mem_reg(scc_x86_operand_value_t op0,
|
||||
scc_x86_operand_value_t op1) {
|
||||
Assert(op0.size == op1.size);
|
||||
Assert(op0.size_bits == op1.size_bits);
|
||||
Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_REG);
|
||||
return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_GPR8
|
||||
: SCC_X86_IFORM_MOV_MEMV_GPRV;
|
||||
return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_MEMB_GPR8
|
||||
: SCC_X86_IFORM_MOV_MEMV_GPRV;
|
||||
}
|
||||
|
||||
static inline scc_x86_iform_t
|
||||
scc_mir_x86_mov_mem_imm(scc_x86_operand_value_t op0,
|
||||
scc_x86_operand_value_t op1) {
|
||||
Assert(op0.size == op1.size);
|
||||
Assert(op0.size_bits == op1.size_bits);
|
||||
Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_IMM);
|
||||
return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_IMMB
|
||||
: SCC_X86_IFORM_MOV_MEMV_IMMZ;
|
||||
return op0.size_bits == 8 ? SCC_X86_IFORM_MOV_MEMB_IMMB
|
||||
: SCC_X86_IFORM_MOV_MEMV_IMMZ;
|
||||
}
|
||||
|
||||
static inline u8 get_op_size(scc_x86_operand_value_t op, cbool get_value) {
|
||||
static inline u8 get_op_size_bits(scc_x86_operand_value_t op, cbool get_value) {
|
||||
if (get_value) {
|
||||
return op.size;
|
||||
return op.size_bits;
|
||||
}
|
||||
if (op.kind == SCC_X86_OPR_MEM) {
|
||||
return 8;
|
||||
return 64;
|
||||
}
|
||||
if (op.kind == SCC_X86_OPR_RELOC && op.reloc.kind == SCC_X86_OPR_MEM) {
|
||||
return 8;
|
||||
return 64;
|
||||
}
|
||||
return op.size;
|
||||
return op.size_bits;
|
||||
}
|
||||
|
||||
void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
scc_x86_operand_value_t dst,
|
||||
scc_x86_operand_value_t src) {
|
||||
u8 dst_size = get_op_size(dst, false);
|
||||
u8 src_size = get_op_size(src, false);
|
||||
u8 dst_size = get_op_size_bits(dst, false);
|
||||
u8 src_size = get_op_size_bits(src, false);
|
||||
if (dst_size != src_size) {
|
||||
LOG_FATAL("Mismatched register sizes for move %d != %d", dst_size,
|
||||
src_size);
|
||||
@@ -75,7 +76,7 @@ void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
} else if (src.kind == SCC_X86_OPR_MEM ||
|
||||
(src.kind == SCC_X86_OPR_RELOC &&
|
||||
src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) {
|
||||
Assert(dst_size == 8);
|
||||
Assert(dst_size == 64);
|
||||
scc_mir_x86_instr_2(&ins, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src,
|
||||
scc_pos_create());
|
||||
} else {
|
||||
@@ -100,8 +101,8 @@ void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
scc_x86_operand_value_t dst,
|
||||
scc_x86_operand_value_t src_addr) {
|
||||
u8 dst_size = get_op_size(dst, false);
|
||||
u8 src_addr_size = get_op_size(src_addr, true);
|
||||
u8 dst_size = get_op_size_bits(dst, false);
|
||||
u8 src_addr_size = get_op_size_bits(src_addr, true);
|
||||
if (dst_size != src_addr_size) {
|
||||
LOG_FATAL("Mismatched sizes for load %d != %d", dst_size,
|
||||
src_addr_size);
|
||||
@@ -117,9 +118,9 @@ void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
.index = SCC_X86_REG_INVALID,
|
||||
.scale = 1,
|
||||
.disp.displacement = 0,
|
||||
.disp.displacement_bits = src_addr_size * 8,
|
||||
.disp.displacement_bits = src_addr_size,
|
||||
},
|
||||
.size = src_addr_size,
|
||||
.size_bits = src_addr_size,
|
||||
};
|
||||
} else if (src_addr.kind == SCC_X86_OPR_MEM) {
|
||||
mem_op = src_addr;
|
||||
@@ -135,8 +136,8 @@ void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
scc_x86_operand_value_t dst_addr,
|
||||
scc_x86_operand_value_t src) {
|
||||
u8 dst_addr_size = get_op_size(dst_addr, true);
|
||||
u8 src_size = get_op_size(src, false);
|
||||
u8 dst_addr_size = get_op_size_bits(dst_addr, true);
|
||||
u8 src_size = get_op_size_bits(src, false);
|
||||
if (dst_addr_size != src_size) {
|
||||
LOG_FATAL("Mismatched sizes for store %d != %d", dst_addr_size,
|
||||
src_size);
|
||||
@@ -151,9 +152,9 @@ void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec,
|
||||
.index = SCC_X86_REG_INVALID,
|
||||
.scale = 1,
|
||||
.disp.displacement = 0,
|
||||
.disp.displacement_bits = dst_addr_size * 8,
|
||||
.disp.displacement_bits = dst_addr_size,
|
||||
},
|
||||
.size = dst_addr_size,
|
||||
.size_bits = dst_addr_size,
|
||||
};
|
||||
} else if (dst_addr.kind == SCC_X86_OPR_MEM) {
|
||||
mem_op = dst_addr;
|
||||
|
||||
@@ -179,7 +179,7 @@ static void x86_alloc_iter_begin(scc_reg_alloc_iter_t *iter) {
|
||||
}
|
||||
|
||||
static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg,
|
||||
int *out_size,
|
||||
int *out_size_bits,
|
||||
scc_reg_op_access_t *out_access) {
|
||||
const scc_mir_x86_instr_t *ins = (const scc_mir_x86_instr_t *)iter->instr;
|
||||
scc_x86_iform_t opcode = ins->x86_instr.opcode;
|
||||
@@ -191,7 +191,7 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg,
|
||||
scc_reg_op_access_t base_access =
|
||||
get_operand_access(opcode, iter->op_idx);
|
||||
|
||||
*out_size = op->size;
|
||||
*out_size_bits = op->size_bits;
|
||||
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);
|
||||
@@ -204,7 +204,7 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg,
|
||||
continue;
|
||||
} else if (op->kind == SCC_X86_OPR_MEM) {
|
||||
const scc_x86_mem_t *mem = &op->mem;
|
||||
*out_size = 8;
|
||||
*out_size_bits = 64;
|
||||
// 子索引 0: 基址寄存器
|
||||
if (iter->op_sub_idx == 0) {
|
||||
if (mem->base != SCC_X86_REG_INVALID &&
|
||||
|
||||
@@ -23,7 +23,7 @@ void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func,
|
||||
switch (instr->opcode) {
|
||||
case SCC_MIR_PSEUDO_ALLOCA:
|
||||
scc_tree_dump_append_fmt(td, " alloca(%d)",
|
||||
instr->data.alloc.size);
|
||||
instr->data.alloc.size_bits);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -41,7 +41,7 @@ static void frame_layout_impl(scc_frame_layout_t *ctx,
|
||||
.index = SCC_X86_REG_INVALID,
|
||||
.scale = 1,
|
||||
},
|
||||
op->size);
|
||||
op->size_bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ static void frame_layout_impl(scc_frame_layout_t *ctx,
|
||||
.index = SCC_X86_REG_INVALID,
|
||||
.scale = 1,
|
||||
},
|
||||
op->size);
|
||||
op->size_bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ static void prologue(scc_mir_instr_vec_t *userdata,
|
||||
/// FILL to shadow space
|
||||
}
|
||||
|
||||
u8 size = 8;
|
||||
u8 size = 64;
|
||||
// sub rsp, frame_size
|
||||
if (frame_size > 0) {
|
||||
scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_SUB_GPRV_IMMZ,
|
||||
@@ -141,7 +141,7 @@ static void epilogue(scc_mir_instr_vec_t *userdata,
|
||||
*/
|
||||
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
|
||||
int frame_size = meta->frame_size;
|
||||
u8 size = 8;
|
||||
u8 size = 64;
|
||||
// add rsp, frame_size
|
||||
if (frame_size > 0) {
|
||||
scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_ADD_GPRV_IMMZ,
|
||||
@@ -178,7 +178,7 @@ https://learn.microsoft.com/zh-cn/cpp/build/x64-calling-convention?view=msvc-180
|
||||
static void lower_call(void *userdata, const scc_lir_instr_t *instr) {
|
||||
scc_x86_64_isel_t *isel = userdata;
|
||||
|
||||
u8 size = 8;
|
||||
u8 size = 64;
|
||||
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(isel->func);
|
||||
int call_stack_size = instr->metadata.call.arg_count * 8;
|
||||
if (meta->frame_size < call_stack_size) {
|
||||
@@ -233,7 +233,7 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) {
|
||||
Panic("unhandled opcode");
|
||||
}
|
||||
|
||||
int ret_size = instr->size;
|
||||
int ret_size = instr->size_bits;
|
||||
scc_x86_operand_value_t ret_reg =
|
||||
scc_x86_lir_val_to_mir_op(isel, &instr->to, ret_size);
|
||||
if (ret_reg.kind != SCC_X86_OPR_NONE && ret_size != 0) {
|
||||
@@ -265,7 +265,7 @@ static void lower_param(void *userdata, const scc_lir_val_t *val,
|
||||
void *out_op) {
|
||||
scc_x86_operand_value_t *out = out_op;
|
||||
Assert(val->kind == SCC_LIR_INSTR_KIND_ARG);
|
||||
u8 size = 8;
|
||||
u8 size = 64;
|
||||
switch (val->data.arg) {
|
||||
case 0:
|
||||
*out = scc_x86_op_preg(SCC_X86_REG_RCX, size);
|
||||
@@ -292,10 +292,10 @@ static void lower_ret(void *userdata, const scc_lir_instr_t *instr) {
|
||||
scc_x86_64_isel_t *isel = userdata;
|
||||
scc_lir_val_t ret_val = instr->metadata.ret_val;
|
||||
u8 size = 0;
|
||||
if (instr->size) {
|
||||
size = instr->size;
|
||||
if (instr->size_bits) {
|
||||
size = instr->size_bits;
|
||||
} else {
|
||||
size = 8;
|
||||
size = 64;
|
||||
}
|
||||
if (ret_val.kind != SCC_LIR_INSTR_KIND_NONE) {
|
||||
scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RAX, size),
|
||||
|
||||
Reference in New Issue
Block a user