feat: 新增 i32 / u64 / char 类型 + 字符字面量 "'a'"
This commit is contained in:
@@ -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 失败是预期的 (自引用), 存储零初始化
|
||||
|
||||
Reference in New Issue
Block a user