aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-02-23 00:28:49 -0500
committerJacob Young <jacobly0@users.noreply.github.com>2023-02-23 01:21:59 -0500
commit57f6adf85da58c0c91a036deaa614c30df010b78 (patch)
tree8f9e2fafe159bc4d51123ead1a22036f4a995eae /src/codegen/c.zig
parent597e8011f7b2ea76755165fa5a09b2f725180268 (diff)
downloadzig-57f6adf85da58c0c91a036deaa614c30df010b78.tar.gz
zig-57f6adf85da58c0c91a036deaa614c30df010b78.zip
CBE: implement c varargs
Removed some backend test skip checks for things disabled in std.
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig93
1 files changed, 89 insertions, 4 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index b5269acc5c..390e8f8f4e 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -211,6 +211,15 @@ const reserved_idents = std.ComptimeStringMap(void, .{
.{ "volatile", {} },
.{ "while ", {} },
+ // stdarg.h
+ .{ "va_start", {} },
+ .{ "va_arg", {} },
+ .{ "va_end", {} },
+ .{ "va_copy", {} },
+
+ // stddef.h
+ .{ "offsetof", {} },
+
// windows.h
.{ "max", {} },
.{ "min", {} },
@@ -2952,10 +2961,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
.error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}),
.vector_store_elem => return f.fail("TODO: C backend: implement vector_store_elem", .{}),
- .c_va_arg => return f.fail("TODO implement c_va_arg", .{}),
- .c_va_copy => return f.fail("TODO implement c_va_copy", .{}),
- .c_va_end => return f.fail("TODO implement c_va_end", .{}),
- .c_va_start => return f.fail("TODO implement c_va_start", .{}),
+ .c_va_start => try airCVaStart(f, inst),
+ .c_va_arg => try airCVaArg(f, inst),
+ .c_va_end => try airCVaEnd(f, inst),
+ .c_va_copy => try airCVaCopy(f, inst),
// zig fmt: on
};
if (result_value == .new_local) {
@@ -6862,6 +6871,82 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
+fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
+ if (f.liveness.isUnused(inst)) return .none;
+
+ const inst_ty = f.air.typeOfIndex(inst);
+ const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);
+
+ const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
+ if (param_len == 0)
+ return f.fail("CBE: C requires at least one runtime argument for varargs functions", .{});
+
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
+ try writer.writeAll("va_start(*(va_list *)&");
+ try f.writeCValue(writer, local, .Other);
+ try writer.writeAll(", ");
+ try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument);
+ try writer.writeAll(");\n");
+ return local;
+}
+
+fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
+ const ty_op = f.air.instructions.items(.data)[inst].ty_op;
+ if (f.liveness.isUnused(inst)) {
+ try reap(f, inst, &.{ty_op.operand});
+ return .none;
+ }
+
+ const inst_ty = f.air.typeOfIndex(inst);
+ const va_list = try f.resolveInst(ty_op.operand);
+ try reap(f, inst, &.{ty_op.operand});
+
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
+ try f.writeCValue(writer, local, .Other);
+ try writer.writeAll(" = va_arg(*(va_list *)");
+ try f.writeCValue(writer, va_list, .Other);
+ try writer.writeAll(", ");
+ try f.renderType(writer, f.air.getRefType(ty_op.ty));
+ try writer.writeAll(");\n");
+ return local;
+}
+
+fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
+ const un_op = f.air.instructions.items(.data)[inst].un_op;
+
+ const va_list = try f.resolveInst(un_op);
+ try reap(f, inst, &.{un_op});
+
+ const writer = f.object.writer();
+ try writer.writeAll("va_end(*(va_list *)");
+ try f.writeCValue(writer, va_list, .Other);
+ try writer.writeAll(");\n");
+ return .none;
+}
+
+fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
+ const ty_op = f.air.instructions.items(.data)[inst].ty_op;
+ if (f.liveness.isUnused(inst)) {
+ try reap(f, inst, &.{ty_op.operand});
+ return .none;
+ }
+
+ const inst_ty = f.air.typeOfIndex(inst);
+ const va_list = try f.resolveInst(ty_op.operand);
+ try reap(f, inst, &.{ty_op.operand});
+
+ const writer = f.object.writer();
+ const local = try f.allocLocal(inst, inst_ty);
+ try writer.writeAll("va_copy(*(va_list *)&");
+ try f.writeCValue(writer, local, .Other);
+ try writer.writeAll(", *(va_list *)");
+ try f.writeCValue(writer, va_list, .Other);
+ try writer.writeAll(");\n");
+ return local;
+}
+
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
// Note: unordered is actually even less atomic than relaxed