| ... | ... | @@ -844,15 +844,77 @@ pub const DeclGen = struct { |
| 844 | 844 | var llvm_field_types = try std.ArrayListUnmanaged(*const llvm.Type).initCapacity(gpa, struct_obj.fields.count()); |
| 845 | 845 | defer llvm_field_types.deinit(gpa); |
| 846 | 846 | |
| 847 | | for (struct_obj.fields.values()) |field| { |
| 848 | | if (!field.ty.hasCodeGenBits()) continue; |
| 849 | | llvm_field_types.appendAssumeCapacity(try dg.llvmType(field.ty)); |
| 847 | if (struct_obj.layout == .Packed) { |
| 848 | const target = dg.module.getTarget(); |
| 849 | comptime assert(Type.packed_struct_layout_version == 1); |
| 850 | var offset: u64 = 0; |
| 851 | var running_bits: u16 = 0; |
| 852 | for (struct_obj.fields.values()) |field| { |
| 853 | if (!field.ty.hasCodeGenBits()) continue; |
| 854 | |
| 855 | const field_align = field.packedAlignment(); |
| 856 | if (field_align == 0) { |
| 857 | running_bits += @intCast(u16, field.ty.bitSize(target)); |
| 858 | } else { |
| 859 | if (running_bits != 0) { |
| 860 | var int_payload: Type.Payload.Bits = .{ |
| 861 | .base = .{ .tag = .int_unsigned }, |
| 862 | .data = running_bits, |
| 863 | }; |
| 864 | const int_ty: Type = .{ .ptr_otherwise = &int_payload.base }; |
| 865 | const int_align = int_ty.abiAlignment(target); |
| 866 | const llvm_int_ty = try dg.llvmType(int_ty); |
| 867 | const prev_offset = offset; |
| 868 | offset = std.mem.alignForwardGeneric(u64, offset, int_align); |
| 869 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 870 | if (padding_bytes != 0) { |
| 871 | const padding = dg.context.intType(8).arrayType(padding_bytes); |
| 872 | llvm_field_types.appendAssumeCapacity(padding); |
| 873 | } |
| 874 | llvm_field_types.appendAssumeCapacity(llvm_int_ty); |
| 875 | offset += int_ty.abiSize(target); |
| 876 | running_bits = 0; |
| 877 | } |
| 878 | const prev_offset = offset; |
| 879 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 880 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 881 | if (padding_bytes != 0) { |
| 882 | const padding = dg.context.intType(8).arrayType(padding_bytes); |
| 883 | llvm_field_types.appendAssumeCapacity(padding); |
| 884 | } |
| 885 | llvm_field_types.appendAssumeCapacity(try dg.llvmType(field.ty)); |
| 886 | offset += field.ty.abiSize(target); |
| 887 | } |
| 888 | } |
| 889 | |
| 890 | if (running_bits != 0) { |
| 891 | var int_payload: Type.Payload.Bits = .{ |
| 892 | .base = .{ .tag = .int_unsigned }, |
| 893 | .data = running_bits, |
| 894 | }; |
| 895 | const int_ty: Type = .{ .ptr_otherwise = &int_payload.base }; |
| 896 | const int_align = int_ty.abiAlignment(target); |
| 897 | const prev_offset = offset; |
| 898 | offset = std.mem.alignForwardGeneric(u64, offset, int_align); |
| 899 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 900 | if (padding_bytes != 0) { |
| 901 | const padding = dg.context.intType(8).arrayType(padding_bytes); |
| 902 | llvm_field_types.appendAssumeCapacity(padding); |
| 903 | } |
| 904 | const llvm_int_ty = try dg.llvmType(int_ty); |
| 905 | llvm_field_types.appendAssumeCapacity(llvm_int_ty); |
| 906 | } |
| 907 | } else { |
| 908 | for (struct_obj.fields.values()) |field| { |
| 909 | if (!field.ty.hasCodeGenBits()) continue; |
| 910 | llvm_field_types.appendAssumeCapacity(try dg.llvmType(field.ty)); |
| 911 | } |
| 850 | 912 | } |
| 851 | 913 | |
| 852 | 914 | llvm_struct_ty.structSetBody( |
| 853 | 915 | llvm_field_types.items.ptr, |
| 854 | 916 | @intCast(c_uint, llvm_field_types.items.len), |
| 855 | | llvm.Bool.fromBool(struct_obj.layout == .Packed), |
| 917 | .False, |
| 856 | 918 | ); |
| 857 | 919 | |
| 858 | 920 | return llvm_struct_ty; |
| ... | ... | @@ -980,23 +1042,23 @@ pub const DeclGen = struct { |
| 980 | 1042 | } |
| 981 | 1043 | } |
| 982 | 1044 | |
| 983 | | fn genTypedValue(self: *DeclGen, tv: TypedValue) Error!*const llvm.Value { |
| 1045 | fn genTypedValue(dg: *DeclGen, tv: TypedValue) Error!*const llvm.Value { |
| 984 | 1046 | if (tv.val.isUndef()) { |
| 985 | | const llvm_type = try self.llvmType(tv.ty); |
| 1047 | const llvm_type = try dg.llvmType(tv.ty); |
| 986 | 1048 | return llvm_type.getUndef(); |
| 987 | 1049 | } |
| 988 | 1050 | |
| 989 | 1051 | switch (tv.ty.zigTypeTag()) { |
| 990 | 1052 | .Bool => { |
| 991 | | const llvm_type = try self.llvmType(tv.ty); |
| 1053 | const llvm_type = try dg.llvmType(tv.ty); |
| 992 | 1054 | return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(); |
| 993 | 1055 | }, |
| 994 | 1056 | .Int => { |
| 995 | 1057 | var bigint_space: Value.BigIntSpace = undefined; |
| 996 | 1058 | const bigint = tv.val.toBigInt(&bigint_space); |
| 997 | | const target = self.module.getTarget(); |
| 1059 | const target = dg.module.getTarget(); |
| 998 | 1060 | const int_info = tv.ty.intInfo(target); |
| 999 | | const llvm_type = self.context.intType(int_info.bits); |
| 1061 | const llvm_type = dg.context.intType(int_info.bits); |
| 1000 | 1062 | |
| 1001 | 1063 | const unsigned_val = v: { |
| 1002 | 1064 | if (bigint.limbs.len == 1) { |
| ... | ... | @@ -1022,9 +1084,9 @@ pub const DeclGen = struct { |
| 1022 | 1084 | var bigint_space: Value.BigIntSpace = undefined; |
| 1023 | 1085 | const bigint = int_val.toBigInt(&bigint_space); |
| 1024 | 1086 | |
| 1025 | | const target = self.module.getTarget(); |
| 1087 | const target = dg.module.getTarget(); |
| 1026 | 1088 | const int_info = tv.ty.intInfo(target); |
| 1027 | | const llvm_type = self.context.intType(int_info.bits); |
| 1089 | const llvm_type = dg.context.intType(int_info.bits); |
| 1028 | 1090 | |
| 1029 | 1091 | const unsigned_val = v: { |
| 1030 | 1092 | if (bigint.limbs.len == 1) { |
| ... | ... | @@ -1044,8 +1106,8 @@ pub const DeclGen = struct { |
| 1044 | 1106 | return unsigned_val; |
| 1045 | 1107 | }, |
| 1046 | 1108 | .Float => { |
| 1047 | | const llvm_ty = try self.llvmType(tv.ty); |
| 1048 | | if (tv.ty.floatBits(self.module.getTarget()) <= 64) { |
| 1109 | const llvm_ty = try dg.llvmType(tv.ty); |
| 1110 | if (tv.ty.floatBits(dg.module.getTarget()) <= 64) { |
| 1049 | 1111 | return llvm_ty.constReal(tv.val.toFloat(f64)); |
| 1050 | 1112 | } |
| 1051 | 1113 | |
| ... | ... | @@ -1056,18 +1118,18 @@ pub const DeclGen = struct { |
| 1056 | 1118 | std.mem.swap(u64, &buf[0], &buf[1]); |
| 1057 | 1119 | } |
| 1058 | 1120 | |
| 1059 | | const int = self.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf); |
| 1121 | const int = dg.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf); |
| 1060 | 1122 | return int.constBitCast(llvm_ty); |
| 1061 | 1123 | }, |
| 1062 | 1124 | .Pointer => switch (tv.val.tag()) { |
| 1063 | | .decl_ref_mut => return lowerDeclRefValue(self, tv, tv.val.castTag(.decl_ref_mut).?.data.decl), |
| 1064 | | .decl_ref => return lowerDeclRefValue(self, tv, tv.val.castTag(.decl_ref).?.data), |
| 1125 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl), |
| 1126 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), |
| 1065 | 1127 | .variable => { |
| 1066 | 1128 | const decl = tv.val.castTag(.variable).?.data.owner_decl; |
| 1067 | 1129 | decl.alive = true; |
| 1068 | | const val = try self.resolveGlobalDecl(decl); |
| 1069 | | const llvm_var_type = try self.llvmType(tv.ty); |
| 1070 | | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); |
| 1130 | const val = try dg.resolveGlobalDecl(decl); |
| 1131 | const llvm_var_type = try dg.llvmType(tv.ty); |
| 1132 | const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); |
| 1071 | 1133 | const llvm_type = llvm_var_type.pointerType(llvm_addrspace); |
| 1072 | 1134 | return val.constBitCast(llvm_type); |
| 1073 | 1135 | }, |
| ... | ... | @@ -1075,26 +1137,26 @@ pub const DeclGen = struct { |
| 1075 | 1137 | const slice = tv.val.castTag(.slice).?.data; |
| 1076 | 1138 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1077 | 1139 | const fields: [2]*const llvm.Value = .{ |
| 1078 | | try self.genTypedValue(.{ |
| 1140 | try dg.genTypedValue(.{ |
| 1079 | 1141 | .ty = tv.ty.slicePtrFieldType(&buf), |
| 1080 | 1142 | .val = slice.ptr, |
| 1081 | 1143 | }), |
| 1082 | | try self.genTypedValue(.{ |
| 1144 | try dg.genTypedValue(.{ |
| 1083 | 1145 | .ty = Type.usize, |
| 1084 | 1146 | .val = slice.len, |
| 1085 | 1147 | }), |
| 1086 | 1148 | }; |
| 1087 | | return self.context.constStruct(&fields, fields.len, .False); |
| 1149 | return dg.context.constStruct(&fields, fields.len, .False); |
| 1088 | 1150 | }, |
| 1089 | 1151 | .int_u64, .one, .int_big_positive => { |
| 1090 | | const llvm_usize = try self.llvmType(Type.usize); |
| 1152 | const llvm_usize = try dg.llvmType(Type.usize); |
| 1091 | 1153 | const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(), .False); |
| 1092 | | return llvm_int.constIntToPtr(try self.llvmType(tv.ty)); |
| 1154 | return llvm_int.constIntToPtr(try dg.llvmType(tv.ty)); |
| 1093 | 1155 | }, |
| 1094 | 1156 | .field_ptr => { |
| 1095 | 1157 | const field_ptr = tv.val.castTag(.field_ptr).?.data; |
| 1096 | | const parent_ptr = try self.lowerParentPtr(field_ptr.container_ptr); |
| 1097 | | const llvm_u32 = self.context.intType(32); |
| 1158 | const parent_ptr = try dg.lowerParentPtr(field_ptr.container_ptr); |
| 1159 | const llvm_u32 = dg.context.intType(32); |
| 1098 | 1160 | const indices: [2]*const llvm.Value = .{ |
| 1099 | 1161 | llvm_u32.constInt(0, .False), |
| 1100 | 1162 | llvm_u32.constInt(field_ptr.field_index, .False), |
| ... | ... | @@ -1103,8 +1165,8 @@ pub const DeclGen = struct { |
| 1103 | 1165 | }, |
| 1104 | 1166 | .elem_ptr => { |
| 1105 | 1167 | const elem_ptr = tv.val.castTag(.elem_ptr).?.data; |
| 1106 | | const parent_ptr = try self.lowerParentPtr(elem_ptr.array_ptr); |
| 1107 | | const llvm_usize = try self.llvmType(Type.usize); |
| 1168 | const parent_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr); |
| 1169 | const llvm_usize = try dg.llvmType(Type.usize); |
| 1108 | 1170 | if (parent_ptr.typeOf().getElementType().getTypeKind() == .Array) { |
| 1109 | 1171 | const indices: [2]*const llvm.Value = .{ |
| 1110 | 1172 | llvm_usize.constInt(0, .False), |
| ... | ... | @@ -1119,15 +1181,15 @@ pub const DeclGen = struct { |
| 1119 | 1181 | } |
| 1120 | 1182 | }, |
| 1121 | 1183 | .null_value, .zero => { |
| 1122 | | const llvm_type = try self.llvmType(tv.ty); |
| 1184 | const llvm_type = try dg.llvmType(tv.ty); |
| 1123 | 1185 | return llvm_type.constNull(); |
| 1124 | 1186 | }, |
| 1125 | | else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }), |
| 1187 | else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }), |
| 1126 | 1188 | }, |
| 1127 | 1189 | .Array => switch (tv.val.tag()) { |
| 1128 | 1190 | .bytes => { |
| 1129 | 1191 | const bytes = tv.val.castTag(.bytes).?.data; |
| 1130 | | return self.context.constString( |
| 1192 | return dg.context.constString( |
| 1131 | 1193 | bytes.ptr, |
| 1132 | 1194 | @intCast(c_uint, bytes.len), |
| 1133 | 1195 | .True, // don't null terminate. bytes has the sentinel, if any. |
| ... | ... | @@ -1136,13 +1198,13 @@ pub const DeclGen = struct { |
| 1136 | 1198 | .array => { |
| 1137 | 1199 | const elem_vals = tv.val.castTag(.array).?.data; |
| 1138 | 1200 | const elem_ty = tv.ty.elemType(); |
| 1139 | | const gpa = self.gpa; |
| 1201 | const gpa = dg.gpa; |
| 1140 | 1202 | const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len); |
| 1141 | 1203 | defer gpa.free(llvm_elems); |
| 1142 | 1204 | for (elem_vals) |elem_val, i| { |
| 1143 | | llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = elem_val }); |
| 1205 | llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val }); |
| 1144 | 1206 | } |
| 1145 | | const llvm_elem_ty = try self.llvmType(elem_ty); |
| 1207 | const llvm_elem_ty = try dg.llvmType(elem_ty); |
| 1146 | 1208 | return llvm_elem_ty.constArray( |
| 1147 | 1209 | llvm_elems.ptr, |
| 1148 | 1210 | @intCast(c_uint, llvm_elems.len), |
| ... | ... | @@ -1154,16 +1216,16 @@ pub const DeclGen = struct { |
| 1154 | 1216 | const sentinel = tv.ty.sentinel(); |
| 1155 | 1217 | const len = @intCast(usize, tv.ty.arrayLen()); |
| 1156 | 1218 | const len_including_sent = len + @boolToInt(sentinel != null); |
| 1157 | | const gpa = self.gpa; |
| 1219 | const gpa = dg.gpa; |
| 1158 | 1220 | const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent); |
| 1159 | 1221 | defer gpa.free(llvm_elems); |
| 1160 | 1222 | for (llvm_elems[0..len]) |*elem| { |
| 1161 | | elem.* = try self.genTypedValue(.{ .ty = elem_ty, .val = val }); |
| 1223 | elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val }); |
| 1162 | 1224 | } |
| 1163 | 1225 | if (sentinel) |sent| { |
| 1164 | | llvm_elems[len] = try self.genTypedValue(.{ .ty = elem_ty, .val = sent }); |
| 1226 | llvm_elems[len] = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent }); |
| 1165 | 1227 | } |
| 1166 | | const llvm_elem_ty = try self.llvmType(elem_ty); |
| 1228 | const llvm_elem_ty = try dg.llvmType(elem_ty); |
| 1167 | 1229 | return llvm_elem_ty.constArray( |
| 1168 | 1230 | llvm_elems.ptr, |
| 1169 | 1231 | @intCast(c_uint, llvm_elems.len), |
| ... | ... | @@ -1172,9 +1234,9 @@ pub const DeclGen = struct { |
| 1172 | 1234 | .empty_array_sentinel => { |
| 1173 | 1235 | const elem_ty = tv.ty.elemType(); |
| 1174 | 1236 | const sent_val = tv.ty.sentinel().?; |
| 1175 | | const sentinel = try self.genTypedValue(.{ .ty = elem_ty, .val = sent_val }); |
| 1237 | const sentinel = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent_val }); |
| 1176 | 1238 | const llvm_elems: [1]*const llvm.Value = .{sentinel}; |
| 1177 | | const llvm_elem_ty = try self.llvmType(elem_ty); |
| 1239 | const llvm_elem_ty = try dg.llvmType(elem_ty); |
| 1178 | 1240 | return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len); |
| 1179 | 1241 | }, |
| 1180 | 1242 | else => unreachable, |
| ... | ... | @@ -1182,7 +1244,7 @@ pub const DeclGen = struct { |
| 1182 | 1244 | .Optional => { |
| 1183 | 1245 | var buf: Type.Payload.ElemType = undefined; |
| 1184 | 1246 | const payload_ty = tv.ty.optionalChild(&buf); |
| 1185 | | const llvm_i1 = self.context.intType(1); |
| 1247 | const llvm_i1 = dg.context.intType(1); |
| 1186 | 1248 | const is_pl = !tv.val.isNull(); |
| 1187 | 1249 | const non_null_bit = if (is_pl) llvm_i1.constAllOnes() else llvm_i1.constNull(); |
| 1188 | 1250 | if (!payload_ty.hasCodeGenBits()) { |
| ... | ... | @@ -1190,22 +1252,22 @@ pub const DeclGen = struct { |
| 1190 | 1252 | } |
| 1191 | 1253 | if (tv.ty.isPtrLikeOptional()) { |
| 1192 | 1254 | if (tv.val.castTag(.opt_payload)) |payload| { |
| 1193 | | return self.genTypedValue(.{ .ty = payload_ty, .val = payload.data }); |
| 1255 | return dg.genTypedValue(.{ .ty = payload_ty, .val = payload.data }); |
| 1194 | 1256 | } else if (is_pl) { |
| 1195 | | return self.genTypedValue(.{ .ty = payload_ty, .val = tv.val }); |
| 1257 | return dg.genTypedValue(.{ .ty = payload_ty, .val = tv.val }); |
| 1196 | 1258 | } else { |
| 1197 | | const llvm_ty = try self.llvmType(tv.ty); |
| 1259 | const llvm_ty = try dg.llvmType(tv.ty); |
| 1198 | 1260 | return llvm_ty.constNull(); |
| 1199 | 1261 | } |
| 1200 | 1262 | } |
| 1201 | 1263 | const fields: [2]*const llvm.Value = .{ |
| 1202 | | try self.genTypedValue(.{ |
| 1264 | try dg.genTypedValue(.{ |
| 1203 | 1265 | .ty = payload_ty, |
| 1204 | 1266 | .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), |
| 1205 | 1267 | }), |
| 1206 | 1268 | non_null_bit, |
| 1207 | 1269 | }; |
| 1208 | | return self.context.constStruct(&fields, fields.len, .False); |
| 1270 | return dg.context.constStruct(&fields, fields.len, .False); |
| 1209 | 1271 | }, |
| 1210 | 1272 | .Fn => { |
| 1211 | 1273 | const fn_decl = switch (tv.val.tag()) { |
| ... | ... | @@ -1214,14 +1276,14 @@ pub const DeclGen = struct { |
| 1214 | 1276 | else => unreachable, |
| 1215 | 1277 | }; |
| 1216 | 1278 | fn_decl.alive = true; |
| 1217 | | return self.resolveLlvmFunction(fn_decl); |
| 1279 | return dg.resolveLlvmFunction(fn_decl); |
| 1218 | 1280 | }, |
| 1219 | 1281 | .ErrorSet => { |
| 1220 | | const llvm_ty = try self.llvmType(tv.ty); |
| 1282 | const llvm_ty = try dg.llvmType(tv.ty); |
| 1221 | 1283 | switch (tv.val.tag()) { |
| 1222 | 1284 | .@"error" => { |
| 1223 | 1285 | const err_name = tv.val.castTag(.@"error").?.data.name; |
| 1224 | | const kv = try self.module.getErrorValue(err_name); |
| 1286 | const kv = try dg.module.getErrorValue(err_name); |
| 1225 | 1287 | return llvm_ty.constInt(kv.value, .False); |
| 1226 | 1288 | }, |
| 1227 | 1289 | else => { |
| ... | ... | @@ -1238,76 +1300,138 @@ pub const DeclGen = struct { |
| 1238 | 1300 | if (!payload_type.hasCodeGenBits()) { |
| 1239 | 1301 | // We use the error type directly as the type. |
| 1240 | 1302 | const err_val = if (!is_pl) tv.val else Value.initTag(.zero); |
| 1241 | | return self.genTypedValue(.{ .ty = error_type, .val = err_val }); |
| 1303 | return dg.genTypedValue(.{ .ty = error_type, .val = err_val }); |
| 1242 | 1304 | } |
| 1243 | 1305 | |
| 1244 | 1306 | const fields: [2]*const llvm.Value = .{ |
| 1245 | | try self.genTypedValue(.{ |
| 1307 | try dg.genTypedValue(.{ |
| 1246 | 1308 | .ty = error_type, |
| 1247 | 1309 | .val = if (is_pl) Value.initTag(.zero) else tv.val, |
| 1248 | 1310 | }), |
| 1249 | | try self.genTypedValue(.{ |
| 1311 | try dg.genTypedValue(.{ |
| 1250 | 1312 | .ty = payload_type, |
| 1251 | 1313 | .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), |
| 1252 | 1314 | }), |
| 1253 | 1315 | }; |
| 1254 | | return self.context.constStruct(&fields, fields.len, .False); |
| 1316 | return dg.context.constStruct(&fields, fields.len, .False); |
| 1255 | 1317 | }, |
| 1256 | 1318 | .Struct => { |
| 1257 | | const llvm_struct_ty = try self.llvmType(tv.ty); |
| 1319 | const llvm_struct_ty = try dg.llvmType(tv.ty); |
| 1258 | 1320 | const field_vals = tv.val.castTag(.@"struct").?.data; |
| 1259 | | const gpa = self.gpa; |
| 1321 | const gpa = dg.gpa; |
| 1260 | 1322 | |
| 1261 | 1323 | var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, field_vals.len); |
| 1262 | 1324 | defer llvm_fields.deinit(gpa); |
| 1263 | 1325 | |
| 1264 | | for (field_vals) |field_val, i| { |
| 1265 | | const field_ty = tv.ty.structFieldType(i); |
| 1266 | | if (!field_ty.hasCodeGenBits()) continue; |
| 1267 | | |
| 1268 | | llvm_fields.appendAssumeCapacity(try self.genTypedValue(.{ |
| 1269 | | .ty = field_ty, |
| 1270 | | .val = field_val, |
| 1271 | | })); |
| 1326 | const struct_obj = tv.ty.castTag(.@"struct").?.data; |
| 1327 | if (struct_obj.layout == .Packed) { |
| 1328 | const target = dg.module.getTarget(); |
| 1329 | const fields = struct_obj.fields.values(); |
| 1330 | comptime assert(Type.packed_struct_layout_version == 1); |
| 1331 | var offset: u64 = 0; |
| 1332 | var running_bits: u16 = 0; |
| 1333 | var running_int: *const llvm.Value = llvm_struct_ty.structGetTypeAtIndex(0).constNull(); |
| 1334 | for (field_vals) |field_val, i| { |
| 1335 | const field = fields[i]; |
| 1336 | if (!field.ty.hasCodeGenBits()) continue; |
| 1337 | |
| 1338 | const field_align = field.packedAlignment(); |
| 1339 | if (field_align == 0) { |
| 1340 | const non_int_val = try dg.genTypedValue(.{ |
| 1341 | .ty = field.ty, |
| 1342 | .val = field_val, |
| 1343 | }); |
| 1344 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); |
| 1345 | const llvm_int_ty = dg.context.intType(ty_bit_size); |
| 1346 | const int_val = non_int_val.constBitCast(llvm_int_ty); |
| 1347 | const shift_rhs = llvm_int_ty.constInt(running_bits, .False); |
| 1348 | const shifted = int_val.constShl(shift_rhs); |
| 1349 | running_int = running_int.constOr(shifted); |
| 1350 | running_bits += ty_bit_size; |
| 1351 | } else { |
| 1352 | if (running_bits != 0) { |
| 1353 | var int_payload: Type.Payload.Bits = .{ |
| 1354 | .base = .{ .tag = .int_unsigned }, |
| 1355 | .data = running_bits, |
| 1356 | }; |
| 1357 | const int_ty: Type = .{ .ptr_otherwise = &int_payload.base }; |
| 1358 | const int_align = int_ty.abiAlignment(target); |
| 1359 | const prev_offset = offset; |
| 1360 | offset = std.mem.alignForwardGeneric(u64, offset, int_align); |
| 1361 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 1362 | if (padding_bytes != 0) { |
| 1363 | const padding = dg.context.intType(8).arrayType(padding_bytes); |
| 1364 | llvm_fields.appendAssumeCapacity(padding.getUndef()); |
| 1365 | } |
| 1366 | llvm_fields.appendAssumeCapacity(running_int); |
| 1367 | running_int = llvm_struct_ty.structGetTypeAtIndex(@intCast(c_uint, llvm_fields.items.len)).constNull(); |
| 1368 | offset += int_ty.abiSize(target); |
| 1369 | running_bits = 0; |
| 1370 | } |
| 1371 | const prev_offset = offset; |
| 1372 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 1373 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 1374 | if (padding_bytes != 0) { |
| 1375 | const padding = dg.context.intType(8).arrayType(padding_bytes); |
| 1376 | llvm_fields.appendAssumeCapacity(padding.getUndef()); |
| 1377 | } |
| 1378 | llvm_fields.appendAssumeCapacity(try dg.genTypedValue(.{ |
| 1379 | .ty = field.ty, |
| 1380 | .val = field_val, |
| 1381 | })); |
| 1382 | offset += field.ty.abiSize(target); |
| 1383 | } |
| 1384 | } |
| 1385 | } else { |
| 1386 | for (field_vals) |field_val, i| { |
| 1387 | const field_ty = tv.ty.structFieldType(i); |
| 1388 | if (!field_ty.hasCodeGenBits()) continue; |
| 1389 | |
| 1390 | llvm_fields.appendAssumeCapacity(try dg.genTypedValue(.{ |
| 1391 | .ty = field_ty, |
| 1392 | .val = field_val, |
| 1393 | })); |
| 1394 | } |
| 1272 | 1395 | } |
| 1396 | |
| 1273 | 1397 | return llvm_struct_ty.constNamedStruct( |
| 1274 | 1398 | llvm_fields.items.ptr, |
| 1275 | 1399 | @intCast(c_uint, llvm_fields.items.len), |
| 1276 | 1400 | ); |
| 1277 | 1401 | }, |
| 1278 | 1402 | .Union => { |
| 1279 | | const llvm_union_ty = try self.llvmType(tv.ty); |
| 1403 | const llvm_union_ty = try dg.llvmType(tv.ty); |
| 1280 | 1404 | const tag_and_val = tv.val.castTag(.@"union").?.data; |
| 1281 | 1405 | |
| 1282 | | const target = self.module.getTarget(); |
| 1406 | const target = dg.module.getTarget(); |
| 1283 | 1407 | const layout = tv.ty.unionGetLayout(target); |
| 1284 | 1408 | |
| 1285 | 1409 | if (layout.payload_size == 0) { |
| 1286 | | return genTypedValue(self, .{ .ty = tv.ty.unionTagType().?, .val = tag_and_val.tag }); |
| 1410 | return genTypedValue(dg, .{ .ty = tv.ty.unionTagType().?, .val = tag_and_val.tag }); |
| 1287 | 1411 | } |
| 1288 | 1412 | const field_ty = tv.ty.unionFieldType(tag_and_val.tag); |
| 1289 | 1413 | const payload = p: { |
| 1290 | 1414 | if (!field_ty.hasCodeGenBits()) { |
| 1291 | 1415 | const padding_len = @intCast(c_uint, layout.payload_size); |
| 1292 | | break :p self.context.intType(8).arrayType(padding_len).getUndef(); |
| 1416 | break :p dg.context.intType(8).arrayType(padding_len).getUndef(); |
| 1293 | 1417 | } |
| 1294 | | const field = try genTypedValue(self, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 1418 | const field = try genTypedValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 1295 | 1419 | const field_size = field_ty.abiSize(target); |
| 1296 | 1420 | if (field_size == layout.payload_size) { |
| 1297 | 1421 | break :p field; |
| 1298 | 1422 | } |
| 1299 | 1423 | const padding_len = @intCast(c_uint, layout.payload_size - field_size); |
| 1300 | 1424 | const fields: [2]*const llvm.Value = .{ |
| 1301 | | field, self.context.intType(8).arrayType(padding_len).getUndef(), |
| 1425 | field, dg.context.intType(8).arrayType(padding_len).getUndef(), |
| 1302 | 1426 | }; |
| 1303 | | break :p self.context.constStruct(&fields, fields.len, .False); |
| 1427 | break :p dg.context.constStruct(&fields, fields.len, .False); |
| 1304 | 1428 | }; |
| 1305 | 1429 | if (layout.tag_size == 0) { |
| 1306 | 1430 | const llvm_payload_ty = llvm_union_ty.structGetTypeAtIndex(0); |
| 1307 | 1431 | const fields: [1]*const llvm.Value = .{payload.constBitCast(llvm_payload_ty)}; |
| 1308 | 1432 | return llvm_union_ty.constNamedStruct(&fields, fields.len); |
| 1309 | 1433 | } |
| 1310 | | const llvm_tag_value = try genTypedValue(self, .{ |
| 1434 | const llvm_tag_value = try genTypedValue(dg, .{ |
| 1311 | 1435 | .ty = tv.ty.unionTagType().?, |
| 1312 | 1436 | .val = tag_and_val.tag, |
| 1313 | 1437 | }); |
| ... | ... | @@ -1329,15 +1453,15 @@ pub const DeclGen = struct { |
| 1329 | 1453 | assert(vector_len == bytes.len or vector_len + 1 == bytes.len); |
| 1330 | 1454 | |
| 1331 | 1455 | const elem_ty = tv.ty.elemType(); |
| 1332 | | const llvm_elems = try self.gpa.alloc(*const llvm.Value, vector_len); |
| 1333 | | defer self.gpa.free(llvm_elems); |
| 1456 | const llvm_elems = try dg.gpa.alloc(*const llvm.Value, vector_len); |
| 1457 | defer dg.gpa.free(llvm_elems); |
| 1334 | 1458 | for (llvm_elems) |*elem, i| { |
| 1335 | 1459 | var byte_payload: Value.Payload.U64 = .{ |
| 1336 | 1460 | .base = .{ .tag = .int_u64 }, |
| 1337 | 1461 | .data = bytes[i], |
| 1338 | 1462 | }; |
| 1339 | 1463 | |
| 1340 | | elem.* = try self.genTypedValue(.{ |
| 1464 | elem.* = try dg.genTypedValue(.{ |
| 1341 | 1465 | .ty = elem_ty, |
| 1342 | 1466 | .val = Value.initPayload(&byte_payload.base), |
| 1343 | 1467 | }); |
| ... | ... | @@ -1354,10 +1478,10 @@ pub const DeclGen = struct { |
| 1354 | 1478 | const vector_len = @intCast(usize, tv.ty.arrayLen()); |
| 1355 | 1479 | assert(vector_len == elem_vals.len or vector_len + 1 == elem_vals.len); |
| 1356 | 1480 | const elem_ty = tv.ty.elemType(); |
| 1357 | | const llvm_elems = try self.gpa.alloc(*const llvm.Value, vector_len); |
| 1358 | | defer self.gpa.free(llvm_elems); |
| 1481 | const llvm_elems = try dg.gpa.alloc(*const llvm.Value, vector_len); |
| 1482 | defer dg.gpa.free(llvm_elems); |
| 1359 | 1483 | for (llvm_elems) |*elem, i| { |
| 1360 | | elem.* = try self.genTypedValue(.{ .ty = elem_ty, .val = elem_vals[i] }); |
| 1484 | elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_vals[i] }); |
| 1361 | 1485 | } |
| 1362 | 1486 | return llvm.constVector( |
| 1363 | 1487 | llvm_elems.ptr, |
| ... | ... | @@ -1369,10 +1493,10 @@ pub const DeclGen = struct { |
| 1369 | 1493 | const val = tv.val.castTag(.repeated).?.data; |
| 1370 | 1494 | const elem_ty = tv.ty.elemType(); |
| 1371 | 1495 | const len = @intCast(usize, tv.ty.arrayLen()); |
| 1372 | | const llvm_elems = try self.gpa.alloc(*const llvm.Value, len); |
| 1373 | | defer self.gpa.free(llvm_elems); |
| 1496 | const llvm_elems = try dg.gpa.alloc(*const llvm.Value, len); |
| 1497 | defer dg.gpa.free(llvm_elems); |
| 1374 | 1498 | for (llvm_elems) |*elem| { |
| 1375 | | elem.* = try self.genTypedValue(.{ .ty = elem_ty, .val = val }); |
| 1499 | elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val }); |
| 1376 | 1500 | } |
| 1377 | 1501 | return llvm.constVector( |
| 1378 | 1502 | llvm_elems.ptr, |
| ... | ... | @@ -1395,7 +1519,7 @@ pub const DeclGen = struct { |
| 1395 | 1519 | |
| 1396 | 1520 | .Frame, |
| 1397 | 1521 | .AnyFrame, |
| 1398 | | => return self.todo("implement const of type '{}'", .{tv.ty}), |
| 1522 | => return dg.todo("implement const of type '{}'", .{tv.ty}), |
| 1399 | 1523 | } |
| 1400 | 1524 | } |
| 1401 | 1525 | |
| ... | ... | @@ -2403,26 +2527,28 @@ pub const FuncGen = struct { |
| 2403 | 2527 | |
| 2404 | 2528 | assert(isByRef(struct_ty)); |
| 2405 | 2529 | |
| 2406 | | const field_ptr = switch (struct_ty.zigTypeTag()) { |
| 2407 | | .Struct => blk: { |
| 2408 | | const llvm_field_index = llvmFieldIndex(struct_ty, field_index); |
| 2409 | | break :blk self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); |
| 2530 | const target = self.dg.module.getTarget(); |
| 2531 | switch (struct_ty.zigTypeTag()) { |
| 2532 | .Struct => { |
| 2533 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 2534 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf); |
| 2535 | const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); |
| 2536 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); |
| 2537 | return self.load(field_ptr, field_ptr_ty); |
| 2410 | 2538 | }, |
| 2411 | | .Union => blk: { |
| 2539 | .Union => { |
| 2412 | 2540 | const llvm_field_ty = try self.dg.llvmType(field_ty); |
| 2413 | | const target = self.dg.module.getTarget(); |
| 2414 | 2541 | const layout = struct_ty.unionGetLayout(target); |
| 2415 | 2542 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 2416 | 2543 | const union_field_ptr = self.builder.buildStructGEP(struct_llvm_val, payload_index, ""); |
| 2417 | | break :blk self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); |
| 2544 | const field_ptr = self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); |
| 2545 | if (isByRef(field_ty)) { |
| 2546 | return field_ptr; |
| 2547 | } else { |
| 2548 | return self.builder.buildLoad(field_ptr, ""); |
| 2549 | } |
| 2418 | 2550 | }, |
| 2419 | 2551 | else => unreachable, |
| 2420 | | }; |
| 2421 | | |
| 2422 | | if (isByRef(field_ty)) { |
| 2423 | | return field_ptr; |
| 2424 | | } else { |
| 2425 | | return self.builder.buildLoad(field_ptr, ""); |
| 2426 | 2552 | } |
| 2427 | 2553 | } |
| 2428 | 2554 | |
| ... | ... | @@ -3730,11 +3856,11 @@ pub const FuncGen = struct { |
| 3730 | 3856 | if (opt_abi_ty) |abi_ty| { |
| 3731 | 3857 | // operand needs widening and truncating |
| 3732 | 3858 | const casted_ptr = self.builder.buildBitCast(ptr, abi_ty.pointerType(0), ""); |
| 3733 | | const load_inst = self.load(casted_ptr, ptr_ty).?; |
| 3859 | const load_inst = (try self.load(casted_ptr, ptr_ty)).?; |
| 3734 | 3860 | load_inst.setOrdering(ordering); |
| 3735 | 3861 | return self.builder.buildTrunc(load_inst, try self.dg.llvmType(operand_ty), ""); |
| 3736 | 3862 | } |
| 3737 | | const load_inst = self.load(ptr, ptr_ty).?; |
| 3863 | const load_inst = (try self.load(ptr, ptr_ty)).?; |
| 3738 | 3864 | load_inst.setOrdering(ordering); |
| 3739 | 3865 | return load_inst; |
| 3740 | 3866 | } |
| ... | ... | @@ -3997,7 +4123,9 @@ pub const FuncGen = struct { |
| 3997 | 4123 | const struct_ty = struct_ptr_ty.childType(); |
| 3998 | 4124 | switch (struct_ty.zigTypeTag()) { |
| 3999 | 4125 | .Struct => { |
| 4000 | | const llvm_field_index = llvmFieldIndex(struct_ty, field_index); |
| 4126 | const target = self.dg.module.getTarget(); |
| 4127 | var ty_buf: Type.Payload.Pointer = undefined; |
| 4128 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ty_buf); |
| 4001 | 4129 | return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); |
| 4002 | 4130 | }, |
| 4003 | 4131 | .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index), |
| ... | ... | @@ -4041,15 +4169,52 @@ pub const FuncGen = struct { |
| 4041 | 4169 | return self.llvmModule().getIntrinsicDeclaration(id, types.ptr, types.len); |
| 4042 | 4170 | } |
| 4043 | 4171 | |
| 4044 | | fn load(self: *FuncGen, ptr: *const llvm.Value, ptr_ty: Type) ?*const llvm.Value { |
| 4045 | | const pointee_ty = ptr_ty.childType(); |
| 4046 | | if (!pointee_ty.hasCodeGenBits()) return null; |
| 4047 | | if (isByRef(pointee_ty)) return ptr; |
| 4048 | | const llvm_inst = self.builder.buildLoad(ptr, ""); |
| 4172 | fn load(self: *FuncGen, ptr: *const llvm.Value, ptr_ty: Type) !?*const llvm.Value { |
| 4173 | const info = ptr_ty.ptrInfo().data; |
| 4174 | if (!info.pointee_type.hasCodeGenBits()) return null; |
| 4175 | |
| 4049 | 4176 | const target = self.dg.module.getTarget(); |
| 4050 | | llvm_inst.setAlignment(ptr_ty.ptrAlignment(target)); |
| 4051 | | llvm_inst.setVolatile(llvm.Bool.fromBool(ptr_ty.isVolatilePtr())); |
| 4052 | | return llvm_inst; |
| 4177 | const ptr_alignment = ptr_ty.ptrAlignment(target); |
| 4178 | const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); |
| 4179 | if (info.host_size == 0) { |
| 4180 | if (isByRef(info.pointee_type)) return ptr; |
| 4181 | const llvm_inst = self.builder.buildLoad(ptr, ""); |
| 4182 | llvm_inst.setAlignment(ptr_alignment); |
| 4183 | llvm_inst.setVolatile(ptr_volatile); |
| 4184 | return llvm_inst; |
| 4185 | } |
| 4186 | |
| 4187 | const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); |
| 4188 | const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); |
| 4189 | const containing_int = self.builder.buildLoad(int_ptr, ""); |
| 4190 | containing_int.setAlignment(ptr_alignment); |
| 4191 | containing_int.setVolatile(ptr_volatile); |
| 4192 | |
| 4193 | const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(target)); |
| 4194 | const shift_amt = containing_int.typeOf().constInt(info.bit_offset, .False); |
| 4195 | const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); |
| 4196 | const elem_llvm_ty = try self.dg.llvmType(info.pointee_type); |
| 4197 | |
| 4198 | if (isByRef(info.pointee_type)) { |
| 4199 | const result_align = info.pointee_type.abiAlignment(target); |
| 4200 | const result_ptr = self.buildAlloca(elem_llvm_ty); |
| 4201 | result_ptr.setAlignment(result_align); |
| 4202 | |
| 4203 | const same_size_int = self.context.intType(elem_bits); |
| 4204 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 4205 | const bitcasted_ptr = self.builder.buildBitCast(result_ptr, same_size_int.pointerType(0), ""); |
| 4206 | const store_inst = self.builder.buildStore(truncated_int, bitcasted_ptr); |
| 4207 | store_inst.setAlignment(result_align); |
| 4208 | return result_ptr; |
| 4209 | } |
| 4210 | |
| 4211 | if (info.pointee_type.zigTypeTag() == .Float) { |
| 4212 | const same_size_int = self.context.intType(elem_bits); |
| 4213 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 4214 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 4215 | } |
| 4216 | |
| 4217 | return self.builder.buildTrunc(shifted_value, elem_llvm_ty, ""); |
| 4053 | 4218 | } |
| 4054 | 4219 | |
| 4055 | 4220 | fn store( |
| ... | ... | @@ -4059,16 +4224,50 @@ pub const FuncGen = struct { |
| 4059 | 4224 | elem: *const llvm.Value, |
| 4060 | 4225 | ordering: llvm.AtomicOrdering, |
| 4061 | 4226 | ) void { |
| 4062 | | const elem_ty = ptr_ty.childType(); |
| 4227 | const info = ptr_ty.ptrInfo().data; |
| 4228 | const elem_ty = info.pointee_type; |
| 4063 | 4229 | if (!elem_ty.hasCodeGenBits()) { |
| 4064 | 4230 | return; |
| 4065 | 4231 | } |
| 4066 | 4232 | const target = self.dg.module.getTarget(); |
| 4233 | const ptr_alignment = ptr_ty.ptrAlignment(target); |
| 4234 | const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); |
| 4235 | if (info.host_size != 0) { |
| 4236 | const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); |
| 4237 | const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); |
| 4238 | const containing_int = self.builder.buildLoad(int_ptr, ""); |
| 4239 | assert(ordering == .NotAtomic); |
| 4240 | containing_int.setAlignment(ptr_alignment); |
| 4241 | containing_int.setVolatile(ptr_volatile); |
| 4242 | const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(target)); |
| 4243 | const containing_int_ty = containing_int.typeOf(); |
| 4244 | const shift_amt = containing_int_ty.constInt(info.bit_offset, .False); |
| 4245 | // Convert to equally-sized integer type in order to perform the bit |
| 4246 | // operations on the value to store |
| 4247 | const value_bits_type = self.context.intType(elem_bits); |
| 4248 | const value_bits = self.builder.buildBitCast(elem, value_bits_type, ""); |
| 4249 | |
| 4250 | var mask_val = value_bits_type.constAllOnes(); |
| 4251 | mask_val = mask_val.constZExt(containing_int_ty); |
| 4252 | mask_val = mask_val.constShl(shift_amt); |
| 4253 | mask_val = mask_val.constNot(); |
| 4254 | |
| 4255 | const anded_containing_int = self.builder.buildAnd(containing_int, mask_val, ""); |
| 4256 | const extended_value = self.builder.buildZExt(value_bits, containing_int_ty, ""); |
| 4257 | const shifted_value = self.builder.buildShl(extended_value, shift_amt, ""); |
| 4258 | const ored_value = self.builder.buildOr(shifted_value, anded_containing_int, ""); |
| 4259 | |
| 4260 | const store_inst = self.builder.buildStore(ored_value, int_ptr); |
| 4261 | assert(ordering == .NotAtomic); |
| 4262 | store_inst.setAlignment(ptr_alignment); |
| 4263 | store_inst.setVolatile(ptr_volatile); |
| 4264 | return; |
| 4265 | } |
| 4067 | 4266 | if (!isByRef(elem_ty)) { |
| 4068 | 4267 | const store_inst = self.builder.buildStore(elem, ptr); |
| 4069 | 4268 | store_inst.setOrdering(ordering); |
| 4070 | | store_inst.setAlignment(ptr_ty.ptrAlignment(target)); |
| 4071 | | store_inst.setVolatile(llvm.Bool.fromBool(ptr_ty.isVolatilePtr())); |
| 4269 | store_inst.setAlignment(ptr_alignment); |
| 4270 | store_inst.setVolatile(ptr_volatile); |
| 4072 | 4271 | return; |
| 4073 | 4272 | } |
| 4074 | 4273 | assert(ordering == .NotAtomic); |
| ... | ... | @@ -4080,7 +4279,7 @@ pub const FuncGen = struct { |
| 4080 | 4279 | self.builder.buildBitCast(elem, llvm_ptr_u8, ""), |
| 4081 | 4280 | elem_ty.abiAlignment(target), |
| 4082 | 4281 | self.context.intType(Type.usize.intInfo(target).bits).constInt(size_bytes, .False), |
| 4083 | | ptr_ty.isVolatilePtr(), |
| 4282 | info.@"volatile", |
| 4084 | 4283 | ); |
| 4085 | 4284 | } |
| 4086 | 4285 | }; |
| ... | ... | @@ -4323,15 +4522,104 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca |
| 4323 | 4522 | } |
| 4324 | 4523 | |
| 4325 | 4524 | /// Take into account 0 bit fields. |
| 4326 | | fn llvmFieldIndex(ty: Type, index: u32) c_uint { |
| 4525 | fn llvmFieldIndex( |
| 4526 | ty: Type, |
| 4527 | field_index: u32, |
| 4528 | target: std.Target, |
| 4529 | ptr_pl_buf: *Type.Payload.Pointer, |
| 4530 | ) c_uint { |
| 4327 | 4531 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 4328 | | var result: c_uint = 0; |
| 4329 | | for (struct_obj.fields.values()[0..index]) |field| { |
| 4330 | | if (field.ty.hasCodeGenBits()) { |
| 4331 | | result += 1; |
| 4532 | if (struct_obj.layout != .Packed) { |
| 4533 | var llvm_field_index: c_uint = 0; |
| 4534 | for (struct_obj.fields.values()) |field, i| { |
| 4535 | if (!field.ty.hasCodeGenBits()) continue; |
| 4536 | |
| 4537 | if (i == field_index) { |
| 4538 | ptr_pl_buf.* = .{ |
| 4539 | .data = .{ |
| 4540 | .pointee_type = field.ty, |
| 4541 | .@"align" = field.normalAlignment(target), |
| 4542 | .@"addrspace" = .generic, |
| 4543 | }, |
| 4544 | }; |
| 4545 | return llvm_field_index; |
| 4546 | } |
| 4547 | llvm_field_index += 1; |
| 4548 | } |
| 4549 | unreachable; |
| 4550 | } |
| 4551 | |
| 4552 | // Our job here is to return the host integer field index. |
| 4553 | comptime assert(Type.packed_struct_layout_version == 1); |
| 4554 | var offset: u64 = 0; |
| 4555 | var running_bits: u16 = 0; |
| 4556 | var llvm_field_index: c_uint = 0; |
| 4557 | for (struct_obj.fields.values()) |field, i| { |
| 4558 | if (!field.ty.hasCodeGenBits()) continue; |
| 4559 | |
| 4560 | const field_align = field.packedAlignment(); |
| 4561 | if (field_align == 0) { |
| 4562 | if (i == field_index) { |
| 4563 | ptr_pl_buf.* = .{ |
| 4564 | .data = .{ |
| 4565 | .pointee_type = field.ty, |
| 4566 | .bit_offset = running_bits, |
| 4567 | .@"addrspace" = .generic, |
| 4568 | }, |
| 4569 | }; |
| 4570 | } |
| 4571 | running_bits += @intCast(u16, field.ty.bitSize(target)); |
| 4572 | } else { |
| 4573 | if (running_bits != 0) { |
| 4574 | var int_payload: Type.Payload.Bits = .{ |
| 4575 | .base = .{ .tag = .int_unsigned }, |
| 4576 | .data = running_bits, |
| 4577 | }; |
| 4578 | const int_ty: Type = .{ .ptr_otherwise = &int_payload.base }; |
| 4579 | if (i > field_index) { |
| 4580 | ptr_pl_buf.data.host_size = @intCast(u16, int_ty.abiSize(target)); |
| 4581 | return llvm_field_index; |
| 4582 | } |
| 4583 | |
| 4584 | const int_align = int_ty.abiAlignment(target); |
| 4585 | const prev_offset = offset; |
| 4586 | offset = std.mem.alignForwardGeneric(u64, offset, int_align); |
| 4587 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 4588 | if (padding_bytes != 0) { |
| 4589 | llvm_field_index += 1; |
| 4590 | } |
| 4591 | llvm_field_index += 1; |
| 4592 | offset += int_ty.abiSize(target); |
| 4593 | running_bits = 0; |
| 4594 | } |
| 4595 | const prev_offset = offset; |
| 4596 | offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| 4597 | const padding_bytes = @intCast(c_uint, offset - prev_offset); |
| 4598 | if (padding_bytes != 0) { |
| 4599 | llvm_field_index += 1; |
| 4600 | } |
| 4601 | if (i == field_index) { |
| 4602 | ptr_pl_buf.* = .{ |
| 4603 | .data = .{ |
| 4604 | .pointee_type = field.ty, |
| 4605 | .@"align" = field_align, |
| 4606 | .@"addrspace" = .generic, |
| 4607 | }, |
| 4608 | }; |
| 4609 | return llvm_field_index; |
| 4610 | } |
| 4611 | llvm_field_index += 1; |
| 4612 | offset += field.ty.abiSize(target); |
| 4332 | 4613 | } |
| 4333 | 4614 | } |
| 4334 | | return result; |
| 4615 | assert(running_bits != 0); |
| 4616 | var int_payload: Type.Payload.Bits = .{ |
| 4617 | .base = .{ .tag = .int_unsigned }, |
| 4618 | .data = running_bits, |
| 4619 | }; |
| 4620 | const int_ty: Type = .{ .ptr_otherwise = &int_payload.base }; |
| 4621 | ptr_pl_buf.data.host_size = @intCast(u16, int_ty.abiSize(target)); |
| 4622 | return llvm_field_index; |
| 4335 | 4623 | } |
| 4336 | 4624 | |
| 4337 | 4625 | fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool { |