This commit is contained in:
agra
2026-02-22 13:17:38 +02:00
parent b02fe37a87
commit 775dcb44cc
2 changed files with 97 additions and 45 deletions

View File

@@ -2349,10 +2349,47 @@ pub const CodeGen = struct {
.bool_literal => |lit| {
return c.LLVMConstInt(llvm_ty, if (lit.value) 1 else 0, 0);
},
.string_literal => |sl| {
const content = if (sl.is_raw) sl.raw else (unescape.unescapeString(self.allocator, sl.raw) catch return null);
return self.buildConstStrGlobal(content);
},
.struct_literal => |sl| {
return self.evalConstantStruct(sl, target_ty);
},
else => return null,
}
}
/// Evaluate a struct literal as a constant (for global initializers).
fn evalConstantStruct(self: *CodeGen, sl: ast.StructLiteral, target_ty: Type) ?c.LLVMValueRef {
const struct_name = sl.struct_name orelse target_ty.struct_type;
const info = self.lookupStructInfo(struct_name) orelse return null;
if (info.field_names.len > 32) return null;
var field_vals: [32]c.LLVMValueRef = undefined;
const n = info.field_names.len;
// Initialize with undef for each field
for (0..n) |i| {
field_vals[i] = c.LLVMGetUndef(self.typeToLLVM(info.field_types[i]));
}
// Fill in provided field values
for (sl.field_inits) |fi| {
const field_name = fi.name orelse continue; // skip positional for now
const idx = blk: {
for (info.field_names, 0..) |fn_name, j| {
if (std.mem.eql(u8, fn_name, field_name)) break :blk j;
}
return null; // unknown field
};
const val = self.evalConstant(fi.value, info.field_types[idx]) orelse return null;
field_vals[idx] = val;
}
return c.LLVMConstNamedStruct(info.llvm_type, @ptrCast(&field_vals), @intCast(n));
}
/// Register a top-level value constant (e.g., `SPECIAL_VALUE :u8: 42;`) as an LLVM global.
fn registerTopLevelConstant(self: *CodeGen, cd: ast.ConstDecl) !void {
const ta = cd.type_annotation orelse return; // need explicit type for top-level constants
@@ -2382,9 +2419,24 @@ pub const CodeGen = struct {
const llvm_ty = self.typeToLLVM(sx_ty);
const name_z = try self.allocator.dupeZ(u8, vd.name);
const global = c.LLVMAddGlobal(self.module, llvm_ty, name_z.ptr);
// Initialize with undef (will be set at runtime, e.g. by load_gl)
// Try constant-evaluable initializer → register as comptime_global for JIT compatibility
if (vd.value) |val_node| {
if (self.evalConstant(val_node, sx_ty)) |const_val| {
c.LLVMSetInitializer(global, const_val);
c.LLVMSetGlobalConstant(global, 1);
try self.comptime_globals.put(vd.name, .{
.global = global,
.ty = sx_ty,
.expr = val_node,
.is_resolved = true,
});
return;
}
}
// Non-constant globals: mutable, initialized with undef (set at runtime, e.g. by load_gl)
c.LLVMSetInitializer(global, self.getUndef(llvm_ty));
// NOT constant — this is a mutable global
c.LLVMSetGlobalConstant(global, 0);
try self.global_mutable_vars.put(vd.name, .{ .ptr = global, .ty = sx_ty });