This commit is contained in:
agra
2026-03-05 16:20:36 +02:00
parent 22bc2439ce
commit f9dda972d2
36 changed files with 1063 additions and 7 deletions

View File

@@ -282,6 +282,7 @@ pub const LLVMEmitter = struct {
.float => |v| c.LLVMConstReal(llvm_ty, v),
.boolean => |v| c.LLVMConstInt(llvm_ty, @intFromBool(v), 0),
.string => |sid| self.emitConstStringGlobal(self.ir_mod.types.getString(sid)),
.aggregate => |agg| self.emitConstAggregate(agg, llvm_ty),
.vtable => c.LLVMConstNull(llvm_ty), // placeholder — initialized in initVtableGlobals after function declarations
else => c.LLVMConstNull(llvm_ty),
};
@@ -354,15 +355,16 @@ pub const LLVMEmitter = struct {
// main always returns i32 at the LLVM level (JIT expects it)
const raw_ret_ty = self.toLLVMType(func.ret);
const ret_ty = if (is_main) self.cached_i32 else if (func.is_extern) self.abiCoerceParamType(func.ret, raw_ret_ty) else raw_ret_ty;
const needs_c_abi = func.is_extern or func.call_conv == .c;
const ret_ty = if (is_main) self.cached_i32 else if (needs_c_abi) self.abiCoerceParamType(func.ret, raw_ret_ty) else raw_ret_ty;
// Build parameter types — apply C ABI coercion for foreign (extern) functions
// Build parameter types — apply C ABI coercion for foreign/callconv(.c) functions
const param_count: c_uint = @intCast(func.params.len);
const param_types = self.alloc.alloc(c.LLVMTypeRef, func.params.len) catch unreachable;
defer self.alloc.free(param_types);
for (func.params, 0..) |param, j| {
const llvm_ty = self.toLLVMType(param.ty);
param_types[j] = if (func.is_extern) self.abiCoerceParamType(param.ty, llvm_ty) else llvm_ty;
param_types[j] = if (needs_c_abi) self.abiCoerceParamType(param.ty, llvm_ty) else llvm_ty;
}
const fn_type = c.LLVMFunctionType(ret_ty, param_types.ptr, param_count, 0);
@@ -378,6 +380,11 @@ pub const LLVMEmitter = struct {
.private => c.LLVMSetLinkage(llvm_func, c.LLVMPrivateLinkage),
}
// Set calling convention
if (func.call_conv == .c) {
c.LLVMSetFunctionCallConv(llvm_func, c.LLVMCCallConv);
}
// Add frame-pointer and nounwind attributes for correct ARM64 codegen
{
const fp_kind = "frame-pointer";
@@ -2840,6 +2847,23 @@ pub const LLVMEmitter = struct {
return c.LLVMConstStructInContext(self.context, &fields, 2, 0);
}
fn emitConstAggregate(self: *LLVMEmitter, agg: []const ir_inst.ConstantValue, llvm_ty: c.LLVMTypeRef) c.LLVMValueRef {
const elem_ty = c.LLVMGetElementType(llvm_ty);
const n: c_uint = @intCast(agg.len);
const vals = self.alloc.alloc(c.LLVMValueRef, agg.len) catch return c.LLVMConstNull(llvm_ty);
defer self.alloc.free(vals);
for (agg, 0..) |cv, i| {
vals[i] = switch (cv) {
.int => |v| c.LLVMConstInt(elem_ty, @bitCast(v), 1),
.float => |v| c.LLVMConstReal(elem_ty, v),
.boolean => |v| c.LLVMConstInt(elem_ty, @intFromBool(v), 0),
.aggregate => |inner| self.emitConstAggregate(inner, elem_ty),
else => c.LLVMConstNull(elem_ty),
};
}
return c.LLVMConstArray(elem_ty, vals.ptr, n);
}
fn emitStringConstant(self: *LLVMEmitter, str: []const u8) c.LLVMValueRef {
// LLVMBuildGlobalStringPtr needs a null-terminated C string
const str_z = self.alloc.dupeZ(u8, str) catch unreachable;