aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig83
1 files changed, 72 insertions, 11 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 6a7ef2c007..7db7f56de6 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -542,9 +542,14 @@ pub const DeclGen = struct {
return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty);
},
},
- .Union => FieldInfo{
- .name = container_ty.unionFields().keys()[index],
- .ty = container_ty.unionFields().values()[index].ty,
+ .Union => switch (container_ty.containerLayout()) {
+ .Auto, .Extern => FieldInfo{
+ .name = container_ty.unionFields().keys()[index],
+ .ty = container_ty.unionFields().values()[index].ty,
+ },
+ .Packed => {
+ return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty);
+ },
},
.Pointer => field_info: {
assert(container_ty.isSlice());
@@ -1165,6 +1170,27 @@ pub const DeclGen = struct {
try writer.writeByte(')');
}
+ const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
+ const field_ty = ty.unionFields().values()[index].ty;
+ const field_name = ty.unionFields().keys()[index];
+ if (ty.containerLayout() == .Packed) {
+ if (field_ty.hasRuntimeBits()) {
+ if (field_ty.isPtrAtRuntime()) {
+ try writer.writeByte('(');
+ try dg.renderTypecast(writer, ty);
+ try writer.writeByte(')');
+ } else if (field_ty.zigTypeTag() == .Float) {
+ try writer.writeByte('(');
+ try dg.renderTypecast(writer, ty);
+ try writer.writeByte(')');
+ }
+ try dg.renderValue(writer, field_ty, union_obj.val, .Initializer);
+ } else {
+ try writer.writeAll("0");
+ }
+ return;
+ }
+
try writer.writeByte('{');
if (ty.unionTagTypeSafety()) |tag_ty| {
const layout = ty.unionGetLayout(target);
@@ -1176,9 +1202,6 @@ pub const DeclGen = struct {
try writer.writeAll(".payload = {");
}
- const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
- const field_ty = ty.unionFields().values()[index].ty;
- const field_name = ty.unionFields().keys()[index];
var it = ty.unionFields().iterator();
if (field_ty.hasRuntimeBits()) {
try writer.print(".{ } = ", .{fmtIdent(field_name)});
@@ -1794,9 +1817,17 @@ pub const DeclGen = struct {
return w.writeAll(name);
},
- .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed)
- try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind)
- else if (t.isSimpleTupleOrAnonStruct()) {
+ .Struct, .Union => |tag| if (t.containerLayout() == .Packed) {
+ if (t.castTag(.@"struct")) |struct_obj| {
+ try dg.renderType(w, struct_obj.data.backing_int_ty, kind);
+ } else {
+ var buf: Type.Payload.Bits = .{
+ .base = .{ .tag = .int_unsigned },
+ .data = @intCast(u16, t.bitSize(target)),
+ };
+ try dg.renderType(w, Type.initPayload(&buf.base), kind);
+ }
+ } else if (t.isSimpleTupleOrAnonStruct()) {
const ExpectedContents = struct { types: [8]Type, values: [8]Value };
var stack align(@alignOf(ExpectedContents)) =
std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa);
@@ -4388,7 +4419,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
return local;
} else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug
},
- .@"union", .union_safety_tagged, .union_tagged => .{
+ .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
+ try f.writeCValue(writer, struct_ptr, .Other);
+ try writer.writeAll(";\n");
+ return local;
+ } else .{
.identifier = struct_ty.unionFields().keys()[index],
},
.tuple, .anon_struct => field_name: {
@@ -4502,7 +4537,26 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
},
},
- .@"union", .union_safety_tagged, .union_tagged => .{
+ .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
+ const operand_lval = if (struct_byval == .constant) blk: {
+ const operand_local = try f.allocLocal(struct_ty, .Const);
+ try writer.writeAll(" = ");
+ try f.writeCValue(writer, struct_byval, .Initializer);
+ try writer.writeAll(";\n");
+ break :blk operand_local;
+ } else struct_byval;
+
+ const local = try f.allocLocal(inst_ty, .Mut);
+ try writer.writeAll(";\n");
+ try writer.writeAll("memcpy(&");
+ try f.writeCValue(writer, local, .FunctionArgument);
+ try writer.writeAll(", &");
+ try f.writeCValue(writer, operand_lval, .FunctionArgument);
+ try writer.writeAll(", sizeof(");
+ try f.renderTypecast(writer, inst_ty);
+ try writer.writeAll("));\n");
+ return local;
+ } else .{
.identifier = struct_ty.unionFields().keys()[extra.field_index],
},
.tuple, .anon_struct => blk: {
@@ -5565,6 +5619,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const local = try f.allocLocal(union_ty, .Const);
+ if (union_obj.layout == .Packed) {
+ try writer.writeAll(" = ");
+ try f.writeCValue(writer, payload, .Initializer);
+ try writer.writeAll(";\n");
+ return local;
+ }
+
try writer.writeAll(" = {");
if (union_ty.unionTagTypeSafety()) |tag_ty| {
const layout = union_ty.unionGetLayout(target);