Skip to content

Commit 74673b7

Browse files
Vexuandrewrk
authored andcommitted
stage2 llvm: implement more C ABI
1 parent 4d7f5a1 commit 74673b7

File tree

3 files changed

+119
-10
lines changed

3 files changed

+119
-10
lines changed

src/codegen/llvm.zig

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,40 @@ pub const Object = struct {
921921
};
922922
try args.append(loaded);
923923
},
924+
.multiple_llvm_float => {
925+
const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len];
926+
const param_ty = fn_info.param_types[it.zig_index - 1];
927+
const param_llvm_ty = try dg.lowerType(param_ty);
928+
const param_alignment = param_ty.abiAlignment(target);
929+
const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty);
930+
arg_ptr.setAlignment(param_alignment);
931+
var field_types_buf: [8]*const llvm.Type = undefined;
932+
const field_types = field_types_buf[0..llvm_floats.len];
933+
for (llvm_floats) |float_bits, i| {
934+
switch (float_bits) {
935+
64 => field_types[i] = dg.context.doubleType(),
936+
80 => field_types[i] = dg.context.x86FP80Type(),
937+
else => {},
938+
}
939+
}
940+
const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
941+
const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), "");
942+
for (llvm_floats) |_, i_usize| {
943+
const i = @intCast(c_uint, i_usize);
944+
const param = llvm_func.getParam(i);
945+
const field_ptr = builder.buildStructGEP(casted_ptr, i, "");
946+
const store_inst = builder.buildStore(param, field_ptr);
947+
store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8);
948+
}
949+
950+
const is_by_ref = isByRef(param_ty);
951+
const loaded = if (is_by_ref) arg_ptr else l: {
952+
const load_inst = builder.buildLoad(arg_ptr, "");
953+
load_inst.setAlignment(param_alignment);
954+
break :l load_inst;
955+
};
956+
try args.append(loaded);
957+
},
924958
.as_u16 => {
925959
const param = llvm_func.getParam(llvm_arg_i);
926960
llvm_arg_i += 1;
@@ -2341,6 +2375,14 @@ pub const DeclGen = struct {
23412375
dg.addFnAttr(llvm_fn, "noreturn");
23422376
}
23432377

2378+
var llvm_arg_i = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing);
2379+
var it = iterateParamTypes(dg, fn_info);
2380+
while (it.next()) |_| : (llvm_arg_i += 1) {
2381+
if (!it.byval_attr) continue;
2382+
const param = llvm_fn.getParam(llvm_arg_i);
2383+
llvm_fn.addByValAttr(llvm_arg_i, param.typeOf().getElementType());
2384+
}
2385+
23442386
return llvm_fn;
23452387
}
23462388

@@ -2894,6 +2936,18 @@ pub const DeclGen = struct {
28942936
llvm_params.appendAssumeCapacity(big_int_ty);
28952937
}
28962938
},
2939+
.multiple_llvm_float => {
2940+
const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];
2941+
try llvm_params.ensureUnusedCapacity(it.llvm_types_len);
2942+
for (llvm_ints) |float_bits| {
2943+
const float_ty = switch (float_bits) {
2944+
64 => dg.context.doubleType(),
2945+
80 => dg.context.x86FP80Type(),
2946+
else => unreachable,
2947+
};
2948+
llvm_params.appendAssumeCapacity(float_ty);
2949+
}
2950+
},
28972951
.as_u16 => {
28982952
try llvm_params.append(dg.context.intType(16));
28992953
},
@@ -4402,6 +4456,39 @@ pub const FuncGen = struct {
44024456
llvm_args.appendAssumeCapacity(load_inst);
44034457
}
44044458
},
4459+
.multiple_llvm_float => {
4460+
const arg = args[it.zig_index - 1];
4461+
const param_ty = self.air.typeOf(arg);
4462+
const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len];
4463+
const llvm_arg = try self.resolveInst(arg);
4464+
const is_by_ref = isByRef(param_ty);
4465+
const arg_ptr = if (is_by_ref) llvm_arg else p: {
4466+
const p = self.buildAlloca(llvm_arg.typeOf());
4467+
const store_inst = self.builder.buildStore(llvm_arg, p);
4468+
store_inst.setAlignment(param_ty.abiAlignment(target));
4469+
break :p p;
4470+
};
4471+
4472+
var field_types_buf: [8]*const llvm.Type = undefined;
4473+
const field_types = field_types_buf[0..llvm_floats.len];
4474+
for (llvm_floats) |float_bits, i| {
4475+
switch (float_bits) {
4476+
64 => field_types[i] = self.dg.context.doubleType(),
4477+
80 => field_types[i] = self.dg.context.x86FP80Type(),
4478+
else => {},
4479+
}
4480+
}
4481+
const ints_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
4482+
const casted_ptr = self.builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), "");
4483+
try llvm_args.ensureUnusedCapacity(it.llvm_types_len);
4484+
for (llvm_floats) |_, i_usize| {
4485+
const i = @intCast(c_uint, i_usize);
4486+
const field_ptr = self.builder.buildStructGEP(casted_ptr, i, "");
4487+
const load_inst = self.builder.buildLoad(field_ptr, "");
4488+
load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8);
4489+
llvm_args.appendAssumeCapacity(load_inst);
4490+
}
4491+
},
44054492
.as_u16 => {
44064493
const arg = args[it.zig_index - 1];
44074494
const llvm_arg = try self.resolveInst(arg);
@@ -9367,16 +9454,20 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm.
93679454
llvm_types_index += 1;
93689455
},
93699456
.sse => {
9370-
@panic("TODO");
9457+
llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
9458+
llvm_types_index += 1;
93719459
},
93729460
.sseup => {
9373-
@panic("TODO");
9461+
llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
9462+
llvm_types_index += 1;
93749463
},
93759464
.x87 => {
9376-
@panic("TODO");
9465+
llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
9466+
llvm_types_index += 1;
93779467
},
93789468
.x87up => {
9379-
@panic("TODO");
9469+
llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
9470+
llvm_types_index += 1;
93809471
},
93819472
.complex_x87 => {
93829473
@panic("TODO");
@@ -9422,20 +9513,23 @@ const ParamTypeIterator = struct {
94229513
target: std.Target,
94239514
llvm_types_len: u32,
94249515
llvm_types_buffer: [8]u16,
9516+
byval_attr: bool,
94259517

94269518
const Lowering = enum {
94279519
no_bits,
94289520
byval,
94299521
byref,
94309522
abi_sized_int,
94319523
multiple_llvm_ints,
9524+
multiple_llvm_float,
94329525
slice,
94339526
as_u16,
94349527
};
94359528

94369529
pub fn next(it: *ParamTypeIterator) ?Lowering {
94379530
if (it.zig_index >= it.fn_info.param_types.len) return null;
94389531
const ty = it.fn_info.param_types[it.zig_index];
9532+
it.byval_attr = false;
94399533
return nextInner(it, ty);
94409534
}
94419535

@@ -9521,6 +9615,7 @@ const ParamTypeIterator = struct {
95219615
.memory => {
95229616
it.zig_index += 1;
95239617
it.llvm_index += 1;
9618+
it.byval_attr = true;
95249619
return .byref;
95259620
},
95269621
.sse => {
@@ -9540,6 +9635,7 @@ const ParamTypeIterator = struct {
95409635
if (classes[0] == .memory) {
95419636
it.zig_index += 1;
95429637
it.llvm_index += 1;
9638+
it.byval_attr = true;
95439639
return .byref;
95449640
}
95459641
var llvm_types_buffer: [8]u16 = undefined;
@@ -9551,16 +9647,20 @@ const ParamTypeIterator = struct {
95519647
llvm_types_index += 1;
95529648
},
95539649
.sse => {
9554-
@panic("TODO");
9650+
llvm_types_buffer[llvm_types_index] = 64;
9651+
llvm_types_index += 1;
95559652
},
95569653
.sseup => {
9557-
@panic("TODO");
9654+
llvm_types_buffer[llvm_types_index] = 64;
9655+
llvm_types_index += 1;
95589656
},
95599657
.x87 => {
9560-
@panic("TODO");
9658+
llvm_types_buffer[llvm_types_index] = 80;
9659+
llvm_types_index += 1;
95619660
},
95629661
.x87up => {
9563-
@panic("TODO");
9662+
llvm_types_buffer[llvm_types_index] = 80;
9663+
llvm_types_index += 1;
95649664
},
95659665
.complex_x87 => {
95669666
@panic("TODO");
@@ -9574,11 +9674,16 @@ const ParamTypeIterator = struct {
95749674
it.llvm_index += 1;
95759675
return .abi_sized_int;
95769676
}
9677+
if (classes[0] == .sse and classes[1] == .none) {
9678+
it.zig_index += 1;
9679+
it.llvm_index += 1;
9680+
return .byval;
9681+
}
95779682
it.llvm_types_buffer = llvm_types_buffer;
95789683
it.llvm_types_len = llvm_types_index;
95799684
it.llvm_index += llvm_types_index;
95809685
it.zig_index += 1;
9581-
return .multiple_llvm_ints;
9686+
return if (classes[0] == .integer) .multiple_llvm_ints else .multiple_llvm_float;
95829687
},
95839688
},
95849689
.wasm32 => {
@@ -9619,6 +9724,7 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp
96199724
.target = dg.module.getTarget(),
96209725
.llvm_types_buffer = undefined,
96219726
.llvm_types_len = 0,
9727+
.byval_attr = false,
96229728
};
96239729
}
96249730

src/codegen/llvm/bindings.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ pub const Value = opaque {
248248

249249
pub const addFunctionAttr = ZigLLVMAddFunctionAttr;
250250
extern fn ZigLLVMAddFunctionAttr(Fn: *const Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void;
251+
252+
pub const addByValAttr = ZigLLVMAddByValAttr;
253+
extern fn ZigLLVMAddByValAttr(Fn: *const Value, ArgNo: c_uint, type: *const Type) void;
251254
};
252255

253256
pub const Type = opaque {

test/standalone.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
4040
}
4141
// C ABI compatibility issue: https://github.com/ziglang/zig/issues/1481
4242
if (builtin.cpu.arch == .x86_64) {
43-
if (builtin.zig_backend == .stage1) { // https://github.com/ziglang/zig/issues/12222
43+
if (builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) { // https://github.com/ziglang/zig/issues/12222
4444
cases.addBuildFile("test/c_abi/build.zig", .{});
4545
}
4646
}

0 commit comments

Comments
 (0)