authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-23 21:18:26-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-23 21:25:29-05:00
logf8aecef6705a75a4c35754bcac32c27602b84711
tree96a98d4ea9cb935a3eec830b00c80a2658363ed3
parent1f3d9f79c19c225b2043a1d0355cbc74addcf03a

CBE: implement the future

Turns out f(...) will be supported one day.

2 files changed, 14 insertions(+), 6 deletions(-)

src/codegen/c.zig+4-5
......@@ -6876,17 +6876,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
68766876
68776877 const inst_ty = f.air.typeOfIndex(inst);
68786878 const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);
6879
68806879 const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
6881 if (param_len == 0)
6882 return f.fail("CBE: C requires at least one runtime argument for varargs functions", .{});
68836880
68846881 const writer = f.object.writer();
68856882 const local = try f.allocLocal(inst, inst_ty);
68866883 try writer.writeAll("va_start(*(va_list *)&");
68876884 try f.writeCValue(writer, local, .Other);
6888 try writer.writeAll(", ");
6889 try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument);
6885 if (param_len > 0) {
6886 try writer.writeAll(", ");
6887 try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument);
6888 }
68906889 try writer.writeAll(");\n");
68916890 return local;
68926891}
test/behavior/var_args.zig+10-1
......@@ -111,6 +111,12 @@ test "simple variadic function" {
111111 return @cVaArg(&ap, c_int);
112112 }
113113
114 fn compatible(_: c_int, ...) callconv(.C) c_int {
115 var ap = @cVaStart();
116 defer @cVaEnd(&ap);
117 return @cVaArg(&ap, c_int);
118 }
119
114120 fn add(count: c_int, ...) callconv(.C) c_int {
115121 var ap = @cVaStart();
116122 defer @cVaEnd(&ap);
......@@ -123,10 +129,13 @@ test "simple variadic function" {
123129 }
124130 };
125131
126 if (builtin.zig_backend != .stage2_c) { // C doesn't support varargs without a preceding runtime arg.
132 if (builtin.zig_backend != .stage2_c) {
133 // pre C23 doesn't support varargs without a preceding runtime arg.
127134 try std.testing.expectEqual(@as(c_int, 0), S.simple(@as(c_int, 0)));
128135 try std.testing.expectEqual(@as(c_int, 1024), S.simple(@as(c_int, 1024)));
129136 }
137 try std.testing.expectEqual(@as(c_int, 0), S.compatible(undefined, @as(c_int, 0)));
138 try std.testing.expectEqual(@as(c_int, 1024), S.compatible(undefined, @as(c_int, 1024)));
130139 try std.testing.expectEqual(@as(c_int, 0), S.add(0));
131140 try std.testing.expectEqual(@as(c_int, 1), S.add(1, @as(c_int, 1)));
132141 try std.testing.expectEqual(@as(c_int, 3), S.add(2, @as(c_int, 1), @as(c_int, 2)));