| ... | @@ -982,44 +982,36 @@ pub const DeclGen = struct { | ... | @@ -982,44 +982,36 @@ pub const DeclGen = struct { |
| 982 | | 982 | |
| 983 | try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len); | 983 | try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len); |
| 984 | | 984 | |
| 985 | // We need to insert extra padding if LLVM's isn't enough. | 985 | comptime assert(struct_layout_version == 2); |
| 986 | var zig_offset: u64 = 0; | 986 | var offset: u64 = 0; |
| 987 | var llvm_offset: u64 = 0; | 987 | var big_align: u32 = 0; |
| 988 | var zig_big_align: u32 = 0; | | |
| 989 | var llvm_big_align: u32 = 0; | | |
| 990 | | 988 | |
| 991 | for (tuple.types) |field_ty, i| { | 989 | for (tuple.types) |field_ty, i| { |
| 992 | const field_val = tuple.values[i]; | 990 | const field_val = tuple.values[i]; |
| 993 | if (field_val.tag() != .unreachable_value) continue; | 991 | if (field_val.tag() != .unreachable_value) continue; |
| 994 | | 992 | |
| 995 | const field_align = field_ty.abiAlignment(target); | 993 | const field_align = field_ty.abiAlignment(target); |
| 996 | zig_big_align = @maximum(zig_big_align, field_align); | 994 | big_align = @maximum(big_align, field_align); |
| 997 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, field_align); | 995 | const prev_offset = offset; |
| | 996 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 998 | | 997 | |
| 999 | const field_llvm_ty = try dg.llvmType(field_ty); | 998 | const padding_len = offset - prev_offset; |
| 1000 | const field_llvm_align = dg.object.target_data.ABIAlignmentOfType(field_llvm_ty); | | |
| 1001 | llvm_big_align = @maximum(llvm_big_align, field_llvm_align); | | |
| 1002 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, field_llvm_align); | | |
| 1003 | | | |
| 1004 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | | |
| 1005 | if (padding_len > 0) { | 999 | if (padding_len > 0) { |
| 1006 | const llvm_array_ty = dg.context.intType(8).arrayType(padding_len); | 1000 | const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); |
| 1007 | try llvm_field_types.append(gpa, llvm_array_ty); | 1001 | try llvm_field_types.append(gpa, llvm_array_ty); |
| 1008 | llvm_offset = zig_offset; | | |
| 1009 | } | 1002 | } |
| | 1003 | const field_llvm_ty = try dg.llvmType(field_ty); |
| 1010 | try llvm_field_types.append(gpa, field_llvm_ty); | 1004 | try llvm_field_types.append(gpa, field_llvm_ty); |
| 1011 | | 1005 | |
| 1012 | llvm_offset += dg.object.target_data.ABISizeOfType(field_llvm_ty); | 1006 | offset += field_ty.abiSize(target); |
| 1013 | zig_offset += field_ty.abiSize(target); | | |
| 1014 | } | 1007 | } |
| 1015 | { | 1008 | { |
| 1016 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, zig_big_align); | 1009 | const prev_offset = offset; |
| 1017 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, llvm_big_align); | 1010 | offset = std.mem.alignForwardGeneric(u64, offset, big_align); |
| 1018 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | 1011 | const padding_len = offset - prev_offset; |
| 1019 | if (padding_len > 0) { | 1012 | if (padding_len > 0) { |
| 1020 | const llvm_array_ty = dg.context.intType(8).arrayType(padding_len); | 1013 | const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); |
| 1021 | try llvm_field_types.append(gpa, llvm_array_ty); | 1014 | try llvm_field_types.append(gpa, llvm_array_ty); |
| 1022 | llvm_offset = zig_offset; | | |
| 1023 | } | 1015 | } |
| 1024 | } | 1016 | } |
| 1025 | | 1017 | |
| ... | @@ -1055,43 +1047,35 @@ pub const DeclGen = struct { | ... | @@ -1055,43 +1047,35 @@ pub const DeclGen = struct { |
| 1055 | | 1047 | |
| 1056 | try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count()); | 1048 | try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count()); |
| 1057 | | 1049 | |
| 1058 | // We need to insert extra padding if LLVM's isn't enough. | 1050 | comptime assert(struct_layout_version == 2); |
| 1059 | var zig_offset: u64 = 0; | 1051 | var offset: u64 = 0; |
| 1060 | var llvm_offset: u64 = 0; | 1052 | var big_align: u32 = 0; |
| 1061 | var zig_big_align: u32 = 0; | | |
| 1062 | var llvm_big_align: u32 = 0; | | |
| 1063 | | 1053 | |
| 1064 | for (struct_obj.fields.values()) |field| { | 1054 | for (struct_obj.fields.values()) |field| { |
| 1065 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | 1055 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; |
| 1066 | | 1056 | |
| 1067 | const field_align = field.normalAlignment(target); | 1057 | const field_align = field.normalAlignment(target); |
| 1068 | zig_big_align = @maximum(zig_big_align, field_align); | 1058 | big_align = @maximum(big_align, field_align); |
| 1069 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, field_align); | 1059 | const prev_offset = offset; |
| 1070 | | 1060 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 1071 | const field_llvm_ty = try dg.llvmType(field.ty); | | |
| 1072 | const field_llvm_align = dg.object.target_data.ABIAlignmentOfType(field_llvm_ty); | | |
| 1073 | llvm_big_align = @maximum(llvm_big_align, field_llvm_align); | | |
| 1074 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, field_llvm_align); | | |
| 1075 | | 1061 | |
| 1076 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | 1062 | const padding_len = offset - prev_offset; |
| 1077 | if (padding_len > 0) { | 1063 | if (padding_len > 0) { |
| 1078 | const llvm_array_ty = dg.context.intType(8).arrayType(padding_len); | 1064 | const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); |
| 1079 | try llvm_field_types.append(gpa, llvm_array_ty); | 1065 | try llvm_field_types.append(gpa, llvm_array_ty); |
| 1080 | llvm_offset = zig_offset; | | |
| 1081 | } | 1066 | } |
| | 1067 | const field_llvm_ty = try dg.llvmType(field.ty); |
| 1082 | try llvm_field_types.append(gpa, field_llvm_ty); | 1068 | try llvm_field_types.append(gpa, field_llvm_ty); |
| 1083 | | 1069 | |
| 1084 | llvm_offset += dg.object.target_data.ABISizeOfType(field_llvm_ty); | 1070 | offset += field.ty.abiSize(target); |
| 1085 | zig_offset += field.ty.abiSize(target); | | |
| 1086 | } | 1071 | } |
| 1087 | { | 1072 | { |
| 1088 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, zig_big_align); | 1073 | const prev_offset = offset; |
| 1089 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, llvm_big_align); | 1074 | offset = std.mem.alignForwardGeneric(u64, offset, big_align); |
| 1090 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | 1075 | const padding_len = offset - prev_offset; |
| 1091 | if (padding_len > 0) { | 1076 | if (padding_len > 0) { |
| 1092 | const llvm_array_ty = dg.context.intType(8).arrayType(padding_len); | 1077 | const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); |
| 1093 | try llvm_field_types.append(gpa, llvm_array_ty); | 1078 | try llvm_field_types.append(gpa, llvm_array_ty); |
| 1094 | llvm_offset = zig_offset; | | |
| 1095 | } | 1079 | } |
| 1096 | } | 1080 | } |
| 1097 | | 1081 | |
| ... | @@ -1111,71 +1095,61 @@ pub const DeclGen = struct { | ... | @@ -1111,71 +1095,61 @@ pub const DeclGen = struct { |
| 1111 | // reference, we need to copy it here. | 1095 | // reference, we need to copy it here. |
| 1112 | gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator()); | 1096 | gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator()); |
| 1113 | | 1097 | |
| | 1098 | const layout = t.unionGetLayout(target); |
| 1114 | const union_obj = t.cast(Type.Payload.Union).?.data; | 1099 | const union_obj = t.cast(Type.Payload.Union).?.data; |
| 1115 | if (t.unionTagType()) |enum_tag_ty| { | | |
| 1116 | const layout = union_obj.getLayout(target, true); | | |
| 1117 | | 1100 | |
| 1118 | if (layout.payload_size == 0) { | 1101 | if (layout.payload_size == 0) { |
| 1119 | const enum_tag_llvm_ty = try dg.llvmType(enum_tag_ty); | 1102 | const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty); |
| 1120 | gop.value_ptr.* = enum_tag_llvm_ty; | 1103 | gop.value_ptr.* = enum_tag_llvm_ty; |
| 1121 | return enum_tag_llvm_ty; | 1104 | return enum_tag_llvm_ty; |
| 1122 | } | 1105 | } |
| 1123 | | 1106 | |
| 1124 | const name = try union_obj.getFullyQualifiedName(gpa); | 1107 | const name = try union_obj.getFullyQualifiedName(gpa); |
| 1125 | defer gpa.free(name); | 1108 | defer gpa.free(name); |
| 1126 | | 1109 | |
| 1127 | const llvm_union_ty = dg.context.structCreateNamed(name); | 1110 | const llvm_union_ty = dg.context.structCreateNamed(name); |
| 1128 | gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls | 1111 | gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls |
| 1129 | | 1112 | |
| 1130 | const aligned_field = union_obj.fields.values()[layout.most_aligned_field]; | 1113 | const aligned_field = union_obj.fields.values()[layout.most_aligned_field]; |
| 1131 | const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty); | 1114 | const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty); |
| 1132 | | 1115 | |
| 1133 | const llvm_payload_ty = t: { | 1116 | const llvm_payload_ty = t: { |
| 1134 | if (layout.most_aligned_field_size == layout.payload_size) { | 1117 | if (layout.most_aligned_field_size == layout.payload_size) { |
| 1135 | break :t llvm_aligned_field_ty; | 1118 | break :t llvm_aligned_field_ty; |
| 1136 | } | 1119 | } |
| 1137 | const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size); | 1120 | const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size); |
| 1138 | const fields: [2]*const llvm.Type = .{ | 1121 | const fields: [2]*const llvm.Type = .{ |
| 1139 | llvm_aligned_field_ty, | 1122 | llvm_aligned_field_ty, |
| 1140 | dg.context.intType(8).arrayType(padding_len), | 1123 | dg.context.intType(8).arrayType(padding_len), |
| 1141 | }; | | |
| 1142 | break :t dg.context.structType(&fields, fields.len, .True); | | |
| 1143 | }; | 1124 | }; |
| | 1125 | break :t dg.context.structType(&fields, fields.len, .True); |
| | 1126 | }; |
| 1144 | | 1127 | |
| 1145 | if (layout.tag_size == 0) { | 1128 | if (layout.tag_size == 0) { |
| 1146 | var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty}; | 1129 | var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty}; |
| 1147 | llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); | | |
| 1148 | return llvm_union_ty; | | |
| 1149 | } | | |
| 1150 | const enum_tag_llvm_ty = try dg.llvmType(enum_tag_ty); | | |
| 1151 | | | |
| 1152 | // Put the tag before or after the payload depending on which one's | | |
| 1153 | // alignment is greater. | | |
| 1154 | var llvm_fields: [2]*const llvm.Type = undefined; | | |
| 1155 | if (layout.tag_align >= layout.payload_align) { | | |
| 1156 | llvm_fields[0] = enum_tag_llvm_ty; | | |
| 1157 | llvm_fields[1] = llvm_payload_ty; | | |
| 1158 | } else { | | |
| 1159 | llvm_fields[0] = llvm_payload_ty; | | |
| 1160 | llvm_fields[1] = enum_tag_llvm_ty; | | |
| 1161 | } | | |
| 1162 | llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); | 1130 | llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); |
| 1163 | return llvm_union_ty; | 1131 | return llvm_union_ty; |
| 1164 | } | 1132 | } |
| 1165 | // Untagged union | 1133 | const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty); |
| 1166 | const layout = union_obj.getLayout(target, false); | | |
| 1167 | | 1134 | |
| 1168 | const name = try union_obj.getFullyQualifiedName(gpa); | 1135 | // Put the tag before or after the payload depending on which one's |
| 1169 | defer gpa.free(name); | 1136 | // alignment is greater. |
| | 1137 | var llvm_fields: [3]*const llvm.Type = undefined; |
| | 1138 | var llvm_fields_len: c_uint = 2; |
| 1170 | | 1139 | |
| 1171 | const llvm_union_ty = dg.context.structCreateNamed(name); | 1140 | if (layout.tag_align >= layout.payload_align) { |
| 1172 | gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls | 1141 | llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined }; |
| | 1142 | } else { |
| | 1143 | llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined }; |
| | 1144 | } |
| 1173 | | 1145 | |
| 1174 | const big_field = union_obj.fields.values()[layout.biggest_field]; | 1146 | // Insert padding to make the LLVM struct ABI size match the Zig union ABI size. |
| 1175 | const llvm_big_field_ty = try dg.llvmType(big_field.ty); | 1147 | if (layout.padding != 0) { |
| | 1148 | llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding); |
| | 1149 | llvm_fields_len = 3; |
| | 1150 | } |
| 1176 | | 1151 | |
| 1177 | var llvm_fields: [1]*const llvm.Type = .{llvm_big_field_ty}; | 1152 | llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False); |
| 1178 | llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); | | |
| 1179 | return llvm_union_ty; | 1153 | return llvm_union_ty; |
| 1180 | }, | 1154 | }, |
| 1181 | .Fn => { | 1155 | .Fn => { |
| ... | @@ -1586,33 +1560,25 @@ pub const DeclGen = struct { | ... | @@ -1586,33 +1560,25 @@ pub const DeclGen = struct { |
| 1586 | var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count); | 1560 | var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count); |
| 1587 | defer llvm_fields.deinit(gpa); | 1561 | defer llvm_fields.deinit(gpa); |
| 1588 | | 1562 | |
| 1589 | // These are used to detect where the extra padding fields are so that we | 1563 | comptime assert(struct_layout_version == 2); |
| 1590 | // can initialize them with undefined. | 1564 | var offset: u64 = 0; |
| 1591 | var zig_offset: u64 = 0; | 1565 | var big_align: u32 = 0; |
| 1592 | var llvm_offset: u64 = 0; | | |
| 1593 | var zig_big_align: u32 = 0; | | |
| 1594 | var llvm_big_align: u32 = 0; | | |
| 1595 | | 1566 | |
| 1596 | var need_unnamed = false; | 1567 | var need_unnamed = false; |
| 1597 | for (struct_obj.fields.values()) |field, i| { | 1568 | for (struct_obj.fields.values()) |field, i| { |
| 1598 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | 1569 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; |
| 1599 | | 1570 | |
| 1600 | const field_align = field.normalAlignment(target); | 1571 | const field_align = field.normalAlignment(target); |
| 1601 | zig_big_align = @maximum(zig_big_align, field_align); | 1572 | big_align = @maximum(big_align, field_align); |
| 1602 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, field_align); | 1573 | const prev_offset = offset; |
| 1603 | | 1574 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 1604 | const field_llvm_ty = try dg.llvmType(field.ty); | | |
| 1605 | const field_llvm_align = dg.object.target_data.ABIAlignmentOfType(field_llvm_ty); | | |
| 1606 | llvm_big_align = @maximum(llvm_big_align, field_llvm_align); | | |
| 1607 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, field_llvm_align); | | |
| 1608 | | 1575 | |
| 1609 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | 1576 | const padding_len = offset - prev_offset; |
| 1610 | if (padding_len > 0) { | 1577 | if (padding_len > 0) { |
| 1611 | const llvm_array_ty = dg.context.intType(8).arrayType(padding_len); | 1578 | const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); |
| 1612 | // TODO make this and all other padding elsewhere in debug | 1579 | // TODO make this and all other padding elsewhere in debug |
| 1613 | // builds be 0xaa not undef. | 1580 | // builds be 0xaa not undef. |
| 1614 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); | 1581 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 1615 | llvm_offset = zig_offset; | | |
| 1616 | } | 1582 | } |
| 1617 | | 1583 | |
| 1618 | const field_llvm_val = try dg.genTypedValue(.{ | 1584 | const field_llvm_val = try dg.genTypedValue(.{ |
| ... | @@ -1624,17 +1590,15 @@ pub const DeclGen = struct { | ... | @@ -1624,17 +1590,15 @@ pub const DeclGen = struct { |
| 1624 | | 1590 | |
| 1625 | llvm_fields.appendAssumeCapacity(field_llvm_val); | 1591 | llvm_fields.appendAssumeCapacity(field_llvm_val); |
| 1626 | | 1592 | |
| 1627 | llvm_offset += dg.object.target_data.ABISizeOfType(field_llvm_ty); | 1593 | offset += field.ty.abiSize(target); |
| 1628 | zig_offset += field.ty.abiSize(target); | | |
| 1629 | } | 1594 | } |
| 1630 | { | 1595 | { |
| 1631 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, zig_big_align); | 1596 | const prev_offset = offset; |
| 1632 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, llvm_big_align); | 1597 | offset = std.mem.alignForwardGeneric(u64, offset, big_align); |
| 1633 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | 1598 | const padding_len = offset - prev_offset; |
| 1634 | if (padding_len > 0) { | 1599 | if (padding_len > 0) { |
| 1635 | const llvm_array_ty = dg.context.intType(8).arrayType(padding_len); | 1600 | const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); |
| 1636 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); | 1601 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 1637 | llvm_offset = zig_offset; | | |
| 1638 | } | 1602 | } |
| 1639 | } | 1603 | } |
| 1640 | | 1604 | |
| ... | @@ -1703,16 +1667,21 @@ pub const DeclGen = struct { | ... | @@ -1703,16 +1667,21 @@ pub const DeclGen = struct { |
| 1703 | .ty = tv.ty.unionTagType().?, | 1667 | .ty = tv.ty.unionTagType().?, |
| 1704 | .val = tag_and_val.tag, | 1668 | .val = tag_and_val.tag, |
| 1705 | }); | 1669 | }); |
| 1706 | var fields: [2]*const llvm.Value = undefined; | 1670 | var fields: [3]*const llvm.Value = undefined; |
| | 1671 | var fields_len: c_uint = 2; |
| 1707 | if (layout.tag_align >= layout.payload_align) { | 1672 | if (layout.tag_align >= layout.payload_align) { |
| 1708 | fields = .{ llvm_tag_value, payload }; | 1673 | fields = .{ llvm_tag_value, payload, undefined }; |
| 1709 | } else { | 1674 | } else { |
| 1710 | fields = .{ payload, llvm_tag_value }; | 1675 | fields = .{ payload, llvm_tag_value, undefined }; |
| | 1676 | } |
| | 1677 | if (layout.padding != 0) { |
| | 1678 | fields[2] = dg.context.intType(8).arrayType(layout.padding).getUndef(); |
| | 1679 | fields_len = 3; |
| 1711 | } | 1680 | } |
| 1712 | if (need_unnamed) { | 1681 | if (need_unnamed) { |
| 1713 | return dg.context.constStruct(&fields, fields.len, .False); | 1682 | return dg.context.constStruct(&fields, fields_len, .False); |
| 1714 | } else { | 1683 | } else { |
| 1715 | return llvm_union_ty.constNamedStruct(&fields, fields.len); | 1684 | return llvm_union_ty.constNamedStruct(&fields, fields_len); |
| 1716 | } | 1685 | } |
| 1717 | }, | 1686 | }, |
| 1718 | .Vector => switch (tv.val.tag()) { | 1687 | .Vector => switch (tv.val.tag()) { |
| ... | @@ -1867,7 +1836,7 @@ pub const DeclGen = struct { | ... | @@ -1867,7 +1836,7 @@ pub const DeclGen = struct { |
| 1867 | }, | 1836 | }, |
| 1868 | .Struct => { | 1837 | .Struct => { |
| 1869 | var ty_buf: Type.Payload.Pointer = undefined; | 1838 | var ty_buf: Type.Payload.Pointer = undefined; |
| 1870 | const llvm_field_index = dg.llvmFieldIndex(parent.ty, field_index, &ty_buf).?; | 1839 | const llvm_field_index = llvmFieldIndex(parent.ty, field_index, target, &ty_buf).?; |
| 1871 | const indices: [2]*const llvm.Value = .{ | 1840 | const indices: [2]*const llvm.Value = .{ |
| 1872 | llvm_u32.constInt(0, .False), | 1841 | llvm_u32.constInt(0, .False), |
| 1873 | llvm_u32.constInt(llvm_field_index, .False), | 1842 | llvm_u32.constInt(llvm_field_index, .False), |
| ... | @@ -2098,107 +2067,6 @@ pub const DeclGen = struct { | ... | @@ -2098,107 +2067,6 @@ pub const DeclGen = struct { |
| 2098 | return null; | 2067 | return null; |
| 2099 | } | 2068 | } |
| 2100 | } | 2069 | } |
| 2101 | | | |
| 2102 | /// Take into account 0 bit fields and padding. Returns null if an llvm | | |
| 2103 | /// field could not be found. | | |
| 2104 | /// This only happens if you want the field index of a zero sized field at | | |
| 2105 | /// the end of the struct. | | |
| 2106 | fn llvmFieldIndex( | | |
| 2107 | dg: *DeclGen, | | |
| 2108 | ty: Type, | | |
| 2109 | field_index: usize, | | |
| 2110 | ptr_pl_buf: *Type.Payload.Pointer, | | |
| 2111 | ) ?c_uint { | | |
| 2112 | const target = dg.module.getTarget(); | | |
| 2113 | | | |
| 2114 | // Detects where we inserted extra padding fields so that we can skip | | |
| 2115 | // over them in this function. | | |
| 2116 | var zig_offset: u64 = 0; | | |
| 2117 | var llvm_offset: u64 = 0; | | |
| 2118 | var zig_big_align: u32 = 0; | | |
| 2119 | var llvm_big_align: u32 = 0; | | |
| 2120 | | | |
| 2121 | if (ty.isTupleOrAnonStruct()) { | | |
| 2122 | const tuple = ty.tupleFields(); | | |
| 2123 | var llvm_field_index: c_uint = 0; | | |
| 2124 | for (tuple.types) |field_ty, i| { | | |
| 2125 | if (tuple.values[i].tag() != .unreachable_value) continue; | | |
| 2126 | | | |
| 2127 | const field_align = field_ty.abiAlignment(target); | | |
| 2128 | zig_big_align = @maximum(zig_big_align, field_align); | | |
| 2129 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, field_align); | | |
| 2130 | | | |
| 2131 | // assert no error because we have already seen a successful | | |
| 2132 | // llvmType on this field. | | |
| 2133 | const field_llvm_ty = dg.llvmType(field_ty) catch unreachable; | | |
| 2134 | const field_llvm_align = dg.object.target_data.ABIAlignmentOfType(field_llvm_ty); | | |
| 2135 | llvm_big_align = @maximum(llvm_big_align, field_llvm_align); | | |
| 2136 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, field_llvm_align); | | |
| 2137 | | | |
| 2138 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | | |
| 2139 | if (padding_len > 0) { | | |
| 2140 | llvm_field_index += 1; | | |
| 2141 | llvm_offset = zig_offset; | | |
| 2142 | } | | |
| 2143 | | | |
| 2144 | if (field_index == i) { | | |
| 2145 | ptr_pl_buf.* = .{ | | |
| 2146 | .data = .{ | | |
| 2147 | .pointee_type = field_ty, | | |
| 2148 | .@"align" = field_align, | | |
| 2149 | .@"addrspace" = .generic, | | |
| 2150 | }, | | |
| 2151 | }; | | |
| 2152 | return llvm_field_index; | | |
| 2153 | } | | |
| 2154 | | | |
| 2155 | llvm_field_index += 1; | | |
| 2156 | llvm_offset += dg.object.target_data.ABISizeOfType(field_llvm_ty); | | |
| 2157 | zig_offset += field_ty.abiSize(target); | | |
| 2158 | } | | |
| 2159 | return null; | | |
| 2160 | } | | |
| 2161 | assert(ty.containerLayout() != .Packed); | | |
| 2162 | | | |
| 2163 | var llvm_field_index: c_uint = 0; | | |
| 2164 | for (ty.structFields().values()) |field, i| { | | |
| 2165 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | | |
| 2166 | | | |
| 2167 | const field_align = field.normalAlignment(target); | | |
| 2168 | zig_big_align = @maximum(zig_big_align, field_align); | | |
| 2169 | zig_offset = std.mem.alignForwardGeneric(u64, zig_offset, field_align); | | |
| 2170 | | | |
| 2171 | // assert no error because we have already seen a successful llvmType on this field. | | |
| 2172 | const field_llvm_ty = dg.llvmType(field.ty) catch unreachable; | | |
| 2173 | const field_llvm_align = dg.object.target_data.ABIAlignmentOfType(field_llvm_ty); | | |
| 2174 | llvm_big_align = @maximum(llvm_big_align, field_llvm_align); | | |
| 2175 | llvm_offset = std.mem.alignForwardGeneric(u64, llvm_offset, field_llvm_align); | | |
| 2176 | | | |
| 2177 | const padding_len = @intCast(c_uint, zig_offset - llvm_offset); | | |
| 2178 | if (padding_len > 0) { | | |
| 2179 | llvm_field_index += 1; | | |
| 2180 | llvm_offset = zig_offset; | | |
| 2181 | } | | |
| 2182 | | | |
| 2183 | if (field_index == i) { | | |
| 2184 | ptr_pl_buf.* = .{ | | |
| 2185 | .data = .{ | | |
| 2186 | .pointee_type = field.ty, | | |
| 2187 | .@"align" = field_align, | | |
| 2188 | .@"addrspace" = .generic, | | |
| 2189 | }, | | |
| 2190 | }; | | |
| 2191 | return llvm_field_index; | | |
| 2192 | } | | |
| 2193 | | | |
| 2194 | llvm_field_index += 1; | | |
| 2195 | llvm_offset += dg.object.target_data.ABISizeOfType(field_llvm_ty); | | |
| 2196 | zig_offset += field.ty.abiSize(target); | | |
| 2197 | } else { | | |
| 2198 | // We did not find an llvm field that corresponds to this zig field. | | |
| 2199 | return null; | | |
| 2200 | } | | |
| 2201 | } | | |
| 2202 | }; | 2070 | }; |
| 2203 | | 2071 | |
| 2204 | pub const FuncGen = struct { | 2072 | pub const FuncGen = struct { |
| ... | @@ -2807,7 +2675,13 @@ pub const FuncGen = struct { | ... | @@ -2807,7 +2675,13 @@ pub const FuncGen = struct { |
| 2807 | const cond = try self.resolveInst(pl_op.operand); | 2675 | const cond = try self.resolveInst(pl_op.operand); |
| 2808 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); | 2676 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 2809 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); | 2677 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| 2810 | const llvm_switch = self.builder.buildSwitch(cond, else_block, switch_br.data.cases_len); | 2678 | const target = self.dg.module.getTarget(); |
| | 2679 | const llvm_usize = self.context.intType(target.cpu.arch.ptrBitWidth()); |
| | 2680 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) |
| | 2681 | self.builder.buildPtrToInt(cond, llvm_usize, "") |
| | 2682 | else |
| | 2683 | cond; |
| | 2684 | const llvm_switch = self.builder.buildSwitch(cond_int, else_block, switch_br.data.cases_len); |
| 2811 | | 2685 | |
| 2812 | var extra_index: usize = switch_br.end; | 2686 | var extra_index: usize = switch_br.end; |
| 2813 | var case_i: u32 = 0; | 2687 | var case_i: u32 = 0; |
| ... | @@ -2822,7 +2696,11 @@ pub const FuncGen = struct { | ... | @@ -2822,7 +2696,11 @@ pub const FuncGen = struct { |
| 2822 | | 2696 | |
| 2823 | for (items) |item| { | 2697 | for (items) |item| { |
| 2824 | const llvm_item = try self.resolveInst(item); | 2698 | const llvm_item = try self.resolveInst(item); |
| 2825 | llvm_switch.addCase(llvm_item, case_block); | 2699 | const llvm_int_item = if (llvm_item.typeOf().getTypeKind() == .Pointer) |
| | 2700 | llvm_item.constPtrToInt(llvm_usize) |
| | 2701 | else |
| | 2702 | llvm_item; |
| | 2703 | llvm_switch.addCase(llvm_int_item, case_block); |
| 2826 | } | 2704 | } |
| 2827 | | 2705 | |
| 2828 | self.builder.positionBuilderAtEnd(case_block); | 2706 | self.builder.positionBuilderAtEnd(case_block); |
| ... | @@ -3077,7 +2955,7 @@ pub const FuncGen = struct { | ... | @@ -3077,7 +2955,7 @@ pub const FuncGen = struct { |
| 3077 | }, | 2955 | }, |
| 3078 | else => { | 2956 | else => { |
| 3079 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 2957 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 3080 | const llvm_field_index = self.dg.llvmFieldIndex(struct_ty, field_index, &ptr_ty_buf).?; | 2958 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; |
| 3081 | return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, ""); | 2959 | return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, ""); |
| 3082 | }, | 2960 | }, |
| 3083 | }, | 2961 | }, |
| ... | @@ -3092,7 +2970,7 @@ pub const FuncGen = struct { | ... | @@ -3092,7 +2970,7 @@ pub const FuncGen = struct { |
| 3092 | .Struct => { | 2970 | .Struct => { |
| 3093 | assert(struct_ty.containerLayout() != .Packed); | 2971 | assert(struct_ty.containerLayout() != .Packed); |
| 3094 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 2972 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 3095 | const llvm_field_index = self.dg.llvmFieldIndex(struct_ty, field_index, &ptr_ty_buf).?; | 2973 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; |
| 3096 | const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); | 2974 | const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); |
| 3097 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); | 2975 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); |
| 3098 | return self.load(field_ptr, field_ptr_ty); | 2976 | return self.load(field_ptr, field_ptr_ty); |
| ... | @@ -4907,6 +4785,7 @@ pub const FuncGen = struct { | ... | @@ -4907,6 +4785,7 @@ pub const FuncGen = struct { |
| 4907 | const len = @intCast(usize, result_ty.arrayLen()); | 4785 | const len = @intCast(usize, result_ty.arrayLen()); |
| 4908 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 4786 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 4909 | const llvm_result_ty = try self.dg.llvmType(result_ty); | 4787 | const llvm_result_ty = try self.dg.llvmType(result_ty); |
| | 4788 | const target = self.dg.module.getTarget(); |
| 4910 | | 4789 | |
| 4911 | switch (result_ty.zigTypeTag()) { | 4790 | switch (result_ty.zigTypeTag()) { |
| 4912 | .Vector => { | 4791 | .Vector => { |
| ... | @@ -4928,7 +4807,6 @@ pub const FuncGen = struct { | ... | @@ -4928,7 +4807,6 @@ pub const FuncGen = struct { |
| 4928 | const alloca_inst = self.buildAlloca(llvm_result_ty); | 4807 | const alloca_inst = self.buildAlloca(llvm_result_ty); |
| 4929 | // TODO in debug builds init to undef so that the padding will be 0xaa | 4808 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 4930 | // even if we fully populate the fields. | 4809 | // even if we fully populate the fields. |
| 4931 | const target = self.dg.module.getTarget(); | | |
| 4932 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); | 4810 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); |
| 4933 | | 4811 | |
| 4934 | var indices: [2]*const llvm.Value = .{ llvm_u32.constNull(), undefined }; | 4812 | var indices: [2]*const llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| ... | @@ -4936,7 +4814,7 @@ pub const FuncGen = struct { | ... | @@ -4936,7 +4814,7 @@ pub const FuncGen = struct { |
| 4936 | if (result_ty.structFieldValueComptime(i) != null) continue; | 4814 | if (result_ty.structFieldValueComptime(i) != null) continue; |
| 4937 | | 4815 | |
| 4938 | const llvm_elem = try self.resolveInst(elem); | 4816 | const llvm_elem = try self.resolveInst(elem); |
| 4939 | const llvm_i = self.dg.llvmFieldIndex(result_ty, i, &ptr_ty_buf).?; | 4817 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; |
| 4940 | indices[1] = llvm_u32.constInt(llvm_i, .False); | 4818 | indices[1] = llvm_u32.constInt(llvm_i, .False); |
| 4941 | const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); | 4819 | const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); |
| 4942 | const store_inst = self.builder.buildStore(llvm_elem, field_ptr); | 4820 | const store_inst = self.builder.buildStore(llvm_elem, field_ptr); |
| ... | @@ -4950,7 +4828,7 @@ pub const FuncGen = struct { | ... | @@ -4950,7 +4828,7 @@ pub const FuncGen = struct { |
| 4950 | if (result_ty.structFieldValueComptime(i) != null) continue; | 4828 | if (result_ty.structFieldValueComptime(i) != null) continue; |
| 4951 | | 4829 | |
| 4952 | const llvm_elem = try self.resolveInst(elem); | 4830 | const llvm_elem = try self.resolveInst(elem); |
| 4953 | const llvm_i = self.dg.llvmFieldIndex(result_ty, i, &ptr_ty_buf).?; | 4831 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; |
| 4954 | result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, ""); | 4832 | result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, ""); |
| 4955 | } | 4833 | } |
| 4956 | return result; | 4834 | return result; |
| ... | @@ -4960,7 +4838,6 @@ pub const FuncGen = struct { | ... | @@ -4960,7 +4838,6 @@ pub const FuncGen = struct { |
| 4960 | assert(isByRef(result_ty)); | 4838 | assert(isByRef(result_ty)); |
| 4961 | | 4839 | |
| 4962 | const llvm_usize = try self.dg.llvmType(Type.usize); | 4840 | const llvm_usize = try self.dg.llvmType(Type.usize); |
| 4963 | const target = self.dg.module.getTarget(); | | |
| 4964 | const alloca_inst = self.buildAlloca(llvm_result_ty); | 4841 | const alloca_inst = self.buildAlloca(llvm_result_ty); |
| 4965 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); | 4842 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); |
| 4966 | | 4843 | |
| ... | @@ -5033,13 +4910,18 @@ pub const FuncGen = struct { | ... | @@ -5033,13 +4910,18 @@ pub const FuncGen = struct { |
| 5033 | const fields: [1]*const llvm.Type = .{payload}; | 4910 | const fields: [1]*const llvm.Type = .{payload}; |
| 5034 | break :t self.context.structType(&fields, fields.len, .False); | 4911 | break :t self.context.structType(&fields, fields.len, .False); |
| 5035 | } | 4912 | } |
| 5036 | var fields: [2]*const llvm.Type = undefined; | 4913 | var fields: [3]*const llvm.Type = undefined; |
| | 4914 | var fields_len: c_uint = 2; |
| 5037 | if (layout.tag_align >= layout.payload_align) { | 4915 | if (layout.tag_align >= layout.payload_align) { |
| 5038 | fields = .{ tag_llvm_ty, payload }; | 4916 | fields = .{ tag_llvm_ty, payload, undefined }; |
| 5039 | } else { | 4917 | } else { |
| 5040 | fields = .{ payload, tag_llvm_ty }; | 4918 | fields = .{ payload, tag_llvm_ty, undefined }; |
| | 4919 | } |
| | 4920 | if (layout.padding != 0) { |
| | 4921 | fields[2] = self.context.intType(8).arrayType(layout.padding); |
| | 4922 | fields_len = 3; |
| 5041 | } | 4923 | } |
| 5042 | break :t self.context.structType(&fields, fields.len, .False); | 4924 | break :t self.context.structType(&fields, fields_len, .False); |
| 5043 | }; | 4925 | }; |
| 5044 | | 4926 | |
| 5045 | const casted_ptr = self.builder.buildBitCast(result_ptr, llvm_union_ty.pointerType(0), ""); | 4927 | const casted_ptr = self.builder.buildBitCast(result_ptr, llvm_union_ty.pointerType(0), ""); |
| ... | @@ -5255,8 +5137,9 @@ pub const FuncGen = struct { | ... | @@ -5255,8 +5137,9 @@ pub const FuncGen = struct { |
| 5255 | return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); | 5137 | return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); |
| 5256 | }, | 5138 | }, |
| 5257 | else => { | 5139 | else => { |
| | 5140 | const target = self.dg.module.getTarget(); |
| 5258 | var ty_buf: Type.Payload.Pointer = undefined; | 5141 | var ty_buf: Type.Payload.Pointer = undefined; |
| 5259 | if (self.dg.llvmFieldIndex(struct_ty, field_index, &ty_buf)) |llvm_field_index| { | 5142 | if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { |
| 5260 | return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); | 5143 | return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); |
| 5261 | } else { | 5144 | } else { |
| 5262 | // If we found no index then this means this is a zero sized field at the | 5145 | // If we found no index then this means this is a zero sized field at the |
| ... | @@ -5667,6 +5550,88 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca | ... | @@ -5667,6 +5550,88 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca |
| 5667 | }; | 5550 | }; |
| 5668 | } | 5551 | } |
| 5669 | | 5552 | |
| | 5553 | /// Take into account 0 bit fields and padding. Returns null if an llvm |
| | 5554 | /// field could not be found. |
| | 5555 | /// This only happens if you want the field index of a zero sized field at |
| | 5556 | /// the end of the struct. |
| | 5557 | fn llvmFieldIndex( |
| | 5558 | ty: Type, |
| | 5559 | field_index: usize, |
| | 5560 | target: std.Target, |
| | 5561 | ptr_pl_buf: *Type.Payload.Pointer, |
| | 5562 | ) ?c_uint { |
| | 5563 | // Detects where we inserted extra padding fields so that we can skip |
| | 5564 | // over them in this function. |
| | 5565 | comptime assert(struct_layout_version == 2); |
| | 5566 | var offset: u64 = 0; |
| | 5567 | var big_align: u32 = 0; |
| | 5568 | |
| | 5569 | if (ty.isTupleOrAnonStruct()) { |
| | 5570 | const tuple = ty.tupleFields(); |
| | 5571 | var llvm_field_index: c_uint = 0; |
| | 5572 | for (tuple.types) |field_ty, i| { |
| | 5573 | if (tuple.values[i].tag() != .unreachable_value) continue; |
| | 5574 | |
| | 5575 | const field_align = field_ty.abiAlignment(target); |
| | 5576 | big_align = @maximum(big_align, field_align); |
| | 5577 | const prev_offset = offset; |
| | 5578 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| | 5579 | |
| | 5580 | const padding_len = offset - prev_offset; |
| | 5581 | if (padding_len > 0) { |
| | 5582 | llvm_field_index += 1; |
| | 5583 | } |
| | 5584 | |
| | 5585 | if (field_index == i) { |
| | 5586 | ptr_pl_buf.* = .{ |
| | 5587 | .data = .{ |
| | 5588 | .pointee_type = field_ty, |
| | 5589 | .@"align" = field_align, |
| | 5590 | .@"addrspace" = .generic, |
| | 5591 | }, |
| | 5592 | }; |
| | 5593 | return llvm_field_index; |
| | 5594 | } |
| | 5595 | |
| | 5596 | llvm_field_index += 1; |
| | 5597 | offset += field_ty.abiSize(target); |
| | 5598 | } |
| | 5599 | return null; |
| | 5600 | } |
| | 5601 | assert(ty.containerLayout() != .Packed); |
| | 5602 | |
| | 5603 | var llvm_field_index: c_uint = 0; |
| | 5604 | for (ty.structFields().values()) |field, i| { |
| | 5605 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; |
| | 5606 | |
| | 5607 | const field_align = field.normalAlignment(target); |
| | 5608 | big_align = @maximum(big_align, field_align); |
| | 5609 | const prev_offset = offset; |
| | 5610 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| | 5611 | |
| | 5612 | const padding_len = offset - prev_offset; |
| | 5613 | if (padding_len > 0) { |
| | 5614 | llvm_field_index += 1; |
| | 5615 | } |
| | 5616 | |
| | 5617 | if (field_index == i) { |
| | 5618 | ptr_pl_buf.* = .{ |
| | 5619 | .data = .{ |
| | 5620 | .pointee_type = field.ty, |
| | 5621 | .@"align" = field_align, |
| | 5622 | .@"addrspace" = .generic, |
| | 5623 | }, |
| | 5624 | }; |
| | 5625 | return llvm_field_index; |
| | 5626 | } |
| | 5627 | |
| | 5628 | llvm_field_index += 1; |
| | 5629 | offset += field.ty.abiSize(target); |
| | 5630 | } else { |
| | 5631 | // We did not find an llvm field that corresponds to this zig field. |
| | 5632 | return null; |
| | 5633 | } |
| | 5634 | } |
| 5670 | fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool { | 5635 | fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool { |
| 5671 | switch (fn_info.cc) { | 5636 | switch (fn_info.cc) { |
| 5672 | .Unspecified, .Inline => return isByRef(fn_info.return_type), | 5637 | .Unspecified, .Inline => return isByRef(fn_info.return_type), |
| ... | @@ -5757,3 +5722,12 @@ fn backendSupportsF80(target: std.Target) bool { | ... | @@ -5757,3 +5722,12 @@ fn backendSupportsF80(target: std.Target) bool { |
| 5757 | else => false, | 5722 | else => false, |
| 5758 | }; | 5723 | }; |
| 5759 | } | 5724 | } |
| | 5725 | |
| | 5726 | /// We need to insert extra padding if LLVM's isn't enough. |
| | 5727 | /// However we don't want to ever call LLVMABIAlignmentOfType or |
| | 5728 | /// LLVMABISizeOfType because these functions will trip assertions |
| | 5729 | /// when using them for self-referential types. So our strategy is |
| | 5730 | /// to use non-packed llvm structs but to emit all padding explicitly. |
| | 5731 | /// We can do this because for all types, Zig ABI alignment >= LLVM ABI |
| | 5732 | /// alignment. |
| | 5733 | const struct_layout_version = 2; |