diff --git a/libs/abi/cbuild.toml b/libs/abi/cbuild.toml new file mode 100644 index 0000000..44eaa40 --- /dev/null +++ b/libs/abi/cbuild.toml @@ -0,0 +1,9 @@ +[package] +name = "scc_abi" +version = "0.1.0" +authors = [] +description = "" + +# dependencies = [] +# features = {} +# default_features = [] diff --git a/libs/abi/include/scc_type_abi.h b/libs/abi/include/scc_type_abi.h new file mode 100644 index 0000000..1829d5b --- /dev/null +++ b/libs/abi/include/scc_type_abi.h @@ -0,0 +1,105 @@ +/** + * @file scc_abi_type.h + * @brief 目标无关的类型布局描述接口 + * @note 本模块仅定义接口。 + */ + +#ifndef __SCC_ABI_TYPE_H__ +#define __SCC_ABI_TYPE_H__ + +#include + +/** + * @brief ABI 基础类型类别枚举。 + * + * 用于快速查询目标预定义的基本类型属性。复杂类型(指针、数组、结构体) + * 通过组合与递归计算。 + */ +typedef enum scc_abi_base_type_kind { + SCC_ABI_TYPE_VOID, + SCC_ABI_TYPE_CHAR, + SCC_ABI_TYPE_I_CHAR, + SCC_ABI_TYPE_U_CHAR, + SCC_ABI_TYPE_I_SHORT, + SCC_ABI_TYPE_U_SHORT, + SCC_ABI_TYPE_I_INT, + SCC_ABI_TYPE_U_INT, + SCC_ABI_TYPE_I_LONG, + SCC_ABI_TYPE_U_LONG, + SCC_ABI_TYPE_I_LONG_LONG, + SCC_ABI_TYPE_U_LONG_LONG, + SCC_ABI_TYPE_PTR, + SCC_ABI_TYPE_FLOAT, + SCC_ABI_TYPE_DOUBLE, + SCC_ABI_TYPE_USIZE, + SCC_ABI_TYPE_ISIZE, + /* 可扩展:I128, F16, F128, VECTOR, ... */ +} scc_abi_base_type_kind_t; + +/** + * @brief 单个类型的布局信息。 + */ +typedef struct scc_abi_type_layout { + int size; /**< 类型占用的字节数 */ + int alignment; /**< 类型的对齐要求(字节边界) */ +} scc_abi_type_layout_t; + +typedef struct { + scc_abi_base_type_kind_t kind; + scc_abi_type_layout_t layout; +} scc_abi_base_type_impl_t; +#define SCC_ABI_BASE_TYPE_IMPL(type, bytes_size, alians) \ + [type] = { \ + .kind = type, \ + .layout.size = bytes_size, \ + .layout.alignment = alians, \ + } + +/** + * @brief 单个结构体字段的布局信息。 + * 由目标布局算法填充,用于 IR 的 getelementptr 常量索引计算。 + */ +typedef struct scc_abi_field_layout { + int offset; /**< 字段相对于结构体基址的字节偏移 */ + int size; /**< 字段自身大小 */ + int alignment; /**< 字段的对齐要求 */ +} scc_abi_field_layout_t; + +typedef SCC_VEC(scc_abi_field_layout_t) scc_abi_field_layout_vec_t; + +/** + * @brief 获取基本类型的布局信息。 + * + * 目标必须实现此函数,为每个 scc_abi_base_type_kind_t 返回正确的 + * size/alignment。 + * + * @param kind 基本类型类别 + * @param layout 输出参数,存放布局信息 + * @return 成功返回 0,若 kind 不支持则返回 -1 + */ +static inline void +scc_abi_get_base_type_layout(const scc_abi_base_type_impl_t *impls, + scc_abi_base_type_kind_t kind, + scc_abi_type_layout_t *layout) { + if (impls[kind].kind != kind) + Panic("invalid base type kind"); + *layout = impls[kind].layout; +} + +typedef struct scc_abi_type_calc scc_abi_type_calc_t; + +void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, + scc_abi_type_layout_t *layout); + +typedef struct scc_abi_type_calc { + void *ctx; + const scc_abi_base_type_impl_t *impls; + /// @brief 可以是系统内置的结构,比如 struct int128_t + void (*compute_type_layout)(const scc_abi_type_calc_t *ctx, void *type, + scc_abi_type_layout_t *layout); + /// @brief + void (*compute_field_layout)(const scc_abi_type_calc_t *ctx, void *type, + scc_abi_field_layout_vec_t *field_layouts); +} scc_abi_type_calc_t; + +#endif /* __SCC_ABI_TYPE_H__ */ diff --git a/libs/abi/include/target/scc_abi_dummy.h b/libs/abi/include/target/scc_abi_dummy.h new file mode 100644 index 0000000..aa17d66 --- /dev/null +++ b/libs/abi/include/target/scc_abi_dummy.h @@ -0,0 +1,4 @@ +#ifndef __SCC_ABI_DUMMY_H__ +#define __SCC_ABI_DUMMY_H__ + +#endif /* __SCC_ABI_DUMMY_H__ */ diff --git a/libs/abi/include/target/scc_abi_win_x64_pc.h b/libs/abi/include/target/scc_abi_win_x64_pc.h new file mode 100644 index 0000000..95d79c7 --- /dev/null +++ b/libs/abi/include/target/scc_abi_win_x64_pc.h @@ -0,0 +1,40 @@ +#ifndef __SCC_ABI_WIN_X64_PC_H__ +#define __SCC_ABI_WIN_X64_PC_H__ +/** + * @brief Windows x64 ABI Type + * @details + * https://learn.microsoft.com/zh-cn/cpp/build/x64-software-conventions?view=msvc-180 + */ + +#include "../scc_type_abi.h" + +static const scc_abi_base_type_impl_t scc_abi_base_type_impls[] = { + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_VOID, 0, 0), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_CHAR, 1, 1), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_CHAR, 1, 1), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_CHAR, 1, 1), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_SHORT, 2, 2), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_SHORT, 2, 2), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_INT, 4, 4), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_INT, 4, 4), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_LONG, 4, 4), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_LONG, 4, 4), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_I_LONG_LONG, 8, 8), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_U_LONG_LONG, 8, 8), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_PTR, 8, 8), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_FLOAT, 4, 4), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_DOUBLE, 8, 8), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_USIZE, 8, 8), + SCC_ABI_BASE_TYPE_IMPL(SCC_ABI_TYPE_ISIZE, 8, 8), +}; + +static const scc_abi_type_calc_t scc_ast_abi_impl = { + .impls = scc_abi_base_type_impls, + .ctx = nullptr, + .compute_type_layout = scc_abi_compute_ast_type_layout, + .compute_field_layout = nullptr, +}; +#ifdef SCC_ABI_IMPLIMENT +#endif + +#endif /* __SCC_ABI_WIN_X64_PC_H__ */ diff --git a/libs/abi/src/scc_type_abi.c b/libs/abi/src/scc_type_abi.c new file mode 100644 index 0000000..46969d3 --- /dev/null +++ b/libs/abi/src/scc_type_abi.c @@ -0,0 +1,62 @@ +#include +#include +#include + +void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, + scc_abi_type_layout_t *layout) { + scc_ast_type_t *ast_type = type; + scc_abi_base_type_kind_t kind = SCC_ABI_TYPE_VOID; + switch (ast_type->builtin.type) { + case SCC_AST_BUILTIN_TYPE_VOID: + kind = SCC_ABI_TYPE_VOID; + case SCC_AST_BUILTIN_TYPE_CHAR: + kind = SCC_ABI_TYPE_CHAR; + break; + case SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR: + kind = SCC_ABI_TYPE_U_CHAR; + break; + case SCC_AST_BUILTIN_TYPE_SIGNED_CHAR: + kind = SCC_ABI_TYPE_I_CHAR; + break; + case SCC_AST_BUILTIN_TYPE_SHORT: + kind = SCC_ABI_TYPE_I_SHORT; + break; + case SCC_AST_BUILTIN_TYPE_SIGNED_SHORT: + kind = SCC_ABI_TYPE_I_SHORT; + break; + case SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT: + kind = SCC_ABI_TYPE_U_SHORT; + break; + case SCC_AST_BUILTIN_TYPE_INT: + kind = SCC_ABI_TYPE_I_INT; + break; + case SCC_AST_BUILTIN_TYPE_SIGNED_INT: + kind = SCC_ABI_TYPE_I_INT; + break; + case SCC_AST_BUILTIN_TYPE_UNSIGNED_INT: + kind = SCC_ABI_TYPE_U_INT; + break; + case SCC_AST_BUILTIN_TYPE_LONG: + kind = SCC_ABI_TYPE_I_LONG; + break; + case SCC_AST_BUILTIN_TYPE_SIGNED_LONG: + kind = SCC_ABI_TYPE_I_LONG; + break; + case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG: + kind = SCC_ABI_TYPE_U_LONG; + break; + case SCC_AST_BUILTIN_TYPE_LONG_LONG: + kind = SCC_ABI_TYPE_I_LONG_LONG; + break; + case SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG: + kind = SCC_ABI_TYPE_I_LONG_LONG; + break; + case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG: + kind = SCC_ABI_TYPE_U_LONG_LONG; + break; + default: + Panic("Unsupported AST type: %d", ast_type->builtin.type); + break; + } + scc_abi_get_base_type_layout(ctx->impls, kind, layout); +} diff --git a/libs/ast2ir/cbuild.toml b/libs/ast2ir/cbuild.toml index 7e7e21e..833cc97 100644 --- a/libs/ast2ir/cbuild.toml +++ b/libs/ast2ir/cbuild.toml @@ -7,6 +7,7 @@ description = "" dependencies = [ { name = "scc_ast", path = "../ast" }, { name = "scc_ir", path = "../ir" }, + { name = "scc_abi", path = "../abi" }, ] # features = {} # default_features = [] diff --git a/libs/ast2ir/include/abi/win_x64_type_abi.h b/libs/ast2ir/include/abi/win_x64_type_abi.h deleted file mode 100644 index 85b90cb..0000000 --- a/libs/ast2ir/include/abi/win_x64_type_abi.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef __SCC_WIN_X64_TYPE_ABI_H__ -#define __SCC_WIN_X64_TYPE_ABI_H__ - -#include "../scc_type_abi.h" - -/** - * @brief Windows x64 ABI Type - * @details - * https://learn.microsoft.com/zh-cn/cpp/build/x64-software-conventions?view=msvc-180 - */ -static const scc_type_abi_t scc_win_x64_type_abi[] = { - { - .ast_type = SCC_AST_BUILTIN_TYPE_UNKNOWN, - .ir_type = SCC_IR_TYPE_unknown, - .size = 0, - .alignment = 0, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_VOID, - .ir_type = SCC_IR_TYPE_void, - .size = 0, - .alignment = 0, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_BOOL, - .ir_type = SCC_IR_TYPE_u8, - .size = 1, - .alignment = 1, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_CHAR, - .ir_type = SCC_IR_TYPE_i8, - .size = 1, - .alignment = 1, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_SIGNED_CHAR, - .ir_type = SCC_IR_TYPE_i8, - .size = 1, - .alignment = 1, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR, - .ir_type = SCC_IR_TYPE_u8, - .size = 1, - .alignment = 1, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_SHORT, - .ir_type = SCC_IR_TYPE_i16, - .size = 2, - .alignment = 2, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_SIGNED_SHORT, - .ir_type = SCC_IR_TYPE_i16, - .size = 2, - .alignment = 2, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT, - .ir_type = SCC_IR_TYPE_u16, - .size = 2, - .alignment = 2, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_INT, - .ir_type = SCC_IR_TYPE_i32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_SIGNED_INT, - .ir_type = SCC_IR_TYPE_i32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_UNSIGNED_INT, - .ir_type = SCC_IR_TYPE_u32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_LONG, - .ir_type = SCC_IR_TYPE_i32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_SIGNED_LONG, - .ir_type = SCC_IR_TYPE_i32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG, - .ir_type = SCC_IR_TYPE_u32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_LONG_LONG, - .ir_type = SCC_IR_TYPE_i64, - .size = 8, - .alignment = 8, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG, - .ir_type = SCC_IR_TYPE_i64, - .size = 8, - .alignment = 8, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG, - .ir_type = SCC_IR_TYPE_i64, - .size = 8, - .alignment = 8, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_FLOAT, - .ir_type = SCC_IR_TYPE_f32, - .size = 4, - .alignment = 4, - }, - { - .ast_type = SCC_AST_BUILTIN_TYPE_DOUBLE, - .ir_type = SCC_IR_TYPE_f64, - .size = 8, - .alignment = 8, - }, - { - // nullptr - .ast_type = SCC_AST_BUILTIN_TYPE_UNKNOWN, - .ir_type = SCC_IR_TYPE_unknown, - .size = 0, - .alignment = 0, - }, -}; - -#endif /* __SCC_WIN_X64_TYPE_ABI_H__ */ diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index 8f15172..af37a01 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -8,19 +8,20 @@ typedef struct { scc_ir_builder_t builder; - scc_hashtable_t decl2ir_ref; ///< decl to ir_ref - scc_hashtable_t symtab; ///< symbol to ir_ref + scc_hashtable_t ast2ir_cache; ///< ast node to ir ref cache + scc_hashtable_t symtab; ///< symbol to ir_ref // scc_strpool_t strpool; ///< string pool - const scc_type_abi_t *abi; + const scc_abi_type_calc_t *abi; } scc_ast2ir_ctx_t; -void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi, +void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, scc_ir_cprog_t *cprog); void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx); void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, scc_ast_translation_unit_t *tu); -void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl); +void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, + cbool is_global); scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, cbool is_lvalue); void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt); diff --git a/libs/ast2ir/include/scc_type_abi.h b/libs/ast2ir/include/scc_type_abi.h deleted file mode 100644 index 24f2162..0000000 --- a/libs/ast2ir/include/scc_type_abi.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __SCC_TYPE_ABI_H__ -#define __SCC_TYPE_ABI_H__ - -#include -#include - -typedef struct { - scc_ast_builtin_type_t ast_type; - scc_ir_type_tag_t ir_type; - usize size; - usize alignment; -} scc_type_abi_t; - -#endif /* __SCC_TYPE_ABI_H__ */ diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index a55a900..62adf2d 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -1,5 +1,30 @@ +#include "ast_def.h" +#include "ir_builder.h" +#include "ir_def.h" +#include "log.h" #include +static scc_ir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, + scc_ast_type_t *ast_type) { + scc_abi_type_layout_t layout; + // 映射内置类型 + ctx->abi->compute_type_layout(ctx->abi, ast_type, &layout); + switch (layout.size) { + case 1: + return scc_ir_builder_type_i8(&ctx->builder); + case 2: + return scc_ir_builder_type_i16(&ctx->builder); + case 4: + return scc_ir_builder_type_i32(&ctx->builder); + case 8: + return scc_ir_builder_type_i64(&ctx->builder); + break; + default: + break; + } + return SCC_IR_REF_nullptr; +} + static inline void parse_struct_union_layout(scc_ast_type_t *type) {} static inline void parse_lexme2const_int(const char *lexme, @@ -22,27 +47,7 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, switch (ast_type->base.type) { case SCC_AST_TYPE_BUILTIN: { - // 映射内置类型 - scc_ir_type_init(&ir_type, SCC_IR_TYPE_i32); - // TODO: 根据具体内置类型设置 - switch (ast_type->builtin.type) { - case SCC_AST_BUILTIN_TYPE_VOID: - return scc_ir_builder_type_void(&ctx->builder); - case SCC_AST_BUILTIN_TYPE_CHAR: - case SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR: - return scc_ir_builder_type_u8(&ctx->builder); - case SCC_AST_BUILTIN_TYPE_SIGNED_CHAR: - return scc_ir_builder_type_i8(&ctx->builder); - case SCC_AST_BUILTIN_TYPE_INT: - case SCC_AST_BUILTIN_TYPE_SIGNED_INT: - return scc_ir_builder_type_i32(&ctx->builder); - case SCC_AST_BUILTIN_TYPE_UNSIGNED_INT: - return scc_ir_builder_type_u32(&ctx->builder); - default: - Panic("Unsupported AST type: %d", ast_type->builtin.type); - break; - } - break; + return parse_base_type(ctx, ast_type); } case SCC_AST_TYPE_POINTER: { scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR); @@ -94,11 +99,27 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, ir_type.data.function.params = params; break; } - // SCC_AST_TYPE_STRUCT, // 结构体类型 - // SCC_AST_TYPE_UNION, // 联合类型 - // SCC_AST_TYPE_ENUM, // 枚举类型 - case SCC_AST_TYPE_TYPEDEF: + case SCC_AST_TYPE_STRUCT: + case SCC_AST_TYPE_UNION: { + scc_ir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT + ? SCC_IR_TYPE_STRUCT + : SCC_IR_TYPE_UNION); + scc_vec_foreach(ast_type->record.decl->record.fields, i) { + scc_ast_decl_t *decl_field = + scc_vec_at(ast_type->record.decl->record.fields, i); + Assert(decl_field->base.type == SCC_AST_DECL_VAR); + scc_ir_type_ref_t field_type = + scc_ast2ir_type(ctx, decl_field->var.type); + scc_vec_push(ir_type.data.aggregate.fields, field_type); + } break; + } + case SCC_AST_TYPE_ENUM: + return parse_base_type( + ctx, &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, + .builtin = SCC_AST_BUILTIN_TYPE_INT}); + case SCC_AST_TYPE_TYPEDEF: + return 0; default: LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); return 0; @@ -401,7 +422,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, } case SCC_AST_EXPR_CALL: { // 转换参数 - scc_ir_node_ref_vec_t args; + scc_ir_value_ref_vec_t args; scc_vec_init(args); scc_vec_foreach(expr->call.args, i) { @@ -441,23 +462,30 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, elem_ptr); // 作为右值:加载值 } } - // SCC_AST_EXPR_MEMBER, // 成员访问 . - // SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 -> + case SCC_AST_EXPR_MEMBER: + break; + case SCC_AST_EXPR_PTR_MEMBER: + break; // SCC_AST_EXPR_CAST, // 类型转换 case SCC_AST_EXPR_SIZE_OF: { scc_ir_const_int_t val; - val.int64 = 1; + // FIXME + TODO(); + val.int64 = 1; // HACK return scc_ir_builder_const_int( &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), val); } case SCC_AST_EXPR_ALIGN_OF: { scc_ir_const_int_t val; - val.int64 = 1; + TODO(); + val.int64 = 8; return scc_ir_builder_const_int( &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), val); } - // SCC_AST_EXPR_COMPOUND, // 复合字面量 - // SCC_AST_EXPR_LVALUE, // 右值 + case SCC_AST_EXPR_COMPOUND: + break; + case SCC_AST_EXPR_LVALUE: + break; // SCC_AST_EXPR_BUILTIN,// 内置表达式 ... directive map to ir builtin case SCC_AST_EXPR_INT_LITERAL: { // FIXME maybe using some array to int; @@ -512,7 +540,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, } // FIXME hack hashtable scc_ir_value_ref_t in = (scc_ir_value_ref_t)(usize)scc_hashtable_get( - &ctx->decl2ir_ref, expr->identifier._target); + &ctx->ast2ir_cache, expr->identifier._target); Assert(in != 0); if (is_lvalue) { return in; @@ -563,8 +591,8 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { scc_ast2ir_stmt(ctx, SCC_AST_CAST_TO(scc_ast_stmt_t, child_stmt)); } else if (SCC_AST_IS_A(scc_ast_decl_t, child_stmt)) { - scc_ast2ir_decl(ctx, - SCC_AST_CAST_TO(scc_ast_decl_t, child_stmt)); + scc_ast2ir_decl( + ctx, SCC_AST_CAST_TO(scc_ast_decl_t, child_stmt), false); } else { UNREACHABLE(); } @@ -667,7 +695,8 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { if (stmt->for_stmt.init) { if (SCC_AST_IS_A(scc_ast_decl_t, stmt->for_stmt.init)) { scc_ast2ir_decl( - ctx, SCC_AST_CAST_TO(scc_ast_decl_t, stmt->for_stmt.init)); + ctx, SCC_AST_CAST_TO(scc_ast_decl_t, stmt->for_stmt.init), + false); } else if (SCC_AST_IS_A(scc_ast_expr_t, stmt->for_stmt.init)) { scc_ast2ir_expr( ctx, SCC_AST_CAST_TO(scc_ast_expr_t, stmt->for_stmt.init), @@ -728,7 +757,8 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { * @param ctx * @param decl */ -void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { +void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, + cbool is_global) { if (ctx == nullptr || decl == nullptr) { LOG_ERROR("Invalid argument"); return; @@ -738,11 +768,20 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { case SCC_AST_DECL_VAR: { // 转换类型 scc_ir_type_ref_t ir_type_ref = scc_ast2ir_type(ctx, decl->var.type); - // 创建分配节点 - scc_ir_value_ref_t alloc_val_node = - scc_ir_builder_alloca(&ctx->builder, ir_type_ref, decl->name); - scc_hashtable_set(&ctx->decl2ir_ref, decl, + // 创建分配节点 + scc_ir_value_ref_t alloc_val_node = SCC_IR_REF_nullptr; + if (is_global) { + // alloc_val_node = scc_ir_builder_global_alloca( + // &ctx->builder, ir_type_ref, decl->name); + return; + } else { + alloc_val_node = + scc_ir_builder_alloca(&ctx->builder, ir_type_ref, decl->name); + } + Assert(alloc_val_node != SCC_IR_REF_nullptr); + + scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)alloc_val_node); // 如果有初始化表达式 @@ -812,7 +851,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { ctx->builder.ctx.module, param_node_ref); Assert(param_node != nullptr); param_node->name = param->name; - scc_hashtable_set(&ctx->decl2ir_ref, param, + scc_hashtable_set(&ctx->ast2ir_cache, param, (void *)(usize)param_node_ref); } scc_ast2ir_stmt(ctx, decl->func.body); @@ -826,7 +865,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { case SCC_AST_DECL_LIST: { scc_vec_foreach(decl->list.vars, i) { scc_ast_decl_t *sub_decl = scc_vec_at(decl->list.vars, i); - scc_ast2ir_decl(ctx, sub_decl); + scc_ast2ir_decl(ctx, sub_decl, is_global); } break; } @@ -835,10 +874,15 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { } case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: - scc_vec_foreach(decl->record.fields, i) { - scc_ast_decl_t *item = scc_vec_at(decl->record.fields, i); - scc_ast2ir_decl(ctx, item); - } + scc_ast_type_t type = { + .base.type = + SCC_AST_DECL_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION, + .record.decl = decl, + .record.name = decl->name, + }; + scc_ir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type); + scc_ir_builder_global_alloca(&ctx->builder, type_ref, + SCC_IR_REF_nullptr); break; case SCC_AST_DECL_ENUM: scc_ir_const_int_t val; @@ -852,7 +896,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { } scc_ir_value_ref_t item_val_ref = scc_ir_builder_const_int( &ctx->builder, scc_ir_builder_type_i32(&ctx->builder), val); - scc_hashtable_set(&ctx->decl2ir_ref, item, + scc_hashtable_set(&ctx->ast2ir_cache, item, (void *)(usize)item_val_ref); val.int32 += 1; } @@ -871,7 +915,7 @@ void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, scc_vec_foreach(tu->declarations, i) { scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i); - scc_ast2ir_decl(ctx, decl); + scc_ast2ir_decl(ctx, decl, true); } } @@ -880,18 +924,18 @@ static int scc_cmp_node(const void *key1, const void *key2) { return (u32)(usize)key1 - (u32)(usize)key2; } -void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi, +void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, scc_ir_cprog_t *cprog) { Assert(ctx != nullptr); ctx->abi = abi; scc_ir_builder_init(&ctx->builder, cprog); - scc_hashtable_init(&ctx->decl2ir_ref, scc_hash_node, scc_cmp_node); + scc_hashtable_init(&ctx->ast2ir_cache, scc_hash_node, scc_cmp_node); scc_hashtable_init(&ctx->symtab, (scc_hashtable_hash_func_t)scc_strhash32, (scc_hashtable_equal_func_t)scc_strcmp); } void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) { scc_ir_builder_drop(&ctx->builder); - scc_hashtable_drop(&ctx->decl2ir_ref); + scc_hashtable_drop(&ctx->ast2ir_cache); scc_hashtable_drop(&ctx->symtab); } diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index e8d249c..28fd108 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -42,6 +42,19 @@ scc_ir_type_ref_t scc_ir_builder_type(scc_ir_builder_t *builder, void scc_ir_builder_add_instr(scc_ir_builder_t *builder, scc_ir_value_ref_t instr); +scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder, + scc_ir_type_ref_t type, + scc_ir_value_ref_t value); + +/** + * @brief 创建alloca指令(在当前基本块中) + * @param type 分配的类型 + * @param name 变量名(可为nullptr) + */ +scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, + scc_ir_type_ref_t type, + const char *name); + #define SCC_IR_BUILDER_TYPE_FUNC(scc_type) \ [[maybe_unused]] static inline scc_ir_type_ref_t \ scc_ir_builder_type_##scc_type(scc_ir_builder_t *builder) { \ @@ -122,25 +135,15 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str, buff[i - 1] = str[i]; } buff[len - 2] = '\0'; - scc_vec_unsafe_from_buffer(const_array_value.data.const_array.elements, + scc_vec_unsafe_from_buffer(const_array_value.data.const_array.fields, (u8 *)buff, len - 1); scc_ir_value_ref_t const_array_ref = scc_ir_module_add_value(builder->ctx.module, &const_array_value); Assert(const_array_ref != SCC_IR_REF_nullptr); // 3. 创建全局变量节点,类型为指针,初始值指向常量数组 - char *name = scc_malloc(32); - // FIXME MAYBE MEMORY LEAK - - scc_ir_value_ref_t global_value_ref = scc_ir_module_add_value( - builder->ctx.module, &(scc_ir_value_t){ - .name = name, - .tag = SCC_IR_VALUE_TAG_GLOBAL_ALLOC, - .type = array_type_ref, - .data.global_alloc.value = const_array_ref, - }); - scc_snprintf(name, 32, "$G%u", global_value_ref); - scc_vec_push(builder->cprog->global_vals, global_value_ref); + scc_ir_value_ref_t global_value_ref = + scc_ir_builder_global_alloca(builder, array_type_ref, const_array_ref); // scc_hashtable_insert(builder); scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value( @@ -203,15 +206,6 @@ scc_ir_func_ref_t scc_ir_builder_current_bblock(scc_ir_builder_t *builder); void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder, scc_ir_bblock_ref_t bblock); -/** - * @brief 创建alloca指令(在当前基本块中) - * @param type 分配的类型 - * @param name 变量名(可为nullptr) - */ -scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, - scc_ir_type_ref_t type, - const char *name); - scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder, scc_ir_type_ref_t type, const char *name, usize arg_idx); diff --git a/libs/ir/include/ir_def.h b/libs/ir/include/ir_def.h index 8531d5c..fa1b14b 100644 --- a/libs/ir/include/ir_def.h +++ b/libs/ir/include/ir_def.h @@ -12,7 +12,7 @@ typedef SCC_VEC(u8) scc_ir_buffer_t; typedef struct scc_ir_value scc_ir_value_t; typedef ir_handle_t scc_ir_value_ref_t; -typedef SCC_VEC(scc_ir_value_ref_t) scc_ir_node_ref_vec_t; +typedef SCC_VEC(scc_ir_value_ref_t) scc_ir_value_ref_vec_t; typedef struct scc_ir_type scc_ir_type_t; typedef ir_handle_t scc_ir_type_ref_t; @@ -63,7 +63,7 @@ struct scc_ir_type { scc_ir_type_ref_t base; } pointer; struct { - scc_ir_type_ref_vec_t elements; + scc_ir_type_ref_vec_t fields; } aggregate; struct { scc_ir_type_ref_vec_t params; @@ -74,14 +74,14 @@ struct scc_ir_type { struct scc_ir_bblock { scc_ir_label_t label; - scc_ir_node_ref_vec_t instrs; + scc_ir_value_ref_vec_t instrs; // ir_arr_t used_by; }; // basic block struct scc_ir_func { scc_ir_label_t name; scc_ir_type_ref_t type; - scc_ir_node_ref_vec_t params; + scc_ir_value_ref_vec_t params; scc_ir_bblock_ref_vec_t bblocks; }; @@ -225,7 +225,7 @@ typedef enum { struct scc_ir_value { scc_ir_type_ref_t type; scc_ir_label_t name; - scc_ir_node_ref_vec_t used_by; + scc_ir_value_ref_vec_t used_by; scc_ir_value_tag_t tag; union { scc_ir_builtin_t builtin; @@ -234,10 +234,10 @@ struct scc_ir_value { scc_ir_const_float_t const_float; struct { scc_ir_value_ref_t base_type; - scc_ir_buffer_t elements; + scc_ir_buffer_t fields; } const_array; struct { - scc_ir_node_ref_vec_t elements; + scc_ir_value_ref_vec_t fields; } aggregate; struct { usize idx; @@ -276,7 +276,7 @@ struct scc_ir_value { } jump; struct { scc_ir_func_ref_t callee; // TODO function pointer call - scc_ir_node_ref_vec_t args; + scc_ir_value_ref_vec_t args; } call; struct { scc_ir_value_ref_t ret_val; diff --git a/libs/ir/include/ir_prog.h b/libs/ir/include/ir_prog.h index ebd3b10..94d278c 100644 --- a/libs/ir/include/ir_prog.h +++ b/libs/ir/include/ir_prog.h @@ -6,9 +6,9 @@ typedef struct scc_ir_cprog { scc_ir_module_t module; - scc_ir_node_ref_vec_t global_vals; /* 全局变量 */ - scc_ir_func_ref_vec_t func_defs; /* 所有函数定义 */ - scc_ir_func_ref_vec_t func_decls; /* 所有函数包括定义的声明 */ + scc_ir_value_ref_vec_t global_vals; /* 全局变量 */ + scc_ir_func_ref_vec_t func_defs; /* 所有函数定义 */ + scc_ir_func_ref_vec_t func_decls; /* 所有函数包括定义的声明 */ } scc_ir_cprog_t; void scc_ir_cprog_init(scc_ir_cprog_t *in); diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index 2776fe1..a4182af 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -1,3 +1,4 @@ +#include "ir_def.h" #include #include @@ -147,6 +148,24 @@ void scc_ir_builder_add_instr(scc_ir_builder_t *builder, } } +scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder, + scc_ir_type_ref_t type, + scc_ir_value_ref_t value) { + // FIXME MAYBE MEMORY LEAK + char *name = scc_malloc(32); + scc_ir_value_ref_t global_value_ref = scc_ir_module_add_value( + builder->ctx.module, &(scc_ir_value_t){ + .name = name, + .tag = SCC_IR_VALUE_TAG_GLOBAL_ALLOC, + .type = type, + .data.global_alloc.value = value, + }); + scc_snprintf(name, 32, "$G%u", global_value_ref); + + scc_vec_push(builder->cprog->global_vals, global_value_ref); + return global_value_ref; +} + scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, scc_ir_type_ref_t type, const char *name) { @@ -160,9 +179,7 @@ scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &alloc_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -178,7 +195,7 @@ scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &value); - // 添加到当前基本块 + scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -203,9 +220,7 @@ scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &load_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -221,9 +236,7 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &store_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -259,9 +272,7 @@ scc_ir_value_ref_t scc_ir_builder_get_elem_ptr(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &get_ptr_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -285,9 +296,7 @@ scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &binop_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -323,9 +332,7 @@ scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &jump_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -342,9 +349,7 @@ scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &branch_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -375,9 +380,7 @@ scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &call_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -390,9 +393,7 @@ scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &ret_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } @@ -404,7 +405,6 @@ scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) { scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &ret_node); - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); return value_ref; } diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index ce08d35..ea32fbf 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -535,9 +535,9 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx, break; case SCC_IR_VALUE_TAG_AGGREGATE: // 聚合类型:递归输出每个元素(每个占一行) - scc_vec_foreach(value->data.aggregate.elements, i) { + scc_vec_foreach(value->data.aggregate.fields, i) { scc_ir_dump_value_linear( - ctx, scc_vec_at(value->data.aggregate.elements, i)); + ctx, scc_vec_at(value->data.aggregate.fields, i)); scc_tree_dump_append(ctx->dump_ctx, "\n"); } return; @@ -618,8 +618,8 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx, scc_tree_dump_append(ctx->dump_ctx, "const_array "); scc_ir_dump_type_linear(ctx, value->data.const_array.base_type); scc_tree_dump_append(ctx->dump_ctx, " ["); - scc_vec_foreach(value->data.const_array.elements, i) { - u8 ch = scc_vec_at(value->data.const_array.elements, i); + scc_vec_foreach(value->data.const_array.fields, i) { + u8 ch = scc_vec_at(value->data.const_array.fields, i); scc_tree_dump_append_fmt(ctx->dump_ctx, " `%c`, ", ch ? ch : ' '); } scc_tree_dump_append(ctx->dump_ctx, " ]"); diff --git a/libs/ir/src/scc_ir.c b/libs/ir/src/scc_ir.c index 33edede..ff31fb1 100644 --- a/libs/ir/src/scc_ir.c +++ b/libs/ir/src/scc_ir.c @@ -33,6 +33,10 @@ void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag) { scc_vec_init(in->data.function.params); in->data.function.ret_type = 0; break; + case SCC_IR_TYPE_UNION: + case SCC_IR_TYPE_STRUCT: + scc_vec_init(in->data.aggregate.fields); + break; default: UNREACHABLE(); break; diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index 9be35da..8d7c6af 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -674,9 +674,9 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { .sccf_sym_type = SCCF_SYM_TYPE_DATA, .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, }; - scc_vec_foreach(value->data.const_array.elements, j) { + scc_vec_foreach(value->data.const_array.fields, j) { scc_vec_push(ctx->sect_data, - scc_vec_at(value->data.const_array.elements, j)); + scc_vec_at(value->data.const_array.fields, j)); } usize sym_idx = sccf_builder_add_symbol(ctx->builder, galloc->name, &sym); diff --git a/src/main.c b/src/main.c index 4a30656..2d38388 100644 --- a/src/main.c +++ b/src/main.c @@ -211,10 +211,10 @@ sstream_drop: } scc_ast2ir_ctx_t ast2ir_ctx; -#include +#include scc_ir_cprog_t cprog; scc_ir_cprog_init(&cprog); - scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi, &cprog); + scc_ast2ir_ctx_init(&ast2ir_ctx, &scc_ast_abi_impl, &cprog); scc_ast2ir_translation_unit(&ast2ir_ctx, translation_unit); scc_ast2ir_ctx_drop(&ast2ir_ctx); diff --git a/tests/simple/15_array_subscript.c b/tests/simple/15_array_subscript.c index 37543a7..8a1205b 100644 --- a/tests/simple/15_array_subscript.c +++ b/tests/simple/15_array_subscript.c @@ -1,7 +1,7 @@ int main(void) { char buff[] = "hello buffer"; int res = 0; - for (int i = 0; i < sizeof(buff); i += 1) { + for (int i = 0; buff[i] != 0; i += 1) { res += buff[i]; } return res;