| ... | @@ -542,9 +542,14 @@ pub const DeclGen = struct { | ... | @@ -542,9 +542,14 @@ pub const DeclGen = struct { |
| 542 | return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty); | 542 | return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty); |
| 543 | }, | 543 | }, |
| 544 | }, | 544 | }, |
| 545 | .Union => FieldInfo{ | 545 | .Union => switch (container_ty.containerLayout()) { |
| 546 | .name = container_ty.unionFields().keys()[index], | 546 | .Auto, .Extern => FieldInfo{ |
| 547 | .ty = container_ty.unionFields().values()[index].ty, | 547 | .name = container_ty.unionFields().keys()[index], |
| | 548 | .ty = container_ty.unionFields().values()[index].ty, |
| | 549 | }, |
| | 550 | .Packed => { |
| | 551 | return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty); |
| | 552 | }, |
| 548 | }, | 553 | }, |
| 549 | .Pointer => field_info: { | 554 | .Pointer => field_info: { |
| 550 | assert(container_ty.isSlice()); | 555 | assert(container_ty.isSlice()); |
| ... | @@ -1165,6 +1170,27 @@ pub const DeclGen = struct { | ... | @@ -1165,6 +1170,27 @@ pub const DeclGen = struct { |
| 1165 | try writer.writeByte(')'); | 1170 | try writer.writeByte(')'); |
| 1166 | } | 1171 | } |
| 1167 | | 1172 | |
| | 1173 | const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?; |
| | 1174 | const field_ty = ty.unionFields().values()[index].ty; |
| | 1175 | const field_name = ty.unionFields().keys()[index]; |
| | 1176 | if (ty.containerLayout() == .Packed) { |
| | 1177 | if (field_ty.hasRuntimeBits()) { |
| | 1178 | if (field_ty.isPtrAtRuntime()) { |
| | 1179 | try writer.writeByte('('); |
| | 1180 | try dg.renderTypecast(writer, ty); |
| | 1181 | try writer.writeByte(')'); |
| | 1182 | } else if (field_ty.zigTypeTag() == .Float) { |
| | 1183 | try writer.writeByte('('); |
| | 1184 | try dg.renderTypecast(writer, ty); |
| | 1185 | try writer.writeByte(')'); |
| | 1186 | } |
| | 1187 | try dg.renderValue(writer, field_ty, union_obj.val, .Initializer); |
| | 1188 | } else { |
| | 1189 | try writer.writeAll("0"); |
| | 1190 | } |
| | 1191 | return; |
| | 1192 | } |
| | 1193 | |
| 1168 | try writer.writeByte('{'); | 1194 | try writer.writeByte('{'); |
| 1169 | if (ty.unionTagTypeSafety()) |tag_ty| { | 1195 | if (ty.unionTagTypeSafety()) |tag_ty| { |
| 1170 | const layout = ty.unionGetLayout(target); | 1196 | const layout = ty.unionGetLayout(target); |
| ... | @@ -1176,9 +1202,6 @@ pub const DeclGen = struct { | ... | @@ -1176,9 +1202,6 @@ pub const DeclGen = struct { |
| 1176 | try writer.writeAll(".payload = {"); | 1202 | try writer.writeAll(".payload = {"); |
| 1177 | } | 1203 | } |
| 1178 | | 1204 | |
| 1179 | const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?; | | |
| 1180 | const field_ty = ty.unionFields().values()[index].ty; | | |
| 1181 | const field_name = ty.unionFields().keys()[index]; | | |
| 1182 | var it = ty.unionFields().iterator(); | 1205 | var it = ty.unionFields().iterator(); |
| 1183 | if (field_ty.hasRuntimeBits()) { | 1206 | if (field_ty.hasRuntimeBits()) { |
| 1184 | try writer.print(".{ } = ", .{fmtIdent(field_name)}); | 1207 | try writer.print(".{ } = ", .{fmtIdent(field_name)}); |
| ... | @@ -1794,9 +1817,17 @@ pub const DeclGen = struct { | ... | @@ -1794,9 +1817,17 @@ pub const DeclGen = struct { |
| 1794 | | 1817 | |
| 1795 | return w.writeAll(name); | 1818 | return w.writeAll(name); |
| 1796 | }, | 1819 | }, |
| 1797 | .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed) | 1820 | .Struct, .Union => |tag| if (t.containerLayout() == .Packed) { |
| 1798 | try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind) | 1821 | if (t.castTag(.@"struct")) |struct_obj| { |
| 1799 | else if (t.isSimpleTupleOrAnonStruct()) { | 1822 | try dg.renderType(w, struct_obj.data.backing_int_ty, kind); |
| | 1823 | } else { |
| | 1824 | var buf: Type.Payload.Bits = .{ |
| | 1825 | .base = .{ .tag = .int_unsigned }, |
| | 1826 | .data = @intCast(u16, t.bitSize(target)), |
| | 1827 | }; |
| | 1828 | try dg.renderType(w, Type.initPayload(&buf.base), kind); |
| | 1829 | } |
| | 1830 | } else if (t.isSimpleTupleOrAnonStruct()) { |
| 1800 | const ExpectedContents = struct { types: [8]Type, values: [8]Value }; | 1831 | const ExpectedContents = struct { types: [8]Type, values: [8]Value }; |
| 1801 | var stack align(@alignOf(ExpectedContents)) = | 1832 | var stack align(@alignOf(ExpectedContents)) = |
| 1802 | std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa); | 1833 | std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa); |
| ... | @@ -4388,7 +4419,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc | ... | @@ -4388,7 +4419,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 4388 | return local; | 4419 | return local; |
| 4389 | } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug | 4420 | } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug |
| 4390 | }, | 4421 | }, |
| 4391 | .@"union", .union_safety_tagged, .union_tagged => .{ | 4422 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { |
| | 4423 | try f.writeCValue(writer, struct_ptr, .Other); |
| | 4424 | try writer.writeAll(";\n"); |
| | 4425 | return local; |
| | 4426 | } else .{ |
| 4392 | .identifier = struct_ty.unionFields().keys()[index], | 4427 | .identifier = struct_ty.unionFields().keys()[index], |
| 4393 | }, | 4428 | }, |
| 4394 | .tuple, .anon_struct => field_name: { | 4429 | .tuple, .anon_struct => field_name: { |
| ... | @@ -4502,7 +4537,26 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4502,7 +4537,26 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4502 | return local; | 4537 | return local; |
| 4503 | }, | 4538 | }, |
| 4504 | }, | 4539 | }, |
| 4505 | .@"union", .union_safety_tagged, .union_tagged => .{ | 4540 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { |
| | 4541 | const operand_lval = if (struct_byval == .constant) blk: { |
| | 4542 | const operand_local = try f.allocLocal(struct_ty, .Const); |
| | 4543 | try writer.writeAll(" = "); |
| | 4544 | try f.writeCValue(writer, struct_byval, .Initializer); |
| | 4545 | try writer.writeAll(";\n"); |
| | 4546 | break :blk operand_local; |
| | 4547 | } else struct_byval; |
| | 4548 | |
| | 4549 | const local = try f.allocLocal(inst_ty, .Mut); |
| | 4550 | try writer.writeAll(";\n"); |
| | 4551 | try writer.writeAll("memcpy(&"); |
| | 4552 | try f.writeCValue(writer, local, .FunctionArgument); |
| | 4553 | try writer.writeAll(", &"); |
| | 4554 | try f.writeCValue(writer, operand_lval, .FunctionArgument); |
| | 4555 | try writer.writeAll(", sizeof("); |
| | 4556 | try f.renderTypecast(writer, inst_ty); |
| | 4557 | try writer.writeAll("));\n"); |
| | 4558 | return local; |
| | 4559 | } else .{ |
| 4506 | .identifier = struct_ty.unionFields().keys()[extra.field_index], | 4560 | .identifier = struct_ty.unionFields().keys()[extra.field_index], |
| 4507 | }, | 4561 | }, |
| 4508 | .tuple, .anon_struct => blk: { | 4562 | .tuple, .anon_struct => blk: { |
| ... | @@ -5565,6 +5619,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5565,6 +5619,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5565 | | 5619 | |
| 5566 | const writer = f.object.writer(); | 5620 | const writer = f.object.writer(); |
| 5567 | const local = try f.allocLocal(union_ty, .Const); | 5621 | const local = try f.allocLocal(union_ty, .Const); |
| | 5622 | if (union_obj.layout == .Packed) { |
| | 5623 | try writer.writeAll(" = "); |
| | 5624 | try f.writeCValue(writer, payload, .Initializer); |
| | 5625 | try writer.writeAll(";\n"); |
| | 5626 | return local; |
| | 5627 | } |
| | 5628 | |
| 5568 | try writer.writeAll(" = {"); | 5629 | try writer.writeAll(" = {"); |
| 5569 | if (union_ty.unionTagTypeSafety()) |tag_ty| { | 5630 | if (union_ty.unionTagTypeSafety()) |tag_ty| { |
| 5570 | const layout = union_ty.unionGetLayout(target); | 5631 | const layout = union_ty.unionGetLayout(target); |