aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniele Cocca <daniele.cocca@gmail.com>2022-03-15 00:02:17 +0000
committerDaniele Cocca <daniele.cocca@gmail.com>2022-03-18 16:50:34 +0000
commit6fdca525dec95ea9ed96946188af41d3d0c29f47 (patch)
treecbf3fe487335722c726da2c052943f5bfebdce2e /src
parent085e122e296b30de7ef83d10564115a5991bbb2a (diff)
downloadzig-6fdca525dec95ea9ed96946188af41d3d0c29f47.tar.gz
zig-6fdca525dec95ea9ed96946188af41d3d0c29f47.zip
CBE: add support for tuples
Also promote tests that are now passing.
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig85
1 files changed, 80 insertions, 5 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index c306e0a6b0..b814be4445 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1000,6 +1000,46 @@ pub const DeclGen = struct {
return name;
}
+ fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
+ const tuple = t.tupleFields();
+
+ var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
+ defer buffer.deinit();
+ const writer = buffer.writer();
+
+ try buffer.appendSlice("typedef struct {\n");
+ {
+ for (tuple.types) |field_ty, i| {
+ const val = tuple.values[i];
+ if (val.tag() != .unreachable_value) continue;
+
+ var name = std.ArrayList(u8).init(dg.gpa);
+ defer name.deinit();
+ try name.writer().print("field_{d}", .{i});
+
+ try buffer.append(' ');
+ try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, Value.initTag(.abi_align_default));
+ try buffer.appendSlice(";\n");
+ }
+ }
+ try buffer.appendSlice("} ");
+
+ const name_start = buffer.items.len;
+ try writer.print("zig_T_{};\n", .{typeToCIdentifier(t)});
+
+ const rendered = buffer.toOwnedSlice();
+ errdefer dg.typedefs.allocator.free(rendered);
+ const name = rendered[name_start .. rendered.len - 2];
+
+ try dg.typedefs.ensureUnusedCapacity(1);
+ dg.typedefs.putAssumeCapacityNoClobber(
+ try t.copy(dg.typedefs_arena),
+ .{ .name = name, .rendered = rendered },
+ );
+
+ return name;
+ }
+
fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
const union_ty = t.cast(Type.Payload.Union).?.data;
const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator);
@@ -1276,7 +1316,9 @@ pub const DeclGen = struct {
return w.writeAll(name);
},
.Struct => {
- const name = dg.getTypedefName(t) orelse
+ const name = dg.getTypedefName(t) orelse if (t.isTuple())
+ try dg.renderTupleTypedef(t)
+ else
try dg.renderStructTypedef(t);
return w.writeAll(name);
@@ -3116,6 +3158,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
var field_name: []const u8 = undefined;
var field_val_ty: Type = undefined;
+ var buf = std.ArrayList(u8).init(f.object.dg.gpa);
+ defer buf.deinit();
switch (struct_ty.tag()) {
.@"struct" => {
const fields = struct_ty.structFields();
@@ -3127,6 +3171,14 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
field_name = fields.keys()[index];
field_val_ty = fields.values()[index].ty;
},
+ .tuple => {
+ const tuple = struct_ty.tupleFields();
+ if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
+
+ try buf.writer().print("field_{d}", .{index});
+ field_name = buf.items;
+ field_val_ty = tuple.types[index];
+ },
else => unreachable,
}
const payload = if (struct_ty.tag() == .union_tagged) "payload." else "";
@@ -3149,9 +3201,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const struct_byval = try f.resolveInst(extra.struct_operand);
const struct_ty = f.air.typeOf(extra.struct_operand);
+ var buf = std.ArrayList(u8).init(f.object.dg.gpa);
+ defer buf.deinit();
const field_name = switch (struct_ty.tag()) {
.@"struct" => struct_ty.structFields().keys()[extra.field_index],
.@"union", .union_tagged => struct_ty.unionFields().keys()[extra.field_index],
+ .tuple => blk: {
+ const tuple = struct_ty.tupleFields();
+ if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
+
+ try buf.writer().print("field_{d}", .{extra.field_index});
+ break :blk buf.items;
+ },
else => unreachable,
};
const payload = if (struct_ty.tag() == .union_tagged) "payload." else "";
@@ -3652,11 +3713,25 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(inst_ty, .Const);
- try writer.writeAll(" = ");
+ try writer.writeAll(" = {");
+ switch (vector_ty.zigTypeTag()) {
+ .Struct => {
+ const tuple = vector_ty.tupleFields();
+ var i: usize = 0;
+ for (elements) |elem, elem_index| {
+ if (tuple.values[elem_index].tag() != .unreachable_value) continue;
+
+ const value = try f.resolveInst(elem);
+ if (i != 0) try writer.writeAll(", ");
+ try f.writeCValue(writer, value);
+ i += 1;
+ }
+ },
+ else => |tag| return f.fail("TODO: C backend: implement airAggregateInit for type {s}", .{@tagName(tag)}),
+ }
+ try writer.writeAll("};\n");
- _ = elements;
- _ = local;
- return f.fail("TODO: C backend: implement airAggregateInit", .{});
+ return local;
}
fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {