feat: 新增 i32 / u64 / char 类型 + 字符字面量 "'a'"

This commit is contained in:
2026-06-05 20:47:44 +08:00
parent 6fc599e6c2
commit 18172ca724
12 changed files with 146 additions and 16 deletions
+26
View File
@@ -59,9 +59,12 @@ typedef struct {
// === 类型映射(需要 Context===
static LLVMTypeRef to_llvm_type(CgCtx* ctx, TypeKind kind) {
switch (kind) {
case TYPE_I32: return LLVMInt32TypeInContext(ctx->context);
case TYPE_I64: return LLVMInt64TypeInContext(ctx->context);
case TYPE_U64: return LLVMInt64TypeInContext(ctx->context);
case TYPE_F64: return LLVMDoubleTypeInContext(ctx->context);
case TYPE_BOOL: return LLVMInt1TypeInContext(ctx->context);
case TYPE_CHAR: return LLVMInt8TypeInContext(ctx->context);
case TYPE_STR: return LLVMPointerType(LLVMInt8TypeInContext(ctx->context), 0);
case TYPE_STRUCT:
case TYPE_ENUM: return LLVMInt64TypeInContext(ctx->context);
@@ -73,7 +76,10 @@ static LLVMTypeRef to_llvm_type(CgCtx* ctx, TypeKind kind) {
static LLVMValueRef to_llvm_const(LLVMTypeRef ty, AstNode* lit) {
switch (lit->as.literal.lit_type) {
case TYPE_I32:
case TYPE_I64: return LLVMConstInt(ty, (unsigned long long)lit->as.literal.i64_val, true);
case TYPE_U64: return LLVMConstInt(ty, (unsigned long long)lit->as.literal.i64_val, false);
case TYPE_CHAR: return LLVMConstInt(ty, (unsigned long long)lit->as.literal.i64_val, false);
case TYPE_F64: return LLVMConstReal(ty, lit->as.literal.f64_val);
case TYPE_BOOL: return LLVMConstInt(ty, lit->as.literal.bool_val ? 1 : 0, false);
default: return NULL;
@@ -127,6 +133,18 @@ static LLVMTypeRef find_struct_type(CgCtx* ctx, const char* name) {
return NULL;
}
// 将整数值强制转换到目标 LLVM 类型(sext/zext/trunc
static LLVMValueRef coerce_int(CgCtx* ctx, LLVMValueRef val,
LLVMTypeRef from_ty, LLVMTypeRef to_ty) {
if (from_ty == to_ty) return val;
int from_w = LLVMGetIntTypeWidth(from_ty);
int to_w = LLVMGetIntTypeWidth(to_ty);
if (from_w < to_w)
return LLVMBuildSExt(ctx->builder, val, to_ty, "sext");
else
return LLVMBuildTrunc(ctx->builder, val, to_ty, "trunc");
}
// 从 TypeInfo 生成 LLVM 类型(支持数组、结构体等复合类型)
static LLVMTypeRef type_info_to_llvm(CgCtx* ctx, const TypeInfo* ti) {
switch (ti->kind) {
@@ -271,6 +289,8 @@ static LLVMValueRef codegen_expr(CgCtx* ctx, AstNode* node) {
if (strcmp(node->as.call.name, "print_i64") == 0) {
LLVMValueRef arg = codegen_expr(ctx, node->as.call.args[0]);
if (!arg) return NULL;
LLVMTypeRef i64_ty = LLVMInt64TypeInContext(ctx->context);
arg = coerce_int(ctx, arg, LLVMTypeOf(arg), i64_ty);
LLVMValueRef fmt = LLVMBuildGlobalStringPtr(ctx->builder, "%lld\n", "fmt_i64");
LLVMValueRef printf_args[] = { fmt, arg };
return LLVMBuildCall2(ctx->builder, ctx->printf_ty, ctx->printf_fn,
@@ -492,6 +512,12 @@ static void codegen_stmt(CgCtx* ctx, AstNode* node) {
// 尝试生成 init 值;数组类型可能 init 失败 (自引用占位符)
LLVMValueRef init_val = codegen_expr(ctx, node->as.let_stmt.init);
if (init_val) {
// 若 init LLVM 类型与 alloca 类型不同,强制转换(如 i64→i32)
LLVMTypeRef init_ty = LLVMTypeOf(init_val);
if (init_ty != var_type && LLVMGetTypeKind(init_ty) == LLVMIntegerTypeKind
&& LLVMGetTypeKind(var_type) == LLVMIntegerTypeKind) {
init_val = coerce_int(ctx, init_val, init_ty, var_type);
}
LLVMBuildStore(ctx->builder, init_val, alloca);
} else if (node->type.kind == TYPE_ARRAY) {
// 数组声明: init 失败是预期的 (自引用), 存储零初始化