| author | |
| committer | |
| log | f8aecef6705a75a4c35754bcac32c27602b84711 |
| tree | 96a98d4ea9cb935a3eec830b00c80a2658363ed3 |
| parent | 1f3d9f79c19c225b2043a1d0355cbc74addcf03a |
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 { |
| 6876 | 6876 | |
| 6877 | 6877 | const inst_ty = f.air.typeOfIndex(inst); |
| 6878 | 6878 | const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete); |
| 6879 | ||
| 6880 | 6879 | 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", .{}); | |
| 6883 | 6880 | |
| 6884 | 6881 | const writer = f.object.writer(); |
| 6885 | 6882 | const local = try f.allocLocal(inst, inst_ty); |
| 6886 | 6883 | try writer.writeAll("va_start(*(va_list *)&"); |
| 6887 | 6884 | 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 | } | |
| 6890 | 6889 | try writer.writeAll(");\n"); |
| 6891 | 6890 | return local; |
| 6892 | 6891 | } |
test/behavior/var_args.zig+10-1| ... | ... | @@ -111,6 +111,12 @@ test "simple variadic function" { |
| 111 | 111 | return @cVaArg(&ap, c_int); |
| 112 | 112 | } |
| 113 | 113 | |
| 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 | ||
| 114 | 120 | fn add(count: c_int, ...) callconv(.C) c_int { |
| 115 | 121 | var ap = @cVaStart(); |
| 116 | 122 | defer @cVaEnd(&ap); |
| ... | ... | @@ -123,10 +129,13 @@ test "simple variadic function" { |
| 123 | 129 | } |
| 124 | 130 | }; |
| 125 | 131 | |
| 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. | |
| 127 | 134 | try std.testing.expectEqual(@as(c_int, 0), S.simple(@as(c_int, 0))); |
| 128 | 135 | try std.testing.expectEqual(@as(c_int, 1024), S.simple(@as(c_int, 1024))); |
| 129 | 136 | } |
| 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))); | |
| 130 | 139 | try std.testing.expectEqual(@as(c_int, 0), S.add(0)); |
| 131 | 140 | try std.testing.expectEqual(@as(c_int, 1), S.add(1, @as(c_int, 1))); |
| 132 | 141 | try std.testing.expectEqual(@as(c_int, 3), S.add(2, @as(c_int, 1), @as(c_int, 2))); |