| ... | ... | @@ -1,21 +1,6 @@ |
| 1 | 1 | gpa: Allocator, |
| 2 | | use_lib_llvm: bool, |
| 3 | 2 | strip: bool, |
| 4 | 3 | |
| 5 | | llvm: if (build_options.have_llvm) struct { |
| 6 | | context: *llvm.Context, |
| 7 | | module: ?*llvm.Module, |
| 8 | | target: ?*llvm.Target, |
| 9 | | di_builder: ?*llvm.DIBuilder, |
| 10 | | di_compile_unit: ?*llvm.DICompileUnit, |
| 11 | | attribute_kind_ids: ?*[Attribute.Kind.len]c_uint, |
| 12 | | attributes: std.ArrayListUnmanaged(*llvm.Attribute), |
| 13 | | types: std.ArrayListUnmanaged(*llvm.Type), |
| 14 | | globals: std.ArrayListUnmanaged(*llvm.Value), |
| 15 | | constants: std.ArrayListUnmanaged(*llvm.Value), |
| 16 | | replacements: std.AutoHashMapUnmanaged(*llvm.Value, Global.Index), |
| 17 | | } else void, |
| 18 | | |
| 19 | 4 | source_filename: String, |
| 20 | 5 | data_layout: String, |
| 21 | 6 | target_triple: String, |
| ... | ... | @@ -37,6 +22,8 @@ attributes_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 37 | 22 | attributes_indices: std.ArrayListUnmanaged(u32), |
| 38 | 23 | attributes_extra: std.ArrayListUnmanaged(u32), |
| 39 | 24 | |
| 25 | function_attributes_set: std.AutoArrayHashMapUnmanaged(FunctionAttributes, void), |
| 26 | |
| 40 | 27 | globals: std.AutoArrayHashMapUnmanaged(String, Global), |
| 41 | 28 | next_unnamed_global: String, |
| 42 | 29 | next_replaced_global: String, |
| ... | ... | @@ -50,17 +37,29 @@ constant_items: std.MultiArrayList(Constant.Item), |
| 50 | 37 | constant_extra: std.ArrayListUnmanaged(u32), |
| 51 | 38 | constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb), |
| 52 | 39 | |
| 40 | metadata_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 41 | metadata_items: std.MultiArrayList(Metadata.Item), |
| 42 | metadata_extra: std.ArrayListUnmanaged(u32), |
| 43 | metadata_limbs: std.ArrayListUnmanaged(std.math.big.Limb), |
| 44 | metadata_forward_references: std.ArrayListUnmanaged(Metadata), |
| 45 | metadata_named: std.AutoArrayHashMapUnmanaged(MetadataString, struct { |
| 46 | len: u32, |
| 47 | index: Metadata.Item.ExtraIndex, |
| 48 | }), |
| 49 | |
| 50 | metadata_string_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 51 | metadata_string_indices: std.ArrayListUnmanaged(u32), |
| 52 | metadata_string_bytes: std.ArrayListUnmanaged(u8), |
| 53 | |
| 53 | 54 | pub const expected_args_len = 16; |
| 54 | 55 | pub const expected_attrs_len = 16; |
| 55 | 56 | pub const expected_fields_len = 32; |
| 56 | 57 | pub const expected_gep_indices_len = 8; |
| 57 | 58 | pub const expected_cases_len = 8; |
| 58 | 59 | pub const expected_incoming_len = 8; |
| 59 | | pub const expected_intrinsic_name_len = 64; |
| 60 | 60 | |
| 61 | 61 | pub const Options = struct { |
| 62 | 62 | allocator: Allocator, |
| 63 | | use_lib_llvm: bool = false, |
| 64 | 63 | strip: bool = true, |
| 65 | 64 | name: []const u8 = &.{}, |
| 66 | 65 | target: std.Target = builtin.target, |
| ... | ... | @@ -77,11 +76,11 @@ pub const String = enum(u32) { |
| 77 | 76 | return self.toIndex() == null; |
| 78 | 77 | } |
| 79 | 78 | |
| 80 | | pub fn slice(self: String, b: *const Builder) ?[:0]const u8 { |
| 79 | pub fn slice(self: String, builder: *const Builder) ?[]const u8 { |
| 81 | 80 | const index = self.toIndex() orelse return null; |
| 82 | | const start = b.string_indices.items[index]; |
| 83 | | const end = b.string_indices.items[index + 1]; |
| 84 | | return b.string_bytes.items[start .. end - 1 :0]; |
| 81 | const start = builder.string_indices.items[index]; |
| 82 | const end = builder.string_indices.items[index + 1]; |
| 83 | return builder.string_bytes.items[start..end]; |
| 85 | 84 | } |
| 86 | 85 | |
| 87 | 86 | const FormatData = struct { |
| ... | ... | @@ -94,17 +93,21 @@ pub const String = enum(u32) { |
| 94 | 93 | _: std.fmt.FormatOptions, |
| 95 | 94 | writer: anytype, |
| 96 | 95 | ) @TypeOf(writer).Error!void { |
| 97 | | if (comptime std.mem.indexOfNone(u8, fmt_str, "@\"")) |_| |
| 96 | if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_| |
| 98 | 97 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); |
| 99 | 98 | assert(data.string != .none); |
| 100 | | const sentinel_slice = data.string.slice(data.builder) orelse |
| 99 | const string_slice = data.string.slice(data.builder) orelse |
| 101 | 100 | return writer.print("{d}", .{@intFromEnum(data.string)}); |
| 102 | | try printEscapedString(sentinel_slice[0 .. sentinel_slice.len + comptime @intFromBool( |
| 103 | | std.mem.indexOfScalar(u8, fmt_str, '@') != null, |
| 104 | | )], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| |
| 105 | | .always_quote |
| 106 | | else |
| 107 | | .quote_unless_valid_identifier, writer); |
| 101 | if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_| |
| 102 | return writer.writeAll(string_slice); |
| 103 | try printEscapedString( |
| 104 | string_slice, |
| 105 | if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| |
| 106 | .always_quote |
| 107 | else |
| 108 | .quote_unless_valid_identifier, |
| 109 | writer, |
| 110 | ); |
| 108 | 111 | } |
| 109 | 112 | pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) { |
| 110 | 113 | return .{ .data = .{ .string = self, .builder = builder } }; |
| ... | ... | @@ -130,6 +133,72 @@ pub const String = enum(u32) { |
| 130 | 133 | }; |
| 131 | 134 | }; |
| 132 | 135 | |
| 136 | pub const BinaryOpcode = enum(u4) { |
| 137 | add = 0, |
| 138 | sub = 1, |
| 139 | mul = 2, |
| 140 | udiv = 3, |
| 141 | sdiv = 4, |
| 142 | urem = 5, |
| 143 | srem = 6, |
| 144 | shl = 7, |
| 145 | lshr = 8, |
| 146 | ashr = 9, |
| 147 | @"and" = 10, |
| 148 | @"or" = 11, |
| 149 | xor = 12, |
| 150 | }; |
| 151 | |
| 152 | pub const CastOpcode = enum(u4) { |
| 153 | trunc = 0, |
| 154 | zext = 1, |
| 155 | sext = 2, |
| 156 | fptoui = 3, |
| 157 | fptosi = 4, |
| 158 | uitofp = 5, |
| 159 | sitofp = 6, |
| 160 | fptrunc = 7, |
| 161 | fpext = 8, |
| 162 | ptrtoint = 9, |
| 163 | inttoptr = 10, |
| 164 | bitcast = 11, |
| 165 | addrspacecast = 12, |
| 166 | }; |
| 167 | |
| 168 | pub const CmpPredicate = enum(u6) { |
| 169 | fcmp_false = 0, |
| 170 | fcmp_oeq = 1, |
| 171 | fcmp_ogt = 2, |
| 172 | fcmp_oge = 3, |
| 173 | fcmp_olt = 4, |
| 174 | fcmp_ole = 5, |
| 175 | fcmp_one = 6, |
| 176 | fcmp_ord = 7, |
| 177 | fcmp_uno = 8, |
| 178 | fcmp_ueq = 9, |
| 179 | fcmp_ugt = 10, |
| 180 | fcmp_uge = 11, |
| 181 | fcmp_ult = 12, |
| 182 | fcmp_ule = 13, |
| 183 | fcmp_une = 14, |
| 184 | fcmp_true = 15, |
| 185 | icmp_eq = 32, |
| 186 | icmp_ne = 33, |
| 187 | icmp_ugt = 34, |
| 188 | icmp_uge = 35, |
| 189 | icmp_ult = 36, |
| 190 | icmp_ule = 37, |
| 191 | icmp_sgt = 38, |
| 192 | icmp_sge = 39, |
| 193 | icmp_slt = 40, |
| 194 | icmp_sle = 41, |
| 195 | }; |
| 196 | |
| 197 | pub const StrtabString = struct { |
| 198 | offset: usize, |
| 199 | size: usize, |
| 200 | }; |
| 201 | |
| 133 | 202 | pub const Type = enum(u32) { |
| 134 | 203 | void, |
| 135 | 204 | half, |
| ... | ... | @@ -178,20 +247,20 @@ pub const Type = enum(u32) { |
| 178 | 247 | named_structure, |
| 179 | 248 | }; |
| 180 | 249 | |
| 181 | | pub const Simple = enum { |
| 182 | | void, |
| 183 | | half, |
| 184 | | bfloat, |
| 185 | | float, |
| 186 | | double, |
| 187 | | fp128, |
| 188 | | x86_fp80, |
| 189 | | ppc_fp128, |
| 190 | | x86_amx, |
| 191 | | x86_mmx, |
| 192 | | label, |
| 193 | | token, |
| 194 | | metadata, |
| 250 | pub const Simple = enum(u5) { |
| 251 | void = 2, |
| 252 | half = 10, |
| 253 | bfloat = 23, |
| 254 | float = 3, |
| 255 | double = 4, |
| 256 | fp128 = 14, |
| 257 | x86_fp80 = 13, |
| 258 | ppc_fp128 = 15, |
| 259 | x86_amx = 24, |
| 260 | x86_mmx = 17, |
| 261 | label = 5, |
| 262 | token = 22, |
| 263 | metadata = 16, |
| 195 | 264 | }; |
| 196 | 265 | |
| 197 | 266 | pub const Function = struct { |
| ... | ... | @@ -579,7 +648,6 @@ pub const Type = enum(u32) { |
| 579 | 648 | var visited: IsSizedVisited = .{}; |
| 580 | 649 | defer visited.deinit(builder.gpa); |
| 581 | 650 | const result = try self.isSizedVisited(&visited, builder); |
| 582 | | if (builder.useLibLlvm()) assert(result == self.toLlvm(builder).isSized().toBool()); |
| 583 | 651 | return result; |
| 584 | 652 | } |
| 585 | 653 | |
| ... | ... | @@ -766,11 +834,6 @@ pub const Type = enum(u32) { |
| 766 | 834 | return .{ .data = .{ .type = self, .builder = builder } }; |
| 767 | 835 | } |
| 768 | 836 | |
| 769 | | pub fn toLlvm(self: Type, builder: *const Builder) *llvm.Type { |
| 770 | | assert(builder.useLibLlvm()); |
| 771 | | return builder.llvm.types.items[@intFromEnum(self)]; |
| 772 | | } |
| 773 | | |
| 774 | 837 | const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void); |
| 775 | 838 | fn isSizedVisited( |
| 776 | 839 | self: Type, |
| ... | ... | @@ -1051,14 +1114,21 @@ pub const Attribute = union(Kind) { |
| 1051 | 1114 | .no_sanitize_hwaddress, |
| 1052 | 1115 | .sanitize_address_dyninit, |
| 1053 | 1116 | => |kind| { |
| 1054 | | const field = @typeInfo(Attribute).Union.fields[@intFromEnum(kind)]; |
| 1117 | const field = comptime blk: { |
| 1118 | @setEvalBranchQuota(10_000); |
| 1119 | for (@typeInfo(Attribute).Union.fields) |field| { |
| 1120 | if (std.mem.eql(u8, field.name, @tagName(kind))) break :blk field; |
| 1121 | } |
| 1122 | unreachable; |
| 1123 | }; |
| 1055 | 1124 | comptime assert(std.mem.eql(u8, @tagName(kind), field.name)); |
| 1056 | 1125 | return @unionInit(Attribute, field.name, switch (field.type) { |
| 1057 | 1126 | void => {}, |
| 1058 | 1127 | u32 => storage.value, |
| 1059 | 1128 | Alignment, String, Type, UwTable => @enumFromInt(storage.value), |
| 1060 | 1129 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), |
| 1061 | | else => @compileError("bad payload type: " ++ @typeName(field.type)), |
| 1130 | else => @compileError("bad payload type: " ++ field.name ++ ": " ++ |
| 1131 | @typeName(field.type)), |
| 1062 | 1132 | }); |
| 1063 | 1133 | }, |
| 1064 | 1134 | .string, .none => unreachable, |
| ... | ... | @@ -1246,109 +1316,104 @@ pub const Attribute = union(Kind) { |
| 1246 | 1316 | fn toStorage(self: Index, builder: *const Builder) Storage { |
| 1247 | 1317 | return builder.attributes.keys()[@intFromEnum(self)]; |
| 1248 | 1318 | } |
| 1249 | | |
| 1250 | | fn toLlvm(self: Index, builder: *const Builder) *llvm.Attribute { |
| 1251 | | assert(builder.useLibLlvm()); |
| 1252 | | return builder.llvm.attributes.items[@intFromEnum(self)]; |
| 1253 | | } |
| 1254 | 1319 | }; |
| 1255 | 1320 | |
| 1256 | 1321 | pub const Kind = enum(u32) { |
| 1257 | 1322 | // Parameter Attributes |
| 1258 | | zeroext, |
| 1259 | | signext, |
| 1260 | | inreg, |
| 1261 | | byval, |
| 1262 | | byref, |
| 1263 | | preallocated, |
| 1264 | | inalloca, |
| 1265 | | sret, |
| 1266 | | elementtype, |
| 1267 | | @"align", |
| 1268 | | @"noalias", |
| 1269 | | nocapture, |
| 1270 | | nofree, |
| 1271 | | nest, |
| 1272 | | returned, |
| 1273 | | nonnull, |
| 1274 | | dereferenceable, |
| 1275 | | dereferenceable_or_null, |
| 1276 | | swiftself, |
| 1277 | | swiftasync, |
| 1278 | | swifterror, |
| 1279 | | immarg, |
| 1280 | | noundef, |
| 1281 | | nofpclass, |
| 1282 | | alignstack, |
| 1283 | | allocalign, |
| 1284 | | allocptr, |
| 1285 | | readnone, |
| 1286 | | readonly, |
| 1287 | | writeonly, |
| 1323 | zeroext = 34, |
| 1324 | signext = 24, |
| 1325 | inreg = 5, |
| 1326 | byval = 3, |
| 1327 | byref = 69, |
| 1328 | preallocated = 65, |
| 1329 | inalloca = 38, |
| 1330 | sret = 29, // TODO: ? |
| 1331 | elementtype = 77, |
| 1332 | @"align" = 1, |
| 1333 | @"noalias" = 9, |
| 1334 | nocapture = 11, |
| 1335 | nofree = 62, |
| 1336 | nest = 8, |
| 1337 | returned = 22, |
| 1338 | nonnull = 39, |
| 1339 | dereferenceable = 41, |
| 1340 | dereferenceable_or_null = 42, |
| 1341 | swiftself = 46, |
| 1342 | swiftasync = 75, |
| 1343 | swifterror = 47, |
| 1344 | immarg = 60, |
| 1345 | noundef = 68, |
| 1346 | nofpclass = 87, |
| 1347 | alignstack = 25, |
| 1348 | allocalign = 80, |
| 1349 | allocptr = 81, |
| 1350 | readnone = 20, |
| 1351 | readonly = 21, |
| 1352 | writeonly = 52, |
| 1288 | 1353 | |
| 1289 | 1354 | // Function Attributes |
| 1290 | 1355 | //alignstack, |
| 1291 | | allockind, |
| 1292 | | allocsize, |
| 1293 | | alwaysinline, |
| 1294 | | builtin, |
| 1295 | | cold, |
| 1296 | | convergent, |
| 1297 | | disable_sanitizer_information, |
| 1298 | | fn_ret_thunk_extern, |
| 1299 | | hot, |
| 1300 | | inlinehint, |
| 1301 | | jumptable, |
| 1302 | | memory, |
| 1303 | | minsize, |
| 1304 | | naked, |
| 1305 | | nobuiltin, |
| 1306 | | nocallback, |
| 1307 | | noduplicate, |
| 1356 | allockind = 82, |
| 1357 | allocsize = 51, |
| 1358 | alwaysinline = 2, |
| 1359 | builtin = 35, |
| 1360 | cold = 36, |
| 1361 | convergent = 43, |
| 1362 | disable_sanitizer_information = 78, |
| 1363 | fn_ret_thunk_extern = 84, |
| 1364 | hot = 72, |
| 1365 | inlinehint = 4, |
| 1366 | jumptable = 40, |
| 1367 | memory = 86, |
| 1368 | minsize = 6, |
| 1369 | naked = 7, |
| 1370 | nobuiltin = 10, |
| 1371 | nocallback = 71, |
| 1372 | noduplicate = 12, |
| 1308 | 1373 | //nofree, |
| 1309 | | noimplicitfloat, |
| 1310 | | @"noinline", |
| 1311 | | nomerge, |
| 1312 | | nonlazybind, |
| 1313 | | noprofile, |
| 1314 | | skipprofile, |
| 1315 | | noredzone, |
| 1316 | | noreturn, |
| 1317 | | norecurse, |
| 1318 | | willreturn, |
| 1319 | | nosync, |
| 1320 | | nounwind, |
| 1321 | | nosanitize_bounds, |
| 1322 | | nosanitize_coverage, |
| 1323 | | null_pointer_is_valid, |
| 1324 | | optforfuzzing, |
| 1325 | | optnone, |
| 1326 | | optsize, |
| 1374 | noimplicitfloat = 13, |
| 1375 | @"noinline" = 14, |
| 1376 | nomerge = 66, |
| 1377 | nonlazybind = 15, |
| 1378 | noprofile = 73, |
| 1379 | skipprofile = 85, |
| 1380 | noredzone = 16, |
| 1381 | noreturn = 17, |
| 1382 | norecurse = 48, |
| 1383 | willreturn = 61, |
| 1384 | nosync = 63, |
| 1385 | nounwind = 18, |
| 1386 | nosanitize_bounds = 79, |
| 1387 | nosanitize_coverage = 76, |
| 1388 | null_pointer_is_valid = 67, |
| 1389 | optforfuzzing = 57, |
| 1390 | optnone = 37, |
| 1391 | optsize = 19, |
| 1327 | 1392 | //preallocated, |
| 1328 | | returns_twice, |
| 1329 | | safestack, |
| 1330 | | sanitize_address, |
| 1331 | | sanitize_memory, |
| 1332 | | sanitize_thread, |
| 1333 | | sanitize_hwaddress, |
| 1334 | | sanitize_memtag, |
| 1335 | | speculative_load_hardening, |
| 1336 | | speculatable, |
| 1337 | | ssp, |
| 1338 | | sspstrong, |
| 1339 | | sspreq, |
| 1340 | | strictfp, |
| 1341 | | uwtable, |
| 1342 | | nocf_check, |
| 1343 | | shadowcallstack, |
| 1344 | | mustprogress, |
| 1345 | | vscale_range, |
| 1393 | returns_twice = 23, |
| 1394 | safestack = 44, |
| 1395 | sanitize_address = 30, |
| 1396 | sanitize_memory = 32, |
| 1397 | sanitize_thread = 31, |
| 1398 | sanitize_hwaddress = 55, |
| 1399 | sanitize_memtag = 64, |
| 1400 | speculative_load_hardening = 59, |
| 1401 | speculatable = 53, |
| 1402 | ssp = 26, |
| 1403 | sspstrong = 28, |
| 1404 | sspreq = 27, |
| 1405 | strictfp = 54, |
| 1406 | uwtable = 33, |
| 1407 | nocf_check = 56, |
| 1408 | shadowcallstack = 58, |
| 1409 | mustprogress = 70, |
| 1410 | vscale_range = 74, |
| 1346 | 1411 | |
| 1347 | 1412 | // Global Attributes |
| 1348 | | no_sanitize_address, |
| 1349 | | no_sanitize_hwaddress, |
| 1413 | no_sanitize_address = 100, |
| 1414 | no_sanitize_hwaddress = 101, |
| 1350 | 1415 | //sanitize_memtag, |
| 1351 | | sanitize_address_dyninit, |
| 1416 | sanitize_address_dyninit = 102, |
| 1352 | 1417 | |
| 1353 | 1418 | string = std.math.maxInt(u31), |
| 1354 | 1419 | none = std.math.maxInt(u32), |
| ... | ... | @@ -1368,11 +1433,6 @@ pub const Attribute = union(Kind) { |
| 1368 | 1433 | const str: String = @enumFromInt(@intFromEnum(self)); |
| 1369 | 1434 | return if (str.isAnon()) null else str; |
| 1370 | 1435 | } |
| 1371 | | |
| 1372 | | fn toLlvm(self: Kind, builder: *const Builder) *c_uint { |
| 1373 | | assert(builder.useLibLlvm()); |
| 1374 | | return &builder.llvm.attribute_kind_ids.?[@intFromEnum(self)]; |
| 1375 | | } |
| 1376 | 1436 | }; |
| 1377 | 1437 | |
| 1378 | 1438 | pub const FpClass = packed struct(u32) { |
| ... | ... | @@ -1494,12 +1554,12 @@ pub const Attribute = union(Kind) { |
| 1494 | 1554 | |
| 1495 | 1555 | fn toStorage(self: Attribute) Storage { |
| 1496 | 1556 | return switch (self) { |
| 1497 | | inline else => |value| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) { |
| 1557 | inline else => |value, tag| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) { |
| 1498 | 1558 | void => 0, |
| 1499 | 1559 | u32 => value, |
| 1500 | 1560 | Alignment, String, Type, UwTable => @intFromEnum(value), |
| 1501 | 1561 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), |
| 1502 | | else => @compileError("bad payload type: " ++ @typeName(@TypeOf(value))), |
| 1562 | else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))), |
| 1503 | 1563 | } }, |
| 1504 | 1564 | .string => |string_attr| .{ |
| 1505 | 1565 | .kind = Kind.fromString(string_attr.kind), |
| ... | ... | @@ -1709,18 +1769,18 @@ pub const FunctionAttributes = enum(u32) { |
| 1709 | 1769 | } |
| 1710 | 1770 | }; |
| 1711 | 1771 | |
| 1712 | | pub const Linkage = enum { |
| 1713 | | private, |
| 1714 | | internal, |
| 1715 | | weak, |
| 1716 | | weak_odr, |
| 1717 | | linkonce, |
| 1718 | | linkonce_odr, |
| 1719 | | available_externally, |
| 1720 | | appending, |
| 1721 | | common, |
| 1722 | | extern_weak, |
| 1723 | | external, |
| 1772 | pub const Linkage = enum(u4) { |
| 1773 | private = 9, |
| 1774 | internal = 3, |
| 1775 | weak = 1, |
| 1776 | weak_odr = 10, |
| 1777 | linkonce = 4, |
| 1778 | linkonce_odr = 11, |
| 1779 | available_externally = 12, |
| 1780 | appending = 2, |
| 1781 | common = 8, |
| 1782 | extern_weak = 7, |
| 1783 | external = 0, |
| 1724 | 1784 | |
| 1725 | 1785 | pub fn format( |
| 1726 | 1786 | self: Linkage, |
| ... | ... | @@ -1731,20 +1791,16 @@ pub const Linkage = enum { |
| 1731 | 1791 | if (self != .external) try writer.print(" {s}", .{@tagName(self)}); |
| 1732 | 1792 | } |
| 1733 | 1793 | |
| 1734 | | fn toLlvm(self: Linkage) llvm.Linkage { |
| 1735 | | return switch (self) { |
| 1736 | | .private => .Private, |
| 1737 | | .internal => .Internal, |
| 1738 | | .weak => .WeakAny, |
| 1739 | | .weak_odr => .WeakODR, |
| 1740 | | .linkonce => .LinkOnceAny, |
| 1741 | | .linkonce_odr => .LinkOnceODR, |
| 1742 | | .available_externally => .AvailableExternally, |
| 1743 | | .appending => .Appending, |
| 1744 | | .common => .Common, |
| 1745 | | .extern_weak => .ExternalWeak, |
| 1746 | | .external => .External, |
| 1747 | | }; |
| 1794 | fn formatOptional( |
| 1795 | data: ?Linkage, |
| 1796 | comptime _: []const u8, |
| 1797 | _: std.fmt.FormatOptions, |
| 1798 | writer: anytype, |
| 1799 | ) @TypeOf(writer).Error!void { |
| 1800 | if (data) |linkage| try writer.print(" {s}", .{@tagName(linkage)}); |
| 1801 | } |
| 1802 | pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) { |
| 1803 | return .{ .data = self }; |
| 1748 | 1804 | } |
| 1749 | 1805 | }; |
| 1750 | 1806 | |
| ... | ... | @@ -1763,10 +1819,10 @@ pub const Preemption = enum { |
| 1763 | 1819 | } |
| 1764 | 1820 | }; |
| 1765 | 1821 | |
| 1766 | | pub const Visibility = enum { |
| 1767 | | default, |
| 1768 | | hidden, |
| 1769 | | protected, |
| 1822 | pub const Visibility = enum(u2) { |
| 1823 | default = 0, |
| 1824 | hidden = 1, |
| 1825 | protected = 2, |
| 1770 | 1826 | |
| 1771 | 1827 | pub fn format( |
| 1772 | 1828 | self: Visibility, |
| ... | ... | @@ -1776,20 +1832,12 @@ pub const Visibility = enum { |
| 1776 | 1832 | ) @TypeOf(writer).Error!void { |
| 1777 | 1833 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); |
| 1778 | 1834 | } |
| 1779 | | |
| 1780 | | fn toLlvm(self: Visibility) llvm.Visibility { |
| 1781 | | return switch (self) { |
| 1782 | | .default => .Default, |
| 1783 | | .hidden => .Hidden, |
| 1784 | | .protected => .Protected, |
| 1785 | | }; |
| 1786 | | } |
| 1787 | 1835 | }; |
| 1788 | 1836 | |
| 1789 | | pub const DllStorageClass = enum { |
| 1790 | | default, |
| 1791 | | dllimport, |
| 1792 | | dllexport, |
| 1837 | pub const DllStorageClass = enum(u2) { |
| 1838 | default = 0, |
| 1839 | dllimport = 1, |
| 1840 | dllexport = 2, |
| 1793 | 1841 | |
| 1794 | 1842 | pub fn format( |
| 1795 | 1843 | self: DllStorageClass, |
| ... | ... | @@ -1799,22 +1847,14 @@ pub const DllStorageClass = enum { |
| 1799 | 1847 | ) @TypeOf(writer).Error!void { |
| 1800 | 1848 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); |
| 1801 | 1849 | } |
| 1802 | | |
| 1803 | | fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass { |
| 1804 | | return switch (self) { |
| 1805 | | .default => .Default, |
| 1806 | | .dllimport => .DLLImport, |
| 1807 | | .dllexport => .DLLExport, |
| 1808 | | }; |
| 1809 | | } |
| 1810 | 1850 | }; |
| 1811 | 1851 | |
| 1812 | | pub const ThreadLocal = enum { |
| 1813 | | default, |
| 1814 | | generaldynamic, |
| 1815 | | localdynamic, |
| 1816 | | initialexec, |
| 1817 | | localexec, |
| 1852 | pub const ThreadLocal = enum(u3) { |
| 1853 | default = 0, |
| 1854 | generaldynamic = 1, |
| 1855 | localdynamic = 2, |
| 1856 | initialexec = 3, |
| 1857 | localexec = 4, |
| 1818 | 1858 | |
| 1819 | 1859 | pub fn format( |
| 1820 | 1860 | self: ThreadLocal, |
| ... | ... | @@ -1826,24 +1866,14 @@ pub const ThreadLocal = enum { |
| 1826 | 1866 | try writer.print("{s}thread_local", .{prefix}); |
| 1827 | 1867 | if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)}); |
| 1828 | 1868 | } |
| 1829 | | |
| 1830 | | fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode { |
| 1831 | | return switch (self) { |
| 1832 | | .default => .NotThreadLocal, |
| 1833 | | .generaldynamic => .GeneralDynamicTLSModel, |
| 1834 | | .localdynamic => .LocalDynamicTLSModel, |
| 1835 | | .initialexec => .InitialExecTLSModel, |
| 1836 | | .localexec => .LocalExecTLSModel, |
| 1837 | | }; |
| 1838 | | } |
| 1839 | 1869 | }; |
| 1840 | 1870 | |
| 1841 | 1871 | pub const Mutability = enum { global, constant }; |
| 1842 | 1872 | |
| 1843 | | pub const UnnamedAddr = enum { |
| 1844 | | default, |
| 1845 | | unnamed_addr, |
| 1846 | | local_unnamed_addr, |
| 1873 | pub const UnnamedAddr = enum(u2) { |
| 1874 | default = 0, |
| 1875 | unnamed_addr = 1, |
| 1876 | local_unnamed_addr = 2, |
| 1847 | 1877 | |
| 1848 | 1878 | pub fn format( |
| 1849 | 1879 | self: UnnamedAddr, |
| ... | ... | @@ -1971,6 +2001,10 @@ pub const Alignment = enum(u6) { |
| 1971 | 2001 | return if (self == .default) null else @as(u64, 1) << @intFromEnum(self); |
| 1972 | 2002 | } |
| 1973 | 2003 | |
| 2004 | pub fn toLlvm(self: Alignment) u6 { |
| 2005 | return if (self == .default) 0 else (@intFromEnum(self) + 1); |
| 2006 | } |
| 2007 | |
| 1974 | 2008 | pub fn format( |
| 1975 | 2009 | self: Alignment, |
| 1976 | 2010 | comptime prefix: []const u8, |
| ... | ... | @@ -2100,11 +2134,6 @@ pub const CallConv = enum(u10) { |
| 2100 | 2134 | _ => try writer.print(" cc{d}", .{@intFromEnum(self)}), |
| 2101 | 2135 | } |
| 2102 | 2136 | } |
| 2103 | | |
| 2104 | | fn toLlvm(self: CallConv) llvm.CallConv { |
| 2105 | | // These enum values appear in LLVM IR, and so are guaranteed to be stable. |
| 2106 | | return @enumFromInt(@intFromEnum(self)); |
| 2107 | | } |
| 2108 | 2137 | }; |
| 2109 | 2138 | |
| 2110 | 2139 | pub const Global = struct { |
| ... | ... | @@ -2117,6 +2146,7 @@ pub const Global = struct { |
| 2117 | 2146 | externally_initialized: ExternallyInitialized = .default, |
| 2118 | 2147 | type: Type, |
| 2119 | 2148 | partition: String = .none, |
| 2149 | dbg: Metadata = .none, |
| 2120 | 2150 | kind: union(enum) { |
| 2121 | 2151 | alias: Alias.Index, |
| 2122 | 2152 | variable: Variable.Index, |
| ... | ... | @@ -2153,6 +2183,18 @@ pub const Global = struct { |
| 2153 | 2183 | return builder.globals.keys()[@intFromEnum(self.unwrap(builder))]; |
| 2154 | 2184 | } |
| 2155 | 2185 | |
| 2186 | pub fn strtab(self: Index, builder: *const Builder) StrtabString { |
| 2187 | const name_index = self.name(builder).toIndex() orelse return .{ |
| 2188 | .offset = 0, |
| 2189 | .size = 0, |
| 2190 | }; |
| 2191 | |
| 2192 | return .{ |
| 2193 | .offset = builder.string_indices.items[name_index], |
| 2194 | .size = builder.string_indices.items[name_index + 1] - builder.string_indices.items[name_index], |
| 2195 | }; |
| 2196 | } |
| 2197 | |
| 2156 | 2198 | pub fn typeOf(self: Index, builder: *const Builder) Type { |
| 2157 | 2199 | return self.ptrConst(builder).type; |
| 2158 | 2200 | } |
| ... | ... | @@ -2162,32 +2204,25 @@ pub const Global = struct { |
| 2162 | 2204 | } |
| 2163 | 2205 | |
| 2164 | 2206 | pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void { |
| 2165 | | if (builder.useLibLlvm()) self.toLlvm(builder).setLinkage(linkage.toLlvm()); |
| 2166 | 2207 | self.ptr(builder).linkage = linkage; |
| 2167 | 2208 | self.updateDsoLocal(builder); |
| 2168 | 2209 | } |
| 2169 | 2210 | |
| 2170 | 2211 | pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void { |
| 2171 | | if (builder.useLibLlvm()) self.toLlvm(builder).setVisibility(visibility.toLlvm()); |
| 2172 | 2212 | self.ptr(builder).visibility = visibility; |
| 2173 | 2213 | self.updateDsoLocal(builder); |
| 2174 | 2214 | } |
| 2175 | 2215 | |
| 2176 | 2216 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { |
| 2177 | | if (builder.useLibLlvm()) self.toLlvm(builder).setDLLStorageClass(class.toLlvm()); |
| 2178 | 2217 | self.ptr(builder).dll_storage_class = class; |
| 2179 | 2218 | } |
| 2180 | 2219 | |
| 2181 | 2220 | pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void { |
| 2182 | | if (builder.useLibLlvm()) self.toLlvm(builder).setUnnamedAddr( |
| 2183 | | llvm.Bool.fromBool(unnamed_addr != .default), |
| 2184 | | ); |
| 2185 | 2221 | self.ptr(builder).unnamed_addr = unnamed_addr; |
| 2186 | 2222 | } |
| 2187 | 2223 | |
| 2188 | | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2189 | | assert(builder.useLibLlvm()); |
| 2190 | | return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))]; |
| 2224 | pub fn setDebugMetadata(self: Index, dbg: Metadata, builder: *Builder) void { |
| 2225 | self.ptr(builder).dbg = dbg; |
| 2191 | 2226 | } |
| 2192 | 2227 | |
| 2193 | 2228 | const FormatData = struct { |
| ... | ... | @@ -2220,13 +2255,10 @@ pub const Global = struct { |
| 2220 | 2255 | |
| 2221 | 2256 | pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void { |
| 2222 | 2257 | try builder.ensureUnusedGlobalCapacity(.empty); |
| 2223 | | if (builder.useLibLlvm()) |
| 2224 | | try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1); |
| 2225 | 2258 | self.replaceAssumeCapacity(other, builder); |
| 2226 | 2259 | } |
| 2227 | 2260 | |
| 2228 | 2261 | pub fn delete(self: Index, builder: *Builder) void { |
| 2229 | | if (builder.useLibLlvm()) self.toLlvm(builder).eraseGlobalValue(); |
| 2230 | 2262 | self.ptr(builder).kind = .{ .replaced = .none }; |
| 2231 | 2263 | } |
| 2232 | 2264 | |
| ... | ... | @@ -2254,12 +2286,8 @@ pub const Global = struct { |
| 2254 | 2286 | const old_name = self.name(builder); |
| 2255 | 2287 | if (new_name == old_name) return; |
| 2256 | 2288 | const index = @intFromEnum(self.unwrap(builder)); |
| 2257 | | if (builder.useLibLlvm()) |
| 2258 | | builder.llvm.globals.appendAssumeCapacity(builder.llvm.globals.items[index]); |
| 2259 | 2289 | _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); |
| 2260 | | if (builder.useLibLlvm()) _ = builder.llvm.globals.pop(); |
| 2261 | 2290 | builder.globals.swapRemoveAt(index); |
| 2262 | | self.updateName(builder); |
| 2263 | 2291 | if (!old_name.isAnon()) return; |
| 2264 | 2292 | builder.next_unnamed_global = @enumFromInt(@intFromEnum(builder.next_unnamed_global) - 1); |
| 2265 | 2293 | if (builder.next_unnamed_global == old_name) return; |
| ... | ... | @@ -2272,23 +2300,10 @@ pub const Global = struct { |
| 2272 | 2300 | self.renameAssumeCapacity(other_name, builder); |
| 2273 | 2301 | } |
| 2274 | 2302 | |
| 2275 | | fn updateName(self: Index, builder: *const Builder) void { |
| 2276 | | if (!builder.useLibLlvm()) return; |
| 2277 | | const index = @intFromEnum(self.unwrap(builder)); |
| 2278 | | const name_slice = self.name(builder).slice(builder) orelse ""; |
| 2279 | | builder.llvm.globals.items[index].setValueName(name_slice.ptr, name_slice.len); |
| 2280 | | } |
| 2281 | | |
| 2282 | 2303 | fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { |
| 2283 | 2304 | if (self.eql(other, builder)) return; |
| 2284 | 2305 | builder.next_replaced_global = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1); |
| 2285 | 2306 | self.renameAssumeCapacity(builder.next_replaced_global, builder); |
| 2286 | | if (builder.useLibLlvm()) { |
| 2287 | | const self_llvm = self.toLlvm(builder); |
| 2288 | | self_llvm.replaceAllUsesWith(other.toLlvm(builder)); |
| 2289 | | self_llvm.removeGlobalValue(); |
| 2290 | | builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other); |
| 2291 | | } |
| 2292 | 2307 | self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; |
| 2293 | 2308 | } |
| 2294 | 2309 | |
| ... | ... | @@ -2345,13 +2360,8 @@ pub const Alias = struct { |
| 2345 | 2360 | } |
| 2346 | 2361 | |
| 2347 | 2362 | pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void { |
| 2348 | | if (builder.useLibLlvm()) self.toLlvm(builder).setAliasee(aliasee.toLlvm(builder)); |
| 2349 | 2363 | self.ptr(builder).aliasee = aliasee; |
| 2350 | 2364 | } |
| 2351 | | |
| 2352 | | fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2353 | | return self.ptrConst(builder).global.toLlvm(builder); |
| 2354 | | } |
| 2355 | 2365 | }; |
| 2356 | 2366 | }; |
| 2357 | 2367 | |
| ... | ... | @@ -2404,14 +2414,10 @@ pub const Variable = struct { |
| 2404 | 2414 | } |
| 2405 | 2415 | |
| 2406 | 2416 | pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void { |
| 2407 | | if (builder.useLibLlvm()) self.toLlvm(builder).setThreadLocalMode(thread_local.toLlvm()); |
| 2408 | 2417 | self.ptr(builder).thread_local = thread_local; |
| 2409 | 2418 | } |
| 2410 | 2419 | |
| 2411 | 2420 | pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void { |
| 2412 | | if (builder.useLibLlvm()) self.toLlvm(builder).setGlobalConstant( |
| 2413 | | llvm.Bool.fromBool(mutability == .constant), |
| 2414 | | ); |
| 2415 | 2421 | self.ptr(builder).mutability = mutability; |
| 2416 | 2422 | } |
| 2417 | 2423 | |
| ... | ... | @@ -2424,67 +2430,25 @@ pub const Variable = struct { |
| 2424 | 2430 | const variable = self.ptrConst(builder); |
| 2425 | 2431 | const global = variable.global.ptr(builder); |
| 2426 | 2432 | const initializer_type = initializer.typeOf(builder); |
| 2427 | | if (builder.useLibLlvm() and global.type != initializer_type) { |
| 2428 | | try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1); |
| 2429 | | // LLVM does not allow us to change the type of globals. So we must |
| 2430 | | // create a new global with the correct type, copy all its attributes, |
| 2431 | | // and then update all references to point to the new global, |
| 2432 | | // delete the original, and rename the new one to the old one's name. |
| 2433 | | // This is necessary because LLVM does not support const bitcasting |
| 2434 | | // a struct with padding bytes, which is needed to lower a const union value |
| 2435 | | // to LLVM, when a field other than the most-aligned is active. Instead, |
| 2436 | | // we must lower to an unnamed struct, and pointer cast at usage sites |
| 2437 | | // of the global. Such an unnamed struct is the cause of the global type |
| 2438 | | // mismatch, because we don't have the LLVM type until the *value* is created, |
| 2439 | | // whereas the global needs to be created based on the type alone, because |
| 2440 | | // lowering the value may reference the global as a pointer. |
| 2441 | | // Related: https://github.com/ziglang/zig/issues/13265 |
| 2442 | | const old_global = &builder.llvm.globals.items[@intFromEnum(variable.global)]; |
| 2443 | | const new_global = builder.llvm.module.?.addGlobalInAddressSpace( |
| 2444 | | initializer_type.toLlvm(builder), |
| 2445 | | "", |
| 2446 | | @intFromEnum(global.addr_space), |
| 2447 | | ); |
| 2448 | | new_global.setLinkage(global.linkage.toLlvm()); |
| 2449 | | new_global.setUnnamedAddr(llvm.Bool.fromBool(global.unnamed_addr != .default)); |
| 2450 | | new_global.setAlignment(@intCast(variable.alignment.toByteUnits() orelse 0)); |
| 2451 | | if (variable.section != .none) |
| 2452 | | new_global.setSection(variable.section.slice(builder).?); |
| 2453 | | old_global.*.replaceAllUsesWith(new_global); |
| 2454 | | builder.llvm.replacements.putAssumeCapacityNoClobber(old_global.*, variable.global); |
| 2455 | | new_global.takeName(old_global.*); |
| 2456 | | old_global.*.removeGlobalValue(); |
| 2457 | | old_global.* = new_global; |
| 2458 | | self.ptr(builder).mutability = .global; |
| 2459 | | } |
| 2460 | 2433 | global.type = initializer_type; |
| 2461 | 2434 | } |
| 2462 | | if (builder.useLibLlvm()) self.toLlvm(builder).setInitializer(switch (initializer) { |
| 2463 | | .no_init => null, |
| 2464 | | else => initializer.toLlvm(builder), |
| 2465 | | }); |
| 2466 | 2435 | self.ptr(builder).init = initializer; |
| 2467 | 2436 | } |
| 2468 | 2437 | |
| 2469 | 2438 | pub fn setSection(self: Index, section: String, builder: *Builder) void { |
| 2470 | | if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?); |
| 2471 | 2439 | self.ptr(builder).section = section; |
| 2472 | 2440 | } |
| 2473 | 2441 | |
| 2474 | 2442 | pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void { |
| 2475 | | if (builder.useLibLlvm()) |
| 2476 | | self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0)); |
| 2477 | 2443 | self.ptr(builder).alignment = alignment; |
| 2478 | 2444 | } |
| 2479 | 2445 | |
| 2480 | 2446 | pub fn getAlignment(self: Index, builder: *Builder) Alignment { |
| 2481 | | if (builder.useLibLlvm()) |
| 2482 | | return Alignment.fromByteUnits(self.toLlvm(builder).getAlignment()); |
| 2483 | 2447 | return self.ptr(builder).alignment; |
| 2484 | 2448 | } |
| 2485 | 2449 | |
| 2486 | | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2487 | | return self.ptrConst(builder).global.toLlvm(builder); |
| 2450 | pub fn setGlobalVariableExpression(self: Index, expression: Metadata, builder: *Builder) void { |
| 2451 | self.ptrConst(builder).global.setDebugMetadata(expression, builder); |
| 2488 | 2452 | } |
| 2489 | 2453 | }; |
| 2490 | 2454 | }; |
| ... | ... | @@ -2633,6 +2597,10 @@ pub const Intrinsic = enum { |
| 2633 | 2597 | @"threadlocal.address", |
| 2634 | 2598 | vscale, |
| 2635 | 2599 | |
| 2600 | // Debug |
| 2601 | @"dbg.declare", |
| 2602 | @"dbg.value", |
| 2603 | |
| 2636 | 2604 | // AMDGPU |
| 2637 | 2605 | @"amdgcn.workitem.id.x", |
| 2638 | 2606 | @"amdgcn.workitem.id.y", |
| ... | ... | @@ -3727,6 +3695,25 @@ pub const Intrinsic = enum { |
| 3727 | 3695 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, |
| 3728 | 3696 | }, |
| 3729 | 3697 | |
| 3698 | .@"dbg.declare" = .{ |
| 3699 | .ret_len = 0, |
| 3700 | .params = &.{ |
| 3701 | .{ .kind = .{ .type = .metadata } }, |
| 3702 | .{ .kind = .{ .type = .metadata } }, |
| 3703 | .{ .kind = .{ .type = .metadata } }, |
| 3704 | }, |
| 3705 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, |
| 3706 | }, |
| 3707 | .@"dbg.value" = .{ |
| 3708 | .ret_len = 0, |
| 3709 | .params = &.{ |
| 3710 | .{ .kind = .{ .type = .metadata } }, |
| 3711 | .{ .kind = .{ .type = .metadata } }, |
| 3712 | .{ .kind = .{ .type = .metadata } }, |
| 3713 | }, |
| 3714 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, |
| 3715 | }, |
| 3716 | |
| 3730 | 3717 | .@"amdgcn.workitem.id.x" = .{ |
| 3731 | 3718 | .ret_len = 1, |
| 3732 | 3719 | .params = &.{ |
| ... | ... | @@ -3809,7 +3796,9 @@ pub const Function = struct { |
| 3809 | 3796 | blocks: []const Block = &.{}, |
| 3810 | 3797 | instructions: std.MultiArrayList(Instruction) = .{}, |
| 3811 | 3798 | names: [*]const String = &[0]String{}, |
| 3812 | | metadata: ?[*]const Metadata = null, |
| 3799 | value_indices: [*]const u32 = &[0]u32{}, |
| 3800 | debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, Metadata) = .{}, |
| 3801 | debug_values: []const Instruction.Index = &.{}, |
| 3813 | 3802 | extra: []const u32 = &.{}, |
| 3814 | 3803 | |
| 3815 | 3804 | pub const Index = enum(u32) { |
| ... | ... | @@ -3853,7 +3842,6 @@ pub const Function = struct { |
| 3853 | 3842 | } |
| 3854 | 3843 | |
| 3855 | 3844 | pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void { |
| 3856 | | if (builder.useLibLlvm()) self.toLlvm(builder).setFunctionCallConv(call_conv.toLlvm()); |
| 3857 | 3845 | self.ptr(builder).call_conv = call_conv; |
| 3858 | 3846 | } |
| 3859 | 3847 | |
| ... | ... | @@ -3862,94 +3850,19 @@ pub const Function = struct { |
| 3862 | 3850 | new_function_attributes: FunctionAttributes, |
| 3863 | 3851 | builder: *Builder, |
| 3864 | 3852 | ) void { |
| 3865 | | if (builder.useLibLlvm()) { |
| 3866 | | const llvm_function = self.toLlvm(builder); |
| 3867 | | const old_function_attributes = self.ptrConst(builder).attributes; |
| 3868 | | for (0..@max( |
| 3869 | | old_function_attributes.slice(builder).len, |
| 3870 | | new_function_attributes.slice(builder).len, |
| 3871 | | )) |function_attribute_index| { |
| 3872 | | const llvm_attribute_index = |
| 3873 | | @as(llvm.AttributeIndex, @intCast(function_attribute_index)) -% 1; |
| 3874 | | const old_attributes_slice = |
| 3875 | | old_function_attributes.get(function_attribute_index, builder).slice(builder); |
| 3876 | | const new_attributes_slice = |
| 3877 | | new_function_attributes.get(function_attribute_index, builder).slice(builder); |
| 3878 | | var old_attribute_index: usize = 0; |
| 3879 | | var new_attribute_index: usize = 0; |
| 3880 | | while (true) { |
| 3881 | | const old_attribute_kind = if (old_attribute_index < old_attributes_slice.len) |
| 3882 | | old_attributes_slice[old_attribute_index].getKind(builder) |
| 3883 | | else |
| 3884 | | .none; |
| 3885 | | const new_attribute_kind = if (new_attribute_index < new_attributes_slice.len) |
| 3886 | | new_attributes_slice[new_attribute_index].getKind(builder) |
| 3887 | | else |
| 3888 | | .none; |
| 3889 | | switch (std.math.order( |
| 3890 | | @intFromEnum(old_attribute_kind), |
| 3891 | | @intFromEnum(new_attribute_kind), |
| 3892 | | )) { |
| 3893 | | .lt => { |
| 3894 | | // Removed |
| 3895 | | if (old_attribute_kind.toString()) |attribute_name| { |
| 3896 | | const attribute_name_slice = attribute_name.slice(builder).?; |
| 3897 | | llvm_function.removeStringAttributeAtIndex( |
| 3898 | | llvm_attribute_index, |
| 3899 | | attribute_name_slice.ptr, |
| 3900 | | @intCast(attribute_name_slice.len), |
| 3901 | | ); |
| 3902 | | } else { |
| 3903 | | const llvm_kind_id = old_attribute_kind.toLlvm(builder).*; |
| 3904 | | assert(llvm_kind_id != 0); |
| 3905 | | llvm_function.removeEnumAttributeAtIndex( |
| 3906 | | llvm_attribute_index, |
| 3907 | | llvm_kind_id, |
| 3908 | | ); |
| 3909 | | } |
| 3910 | | old_attribute_index += 1; |
| 3911 | | continue; |
| 3912 | | }, |
| 3913 | | .eq => { |
| 3914 | | // Iteration finished |
| 3915 | | if (old_attribute_kind == .none) break; |
| 3916 | | // No change |
| 3917 | | if (old_attributes_slice[old_attribute_index] == |
| 3918 | | new_attributes_slice[new_attribute_index]) |
| 3919 | | { |
| 3920 | | old_attribute_index += 1; |
| 3921 | | new_attribute_index += 1; |
| 3922 | | continue; |
| 3923 | | } |
| 3924 | | old_attribute_index += 1; |
| 3925 | | }, |
| 3926 | | .gt => {}, |
| 3927 | | } |
| 3928 | | // New or changed |
| 3929 | | llvm_function.addAttributeAtIndex( |
| 3930 | | llvm_attribute_index, |
| 3931 | | new_attributes_slice[new_attribute_index].toLlvm(builder), |
| 3932 | | ); |
| 3933 | | new_attribute_index += 1; |
| 3934 | | } |
| 3935 | | } |
| 3936 | | } |
| 3937 | 3853 | self.ptr(builder).attributes = new_function_attributes; |
| 3938 | 3854 | } |
| 3939 | 3855 | |
| 3940 | 3856 | pub fn setSection(self: Index, section: String, builder: *Builder) void { |
| 3941 | | if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?); |
| 3942 | 3857 | self.ptr(builder).section = section; |
| 3943 | 3858 | } |
| 3944 | 3859 | |
| 3945 | 3860 | pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void { |
| 3946 | | if (builder.useLibLlvm()) |
| 3947 | | self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0)); |
| 3948 | 3861 | self.ptr(builder).alignment = alignment; |
| 3949 | 3862 | } |
| 3950 | 3863 | |
| 3951 | | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 3952 | | return self.ptrConst(builder).global.toLlvm(builder); |
| 3864 | pub fn setSubprogram(self: Index, subprogram: Metadata, builder: *Builder) void { |
| 3865 | self.ptrConst(builder).global.setDebugMetadata(subprogram, builder); |
| 3953 | 3866 | } |
| 3954 | 3867 | }; |
| 3955 | 3868 | |
| ... | ... | @@ -4098,6 +4011,143 @@ pub const Function = struct { |
| 4098 | 4011 | va_arg, |
| 4099 | 4012 | xor, |
| 4100 | 4013 | zext, |
| 4014 | |
| 4015 | pub fn toBinaryOpcode(self: Tag) BinaryOpcode { |
| 4016 | return switch (self) { |
| 4017 | .add, |
| 4018 | .@"add nsw", |
| 4019 | .@"add nuw", |
| 4020 | .@"add nuw nsw", |
| 4021 | .fadd, |
| 4022 | .@"fadd fast", |
| 4023 | => .add, |
| 4024 | .sub, |
| 4025 | .@"sub nsw", |
| 4026 | .@"sub nuw", |
| 4027 | .@"sub nuw nsw", |
| 4028 | .fsub, |
| 4029 | .@"fsub fast", |
| 4030 | => .sub, |
| 4031 | .sdiv, |
| 4032 | .@"sdiv exact", |
| 4033 | .fdiv, |
| 4034 | .@"fdiv fast", |
| 4035 | => .sdiv, |
| 4036 | .fmul, |
| 4037 | .@"fmul fast", |
| 4038 | .mul, |
| 4039 | .@"mul nsw", |
| 4040 | .@"mul nuw", |
| 4041 | .@"mul nuw nsw", |
| 4042 | => .mul, |
| 4043 | .srem, |
| 4044 | .frem, |
| 4045 | .@"frem fast", |
| 4046 | => .srem, |
| 4047 | .udiv, |
| 4048 | .@"udiv exact", |
| 4049 | => .udiv, |
| 4050 | .shl, |
| 4051 | .@"shl nsw", |
| 4052 | .@"shl nuw", |
| 4053 | .@"shl nuw nsw", |
| 4054 | => .shl, |
| 4055 | .lshr, |
| 4056 | .@"lshr exact", |
| 4057 | => .lshr, |
| 4058 | .ashr, |
| 4059 | .@"ashr exact", |
| 4060 | => .ashr, |
| 4061 | .@"and" => .@"and", |
| 4062 | .@"or" => .@"or", |
| 4063 | .xor => .xor, |
| 4064 | .urem => .urem, |
| 4065 | else => unreachable, |
| 4066 | }; |
| 4067 | } |
| 4068 | |
| 4069 | pub fn toCastOpcode(self: Tag) CastOpcode { |
| 4070 | return switch (self) { |
| 4071 | .trunc => .trunc, |
| 4072 | .zext => .zext, |
| 4073 | .sext => .sext, |
| 4074 | .fptoui => .fptoui, |
| 4075 | .fptosi => .fptosi, |
| 4076 | .uitofp => .uitofp, |
| 4077 | .sitofp => .sitofp, |
| 4078 | .fptrunc => .fptrunc, |
| 4079 | .fpext => .fpext, |
| 4080 | .ptrtoint => .ptrtoint, |
| 4081 | .inttoptr => .inttoptr, |
| 4082 | .bitcast => .bitcast, |
| 4083 | .addrspacecast => .addrspacecast, |
| 4084 | else => unreachable, |
| 4085 | }; |
| 4086 | } |
| 4087 | |
| 4088 | pub fn toCmpPredicate(self: Tag) CmpPredicate { |
| 4089 | return switch (self) { |
| 4090 | .@"fcmp false", |
| 4091 | .@"fcmp fast false", |
| 4092 | => .fcmp_false, |
| 4093 | .@"fcmp oeq", |
| 4094 | .@"fcmp fast oeq", |
| 4095 | => .fcmp_oeq, |
| 4096 | .@"fcmp oge", |
| 4097 | .@"fcmp fast oge", |
| 4098 | => .fcmp_oge, |
| 4099 | .@"fcmp ogt", |
| 4100 | .@"fcmp fast ogt", |
| 4101 | => .fcmp_ogt, |
| 4102 | .@"fcmp ole", |
| 4103 | .@"fcmp fast ole", |
| 4104 | => .fcmp_ole, |
| 4105 | .@"fcmp olt", |
| 4106 | .@"fcmp fast olt", |
| 4107 | => .fcmp_olt, |
| 4108 | .@"fcmp one", |
| 4109 | .@"fcmp fast one", |
| 4110 | => .fcmp_one, |
| 4111 | .@"fcmp ord", |
| 4112 | .@"fcmp fast ord", |
| 4113 | => .fcmp_ord, |
| 4114 | .@"fcmp true", |
| 4115 | .@"fcmp fast true", |
| 4116 | => .fcmp_true, |
| 4117 | .@"fcmp ueq", |
| 4118 | .@"fcmp fast ueq", |
| 4119 | => .fcmp_ueq, |
| 4120 | .@"fcmp uge", |
| 4121 | .@"fcmp fast uge", |
| 4122 | => .fcmp_uge, |
| 4123 | .@"fcmp ugt", |
| 4124 | .@"fcmp fast ugt", |
| 4125 | => .fcmp_ugt, |
| 4126 | .@"fcmp ule", |
| 4127 | .@"fcmp fast ule", |
| 4128 | => .fcmp_ule, |
| 4129 | .@"fcmp ult", |
| 4130 | .@"fcmp fast ult", |
| 4131 | => .fcmp_ult, |
| 4132 | .@"fcmp une", |
| 4133 | .@"fcmp fast une", |
| 4134 | => .fcmp_une, |
| 4135 | .@"fcmp uno", |
| 4136 | .@"fcmp fast uno", |
| 4137 | => .fcmp_uno, |
| 4138 | .@"icmp eq" => .icmp_eq, |
| 4139 | .@"icmp ne" => .icmp_ne, |
| 4140 | .@"icmp sge" => .icmp_sge, |
| 4141 | .@"icmp sgt" => .icmp_sgt, |
| 4142 | .@"icmp sle" => .icmp_sle, |
| 4143 | .@"icmp slt" => .icmp_slt, |
| 4144 | .@"icmp uge" => .icmp_uge, |
| 4145 | .@"icmp ugt" => .icmp_ugt, |
| 4146 | .@"icmp ule" => .icmp_ule, |
| 4147 | .@"icmp ult" => .icmp_ult, |
| 4148 | else => unreachable, |
| 4149 | }; |
| 4150 | } |
| 4101 | 4151 | }; |
| 4102 | 4152 | |
| 4103 | 4153 | pub const Index = enum(u32) { |
| ... | ... | @@ -4108,6 +4158,10 @@ pub const Function = struct { |
| 4108 | 4158 | return function.names[@intFromEnum(self)]; |
| 4109 | 4159 | } |
| 4110 | 4160 | |
| 4161 | pub fn valueIndex(self: Instruction.Index, function: *const Function) u32 { |
| 4162 | return function.value_indices[@intFromEnum(self)]; |
| 4163 | } |
| 4164 | |
| 4111 | 4165 | pub fn toValue(self: Instruction.Index) Value { |
| 4112 | 4166 | return @enumFromInt(@intFromEnum(self)); |
| 4113 | 4167 | } |
| ... | ... | @@ -4136,6 +4190,7 @@ pub const Function = struct { |
| 4136 | 4190 | .@"store atomic", |
| 4137 | 4191 | .@"switch", |
| 4138 | 4192 | .@"unreachable", |
| 4193 | .block, |
| 4139 | 4194 | => false, |
| 4140 | 4195 | .call, |
| 4141 | 4196 | .@"call fast", |
| ... | ... | @@ -4240,7 +4295,7 @@ pub const Function = struct { |
| 4240 | 4295 | => wip.builder.structTypeAssumeCapacity(.normal, &.{ |
| 4241 | 4296 | wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip), |
| 4242 | 4297 | .i1, |
| 4243 | | }) catch unreachable, |
| 4298 | }), |
| 4244 | 4299 | .extractelement => wip.extraData(ExtractElement, instruction.data) |
| 4245 | 4300 | .val.typeOfWip(wip).childType(wip.builder), |
| 4246 | 4301 | .extractvalue => { |
| ... | ... | @@ -4427,7 +4482,7 @@ pub const Function = struct { |
| 4427 | 4482 | function.extraData(CmpXchg, instruction.data) |
| 4428 | 4483 | .cmp.typeOf(function_index, builder), |
| 4429 | 4484 | .i1, |
| 4430 | | }) catch unreachable, |
| 4485 | }), |
| 4431 | 4486 | .extractelement => function.extraData(ExtractElement, instruction.data) |
| 4432 | 4487 | .val.typeOf(function_index, builder).childType(builder), |
| 4433 | 4488 | .extractvalue => { |
| ... | ... | @@ -4557,20 +4612,6 @@ pub const Function = struct { |
| 4557 | 4612 | ) std.fmt.Formatter(format) { |
| 4558 | 4613 | return .{ .data = .{ .instruction = self, .function = function, .builder = builder } }; |
| 4559 | 4614 | } |
| 4560 | | |
| 4561 | | fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value { |
| 4562 | | assert(wip.builder.useLibLlvm()); |
| 4563 | | const llvm_value = wip.llvm.instructions.items[@intFromEnum(self)]; |
| 4564 | | const global = wip.builder.llvm.replacements.get(llvm_value) orelse return llvm_value; |
| 4565 | | return global.toLlvm(wip.builder); |
| 4566 | | } |
| 4567 | | |
| 4568 | | fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 { |
| 4569 | | return if (wip.builder.strip) |
| 4570 | | "" |
| 4571 | | else |
| 4572 | | wip.names.items[@intFromEnum(self)].slice(wip.builder).?; |
| 4573 | | } |
| 4574 | 4615 | }; |
| 4575 | 4616 | |
| 4576 | 4617 | pub const ExtraIndex = u32; |
| ... | ... | @@ -4664,43 +4705,22 @@ pub const Function = struct { |
| 4664 | 4705 | val: Value, |
| 4665 | 4706 | |
| 4666 | 4707 | pub const Operation = enum(u5) { |
| 4667 | | xchg, |
| 4668 | | add, |
| 4669 | | sub, |
| 4670 | | @"and", |
| 4671 | | nand, |
| 4672 | | @"or", |
| 4673 | | xor, |
| 4674 | | max, |
| 4675 | | min, |
| 4676 | | umax, |
| 4677 | | umin, |
| 4678 | | fadd, |
| 4679 | | fsub, |
| 4680 | | fmax, |
| 4681 | | fmin, |
| 4708 | xchg = 0, |
| 4709 | add = 1, |
| 4710 | sub = 2, |
| 4711 | @"and" = 3, |
| 4712 | nand = 4, |
| 4713 | @"or" = 5, |
| 4714 | xor = 6, |
| 4715 | max = 7, |
| 4716 | min = 8, |
| 4717 | umax = 9, |
| 4718 | umin = 10, |
| 4719 | fadd = 11, |
| 4720 | fsub = 12, |
| 4721 | fmax = 13, |
| 4722 | fmin = 14, |
| 4682 | 4723 | none = std.math.maxInt(u5), |
| 4683 | | |
| 4684 | | fn toLlvm(self: Operation) llvm.AtomicRMWBinOp { |
| 4685 | | return switch (self) { |
| 4686 | | .xchg => .Xchg, |
| 4687 | | .add => .Add, |
| 4688 | | .sub => .Sub, |
| 4689 | | .@"and" => .And, |
| 4690 | | .nand => .Nand, |
| 4691 | | .@"or" => .Or, |
| 4692 | | .xor => .Xor, |
| 4693 | | .max => .Max, |
| 4694 | | .min => .Min, |
| 4695 | | .umax => .UMax, |
| 4696 | | .umin => .UMin, |
| 4697 | | .fadd => .FAdd, |
| 4698 | | .fsub => .FSub, |
| 4699 | | .fmax => .FMax, |
| 4700 | | .fmin => .FMin, |
| 4701 | | .none => unreachable, |
| 4702 | | }; |
| 4703 | | } |
| 4704 | 4724 | }; |
| 4705 | 4725 | }; |
| 4706 | 4726 | |
| ... | ... | @@ -4764,7 +4784,9 @@ pub const Function = struct { |
| 4764 | 4784 | |
| 4765 | 4785 | pub fn deinit(self: *Function, gpa: Allocator) void { |
| 4766 | 4786 | gpa.free(self.extra); |
| 4767 | | if (self.metadata) |metadata| gpa.free(metadata[0..self.instructions.len]); |
| 4787 | gpa.free(self.debug_values); |
| 4788 | self.debug_locations.deinit(gpa); |
| 4789 | gpa.free(self.value_indices[0..self.instructions.len]); |
| 4768 | 4790 | gpa.free(self.names[0..self.instructions.len]); |
| 4769 | 4791 | self.instructions.deinit(gpa); |
| 4770 | 4792 | gpa.free(self.blocks); |
| ... | ... | @@ -4822,7 +4844,7 @@ pub const Function = struct { |
| 4822 | 4844 | Instruction.Alloca.Info, |
| 4823 | 4845 | Instruction.Call.Info, |
| 4824 | 4846 | => @bitCast(value), |
| 4825 | | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 4847 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 4826 | 4848 | }; |
| 4827 | 4849 | return .{ |
| 4828 | 4850 | .data = result, |
| ... | ... | @@ -4838,16 +4860,14 @@ pub const Function = struct { |
| 4838 | 4860 | pub const WipFunction = struct { |
| 4839 | 4861 | builder: *Builder, |
| 4840 | 4862 | function: Function.Index, |
| 4841 | | llvm: if (build_options.have_llvm) struct { |
| 4842 | | builder: *llvm.Builder, |
| 4843 | | blocks: std.ArrayListUnmanaged(*llvm.BasicBlock), |
| 4844 | | instructions: std.ArrayListUnmanaged(*llvm.Value), |
| 4845 | | } else void, |
| 4863 | last_debug_location: Metadata, |
| 4864 | current_debug_location: Metadata, |
| 4846 | 4865 | cursor: Cursor, |
| 4847 | 4866 | blocks: std.ArrayListUnmanaged(Block), |
| 4848 | 4867 | instructions: std.MultiArrayList(Instruction), |
| 4849 | 4868 | names: std.ArrayListUnmanaged(String), |
| 4850 | | metadata: std.ArrayListUnmanaged(Metadata), |
| 4869 | debug_locations: std.AutoArrayHashMapUnmanaged(Instruction.Index, Metadata), |
| 4870 | debug_values: std.AutoArrayHashMapUnmanaged(Instruction.Index, void), |
| 4851 | 4871 | extra: std.ArrayListUnmanaged(u32), |
| 4852 | 4872 | |
| 4853 | 4873 | pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 }; |
| ... | ... | @@ -4873,35 +4893,23 @@ pub const WipFunction = struct { |
| 4873 | 4893 | pub fn toInst(self: Index, function: *const Function) Instruction.Index { |
| 4874 | 4894 | return function.blocks[@intFromEnum(self)].instruction; |
| 4875 | 4895 | } |
| 4876 | | |
| 4877 | | pub fn toLlvm(self: Index, wip: *const WipFunction) *llvm.BasicBlock { |
| 4878 | | assert(wip.builder.useLibLlvm()); |
| 4879 | | return wip.llvm.blocks.items[@intFromEnum(self)]; |
| 4880 | | } |
| 4881 | 4896 | }; |
| 4882 | 4897 | }; |
| 4883 | 4898 | |
| 4884 | 4899 | pub const Instruction = Function.Instruction; |
| 4885 | 4900 | |
| 4886 | 4901 | pub fn init(builder: *Builder, function: Function.Index) Allocator.Error!WipFunction { |
| 4887 | | if (builder.useLibLlvm()) { |
| 4888 | | const llvm_function = function.toLlvm(builder); |
| 4889 | | while (llvm_function.getFirstBasicBlock()) |bb| bb.deleteBasicBlock(); |
| 4890 | | } |
| 4891 | | |
| 4892 | | var self = WipFunction{ |
| 4902 | var self: WipFunction = .{ |
| 4893 | 4903 | .builder = builder, |
| 4894 | 4904 | .function = function, |
| 4895 | | .llvm = if (builder.useLibLlvm()) .{ |
| 4896 | | .builder = builder.llvm.context.createBuilder(), |
| 4897 | | .blocks = .{}, |
| 4898 | | .instructions = .{}, |
| 4899 | | } else undefined, |
| 4905 | .last_debug_location = .none, |
| 4906 | .current_debug_location = .none, |
| 4900 | 4907 | .cursor = undefined, |
| 4901 | 4908 | .blocks = .{}, |
| 4902 | 4909 | .instructions = .{}, |
| 4903 | 4910 | .names = .{}, |
| 4904 | | .metadata = .{}, |
| 4911 | .debug_locations = .{}, |
| 4912 | .debug_values = .{}, |
| 4905 | 4913 | .extra = .{}, |
| 4906 | 4914 | }; |
| 4907 | 4915 | errdefer self.deinit(); |
| ... | ... | @@ -4909,15 +4917,14 @@ pub const WipFunction = struct { |
| 4909 | 4917 | const params_len = function.typeOf(self.builder).functionParameters(self.builder).len; |
| 4910 | 4918 | try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0); |
| 4911 | 4919 | try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 4912 | | if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 4913 | | if (self.builder.useLibLlvm()) |
| 4914 | | try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 4920 | if (!self.builder.strip) { |
| 4921 | try self.names.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 4922 | } |
| 4915 | 4923 | for (0..params_len) |param_index| { |
| 4916 | 4924 | self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) }); |
| 4917 | | if (!self.builder.strip) self.names.appendAssumeCapacity(.empty); // TODO: param names |
| 4918 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 4919 | | function.toLlvm(self.builder).getParam(@intCast(param_index)), |
| 4920 | | ); |
| 4925 | if (!self.builder.strip) { |
| 4926 | self.names.appendAssumeCapacity(.empty); // TODO: param names |
| 4927 | } |
| 4921 | 4928 | } |
| 4922 | 4929 | |
| 4923 | 4930 | return self; |
| ... | ... | @@ -4934,7 +4941,6 @@ pub const WipFunction = struct { |
| 4934 | 4941 | |
| 4935 | 4942 | pub fn block(self: *WipFunction, incoming: u32, name: []const u8) Allocator.Error!Block.Index { |
| 4936 | 4943 | try self.blocks.ensureUnusedCapacity(self.builder.gpa, 1); |
| 4937 | | if (self.builder.useLibLlvm()) try self.llvm.blocks.ensureUnusedCapacity(self.builder.gpa, 1); |
| 4938 | 4944 | |
| 4939 | 4945 | const index: Block.Index = @enumFromInt(self.blocks.items.len); |
| 4940 | 4946 | const final_name = if (self.builder.strip) .empty else try self.builder.string(name); |
| ... | ... | @@ -4943,41 +4949,24 @@ pub const WipFunction = struct { |
| 4943 | 4949 | .incoming = incoming, |
| 4944 | 4950 | .instructions = .{}, |
| 4945 | 4951 | }); |
| 4946 | | if (self.builder.useLibLlvm()) self.llvm.blocks.appendAssumeCapacity( |
| 4947 | | self.builder.llvm.context.appendBasicBlock( |
| 4948 | | self.function.toLlvm(self.builder), |
| 4949 | | final_name.slice(self.builder).?, |
| 4950 | | ), |
| 4951 | | ); |
| 4952 | 4952 | return index; |
| 4953 | 4953 | } |
| 4954 | 4954 | |
| 4955 | 4955 | pub fn ret(self: *WipFunction, val: Value) Allocator.Error!Instruction.Index { |
| 4956 | 4956 | assert(val.typeOfWip(self) == self.function.typeOf(self.builder).functionReturn(self.builder)); |
| 4957 | 4957 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 4958 | | const instruction = try self.addInst(null, .{ .tag = .ret, .data = @intFromEnum(val) }); |
| 4959 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 4960 | | self.llvm.builder.buildRet(val.toLlvm(self)), |
| 4961 | | ); |
| 4962 | | return instruction; |
| 4958 | return try self.addInst(null, .{ .tag = .ret, .data = @intFromEnum(val) }); |
| 4963 | 4959 | } |
| 4964 | 4960 | |
| 4965 | 4961 | pub fn retVoid(self: *WipFunction) Allocator.Error!Instruction.Index { |
| 4966 | 4962 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 4967 | | const instruction = try self.addInst(null, .{ .tag = .@"ret void", .data = undefined }); |
| 4968 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 4969 | | self.llvm.builder.buildRetVoid(), |
| 4970 | | ); |
| 4971 | | return instruction; |
| 4963 | return try self.addInst(null, .{ .tag = .@"ret void", .data = undefined }); |
| 4972 | 4964 | } |
| 4973 | 4965 | |
| 4974 | 4966 | pub fn br(self: *WipFunction, dest: Block.Index) Allocator.Error!Instruction.Index { |
| 4975 | 4967 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 4976 | 4968 | const instruction = try self.addInst(null, .{ .tag = .br, .data = @intFromEnum(dest) }); |
| 4977 | 4969 | dest.ptr(self).branches += 1; |
| 4978 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 4979 | | self.llvm.builder.buildBr(dest.toLlvm(self)), |
| 4980 | | ); |
| 4981 | 4970 | return instruction; |
| 4982 | 4971 | } |
| 4983 | 4972 | |
| ... | ... | @@ -4999,9 +4988,6 @@ pub const WipFunction = struct { |
| 4999 | 4988 | }); |
| 5000 | 4989 | then.ptr(self).branches += 1; |
| 5001 | 4990 | @"else".ptr(self).branches += 1; |
| 5002 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5003 | | self.llvm.builder.buildCondBr(cond.toLlvm(self), then.toLlvm(self), @"else".toLlvm(self)), |
| 5004 | | ); |
| 5005 | 4991 | return instruction; |
| 5006 | 4992 | } |
| 5007 | 4993 | |
| ... | ... | @@ -5022,8 +5008,6 @@ pub const WipFunction = struct { |
| 5022 | 5008 | extra.trail.nextMut(extra.data.cases_len, Block.Index, wip)[self.index] = dest; |
| 5023 | 5009 | self.index += 1; |
| 5024 | 5010 | dest.ptr(wip).branches += 1; |
| 5025 | | if (wip.builder.useLibLlvm()) |
| 5026 | | self.instruction.toLlvm(wip).addCase(val.toLlvm(wip.builder), dest.toLlvm(wip)); |
| 5027 | 5011 | } |
| 5028 | 5012 | |
| 5029 | 5013 | pub fn finish(self: WipSwitch, wip: *WipFunction) void { |
| ... | ... | @@ -5050,18 +5034,12 @@ pub const WipFunction = struct { |
| 5050 | 5034 | }); |
| 5051 | 5035 | _ = self.extra.addManyAsSliceAssumeCapacity(cases_len * 2); |
| 5052 | 5036 | default.ptr(self).branches += 1; |
| 5053 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5054 | | self.llvm.builder.buildSwitch(val.toLlvm(self), default.toLlvm(self), @intCast(cases_len)), |
| 5055 | | ); |
| 5056 | 5037 | return .{ .index = 0, .instruction = instruction }; |
| 5057 | 5038 | } |
| 5058 | 5039 | |
| 5059 | 5040 | pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index { |
| 5060 | 5041 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 5061 | 5042 | const instruction = try self.addInst(null, .{ .tag = .@"unreachable", .data = undefined }); |
| 5062 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5063 | | self.llvm.builder.buildUnreachable(), |
| 5064 | | ); |
| 5065 | 5043 | return instruction; |
| 5066 | 5044 | } |
| 5067 | 5045 | |
| ... | ... | @@ -5079,17 +5057,6 @@ pub const WipFunction = struct { |
| 5079 | 5057 | } |
| 5080 | 5058 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 5081 | 5059 | const instruction = try self.addInst(name, .{ .tag = tag, .data = @intFromEnum(val) }); |
| 5082 | | if (self.builder.useLibLlvm()) { |
| 5083 | | switch (tag) { |
| 5084 | | .fneg => self.llvm.builder.setFastMath(false), |
| 5085 | | .@"fneg fast" => self.llvm.builder.setFastMath(true), |
| 5086 | | else => unreachable, |
| 5087 | | } |
| 5088 | | self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 5089 | | .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg, |
| 5090 | | else => unreachable, |
| 5091 | | }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); |
| 5092 | | } |
| 5093 | 5060 | return instruction.toValue(); |
| 5094 | 5061 | } |
| 5095 | 5062 | |
| ... | ... | @@ -5157,56 +5124,6 @@ pub const WipFunction = struct { |
| 5157 | 5124 | .tag = tag, |
| 5158 | 5125 | .data = self.addExtraAssumeCapacity(Instruction.Binary{ .lhs = lhs, .rhs = rhs }), |
| 5159 | 5126 | }); |
| 5160 | | if (self.builder.useLibLlvm()) { |
| 5161 | | switch (tag) { |
| 5162 | | .fadd, |
| 5163 | | .fdiv, |
| 5164 | | .fmul, |
| 5165 | | .frem, |
| 5166 | | .fsub, |
| 5167 | | => self.llvm.builder.setFastMath(false), |
| 5168 | | .@"fadd fast", |
| 5169 | | .@"fdiv fast", |
| 5170 | | .@"fmul fast", |
| 5171 | | .@"frem fast", |
| 5172 | | .@"fsub fast", |
| 5173 | | => self.llvm.builder.setFastMath(true), |
| 5174 | | else => {}, |
| 5175 | | } |
| 5176 | | self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 5177 | | .add => &llvm.Builder.buildAdd, |
| 5178 | | .@"add nsw" => &llvm.Builder.buildNSWAdd, |
| 5179 | | .@"add nuw" => &llvm.Builder.buildNUWAdd, |
| 5180 | | .@"and" => &llvm.Builder.buildAnd, |
| 5181 | | .ashr => &llvm.Builder.buildAShr, |
| 5182 | | .@"ashr exact" => &llvm.Builder.buildAShrExact, |
| 5183 | | .fadd, .@"fadd fast" => &llvm.Builder.buildFAdd, |
| 5184 | | .fdiv, .@"fdiv fast" => &llvm.Builder.buildFDiv, |
| 5185 | | .fmul, .@"fmul fast" => &llvm.Builder.buildFMul, |
| 5186 | | .frem, .@"frem fast" => &llvm.Builder.buildFRem, |
| 5187 | | .fsub, .@"fsub fast" => &llvm.Builder.buildFSub, |
| 5188 | | .lshr => &llvm.Builder.buildLShr, |
| 5189 | | .@"lshr exact" => &llvm.Builder.buildLShrExact, |
| 5190 | | .mul => &llvm.Builder.buildMul, |
| 5191 | | .@"mul nsw" => &llvm.Builder.buildNSWMul, |
| 5192 | | .@"mul nuw" => &llvm.Builder.buildNUWMul, |
| 5193 | | .@"or" => &llvm.Builder.buildOr, |
| 5194 | | .sdiv => &llvm.Builder.buildSDiv, |
| 5195 | | .@"sdiv exact" => &llvm.Builder.buildExactSDiv, |
| 5196 | | .shl => &llvm.Builder.buildShl, |
| 5197 | | .@"shl nsw" => &llvm.Builder.buildNSWShl, |
| 5198 | | .@"shl nuw" => &llvm.Builder.buildNUWShl, |
| 5199 | | .srem => &llvm.Builder.buildSRem, |
| 5200 | | .sub => &llvm.Builder.buildSub, |
| 5201 | | .@"sub nsw" => &llvm.Builder.buildNSWSub, |
| 5202 | | .@"sub nuw" => &llvm.Builder.buildNUWSub, |
| 5203 | | .udiv => &llvm.Builder.buildUDiv, |
| 5204 | | .@"udiv exact" => &llvm.Builder.buildExactUDiv, |
| 5205 | | .urem => &llvm.Builder.buildURem, |
| 5206 | | .xor => &llvm.Builder.buildXor, |
| 5207 | | else => unreachable, |
| 5208 | | }(self.llvm.builder, lhs.toLlvm(self), rhs.toLlvm(self), instruction.llvmName(self))); |
| 5209 | | } |
| 5210 | 5127 | return instruction.toValue(); |
| 5211 | 5128 | } |
| 5212 | 5129 | |
| ... | ... | @@ -5226,13 +5143,6 @@ pub const WipFunction = struct { |
| 5226 | 5143 | .index = index, |
| 5227 | 5144 | }), |
| 5228 | 5145 | }); |
| 5229 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5230 | | self.llvm.builder.buildExtractElement( |
| 5231 | | val.toLlvm(self), |
| 5232 | | index.toLlvm(self), |
| 5233 | | instruction.llvmName(self), |
| 5234 | | ), |
| 5235 | | ); |
| 5236 | 5146 | return instruction.toValue(); |
| 5237 | 5147 | } |
| 5238 | 5148 | |
| ... | ... | @@ -5254,14 +5164,6 @@ pub const WipFunction = struct { |
| 5254 | 5164 | .index = index, |
| 5255 | 5165 | }), |
| 5256 | 5166 | }); |
| 5257 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5258 | | self.llvm.builder.buildInsertElement( |
| 5259 | | val.toLlvm(self), |
| 5260 | | elem.toLlvm(self), |
| 5261 | | index.toLlvm(self), |
| 5262 | | instruction.llvmName(self), |
| 5263 | | ), |
| 5264 | | ); |
| 5265 | 5167 | return instruction.toValue(); |
| 5266 | 5168 | } |
| 5267 | 5169 | |
| ... | ... | @@ -5284,14 +5186,6 @@ pub const WipFunction = struct { |
| 5284 | 5186 | .mask = mask, |
| 5285 | 5187 | }), |
| 5286 | 5188 | }); |
| 5287 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5288 | | self.llvm.builder.buildShuffleVector( |
| 5289 | | lhs.toLlvm(self), |
| 5290 | | rhs.toLlvm(self), |
| 5291 | | mask.toLlvm(self), |
| 5292 | | instruction.llvmName(self), |
| 5293 | | ), |
| 5294 | | ); |
| 5295 | 5189 | return instruction.toValue(); |
| 5296 | 5190 | } |
| 5297 | 5191 | |
| ... | ... | @@ -5303,10 +5197,9 @@ pub const WipFunction = struct { |
| 5303 | 5197 | ) Allocator.Error!Value { |
| 5304 | 5198 | const scalar_ty = try ty.changeLength(1, self.builder); |
| 5305 | 5199 | const mask_ty = try ty.changeScalar(.i32, self.builder); |
| 5306 | | const zero = try self.builder.intConst(.i32, 0); |
| 5307 | 5200 | const poison = try self.builder.poisonValue(scalar_ty); |
| 5308 | | const mask = try self.builder.splatValue(mask_ty, zero); |
| 5309 | | const scalar = try self.insertElement(poison, elem, zero.toValue(), name); |
| 5201 | const mask = try self.builder.splatValue(mask_ty, .@"0"); |
| 5202 | const scalar = try self.insertElement(poison, elem, .@"0", name); |
| 5310 | 5203 | return self.shuffleVector(scalar, poison, mask, name); |
| 5311 | 5204 | } |
| 5312 | 5205 | |
| ... | ... | @@ -5327,13 +5220,6 @@ pub const WipFunction = struct { |
| 5327 | 5220 | }), |
| 5328 | 5221 | }); |
| 5329 | 5222 | self.extra.appendSliceAssumeCapacity(indices); |
| 5330 | | if (self.builder.useLibLlvm()) { |
| 5331 | | const llvm_name = instruction.llvmName(self); |
| 5332 | | var cur = val.toLlvm(self); |
| 5333 | | for (indices) |index| |
| 5334 | | cur = self.llvm.builder.buildExtractValue(cur, @intCast(index), llvm_name); |
| 5335 | | self.llvm.instructions.appendAssumeCapacity(cur); |
| 5336 | | } |
| 5337 | 5223 | return instruction.toValue(); |
| 5338 | 5224 | } |
| 5339 | 5225 | |
| ... | ... | @@ -5356,35 +5242,6 @@ pub const WipFunction = struct { |
| 5356 | 5242 | }), |
| 5357 | 5243 | }); |
| 5358 | 5244 | self.extra.appendSliceAssumeCapacity(indices); |
| 5359 | | if (self.builder.useLibLlvm()) { |
| 5360 | | const ExpectedContents = [expected_gep_indices_len]*llvm.Value; |
| 5361 | | var stack align(@alignOf(ExpectedContents)) = |
| 5362 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.builder.gpa); |
| 5363 | | const allocator = stack.get(); |
| 5364 | | |
| 5365 | | const llvm_name = instruction.llvmName(self); |
| 5366 | | const llvm_vals = try allocator.alloc(*llvm.Value, indices.len); |
| 5367 | | defer allocator.free(llvm_vals); |
| 5368 | | llvm_vals[0] = val.toLlvm(self); |
| 5369 | | for (llvm_vals[1..], llvm_vals[0 .. llvm_vals.len - 1], indices[0 .. indices.len - 1]) | |
| 5370 | | *cur_val, |
| 5371 | | prev_val, |
| 5372 | | index, |
| 5373 | | | cur_val.* = self.llvm.builder.buildExtractValue(prev_val, @intCast(index), llvm_name); |
| 5374 | | |
| 5375 | | var depth: usize = llvm_vals.len; |
| 5376 | | var cur = elem.toLlvm(self); |
| 5377 | | while (depth > 0) { |
| 5378 | | depth -= 1; |
| 5379 | | cur = self.llvm.builder.buildInsertValue( |
| 5380 | | llvm_vals[depth], |
| 5381 | | cur, |
| 5382 | | @intCast(indices[depth]), |
| 5383 | | llvm_name, |
| 5384 | | ); |
| 5385 | | } |
| 5386 | | self.llvm.instructions.appendAssumeCapacity(cur); |
| 5387 | | } |
| 5388 | 5245 | return instruction.toValue(); |
| 5389 | 5246 | } |
| 5390 | 5247 | |
| ... | ... | @@ -5420,19 +5277,13 @@ pub const WipFunction = struct { |
| 5420 | 5277 | }, |
| 5421 | 5278 | .data = self.addExtraAssumeCapacity(Instruction.Alloca{ |
| 5422 | 5279 | .type = ty, |
| 5423 | | .len = len, |
| 5280 | .len = switch (len) { |
| 5281 | .none => .@"1", |
| 5282 | else => len, |
| 5283 | }, |
| 5424 | 5284 | .info = .{ .alignment = alignment, .addr_space = addr_space }, |
| 5425 | 5285 | }), |
| 5426 | 5286 | }); |
| 5427 | | if (self.builder.useLibLlvm()) { |
| 5428 | | const llvm_instruction = self.llvm.builder.buildAllocaInAddressSpace( |
| 5429 | | ty.toLlvm(self.builder), |
| 5430 | | @intFromEnum(addr_space), |
| 5431 | | instruction.llvmName(self), |
| 5432 | | ); |
| 5433 | | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5434 | | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 5435 | | } |
| 5436 | 5287 | return instruction.toValue(); |
| 5437 | 5288 | } |
| 5438 | 5289 | |
| ... | ... | @@ -5478,17 +5329,6 @@ pub const WipFunction = struct { |
| 5478 | 5329 | .ptr = ptr, |
| 5479 | 5330 | }), |
| 5480 | 5331 | }); |
| 5481 | | if (self.builder.useLibLlvm()) { |
| 5482 | | const llvm_instruction = self.llvm.builder.buildLoad( |
| 5483 | | ty.toLlvm(self.builder), |
| 5484 | | ptr.toLlvm(self), |
| 5485 | | instruction.llvmName(self), |
| 5486 | | ); |
| 5487 | | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); |
| 5488 | | if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm()); |
| 5489 | | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5490 | | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 5491 | | } |
| 5492 | 5332 | return instruction.toValue(); |
| 5493 | 5333 | } |
| 5494 | 5334 | |
| ... | ... | @@ -5532,13 +5372,6 @@ pub const WipFunction = struct { |
| 5532 | 5372 | .ptr = ptr, |
| 5533 | 5373 | }), |
| 5534 | 5374 | }); |
| 5535 | | if (self.builder.useLibLlvm()) { |
| 5536 | | const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self)); |
| 5537 | | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); |
| 5538 | | if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm()); |
| 5539 | | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5540 | | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 5541 | | } |
| 5542 | 5375 | return instruction; |
| 5543 | 5376 | } |
| 5544 | 5377 | |
| ... | ... | @@ -5556,13 +5389,6 @@ pub const WipFunction = struct { |
| 5556 | 5389 | .success_ordering = ordering, |
| 5557 | 5390 | }), |
| 5558 | 5391 | }); |
| 5559 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 5560 | | self.llvm.builder.buildFence( |
| 5561 | | ordering.toLlvm(), |
| 5562 | | llvm.Bool.fromBool(sync_scope == .singlethread), |
| 5563 | | "", |
| 5564 | | ), |
| 5565 | | ); |
| 5566 | 5392 | return instruction; |
| 5567 | 5393 | } |
| 5568 | 5394 | |
| ... | ... | @@ -5605,25 +5431,6 @@ pub const WipFunction = struct { |
| 5605 | 5431 | .new = new, |
| 5606 | 5432 | }), |
| 5607 | 5433 | }); |
| 5608 | | if (self.builder.useLibLlvm()) { |
| 5609 | | const llvm_instruction = self.llvm.builder.buildAtomicCmpXchg( |
| 5610 | | ptr.toLlvm(self), |
| 5611 | | cmp.toLlvm(self), |
| 5612 | | new.toLlvm(self), |
| 5613 | | success_ordering.toLlvm(), |
| 5614 | | failure_ordering.toLlvm(), |
| 5615 | | llvm.Bool.fromBool(sync_scope == .singlethread), |
| 5616 | | ); |
| 5617 | | if (kind == .weak) llvm_instruction.setWeak(.True); |
| 5618 | | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); |
| 5619 | | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5620 | | const llvm_name = instruction.llvmName(self); |
| 5621 | | if (llvm_name.len > 0) llvm_instruction.setValueName( |
| 5622 | | llvm_name.ptr, |
| 5623 | | @intCast(llvm_name.len), |
| 5624 | | ); |
| 5625 | | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 5626 | | } |
| 5627 | 5434 | return instruction.toValue(); |
| 5628 | 5435 | } |
| 5629 | 5436 | |
| ... | ... | @@ -5656,23 +5463,6 @@ pub const WipFunction = struct { |
| 5656 | 5463 | .val = val, |
| 5657 | 5464 | }), |
| 5658 | 5465 | }); |
| 5659 | | if (self.builder.useLibLlvm()) { |
| 5660 | | const llvm_instruction = self.llvm.builder.buildAtomicRmw( |
| 5661 | | operation.toLlvm(), |
| 5662 | | ptr.toLlvm(self), |
| 5663 | | val.toLlvm(self), |
| 5664 | | ordering.toLlvm(), |
| 5665 | | llvm.Bool.fromBool(sync_scope == .singlethread), |
| 5666 | | ); |
| 5667 | | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); |
| 5668 | | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 5669 | | const llvm_name = instruction.llvmName(self); |
| 5670 | | if (llvm_name.len > 0) llvm_instruction.setValueName( |
| 5671 | | llvm_name.ptr, |
| 5672 | | @intCast(llvm_name.len), |
| 5673 | | ); |
| 5674 | | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 5675 | | } |
| 5676 | 5466 | return instruction.toValue(); |
| 5677 | 5467 | } |
| 5678 | 5468 | |
| ... | ... | @@ -5732,28 +5522,6 @@ pub const WipFunction = struct { |
| 5732 | 5522 | }), |
| 5733 | 5523 | }); |
| 5734 | 5524 | self.extra.appendSliceAssumeCapacity(@ptrCast(indices)); |
| 5735 | | if (self.builder.useLibLlvm()) { |
| 5736 | | const ExpectedContents = [expected_gep_indices_len]*llvm.Value; |
| 5737 | | var stack align(@alignOf(ExpectedContents)) = |
| 5738 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.builder.gpa); |
| 5739 | | const allocator = stack.get(); |
| 5740 | | |
| 5741 | | const llvm_indices = try allocator.alloc(*llvm.Value, indices.len); |
| 5742 | | defer allocator.free(llvm_indices); |
| 5743 | | for (llvm_indices, indices) |*llvm_index, index| llvm_index.* = index.toLlvm(self); |
| 5744 | | |
| 5745 | | self.llvm.instructions.appendAssumeCapacity(switch (kind) { |
| 5746 | | .normal => &llvm.Builder.buildGEP, |
| 5747 | | .inbounds => &llvm.Builder.buildInBoundsGEP, |
| 5748 | | }( |
| 5749 | | self.llvm.builder, |
| 5750 | | ty.toLlvm(self.builder), |
| 5751 | | base.toLlvm(self), |
| 5752 | | llvm_indices.ptr, |
| 5753 | | @intCast(llvm_indices.len), |
| 5754 | | instruction.llvmName(self), |
| 5755 | | )); |
| 5756 | | } |
| 5757 | 5525 | return instruction.toValue(); |
| 5758 | 5526 | } |
| 5759 | 5527 | |
| ... | ... | @@ -5765,9 +5533,7 @@ pub const WipFunction = struct { |
| 5765 | 5533 | name: []const u8, |
| 5766 | 5534 | ) Allocator.Error!Value { |
| 5767 | 5535 | assert(ty.isStruct(self.builder)); |
| 5768 | | return self.gep(.inbounds, ty, base, &.{ |
| 5769 | | try self.builder.intValue(.i32, 0), try self.builder.intValue(.i32, index), |
| 5770 | | }, name); |
| 5536 | return self.gep(.inbounds, ty, base, &.{ .@"0", try self.builder.intValue(.i32, index) }, name); |
| 5771 | 5537 | } |
| 5772 | 5538 | |
| 5773 | 5539 | pub fn conv( |
| ... | ... | @@ -5815,22 +5581,6 @@ pub const WipFunction = struct { |
| 5815 | 5581 | .type = ty, |
| 5816 | 5582 | }), |
| 5817 | 5583 | }); |
| 5818 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 5819 | | .addrspacecast => &llvm.Builder.buildAddrSpaceCast, |
| 5820 | | .bitcast => &llvm.Builder.buildBitCast, |
| 5821 | | .fpext => &llvm.Builder.buildFPExt, |
| 5822 | | .fptosi => &llvm.Builder.buildFPToSI, |
| 5823 | | .fptoui => &llvm.Builder.buildFPToUI, |
| 5824 | | .fptrunc => &llvm.Builder.buildFPTrunc, |
| 5825 | | .inttoptr => &llvm.Builder.buildIntToPtr, |
| 5826 | | .ptrtoint => &llvm.Builder.buildPtrToInt, |
| 5827 | | .sext => &llvm.Builder.buildSExt, |
| 5828 | | .sitofp => &llvm.Builder.buildSIToFP, |
| 5829 | | .trunc => &llvm.Builder.buildTrunc, |
| 5830 | | .uitofp => &llvm.Builder.buildUIToFP, |
| 5831 | | .zext => &llvm.Builder.buildZExt, |
| 5832 | | else => unreachable, |
| 5833 | | }(self.llvm.builder, val.toLlvm(self), ty.toLlvm(self.builder), instruction.llvmName(self))); |
| 5834 | 5584 | return instruction.toValue(); |
| 5835 | 5585 | } |
| 5836 | 5586 | |
| ... | ... | @@ -5843,7 +5593,7 @@ pub const WipFunction = struct { |
| 5843 | 5593 | ) Allocator.Error!Value { |
| 5844 | 5594 | return self.cmpTag(switch (cond) { |
| 5845 | 5595 | inline else => |tag| @field(Instruction.Tag, "icmp " ++ @tagName(tag)), |
| 5846 | | }, @intFromEnum(cond), lhs, rhs, name); |
| 5596 | }, lhs, rhs, name); |
| 5847 | 5597 | } |
| 5848 | 5598 | |
| 5849 | 5599 | pub fn fcmp( |
| ... | ... | @@ -5861,7 +5611,7 @@ pub const WipFunction = struct { |
| 5861 | 5611 | .fast => "fast ", |
| 5862 | 5612 | } ++ @tagName(cond_tag)), |
| 5863 | 5613 | }, |
| 5864 | | }, @intFromEnum(cond), lhs, rhs, name); |
| 5614 | }, lhs, rhs, name); |
| 5865 | 5615 | } |
| 5866 | 5616 | |
| 5867 | 5617 | pub const WipPhi = struct { |
| ... | ... | @@ -5877,7 +5627,7 @@ pub const WipFunction = struct { |
| 5877 | 5627 | vals: []const Value, |
| 5878 | 5628 | blocks: []const Block.Index, |
| 5879 | 5629 | wip: *WipFunction, |
| 5880 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!void { |
| 5630 | ) void { |
| 5881 | 5631 | const incoming_len = self.block.ptrConst(wip).incoming; |
| 5882 | 5632 | assert(vals.len == incoming_len and blocks.len == incoming_len); |
| 5883 | 5633 | const instruction = wip.instructions.get(@intFromEnum(self.instruction)); |
| ... | ... | @@ -5885,26 +5635,6 @@ pub const WipFunction = struct { |
| 5885 | 5635 | for (vals) |val| assert(val.typeOfWip(wip) == extra.data.type); |
| 5886 | 5636 | @memcpy(extra.trail.nextMut(incoming_len, Value, wip), vals); |
| 5887 | 5637 | @memcpy(extra.trail.nextMut(incoming_len, Block.Index, wip), blocks); |
| 5888 | | if (wip.builder.useLibLlvm()) { |
| 5889 | | const ExpectedContents = extern struct { |
| 5890 | | values: [expected_incoming_len]*llvm.Value, |
| 5891 | | blocks: [expected_incoming_len]*llvm.BasicBlock, |
| 5892 | | }; |
| 5893 | | var stack align(@alignOf(ExpectedContents)) = |
| 5894 | | std.heap.stackFallback(@sizeOf(ExpectedContents), wip.builder.gpa); |
| 5895 | | const allocator = stack.get(); |
| 5896 | | |
| 5897 | | const llvm_vals = try allocator.alloc(*llvm.Value, incoming_len); |
| 5898 | | defer allocator.free(llvm_vals); |
| 5899 | | const llvm_blocks = try allocator.alloc(*llvm.BasicBlock, incoming_len); |
| 5900 | | defer allocator.free(llvm_blocks); |
| 5901 | | |
| 5902 | | for (llvm_vals, vals) |*llvm_val, incoming_val| llvm_val.* = incoming_val.toLlvm(wip); |
| 5903 | | for (llvm_blocks, blocks) |*llvm_block, incoming_block| |
| 5904 | | llvm_block.* = incoming_block.toLlvm(wip); |
| 5905 | | self.instruction.toLlvm(wip) |
| 5906 | | .addIncoming(llvm_vals.ptr, llvm_blocks.ptr, @intCast(incoming_len)); |
| 5907 | | } |
| 5908 | 5638 | } |
| 5909 | 5639 | }; |
| 5910 | 5640 | |
| ... | ... | @@ -5970,53 +5700,6 @@ pub const WipFunction = struct { |
| 5970 | 5700 | }), |
| 5971 | 5701 | }); |
| 5972 | 5702 | self.extra.appendSliceAssumeCapacity(@ptrCast(args)); |
| 5973 | | if (self.builder.useLibLlvm()) { |
| 5974 | | const ExpectedContents = [expected_args_len]*llvm.Value; |
| 5975 | | var stack align(@alignOf(ExpectedContents)) = |
| 5976 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.builder.gpa); |
| 5977 | | const allocator = stack.get(); |
| 5978 | | |
| 5979 | | const llvm_args = try allocator.alloc(*llvm.Value, args.len); |
| 5980 | | defer allocator.free(llvm_args); |
| 5981 | | for (llvm_args, args) |*llvm_arg, arg_val| llvm_arg.* = arg_val.toLlvm(self); |
| 5982 | | |
| 5983 | | switch (kind) { |
| 5984 | | .normal, |
| 5985 | | .musttail, |
| 5986 | | .notail, |
| 5987 | | .tail, |
| 5988 | | => self.llvm.builder.setFastMath(false), |
| 5989 | | .fast, |
| 5990 | | .musttail_fast, |
| 5991 | | .notail_fast, |
| 5992 | | .tail_fast, |
| 5993 | | => self.llvm.builder.setFastMath(true), |
| 5994 | | } |
| 5995 | | const llvm_instruction = self.llvm.builder.buildCall( |
| 5996 | | ty.toLlvm(self.builder), |
| 5997 | | callee.toLlvm(self), |
| 5998 | | llvm_args.ptr, |
| 5999 | | @intCast(llvm_args.len), |
| 6000 | | switch (ret_ty) { |
| 6001 | | .void => "", |
| 6002 | | else => instruction.llvmName(self), |
| 6003 | | }, |
| 6004 | | ); |
| 6005 | | llvm_instruction.setInstructionCallConv(call_conv.toLlvm()); |
| 6006 | | llvm_instruction.setTailCallKind(switch (kind) { |
| 6007 | | .normal, .fast => .None, |
| 6008 | | .musttail, .musttail_fast => .MustTail, |
| 6009 | | .notail, .notail_fast => .NoTail, |
| 6010 | | .tail, .tail_fast => .Tail, |
| 6011 | | }); |
| 6012 | | for (0.., function_attributes.slice(self.builder)) |index, attributes| { |
| 6013 | | for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute( |
| 6014 | | @as(llvm.AttributeIndex, @intCast(index)) -% 1, |
| 6015 | | attribute.toLlvm(self.builder), |
| 6016 | | ); |
| 6017 | | } |
| 6018 | | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 6019 | | } |
| 6020 | 5703 | return instruction.toValue(); |
| 6021 | 5704 | } |
| 6022 | 5705 | |
| ... | ... | @@ -6117,16 +5800,25 @@ pub const WipFunction = struct { |
| 6117 | 5800 | .type = ty, |
| 6118 | 5801 | }), |
| 6119 | 5802 | }); |
| 6120 | | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 6121 | | self.llvm.builder.buildVAArg( |
| 6122 | | list.toLlvm(self), |
| 6123 | | ty.toLlvm(self.builder), |
| 6124 | | instruction.llvmName(self), |
| 6125 | | ), |
| 6126 | | ); |
| 6127 | 5803 | return instruction.toValue(); |
| 6128 | 5804 | } |
| 6129 | 5805 | |
| 5806 | pub fn debugValue(self: *WipFunction, value: Value) Allocator.Error!Metadata { |
| 5807 | if (self.builder.strip) return .none; |
| 5808 | return switch (value.unwrap()) { |
| 5809 | .instruction => |instr_index| blk: { |
| 5810 | const gop = try self.debug_values.getOrPut(self.builder.gpa, instr_index); |
| 5811 | |
| 5812 | const metadata: Metadata = @enumFromInt(Metadata.first_local_metadata + gop.index); |
| 5813 | if (!gop.found_existing) gop.key_ptr.* = instr_index; |
| 5814 | |
| 5815 | break :blk metadata; |
| 5816 | }, |
| 5817 | .constant => |constant| try self.builder.debugConstant(constant), |
| 5818 | .metadata => |metadata| metadata, |
| 5819 | }; |
| 5820 | } |
| 5821 | |
| 6130 | 5822 | pub fn finish(self: *WipFunction) Allocator.Error!void { |
| 6131 | 5823 | const gpa = self.builder.gpa; |
| 6132 | 5824 | const function = self.function.ptr(self.builder); |
| ... | ... | @@ -6146,6 +5838,7 @@ pub const WipFunction = struct { |
| 6146 | 5838 | @intFromEnum(instruction) |
| 6147 | 5839 | ].toValue(), |
| 6148 | 5840 | .constant => |constant| constant.toValue(), |
| 5841 | .metadata => |metadata| metadata.toValue(), |
| 6149 | 5842 | }; |
| 6150 | 5843 | } |
| 6151 | 5844 | } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) }; |
| ... | ... | @@ -6154,9 +5847,15 @@ pub const WipFunction = struct { |
| 6154 | 5847 | const names = try gpa.alloc(String, final_instructions_len); |
| 6155 | 5848 | errdefer gpa.free(names); |
| 6156 | 5849 | |
| 6157 | | const metadata = |
| 6158 | | if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len); |
| 6159 | | errdefer if (metadata) |new_metadata| gpa.free(new_metadata); |
| 5850 | const value_indices = try gpa.alloc(u32, final_instructions_len); |
| 5851 | errdefer gpa.free(value_indices); |
| 5852 | |
| 5853 | var debug_locations: std.AutoHashMapUnmanaged(Instruction.Index, Metadata) = .{}; |
| 5854 | errdefer debug_locations.deinit(gpa); |
| 5855 | try debug_locations.ensureUnusedCapacity(gpa, @intCast(self.debug_locations.count())); |
| 5856 | |
| 5857 | const debug_values = try gpa.alloc(Instruction.Index, self.debug_values.count()); |
| 5858 | errdefer gpa.free(debug_values); |
| 6160 | 5859 | |
| 6161 | 5860 | var wip_extra: struct { |
| 6162 | 5861 | index: Instruction.ExtraIndex = 0, |
| ... | ... | @@ -6179,7 +5878,7 @@ pub const WipFunction = struct { |
| 6179 | 5878 | Instruction.Alloca.Info, |
| 6180 | 5879 | Instruction.Call.Info, |
| 6181 | 5880 | => @bitCast(value), |
| 6182 | | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 5881 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 6183 | 5882 | }; |
| 6184 | 5883 | wip_extra.index += 1; |
| 6185 | 5884 | } |
| ... | ... | @@ -6210,8 +5909,10 @@ pub const WipFunction = struct { |
| 6210 | 5909 | gpa.free(function.blocks); |
| 6211 | 5910 | function.blocks = &.{}; |
| 6212 | 5911 | gpa.free(function.names[0..function.instructions.len]); |
| 6213 | | if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]); |
| 6214 | | function.metadata = null; |
| 5912 | function.debug_locations.deinit(gpa); |
| 5913 | function.debug_locations = .{}; |
| 5914 | gpa.free(function.debug_values); |
| 5915 | function.debug_values = &.{}; |
| 6215 | 5916 | gpa.free(function.extra); |
| 6216 | 5917 | function.extra = &.{}; |
| 6217 | 5918 | |
| ... | ... | @@ -6238,33 +5939,76 @@ pub const WipFunction = struct { |
| 6238 | 5939 | |
| 6239 | 5940 | var wip_name: struct { |
| 6240 | 5941 | next_name: String = @enumFromInt(0), |
| 5942 | next_unique_name: std.AutoHashMap(String, String), |
| 5943 | builder: *Builder, |
| 6241 | 5944 | |
| 6242 | | fn map(wip_name: *@This(), old_name: String) String { |
| 6243 | | if (old_name != .empty) return old_name; |
| 5945 | fn map(wip_name: *@This(), name: String, sep: []const u8) Allocator.Error!String { |
| 5946 | switch (name) { |
| 5947 | .none => return .none, |
| 5948 | .empty => { |
| 5949 | assert(wip_name.next_name != .none); |
| 5950 | defer wip_name.next_name = @enumFromInt(@intFromEnum(wip_name.next_name) + 1); |
| 5951 | return wip_name.next_name; |
| 5952 | }, |
| 5953 | _ => { |
| 5954 | assert(!name.isAnon()); |
| 5955 | const gop = try wip_name.next_unique_name.getOrPut(name); |
| 5956 | if (!gop.found_existing) { |
| 5957 | gop.value_ptr.* = @enumFromInt(0); |
| 5958 | return name; |
| 5959 | } |
| 6244 | 5960 | |
| 6245 | | const new_name = wip_name.next_name; |
| 6246 | | wip_name.next_name = @enumFromInt(@intFromEnum(new_name) + 1); |
| 6247 | | return new_name; |
| 5961 | while (true) { |
| 5962 | gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1); |
| 5963 | const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{ |
| 5964 | name.fmt(wip_name.builder), |
| 5965 | sep, |
| 5966 | gop.value_ptr.fmt(wip_name.builder), |
| 5967 | }); |
| 5968 | const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name); |
| 5969 | if (!unique_gop.found_existing) { |
| 5970 | unique_gop.value_ptr.* = @enumFromInt(0); |
| 5971 | return unique_name; |
| 5972 | } |
| 5973 | } |
| 5974 | }, |
| 5975 | } |
| 6248 | 5976 | } |
| 6249 | | } = .{}; |
| 5977 | } = .{ |
| 5978 | .next_unique_name = std.AutoHashMap(String, String).init(gpa), |
| 5979 | .builder = self.builder, |
| 5980 | }; |
| 5981 | defer wip_name.next_unique_name.deinit(); |
| 5982 | |
| 5983 | var value_index: u32 = 0; |
| 6250 | 5984 | for (0..params_len) |param_index| { |
| 6251 | 5985 | const old_argument_index: Instruction.Index = @enumFromInt(param_index); |
| 6252 | 5986 | const new_argument_index: Instruction.Index = @enumFromInt(function.instructions.len); |
| 6253 | 5987 | const argument = self.instructions.get(@intFromEnum(old_argument_index)); |
| 6254 | 5988 | assert(argument.tag == .arg); |
| 6255 | 5989 | assert(argument.data == param_index); |
| 5990 | value_indices[function.instructions.len] = value_index; |
| 5991 | value_index += 1; |
| 6256 | 5992 | function.instructions.appendAssumeCapacity(argument); |
| 6257 | | names[@intFromEnum(new_argument_index)] = wip_name.map( |
| 5993 | names[@intFromEnum(new_argument_index)] = try wip_name.map( |
| 6258 | 5994 | if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)], |
| 5995 | ".", |
| 6259 | 5996 | ); |
| 5997 | if (self.debug_locations.get(old_argument_index)) |location| { |
| 5998 | debug_locations.putAssumeCapacity(new_argument_index, location); |
| 5999 | } |
| 6000 | if (self.debug_values.getIndex(old_argument_index)) |index| { |
| 6001 | debug_values[index] = new_argument_index; |
| 6002 | } |
| 6260 | 6003 | } |
| 6261 | 6004 | for (self.blocks.items) |current_block| { |
| 6262 | 6005 | const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len); |
| 6006 | value_indices[function.instructions.len] = value_index; |
| 6263 | 6007 | function.instructions.appendAssumeCapacity(.{ |
| 6264 | 6008 | .tag = .block, |
| 6265 | 6009 | .data = current_block.incoming, |
| 6266 | 6010 | }); |
| 6267 | | names[@intFromEnum(new_block_index)] = wip_name.map(current_block.name); |
| 6011 | names[@intFromEnum(new_block_index)] = try wip_name.map(current_block.name, ""); |
| 6268 | 6012 | for (current_block.instructions.items) |old_instruction_index| { |
| 6269 | 6013 | const new_instruction_index: Instruction.Index = |
| 6270 | 6014 | @enumFromInt(function.instructions.len); |
| ... | ... | @@ -6565,10 +6309,21 @@ pub const WipFunction = struct { |
| 6565 | 6309 | }, |
| 6566 | 6310 | } |
| 6567 | 6311 | function.instructions.appendAssumeCapacity(instruction); |
| 6568 | | names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) |
| 6312 | names[@intFromEnum(new_instruction_index)] = try wip_name.map(if (self.builder.strip) |
| 6569 | 6313 | if (old_instruction_index.hasResultWip(self)) .empty else .none |
| 6570 | 6314 | else |
| 6571 | | self.names.items[@intFromEnum(old_instruction_index)]); |
| 6315 | self.names.items[@intFromEnum(old_instruction_index)], "."); |
| 6316 | |
| 6317 | if (self.debug_locations.get(old_instruction_index)) |location| { |
| 6318 | debug_locations.putAssumeCapacity(new_instruction_index, location); |
| 6319 | } |
| 6320 | |
| 6321 | if (self.debug_values.getIndex(old_instruction_index)) |index| { |
| 6322 | debug_values[index] = new_instruction_index; |
| 6323 | } |
| 6324 | |
| 6325 | value_indices[@intFromEnum(new_instruction_index)] = value_index; |
| 6326 | if (old_instruction_index.hasResultWip(self)) value_index += 1; |
| 6572 | 6327 | } |
| 6573 | 6328 | } |
| 6574 | 6329 | |
| ... | ... | @@ -6576,28 +6331,25 @@ pub const WipFunction = struct { |
| 6576 | 6331 | function.extra = wip_extra.finish(); |
| 6577 | 6332 | function.blocks = blocks; |
| 6578 | 6333 | function.names = names.ptr; |
| 6579 | | function.metadata = if (metadata) |new_metadata| new_metadata.ptr else null; |
| 6334 | function.value_indices = value_indices.ptr; |
| 6335 | function.debug_locations = debug_locations; |
| 6336 | function.debug_values = debug_values; |
| 6580 | 6337 | } |
| 6581 | 6338 | |
| 6582 | 6339 | pub fn deinit(self: *WipFunction) void { |
| 6583 | 6340 | self.extra.deinit(self.builder.gpa); |
| 6584 | | self.metadata.deinit(self.builder.gpa); |
| 6341 | self.debug_values.deinit(self.builder.gpa); |
| 6342 | self.debug_locations.deinit(self.builder.gpa); |
| 6585 | 6343 | self.names.deinit(self.builder.gpa); |
| 6586 | 6344 | self.instructions.deinit(self.builder.gpa); |
| 6587 | 6345 | for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa); |
| 6588 | 6346 | self.blocks.deinit(self.builder.gpa); |
| 6589 | | if (self.builder.useLibLlvm()) { |
| 6590 | | self.llvm.instructions.deinit(self.builder.gpa); |
| 6591 | | self.llvm.blocks.deinit(self.builder.gpa); |
| 6592 | | self.llvm.builder.dispose(); |
| 6593 | | } |
| 6594 | 6347 | self.* = undefined; |
| 6595 | 6348 | } |
| 6596 | 6349 | |
| 6597 | 6350 | fn cmpTag( |
| 6598 | 6351 | self: *WipFunction, |
| 6599 | 6352 | tag: Instruction.Tag, |
| 6600 | | cond: u32, |
| 6601 | 6353 | lhs: Value, |
| 6602 | 6354 | rhs: Value, |
| 6603 | 6355 | name: []const u8, |
| ... | ... | @@ -6657,113 +6409,6 @@ pub const WipFunction = struct { |
| 6657 | 6409 | .rhs = rhs, |
| 6658 | 6410 | }), |
| 6659 | 6411 | }); |
| 6660 | | if (self.builder.useLibLlvm()) { |
| 6661 | | switch (tag) { |
| 6662 | | .@"fcmp false", |
| 6663 | | .@"fcmp oeq", |
| 6664 | | .@"fcmp oge", |
| 6665 | | .@"fcmp ogt", |
| 6666 | | .@"fcmp ole", |
| 6667 | | .@"fcmp olt", |
| 6668 | | .@"fcmp one", |
| 6669 | | .@"fcmp ord", |
| 6670 | | .@"fcmp true", |
| 6671 | | .@"fcmp ueq", |
| 6672 | | .@"fcmp uge", |
| 6673 | | .@"fcmp ugt", |
| 6674 | | .@"fcmp ule", |
| 6675 | | .@"fcmp ult", |
| 6676 | | .@"fcmp une", |
| 6677 | | .@"fcmp uno", |
| 6678 | | => self.llvm.builder.setFastMath(false), |
| 6679 | | .@"fcmp fast false", |
| 6680 | | .@"fcmp fast oeq", |
| 6681 | | .@"fcmp fast oge", |
| 6682 | | .@"fcmp fast ogt", |
| 6683 | | .@"fcmp fast ole", |
| 6684 | | .@"fcmp fast olt", |
| 6685 | | .@"fcmp fast one", |
| 6686 | | .@"fcmp fast ord", |
| 6687 | | .@"fcmp fast true", |
| 6688 | | .@"fcmp fast ueq", |
| 6689 | | .@"fcmp fast uge", |
| 6690 | | .@"fcmp fast ugt", |
| 6691 | | .@"fcmp fast ule", |
| 6692 | | .@"fcmp fast ult", |
| 6693 | | .@"fcmp fast une", |
| 6694 | | .@"fcmp fast uno", |
| 6695 | | => self.llvm.builder.setFastMath(true), |
| 6696 | | .@"icmp eq", |
| 6697 | | .@"icmp ne", |
| 6698 | | .@"icmp sge", |
| 6699 | | .@"icmp sgt", |
| 6700 | | .@"icmp sle", |
| 6701 | | .@"icmp slt", |
| 6702 | | .@"icmp uge", |
| 6703 | | .@"icmp ugt", |
| 6704 | | .@"icmp ule", |
| 6705 | | .@"icmp ult", |
| 6706 | | => {}, |
| 6707 | | else => unreachable, |
| 6708 | | } |
| 6709 | | self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 6710 | | .@"fcmp false", |
| 6711 | | .@"fcmp fast false", |
| 6712 | | .@"fcmp fast oeq", |
| 6713 | | .@"fcmp fast oge", |
| 6714 | | .@"fcmp fast ogt", |
| 6715 | | .@"fcmp fast ole", |
| 6716 | | .@"fcmp fast olt", |
| 6717 | | .@"fcmp fast one", |
| 6718 | | .@"fcmp fast ord", |
| 6719 | | .@"fcmp fast true", |
| 6720 | | .@"fcmp fast ueq", |
| 6721 | | .@"fcmp fast uge", |
| 6722 | | .@"fcmp fast ugt", |
| 6723 | | .@"fcmp fast ule", |
| 6724 | | .@"fcmp fast ult", |
| 6725 | | .@"fcmp fast une", |
| 6726 | | .@"fcmp fast uno", |
| 6727 | | .@"fcmp oeq", |
| 6728 | | .@"fcmp oge", |
| 6729 | | .@"fcmp ogt", |
| 6730 | | .@"fcmp ole", |
| 6731 | | .@"fcmp olt", |
| 6732 | | .@"fcmp one", |
| 6733 | | .@"fcmp ord", |
| 6734 | | .@"fcmp true", |
| 6735 | | .@"fcmp ueq", |
| 6736 | | .@"fcmp uge", |
| 6737 | | .@"fcmp ugt", |
| 6738 | | .@"fcmp ule", |
| 6739 | | .@"fcmp ult", |
| 6740 | | .@"fcmp une", |
| 6741 | | .@"fcmp uno", |
| 6742 | | => self.llvm.builder.buildFCmp( |
| 6743 | | @enumFromInt(cond), |
| 6744 | | lhs.toLlvm(self), |
| 6745 | | rhs.toLlvm(self), |
| 6746 | | instruction.llvmName(self), |
| 6747 | | ), |
| 6748 | | .@"icmp eq", |
| 6749 | | .@"icmp ne", |
| 6750 | | .@"icmp sge", |
| 6751 | | .@"icmp sgt", |
| 6752 | | .@"icmp sle", |
| 6753 | | .@"icmp slt", |
| 6754 | | .@"icmp uge", |
| 6755 | | .@"icmp ugt", |
| 6756 | | .@"icmp ule", |
| 6757 | | .@"icmp ult", |
| 6758 | | => self.llvm.builder.buildICmp( |
| 6759 | | @enumFromInt(cond), |
| 6760 | | lhs.toLlvm(self), |
| 6761 | | rhs.toLlvm(self), |
| 6762 | | instruction.llvmName(self), |
| 6763 | | ), |
| 6764 | | else => unreachable, |
| 6765 | | }); |
| 6766 | | } |
| 6767 | 6412 | return instruction.toValue(); |
| 6768 | 6413 | } |
| 6769 | 6414 | |
| ... | ... | @@ -6785,16 +6430,6 @@ pub const WipFunction = struct { |
| 6785 | 6430 | .data = self.addExtraAssumeCapacity(Instruction.Phi{ .type = ty }), |
| 6786 | 6431 | }); |
| 6787 | 6432 | _ = self.extra.addManyAsSliceAssumeCapacity(incoming * 2); |
| 6788 | | if (self.builder.useLibLlvm()) { |
| 6789 | | switch (tag) { |
| 6790 | | .phi => self.llvm.builder.setFastMath(false), |
| 6791 | | .@"phi fast" => self.llvm.builder.setFastMath(true), |
| 6792 | | else => unreachable, |
| 6793 | | } |
| 6794 | | self.llvm.instructions.appendAssumeCapacity( |
| 6795 | | self.llvm.builder.buildPhi(ty.toLlvm(self.builder), instruction.llvmName(self)), |
| 6796 | | ); |
| 6797 | | } |
| 6798 | 6433 | return .{ .block = self.cursor.block, .instruction = instruction }; |
| 6799 | 6434 | } |
| 6800 | 6435 | |
| ... | ... | @@ -6822,19 +6457,6 @@ pub const WipFunction = struct { |
| 6822 | 6457 | .rhs = rhs, |
| 6823 | 6458 | }), |
| 6824 | 6459 | }); |
| 6825 | | if (self.builder.useLibLlvm()) { |
| 6826 | | switch (tag) { |
| 6827 | | .select => self.llvm.builder.setFastMath(false), |
| 6828 | | .@"select fast" => self.llvm.builder.setFastMath(true), |
| 6829 | | else => unreachable, |
| 6830 | | } |
| 6831 | | self.llvm.instructions.appendAssumeCapacity(self.llvm.builder.buildSelect( |
| 6832 | | cond.toLlvm(self), |
| 6833 | | lhs.toLlvm(self), |
| 6834 | | rhs.toLlvm(self), |
| 6835 | | instruction.llvmName(self), |
| 6836 | | )); |
| 6837 | | } |
| 6838 | 6460 | return instruction.toValue(); |
| 6839 | 6461 | } |
| 6840 | 6462 | |
| ... | ... | @@ -6857,28 +6479,27 @@ pub const WipFunction = struct { |
| 6857 | 6479 | ) Allocator.Error!Instruction.Index { |
| 6858 | 6480 | const block_instructions = &self.cursor.block.ptr(self).instructions; |
| 6859 | 6481 | try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1); |
| 6860 | | if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, 1); |
| 6482 | if (!self.builder.strip) { |
| 6483 | try self.names.ensureUnusedCapacity(self.builder.gpa, 1); |
| 6484 | try self.debug_locations.ensureUnusedCapacity(self.builder.gpa, 1); |
| 6485 | } |
| 6861 | 6486 | try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1); |
| 6862 | | if (self.builder.useLibLlvm()) |
| 6863 | | try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1); |
| 6864 | 6487 | const final_name = if (name) |n| |
| 6865 | 6488 | if (self.builder.strip) .empty else try self.builder.string(n) |
| 6866 | 6489 | else |
| 6867 | 6490 | .none; |
| 6868 | 6491 | |
| 6869 | | if (self.builder.useLibLlvm()) self.llvm.builder.positionBuilder( |
| 6870 | | self.cursor.block.toLlvm(self), |
| 6871 | | for (block_instructions.items[self.cursor.instruction..]) |instruction_index| { |
| 6872 | | const llvm_instruction = |
| 6873 | | self.llvm.instructions.items[@intFromEnum(instruction_index)]; |
| 6874 | | // TODO: remove when constant propagation is implemented |
| 6875 | | if (!llvm_instruction.isConstant().toBool()) break llvm_instruction; |
| 6876 | | } else null, |
| 6877 | | ); |
| 6878 | | |
| 6879 | 6492 | const index: Instruction.Index = @enumFromInt(self.instructions.len); |
| 6880 | 6493 | self.instructions.appendAssumeCapacity(instruction); |
| 6881 | | if (!self.builder.strip) self.names.appendAssumeCapacity(final_name); |
| 6494 | if (!self.builder.strip) { |
| 6495 | self.names.appendAssumeCapacity(final_name); |
| 6496 | if (block_instructions.items.len == 0 or |
| 6497 | self.current_debug_location != self.last_debug_location) |
| 6498 | { |
| 6499 | self.debug_locations.putAssumeCapacity(index, self.current_debug_location); |
| 6500 | self.last_debug_location = self.current_debug_location; |
| 6501 | } |
| 6502 | } |
| 6882 | 6503 | block_instructions.insertAssumeCapacity(self.cursor.instruction, index); |
| 6883 | 6504 | self.cursor.instruction += 1; |
| 6884 | 6505 | return index; |
| ... | ... | @@ -6901,7 +6522,7 @@ pub const WipFunction = struct { |
| 6901 | 6522 | Instruction.Alloca.Info, |
| 6902 | 6523 | Instruction.Call.Info, |
| 6903 | 6524 | => @bitCast(value), |
| 6904 | | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 6525 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 6905 | 6526 | }); |
| 6906 | 6527 | } |
| 6907 | 6528 | return result; |
| ... | ... | @@ -6949,7 +6570,7 @@ pub const WipFunction = struct { |
| 6949 | 6570 | Instruction.Alloca.Info, |
| 6950 | 6571 | Instruction.Call.Info, |
| 6951 | 6572 | => @bitCast(value), |
| 6952 | | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 6573 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 6953 | 6574 | }; |
| 6954 | 6575 | return .{ |
| 6955 | 6576 | .data = result, |
| ... | ... | @@ -6977,24 +6598,6 @@ pub const FloatCondition = enum(u4) { |
| 6977 | 6598 | ult = 12, |
| 6978 | 6599 | ule = 13, |
| 6979 | 6600 | une = 14, |
| 6980 | | |
| 6981 | | fn toLlvm(self: FloatCondition) llvm.RealPredicate { |
| 6982 | | return switch (self) { |
| 6983 | | .oeq => .OEQ, |
| 6984 | | .ogt => .OGT, |
| 6985 | | .oge => .OGE, |
| 6986 | | .olt => .OLT, |
| 6987 | | .ole => .OLE, |
| 6988 | | .one => .ONE, |
| 6989 | | .ord => .ORD, |
| 6990 | | .uno => .UNO, |
| 6991 | | .ueq => .UEQ, |
| 6992 | | .ugt => .UGT, |
| 6993 | | .uge => .UGE, |
| 6994 | | .ult => .ULT, |
| 6995 | | .uno => .UNE, |
| 6996 | | }; |
| 6997 | | } |
| 6998 | 6601 | }; |
| 6999 | 6602 | |
| 7000 | 6603 | pub const IntegerCondition = enum(u6) { |
| ... | ... | @@ -7008,20 +6611,6 @@ pub const IntegerCondition = enum(u6) { |
| 7008 | 6611 | sge = 39, |
| 7009 | 6612 | slt = 40, |
| 7010 | 6613 | sle = 41, |
| 7011 | | |
| 7012 | | fn toLlvm(self: IntegerCondition) llvm.IntPredicate { |
| 7013 | | return switch (self) { |
| 7014 | | .eq => .EQ, |
| 7015 | | .ne => .NE, |
| 7016 | | .ugt => .UGT, |
| 7017 | | .uge => .UGE, |
| 7018 | | .ult => .ULT, |
| 7019 | | .sgt => .SGT, |
| 7020 | | .sge => .SGE, |
| 7021 | | .slt => .SLT, |
| 7022 | | .sle => .SLE, |
| 7023 | | }; |
| 7024 | | } |
| 7025 | 6614 | }; |
| 7026 | 6615 | |
| 7027 | 6616 | pub const MemoryAccessKind = enum(u1) { |
| ... | ... | @@ -7058,10 +6647,10 @@ pub const AtomicOrdering = enum(u3) { |
| 7058 | 6647 | none = 0, |
| 7059 | 6648 | unordered = 1, |
| 7060 | 6649 | monotonic = 2, |
| 7061 | | acquire = 4, |
| 7062 | | release = 5, |
| 7063 | | acq_rel = 6, |
| 7064 | | seq_cst = 7, |
| 6650 | acquire = 3, |
| 6651 | release = 4, |
| 6652 | acq_rel = 5, |
| 6653 | seq_cst = 6, |
| 7065 | 6654 | |
| 7066 | 6655 | pub fn format( |
| 7067 | 6656 | self: AtomicOrdering, |
| ... | ... | @@ -7071,18 +6660,6 @@ pub const AtomicOrdering = enum(u3) { |
| 7071 | 6660 | ) @TypeOf(writer).Error!void { |
| 7072 | 6661 | if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) }); |
| 7073 | 6662 | } |
| 7074 | | |
| 7075 | | fn toLlvm(self: AtomicOrdering) llvm.AtomicOrdering { |
| 7076 | | return switch (self) { |
| 7077 | | .none => .NotAtomic, |
| 7078 | | .unordered => .Unordered, |
| 7079 | | .monotonic => .Monotonic, |
| 7080 | | .acquire => .Acquire, |
| 7081 | | .release => .Release, |
| 7082 | | .acq_rel => .AcquireRelease, |
| 7083 | | .seq_cst => .SequentiallyConsistent, |
| 7084 | | }; |
| 7085 | | } |
| 7086 | 6663 | }; |
| 7087 | 6664 | |
| 7088 | 6665 | const MemoryAccessInfo = packed struct(u32) { |
| ... | ... | @@ -7095,7 +6672,8 @@ const MemoryAccessInfo = packed struct(u32) { |
| 7095 | 6672 | _: u13 = undefined, |
| 7096 | 6673 | }; |
| 7097 | 6674 | |
| 7098 | | pub const FastMath = packed struct(u32) { |
| 6675 | pub const FastMath = packed struct(u8) { |
| 6676 | unsafe_algebra: bool = false, // Legacy |
| 7099 | 6677 | nnan: bool = false, |
| 7100 | 6678 | ninf: bool = false, |
| 7101 | 6679 | nsz: bool = false, |
| ... | ... | @@ -7130,11 +6708,13 @@ pub const FastMathKind = enum { |
| 7130 | 6708 | pub const Constant = enum(u32) { |
| 7131 | 6709 | false, |
| 7132 | 6710 | true, |
| 6711 | @"0", |
| 6712 | @"1", |
| 7133 | 6713 | none, |
| 7134 | | no_init = 1 << 31, |
| 6714 | no_init = (1 << 30) - 1, |
| 7135 | 6715 | _, |
| 7136 | 6716 | |
| 7137 | | const first_global: Constant = @enumFromInt(1 << 30); |
| 6717 | const first_global: Constant = @enumFromInt(1 << 29); |
| 7138 | 6718 | |
| 7139 | 6719 | pub const Tag = enum(u7) { |
| 7140 | 6720 | positive_integer, |
| ... | ... | @@ -7152,7 +6732,6 @@ pub const Constant = enum(u32) { |
| 7152 | 6732 | packed_structure, |
| 7153 | 6733 | array, |
| 7154 | 6734 | string, |
| 7155 | | string_null, |
| 7156 | 6735 | vector, |
| 7157 | 6736 | splat, |
| 7158 | 6737 | zeroinitializer, |
| ... | ... | @@ -7212,6 +6791,49 @@ pub const Constant = enum(u32) { |
| 7212 | 6791 | @"asm sideeffect inteldialect unwind", |
| 7213 | 6792 | @"asm alignstack inteldialect unwind", |
| 7214 | 6793 | @"asm sideeffect alignstack inteldialect unwind", |
| 6794 | |
| 6795 | pub fn toBinaryOpcode(self: Tag) BinaryOpcode { |
| 6796 | return switch (self) { |
| 6797 | .add, |
| 6798 | .@"add nsw", |
| 6799 | .@"add nuw", |
| 6800 | => .add, |
| 6801 | .sub, |
| 6802 | .@"sub nsw", |
| 6803 | .@"sub nuw", |
| 6804 | => .sub, |
| 6805 | .mul, |
| 6806 | .@"mul nsw", |
| 6807 | .@"mul nuw", |
| 6808 | => .mul, |
| 6809 | .shl => .shl, |
| 6810 | .lshr => .lshr, |
| 6811 | .ashr => .ashr, |
| 6812 | .@"and" => .@"and", |
| 6813 | .@"or" => .@"or", |
| 6814 | .xor => .xor, |
| 6815 | else => unreachable, |
| 6816 | }; |
| 6817 | } |
| 6818 | |
| 6819 | pub fn toCastOpcode(self: Tag) CastOpcode { |
| 6820 | return switch (self) { |
| 6821 | .trunc => .trunc, |
| 6822 | .zext => .zext, |
| 6823 | .sext => .sext, |
| 6824 | .fptoui => .fptoui, |
| 6825 | .fptosi => .fptosi, |
| 6826 | .uitofp => .uitofp, |
| 6827 | .sitofp => .sitofp, |
| 6828 | .fptrunc => .fptrunc, |
| 6829 | .fpext => .fpext, |
| 6830 | .ptrtoint => .ptrtoint, |
| 6831 | .inttoptr => .inttoptr, |
| 6832 | .bitcast => .bitcast, |
| 6833 | .addrspacecast => .addrspacecast, |
| 6834 | else => unreachable, |
| 6835 | }; |
| 6836 | } |
| 7215 | 6837 | }; |
| 7216 | 6838 | |
| 7217 | 6839 | pub const Item = struct { |
| ... | ... | @@ -7364,11 +6986,8 @@ pub const Constant = enum(u32) { |
| 7364 | 6986 | .vector, |
| 7365 | 6987 | => builder.constantExtraData(Aggregate, item.data).type, |
| 7366 | 6988 | .splat => builder.constantExtraData(Splat, item.data).type, |
| 7367 | | .string, |
| 7368 | | .string_null, |
| 7369 | | => builder.arrayTypeAssumeCapacity( |
| 7370 | | @as(String, @enumFromInt(item.data)).slice(builder).?.len + |
| 7371 | | @intFromBool(item.tag == .string_null), |
| 6989 | .string => builder.arrayTypeAssumeCapacity( |
| 6990 | @as(String, @enumFromInt(item.data)).slice(builder).?.len, |
| 7372 | 6991 | .i8, |
| 7373 | 6992 | ), |
| 7374 | 6993 | .blockaddress => builder.ptrTypeAssumeCapacity( |
| ... | ... | @@ -7574,7 +7193,7 @@ pub const Constant = enum(u32) { |
| 7574 | 7193 | @ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]); |
| 7575 | 7194 | const limbs = data.builder.constant_limbs |
| 7576 | 7195 | .items[item.data + Integer.limbs ..][0..extra.limbs_len]; |
| 7577 | | const bigint = std.math.big.int.Const{ |
| 7196 | const bigint: std.math.big.int.Const = .{ |
| 7578 | 7197 | .limbs = limbs, |
| 7579 | 7198 | .positive = tag == .positive_integer, |
| 7580 | 7199 | }; |
| ... | ... | @@ -7616,17 +7235,31 @@ pub const Constant = enum(u32) { |
| 7616 | 7235 | }; |
| 7617 | 7236 | } |
| 7618 | 7237 | }; |
| 7238 | const Mantissa64 = std.meta.FieldType(Float.Repr(f64), .mantissa); |
| 7619 | 7239 | const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent); |
| 7620 | 7240 | const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent); |
| 7241 | |
| 7621 | 7242 | const repr: Float.Repr(f32) = @bitCast(item.data); |
| 7243 | const denormal_shift = switch (repr.exponent) { |
| 7244 | std.math.minInt(Exponent32) => @as( |
| 7245 | std.math.Log2Int(Mantissa64), |
| 7246 | @clz(repr.mantissa), |
| 7247 | ) + 1, |
| 7248 | else => 0, |
| 7249 | }; |
| 7622 | 7250 | try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){ |
| 7623 | 7251 | .mantissa = std.math.shl( |
| 7624 | | std.meta.FieldType(Float.Repr(f64), .mantissa), |
| 7252 | Mantissa64, |
| 7625 | 7253 | repr.mantissa, |
| 7626 | | std.math.floatMantissaBits(f64) - std.math.floatMantissaBits(f32), |
| 7254 | std.math.floatMantissaBits(f64) - std.math.floatMantissaBits(f32) + |
| 7255 | denormal_shift, |
| 7627 | 7256 | ), |
| 7628 | 7257 | .exponent = switch (repr.exponent) { |
| 7629 | | std.math.minInt(Exponent32) => std.math.minInt(Exponent64), |
| 7258 | std.math.minInt(Exponent32) => if (repr.mantissa > 0) |
| 7259 | @as(Exponent64, std.math.floatExponentMin(f32) + |
| 7260 | std.math.floatExponentMax(f64)) - denormal_shift |
| 7261 | else |
| 7262 | std.math.minInt(Exponent64), |
| 7630 | 7263 | else => @as(Exponent64, repr.exponent) + |
| 7631 | 7264 | (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)), |
| 7632 | 7265 | std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64), |
| ... | ... | @@ -7703,13 +7336,9 @@ pub const Constant = enum(u32) { |
| 7703 | 7336 | } |
| 7704 | 7337 | try writer.writeByte('>'); |
| 7705 | 7338 | }, |
| 7706 | | inline .string, |
| 7707 | | .string_null, |
| 7708 | | => |tag| try writer.print("c{\"" ++ switch (tag) { |
| 7709 | | .string => "", |
| 7710 | | .string_null => "@", |
| 7711 | | else => unreachable, |
| 7712 | | } ++ "}", .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}), |
| 7339 | .string => try writer.print("c{\"}", .{ |
| 7340 | @as(String, @enumFromInt(item.data)).fmt(data.builder), |
| 7341 | }), |
| 7713 | 7342 | .blockaddress => |tag| { |
| 7714 | 7343 | const extra = data.builder.constantExtraData(BlockAddress, item.data); |
| 7715 | 7344 | const function = extra.function.ptrConst(data.builder); |
| ... | ... | @@ -7859,40 +7488,37 @@ pub const Constant = enum(u32) { |
| 7859 | 7488 | pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) { |
| 7860 | 7489 | return .{ .data = .{ .constant = self, .builder = builder } }; |
| 7861 | 7490 | } |
| 7862 | | |
| 7863 | | pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value { |
| 7864 | | assert(builder.useLibLlvm()); |
| 7865 | | const llvm_value = switch (self.unwrap()) { |
| 7866 | | .constant => |constant| builder.llvm.constants.items[constant], |
| 7867 | | .global => |global| return global.toLlvm(builder), |
| 7868 | | }; |
| 7869 | | const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value; |
| 7870 | | return global.toLlvm(builder); |
| 7871 | | } |
| 7872 | 7491 | }; |
| 7873 | 7492 | |
| 7874 | 7493 | pub const Value = enum(u32) { |
| 7875 | 7494 | none = std.math.maxInt(u31), |
| 7876 | 7495 | false = first_constant + @intFromEnum(Constant.false), |
| 7877 | 7496 | true = first_constant + @intFromEnum(Constant.true), |
| 7497 | @"0" = first_constant + @intFromEnum(Constant.@"0"), |
| 7498 | @"1" = first_constant + @intFromEnum(Constant.@"1"), |
| 7878 | 7499 | _, |
| 7879 | 7500 | |
| 7880 | | const first_constant = 1 << 31; |
| 7501 | const first_constant = 1 << 30; |
| 7502 | const first_metadata = 1 << 31; |
| 7881 | 7503 | |
| 7882 | 7504 | pub fn unwrap(self: Value) union(enum) { |
| 7883 | 7505 | instruction: Function.Instruction.Index, |
| 7884 | 7506 | constant: Constant, |
| 7507 | metadata: Metadata, |
| 7885 | 7508 | } { |
| 7886 | 7509 | return if (@intFromEnum(self) < first_constant) |
| 7887 | 7510 | .{ .instruction = @enumFromInt(@intFromEnum(self)) } |
| 7511 | else if (@intFromEnum(self) < first_metadata) |
| 7512 | .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) } |
| 7888 | 7513 | else |
| 7889 | | .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }; |
| 7514 | .{ .metadata = @enumFromInt(@intFromEnum(self) - first_metadata) }; |
| 7890 | 7515 | } |
| 7891 | 7516 | |
| 7892 | 7517 | pub fn typeOfWip(self: Value, wip: *const WipFunction) Type { |
| 7893 | 7518 | return switch (self.unwrap()) { |
| 7894 | 7519 | .instruction => |instruction| instruction.typeOfWip(wip), |
| 7895 | 7520 | .constant => |constant| constant.typeOf(wip.builder), |
| 7521 | .metadata => .metadata, |
| 7896 | 7522 | }; |
| 7897 | 7523 | } |
| 7898 | 7524 | |
| ... | ... | @@ -7900,12 +7526,13 @@ pub const Value = enum(u32) { |
| 7900 | 7526 | return switch (self.unwrap()) { |
| 7901 | 7527 | .instruction => |instruction| instruction.typeOf(function, builder), |
| 7902 | 7528 | .constant => |constant| constant.typeOf(builder), |
| 7529 | .metadata => .metadata, |
| 7903 | 7530 | }; |
| 7904 | 7531 | } |
| 7905 | 7532 | |
| 7906 | 7533 | pub fn toConst(self: Value) ?Constant { |
| 7907 | 7534 | return switch (self.unwrap()) { |
| 7908 | | .instruction => null, |
| 7535 | .instruction, .metadata => null, |
| 7909 | 7536 | .constant => |constant| constant, |
| 7910 | 7537 | }; |
| 7911 | 7538 | } |
| ... | ... | @@ -7931,397 +7558,854 @@ pub const Value = enum(u32) { |
| 7931 | 7558 | .constant = constant, |
| 7932 | 7559 | .builder = data.builder, |
| 7933 | 7560 | }, fmt_str, fmt_opts, writer), |
| 7561 | .metadata => unreachable, |
| 7934 | 7562 | } |
| 7935 | 7563 | } |
| 7936 | 7564 | pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) { |
| 7937 | 7565 | return .{ .data = .{ .value = self, .function = function, .builder = builder } }; |
| 7938 | 7566 | } |
| 7567 | }; |
| 7939 | 7568 | |
| 7940 | | pub fn toLlvm(self: Value, wip: *const WipFunction) *llvm.Value { |
| 7941 | | return switch (self.unwrap()) { |
| 7942 | | .instruction => |instruction| instruction.toLlvm(wip), |
| 7943 | | .constant => |constant| constant.toLlvm(wip.builder), |
| 7944 | | }; |
| 7569 | pub const MetadataString = enum(u32) { |
| 7570 | none = 0, |
| 7571 | _, |
| 7572 | |
| 7573 | pub fn slice(self: MetadataString, builder: *const Builder) []const u8 { |
| 7574 | const index = @intFromEnum(self); |
| 7575 | const start = builder.metadata_string_indices.items[index]; |
| 7576 | const end = builder.metadata_string_indices.items[index + 1]; |
| 7577 | return builder.metadata_string_bytes.items[start..end]; |
| 7945 | 7578 | } |
| 7946 | | }; |
| 7947 | 7579 | |
| 7948 | | pub const Metadata = enum(u32) { _ }; |
| 7580 | const Adapter = struct { |
| 7581 | builder: *const Builder, |
| 7582 | pub fn hash(_: Adapter, key: []const u8) u32 { |
| 7583 | return @truncate(std.hash.Wyhash.hash(0, key)); |
| 7584 | } |
| 7585 | pub fn eql(ctx: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool { |
| 7586 | const rhs_metadata_string: MetadataString = @enumFromInt(rhs_index); |
| 7587 | return std.mem.eql(u8, lhs_key, rhs_metadata_string.slice(ctx.builder)); |
| 7588 | } |
| 7589 | }; |
| 7949 | 7590 | |
| 7950 | | pub const InitError = error{ |
| 7951 | | InvalidLlvmTriple, |
| 7952 | | } || Allocator.Error; |
| 7591 | const FormatData = struct { |
| 7592 | metadata_string: MetadataString, |
| 7593 | builder: *const Builder, |
| 7594 | }; |
| 7595 | fn format( |
| 7596 | data: FormatData, |
| 7597 | comptime _: []const u8, |
| 7598 | _: std.fmt.FormatOptions, |
| 7599 | writer: anytype, |
| 7600 | ) @TypeOf(writer).Error!void { |
| 7601 | try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, writer); |
| 7602 | } |
| 7603 | fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) { |
| 7604 | return .{ .data = .{ .metadata_string = self, .builder = builder } }; |
| 7605 | } |
| 7606 | }; |
| 7953 | 7607 | |
| 7954 | | pub fn init(options: Options) InitError!Builder { |
| 7955 | | var self = Builder{ |
| 7956 | | .gpa = options.allocator, |
| 7957 | | .use_lib_llvm = options.use_lib_llvm, |
| 7958 | | .strip = options.strip, |
| 7608 | pub const Metadata = enum(u32) { |
| 7609 | none = 0, |
| 7610 | _, |
| 7959 | 7611 | |
| 7960 | | .llvm = undefined, |
| 7612 | const first_forward_reference = 1 << 29; |
| 7613 | const first_local_metadata = 1 << 30; |
| 7961 | 7614 | |
| 7962 | | .source_filename = .none, |
| 7963 | | .data_layout = .none, |
| 7964 | | .target_triple = .none, |
| 7965 | | .module_asm = .{}, |
| 7615 | pub const Tag = enum(u6) { |
| 7616 | none, |
| 7617 | file, |
| 7618 | compile_unit, |
| 7619 | @"compile_unit optimized", |
| 7620 | subprogram, |
| 7621 | @"subprogram local", |
| 7622 | @"subprogram definition", |
| 7623 | @"subprogram local definition", |
| 7624 | @"subprogram optimized", |
| 7625 | @"subprogram optimized local", |
| 7626 | @"subprogram optimized definition", |
| 7627 | @"subprogram optimized local definition", |
| 7628 | lexical_block, |
| 7629 | location, |
| 7630 | basic_bool_type, |
| 7631 | basic_unsigned_type, |
| 7632 | basic_signed_type, |
| 7633 | basic_float_type, |
| 7634 | composite_struct_type, |
| 7635 | composite_union_type, |
| 7636 | composite_enumeration_type, |
| 7637 | composite_array_type, |
| 7638 | composite_vector_type, |
| 7639 | derived_pointer_type, |
| 7640 | derived_member_type, |
| 7641 | subroutine_type, |
| 7642 | enumerator_unsigned, |
| 7643 | enumerator_signed_positive, |
| 7644 | enumerator_signed_negative, |
| 7645 | subrange, |
| 7646 | tuple, |
| 7647 | module_flag, |
| 7648 | expression, |
| 7649 | local_var, |
| 7650 | parameter, |
| 7651 | global_var, |
| 7652 | @"global_var local", |
| 7653 | global_var_expression, |
| 7654 | constant, |
| 7655 | |
| 7656 | pub fn isInline(tag: Tag) bool { |
| 7657 | return switch (tag) { |
| 7658 | .none, |
| 7659 | .expression, |
| 7660 | .constant, |
| 7661 | => true, |
| 7662 | .file, |
| 7663 | .compile_unit, |
| 7664 | .@"compile_unit optimized", |
| 7665 | .subprogram, |
| 7666 | .@"subprogram local", |
| 7667 | .@"subprogram definition", |
| 7668 | .@"subprogram local definition", |
| 7669 | .@"subprogram optimized", |
| 7670 | .@"subprogram optimized local", |
| 7671 | .@"subprogram optimized definition", |
| 7672 | .@"subprogram optimized local definition", |
| 7673 | .lexical_block, |
| 7674 | .location, |
| 7675 | .basic_bool_type, |
| 7676 | .basic_unsigned_type, |
| 7677 | .basic_signed_type, |
| 7678 | .basic_float_type, |
| 7679 | .composite_struct_type, |
| 7680 | .composite_union_type, |
| 7681 | .composite_enumeration_type, |
| 7682 | .composite_array_type, |
| 7683 | .composite_vector_type, |
| 7684 | .derived_pointer_type, |
| 7685 | .derived_member_type, |
| 7686 | .subroutine_type, |
| 7687 | .enumerator_unsigned, |
| 7688 | .enumerator_signed_positive, |
| 7689 | .enumerator_signed_negative, |
| 7690 | .subrange, |
| 7691 | .tuple, |
| 7692 | .module_flag, |
| 7693 | .local_var, |
| 7694 | .parameter, |
| 7695 | .global_var, |
| 7696 | .@"global_var local", |
| 7697 | .global_var_expression, |
| 7698 | => false, |
| 7699 | }; |
| 7700 | } |
| 7701 | }; |
| 7966 | 7702 | |
| 7967 | | .string_map = .{}, |
| 7968 | | .string_indices = .{}, |
| 7969 | | .string_bytes = .{}, |
| 7703 | pub fn isInline(self: Metadata, builder: *const Builder) bool { |
| 7704 | return builder.metadata_items.items(.tag)[@intFromEnum(self)].isInline(); |
| 7705 | } |
| 7970 | 7706 | |
| 7971 | | .types = .{}, |
| 7972 | | .next_unnamed_type = @enumFromInt(0), |
| 7973 | | .next_unique_type_id = .{}, |
| 7974 | | .type_map = .{}, |
| 7975 | | .type_items = .{}, |
| 7976 | | .type_extra = .{}, |
| 7707 | pub fn unwrap(self: Metadata, builder: *const Builder) Metadata { |
| 7708 | var metadata = self; |
| 7709 | while (@intFromEnum(metadata) >= Metadata.first_forward_reference and |
| 7710 | @intFromEnum(metadata) < Metadata.first_local_metadata) |
| 7711 | { |
| 7712 | const index = @intFromEnum(metadata) - Metadata.first_forward_reference; |
| 7713 | metadata = builder.metadata_forward_references.items[index]; |
| 7714 | assert(metadata != .none); |
| 7715 | } |
| 7716 | return metadata; |
| 7717 | } |
| 7977 | 7718 | |
| 7978 | | .attributes = .{}, |
| 7979 | | .attributes_map = .{}, |
| 7980 | | .attributes_indices = .{}, |
| 7981 | | .attributes_extra = .{}, |
| 7719 | pub const Item = struct { |
| 7720 | tag: Tag, |
| 7721 | data: ExtraIndex, |
| 7982 | 7722 | |
| 7983 | | .globals = .{}, |
| 7984 | | .next_unnamed_global = @enumFromInt(0), |
| 7985 | | .next_replaced_global = .none, |
| 7986 | | .next_unique_global_id = .{}, |
| 7987 | | .aliases = .{}, |
| 7988 | | .variables = .{}, |
| 7989 | | .functions = .{}, |
| 7723 | const ExtraIndex = u32; |
| 7724 | }; |
| 7990 | 7725 | |
| 7991 | | .constant_map = .{}, |
| 7992 | | .constant_items = .{}, |
| 7993 | | .constant_extra = .{}, |
| 7994 | | .constant_limbs = .{}, |
| 7726 | pub const DIFlags = packed struct(u32) { |
| 7727 | Visibility: enum(u2) { Zero, Private, Protected, Public } = .Zero, |
| 7728 | FwdDecl: bool = false, |
| 7729 | AppleBlock: bool = false, |
| 7730 | ReservedBit4: u1 = 0, |
| 7731 | Virtual: bool = false, |
| 7732 | Artificial: bool = false, |
| 7733 | Explicit: bool = false, |
| 7734 | Prototyped: bool = false, |
| 7735 | ObjcClassComplete: bool = false, |
| 7736 | ObjectPointer: bool = false, |
| 7737 | Vector: bool = false, |
| 7738 | StaticMember: bool = false, |
| 7739 | LValueReference: bool = false, |
| 7740 | RValueReference: bool = false, |
| 7741 | ExportSymbols: bool = false, |
| 7742 | Inheritance: enum(u2) { |
| 7743 | Zero, |
| 7744 | SingleInheritance, |
| 7745 | MultipleInheritance, |
| 7746 | VirtualInheritance, |
| 7747 | } = .Zero, |
| 7748 | IntroducedVirtual: bool = false, |
| 7749 | BitField: bool = false, |
| 7750 | NoReturn: bool = false, |
| 7751 | ReservedBit21: u1 = 0, |
| 7752 | TypePassbyValue: bool = false, |
| 7753 | TypePassbyReference: bool = false, |
| 7754 | EnumClass: bool = false, |
| 7755 | Thunk: bool = false, |
| 7756 | NonTrivial: bool = false, |
| 7757 | BigEndian: bool = false, |
| 7758 | LittleEndian: bool = false, |
| 7759 | AllCallsDescribed: bool = false, |
| 7760 | Unused: u2 = 0, |
| 7761 | |
| 7762 | pub fn format( |
| 7763 | self: DIFlags, |
| 7764 | comptime _: []const u8, |
| 7765 | _: std.fmt.FormatOptions, |
| 7766 | writer: anytype, |
| 7767 | ) @TypeOf(writer).Error!void { |
| 7768 | var need_pipe = false; |
| 7769 | inline for (@typeInfo(DIFlags).Struct.fields) |field| { |
| 7770 | switch (@typeInfo(field.type)) { |
| 7771 | .Bool => if (@field(self, field.name)) { |
| 7772 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; |
| 7773 | try writer.print("DIFlag{s}", .{field.name}); |
| 7774 | }, |
| 7775 | .Enum => if (@field(self, field.name) != .Zero) { |
| 7776 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; |
| 7777 | try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))}); |
| 7778 | }, |
| 7779 | .Int => assert(@field(self, field.name) == 0), |
| 7780 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ |
| 7781 | @typeName(field.type)), |
| 7782 | } |
| 7783 | } |
| 7784 | if (!need_pipe) try writer.writeByte('0'); |
| 7785 | } |
| 7995 | 7786 | }; |
| 7996 | | if (self.useLibLlvm()) self.llvm = .{ |
| 7997 | | .context = llvm.Context.create(), |
| 7998 | | .module = null, |
| 7999 | | .target = null, |
| 8000 | | .di_builder = null, |
| 8001 | | .di_compile_unit = null, |
| 8002 | | .attribute_kind_ids = null, |
| 8003 | | .attributes = .{}, |
| 8004 | | .types = .{}, |
| 8005 | | .globals = .{}, |
| 8006 | | .constants = .{}, |
| 8007 | | .replacements = .{}, |
| 7787 | |
| 7788 | pub const File = struct { |
| 7789 | filename: MetadataString, |
| 7790 | directory: MetadataString, |
| 8008 | 7791 | }; |
| 8009 | | errdefer self.deinit(); |
| 8010 | 7792 | |
| 8011 | | try self.string_indices.append(self.gpa, 0); |
| 8012 | | assert(try self.string("") == .empty); |
| 7793 | pub const CompileUnit = struct { |
| 7794 | pub const Options = struct { |
| 7795 | optimized: bool, |
| 7796 | }; |
| 8013 | 7797 | |
| 8014 | | if (options.name.len > 0) self.source_filename = try self.string(options.name); |
| 8015 | | if (self.useLibLlvm()) { |
| 8016 | | initializeLLVMTarget(options.target.cpu.arch); |
| 8017 | | self.llvm.module = llvm.Module.createWithName( |
| 8018 | | (self.source_filename.slice(&self) orelse ""), |
| 8019 | | self.llvm.context, |
| 8020 | | ); |
| 8021 | | } |
| 7798 | file: Metadata, |
| 7799 | producer: MetadataString, |
| 7800 | enums: Metadata, |
| 7801 | globals: Metadata, |
| 7802 | }; |
| 8022 | 7803 | |
| 8023 | | if (options.triple.len > 0) { |
| 8024 | | self.target_triple = try self.string(options.triple); |
| 7804 | pub const Subprogram = struct { |
| 7805 | pub const Options = struct { |
| 7806 | di_flags: DIFlags, |
| 7807 | sp_flags: DISPFlags, |
| 7808 | }; |
| 8025 | 7809 | |
| 8026 | | if (self.useLibLlvm()) { |
| 8027 | | var error_message: [*:0]const u8 = undefined; |
| 8028 | | var target: *llvm.Target = undefined; |
| 8029 | | if (llvm.Target.getFromTriple( |
| 8030 | | self.target_triple.slice(&self).?, |
| 8031 | | &target, |
| 8032 | | &error_message, |
| 8033 | | ).toBool()) { |
| 8034 | | defer llvm.disposeMessage(error_message); |
| 8035 | | |
| 8036 | | log.err("LLVM failed to parse '{s}': {s}", .{ |
| 8037 | | self.target_triple.slice(&self).?, |
| 8038 | | error_message, |
| 8039 | | }); |
| 8040 | | return InitError.InvalidLlvmTriple; |
| 7810 | pub const DISPFlags = packed struct(u32) { |
| 7811 | Virtuality: enum(u2) { Zero, Virtual, PureVirtual } = .Zero, |
| 7812 | LocalToUnit: bool = false, |
| 7813 | Definition: bool = false, |
| 7814 | Optimized: bool = false, |
| 7815 | Pure: bool = false, |
| 7816 | Elemental: bool = false, |
| 7817 | Recursive: bool = false, |
| 7818 | MainSubprogram: bool = false, |
| 7819 | Deleted: bool = false, |
| 7820 | ReservedBit10: u1 = 0, |
| 7821 | ObjCDirect: bool = false, |
| 7822 | Unused: u20 = 0, |
| 7823 | |
| 7824 | pub fn format( |
| 7825 | self: DISPFlags, |
| 7826 | comptime _: []const u8, |
| 7827 | _: std.fmt.FormatOptions, |
| 7828 | writer: anytype, |
| 7829 | ) @TypeOf(writer).Error!void { |
| 7830 | var need_pipe = false; |
| 7831 | inline for (@typeInfo(DISPFlags).Struct.fields) |field| { |
| 7832 | switch (@typeInfo(field.type)) { |
| 7833 | .Bool => if (@field(self, field.name)) { |
| 7834 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; |
| 7835 | try writer.print("DISPFlag{s}", .{field.name}); |
| 7836 | }, |
| 7837 | .Enum => if (@field(self, field.name) != .Zero) { |
| 7838 | if (need_pipe) try writer.writeAll(" | ") else need_pipe = true; |
| 7839 | try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))}); |
| 7840 | }, |
| 7841 | .Int => assert(@field(self, field.name) == 0), |
| 7842 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ |
| 7843 | @typeName(field.type)), |
| 7844 | } |
| 7845 | } |
| 7846 | if (!need_pipe) try writer.writeByte('0'); |
| 8041 | 7847 | } |
| 8042 | | self.llvm.target = target; |
| 8043 | | self.llvm.module.?.setTarget(self.target_triple.slice(&self).?); |
| 7848 | }; |
| 7849 | |
| 7850 | file: Metadata, |
| 7851 | name: MetadataString, |
| 7852 | linkage_name: MetadataString, |
| 7853 | line: u32, |
| 7854 | scope_line: u32, |
| 7855 | ty: Metadata, |
| 7856 | di_flags: DIFlags, |
| 7857 | compile_unit: Metadata, |
| 7858 | }; |
| 7859 | |
| 7860 | pub const LexicalBlock = struct { |
| 7861 | scope: Metadata, |
| 7862 | file: Metadata, |
| 7863 | line: u32, |
| 7864 | column: u32, |
| 7865 | }; |
| 7866 | |
| 7867 | pub const Location = struct { |
| 7868 | line: u32, |
| 7869 | column: u32, |
| 7870 | scope: Metadata, |
| 7871 | inlined_at: Metadata, |
| 7872 | }; |
| 7873 | |
| 7874 | pub const BasicType = struct { |
| 7875 | name: MetadataString, |
| 7876 | size_in_bits_lo: u32, |
| 7877 | size_in_bits_hi: u32, |
| 7878 | |
| 7879 | pub fn bitSize(self: BasicType) u64 { |
| 7880 | return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo; |
| 8044 | 7881 | } |
| 8045 | | } |
| 7882 | }; |
| 8046 | 7883 | |
| 8047 | | { |
| 8048 | | const static_len = @typeInfo(Type).Enum.fields.len - 1; |
| 8049 | | try self.type_map.ensureTotalCapacity(self.gpa, static_len); |
| 8050 | | try self.type_items.ensureTotalCapacity(self.gpa, static_len); |
| 8051 | | if (self.useLibLlvm()) try self.llvm.types.ensureTotalCapacity(self.gpa, static_len); |
| 8052 | | inline for (@typeInfo(Type.Simple).Enum.fields) |simple_field| { |
| 8053 | | const result = self.getOrPutTypeNoExtraAssumeCapacity( |
| 8054 | | .{ .tag = .simple, .data = simple_field.value }, |
| 8055 | | ); |
| 8056 | | assert(result.new and result.type == @field(Type, simple_field.name)); |
| 8057 | | if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity( |
| 8058 | | @field(llvm.Context, simple_field.name ++ "Type")(self.llvm.context), |
| 8059 | | ); |
| 7884 | pub const CompositeType = struct { |
| 7885 | name: MetadataString, |
| 7886 | file: Metadata, |
| 7887 | scope: Metadata, |
| 7888 | line: u32, |
| 7889 | underlying_type: Metadata, |
| 7890 | size_in_bits_lo: u32, |
| 7891 | size_in_bits_hi: u32, |
| 7892 | align_in_bits_lo: u32, |
| 7893 | align_in_bits_hi: u32, |
| 7894 | fields_tuple: Metadata, |
| 7895 | |
| 7896 | pub fn bitSize(self: CompositeType) u64 { |
| 7897 | return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo; |
| 8060 | 7898 | } |
| 8061 | | inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits| |
| 8062 | | assert(self.intTypeAssumeCapacity(bits) == |
| 8063 | | @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); |
| 8064 | | inline for (.{ 0, 4 }) |addr_space_index| { |
| 8065 | | const addr_space: AddrSpace = @enumFromInt(addr_space_index); |
| 8066 | | assert(self.ptrTypeAssumeCapacity(addr_space) == |
| 8067 | | @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space}))); |
| 7899 | pub fn bitAlign(self: CompositeType) u64 { |
| 7900 | return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo; |
| 8068 | 7901 | } |
| 8069 | | } |
| 7902 | }; |
| 8070 | 7903 | |
| 8071 | | { |
| 8072 | | if (self.useLibLlvm()) { |
| 8073 | | self.llvm.attribute_kind_ids = try self.gpa.create([Attribute.Kind.len]c_uint); |
| 8074 | | @memset(self.llvm.attribute_kind_ids.?, 0); |
| 7904 | pub const DerivedType = struct { |
| 7905 | name: MetadataString, |
| 7906 | file: Metadata, |
| 7907 | scope: Metadata, |
| 7908 | line: u32, |
| 7909 | underlying_type: Metadata, |
| 7910 | size_in_bits_lo: u32, |
| 7911 | size_in_bits_hi: u32, |
| 7912 | align_in_bits_lo: u32, |
| 7913 | align_in_bits_hi: u32, |
| 7914 | offset_in_bits_lo: u32, |
| 7915 | offset_in_bits_hi: u32, |
| 7916 | |
| 7917 | pub fn bitSize(self: DerivedType) u64 { |
| 7918 | return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo; |
| 8075 | 7919 | } |
| 8076 | | try self.attributes_indices.append(self.gpa, 0); |
| 8077 | | assert(try self.attrs(&.{}) == .none); |
| 8078 | | assert(try self.fnAttrs(&.{}) == .none); |
| 8079 | | } |
| 7920 | pub fn bitAlign(self: DerivedType) u64 { |
| 7921 | return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo; |
| 7922 | } |
| 7923 | pub fn bitOffset(self: DerivedType) u64 { |
| 7924 | return @as(u64, self.offset_in_bits_hi) << 32 | self.offset_in_bits_lo; |
| 7925 | } |
| 7926 | }; |
| 8080 | 7927 | |
| 8081 | | assert(try self.intConst(.i1, 0) == .false); |
| 8082 | | assert(try self.intConst(.i1, 1) == .true); |
| 8083 | | assert(try self.noneConst(.token) == .none); |
| 7928 | pub const SubroutineType = struct { |
| 7929 | types_tuple: Metadata, |
| 7930 | }; |
| 8084 | 7931 | |
| 8085 | | return self; |
| 8086 | | } |
| 7932 | pub const Enumerator = struct { |
| 7933 | name: MetadataString, |
| 7934 | bit_width: u32, |
| 7935 | limbs_index: u32, |
| 7936 | limbs_len: u32, |
| 7937 | }; |
| 8087 | 7938 | |
| 8088 | | pub fn deinit(self: *Builder) void { |
| 8089 | | if (self.useLibLlvm()) { |
| 8090 | | var replacement_it = self.llvm.replacements.keyIterator(); |
| 8091 | | while (replacement_it.next()) |replacement| replacement.*.deleteGlobalValue(); |
| 8092 | | self.llvm.replacements.deinit(self.gpa); |
| 8093 | | self.llvm.constants.deinit(self.gpa); |
| 8094 | | self.llvm.globals.deinit(self.gpa); |
| 8095 | | self.llvm.types.deinit(self.gpa); |
| 8096 | | self.llvm.attributes.deinit(self.gpa); |
| 8097 | | if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids); |
| 8098 | | if (self.llvm.di_builder) |di_builder| di_builder.dispose(); |
| 8099 | | if (self.llvm.module) |module| module.dispose(); |
| 8100 | | self.llvm.context.dispose(); |
| 8101 | | } |
| 7939 | pub const Subrange = struct { |
| 7940 | lower_bound: Metadata, |
| 7941 | count: Metadata, |
| 7942 | }; |
| 8102 | 7943 | |
| 8103 | | self.module_asm.deinit(self.gpa); |
| 7944 | pub const Expression = struct { |
| 7945 | elements_len: u32, |
| 8104 | 7946 | |
| 8105 | | self.string_map.deinit(self.gpa); |
| 8106 | | self.string_indices.deinit(self.gpa); |
| 8107 | | self.string_bytes.deinit(self.gpa); |
| 7947 | // elements: [elements_len]u32 |
| 7948 | }; |
| 8108 | 7949 | |
| 8109 | | self.types.deinit(self.gpa); |
| 8110 | | self.next_unique_type_id.deinit(self.gpa); |
| 8111 | | self.type_map.deinit(self.gpa); |
| 8112 | | self.type_items.deinit(self.gpa); |
| 8113 | | self.type_extra.deinit(self.gpa); |
| 7950 | pub const Tuple = struct { |
| 7951 | elements_len: u32, |
| 8114 | 7952 | |
| 8115 | | self.attributes.deinit(self.gpa); |
| 8116 | | self.attributes_map.deinit(self.gpa); |
| 8117 | | self.attributes_indices.deinit(self.gpa); |
| 8118 | | self.attributes_extra.deinit(self.gpa); |
| 7953 | // elements: [elements_len]Metadata |
| 7954 | }; |
| 8119 | 7955 | |
| 8120 | | self.globals.deinit(self.gpa); |
| 8121 | | self.next_unique_global_id.deinit(self.gpa); |
| 8122 | | self.aliases.deinit(self.gpa); |
| 8123 | | self.variables.deinit(self.gpa); |
| 8124 | | for (self.functions.items) |*function| function.deinit(self.gpa); |
| 8125 | | self.functions.deinit(self.gpa); |
| 7956 | pub const ModuleFlag = struct { |
| 7957 | behavior: Metadata, |
| 7958 | name: MetadataString, |
| 7959 | constant: Metadata, |
| 7960 | }; |
| 8126 | 7961 | |
| 8127 | | self.constant_map.deinit(self.gpa); |
| 8128 | | self.constant_items.deinit(self.gpa); |
| 8129 | | self.constant_extra.deinit(self.gpa); |
| 8130 | | self.constant_limbs.deinit(self.gpa); |
| 7962 | pub const LocalVar = struct { |
| 7963 | name: MetadataString, |
| 7964 | file: Metadata, |
| 7965 | scope: Metadata, |
| 7966 | line: u32, |
| 7967 | ty: Metadata, |
| 7968 | }; |
| 8131 | 7969 | |
| 8132 | | self.* = undefined; |
| 8133 | | } |
| 7970 | pub const Parameter = struct { |
| 7971 | name: MetadataString, |
| 7972 | file: Metadata, |
| 7973 | scope: Metadata, |
| 7974 | line: u32, |
| 7975 | ty: Metadata, |
| 7976 | arg_no: u32, |
| 7977 | }; |
| 7978 | |
| 7979 | pub const GlobalVar = struct { |
| 7980 | pub const Options = struct { |
| 7981 | local: bool, |
| 7982 | }; |
| 7983 | |
| 7984 | name: MetadataString, |
| 7985 | linkage_name: MetadataString, |
| 7986 | file: Metadata, |
| 7987 | scope: Metadata, |
| 7988 | line: u32, |
| 7989 | ty: Metadata, |
| 7990 | variable: Variable.Index, |
| 7991 | }; |
| 7992 | |
| 7993 | pub const GlobalVarExpression = struct { |
| 7994 | variable: Metadata, |
| 7995 | expression: Metadata, |
| 7996 | }; |
| 7997 | |
| 7998 | pub fn toValue(self: Metadata) Value { |
| 7999 | return @enumFromInt(Value.first_metadata + @intFromEnum(self)); |
| 8000 | } |
| 8001 | |
| 8002 | const Formatter = struct { |
| 8003 | builder: *Builder, |
| 8004 | need_comma: bool, |
| 8005 | map: std.AutoArrayHashMapUnmanaged(Metadata, void) = .{}, |
| 8006 | |
| 8007 | const FormatData = struct { |
| 8008 | formatter: *Formatter, |
| 8009 | prefix: []const u8 = "", |
| 8010 | node: Node, |
| 8011 | |
| 8012 | const Node = union(enum) { |
| 8013 | none, |
| 8014 | @"inline": Metadata, |
| 8015 | index: u32, |
| 8016 | |
| 8017 | local_value: ValueData, |
| 8018 | local_metadata: ValueData, |
| 8019 | local_inline: Metadata, |
| 8020 | local_index: u32, |
| 8021 | |
| 8022 | string: MetadataString, |
| 8023 | bool: bool, |
| 8024 | u32: u32, |
| 8025 | u64: u64, |
| 8026 | di_flags: DIFlags, |
| 8027 | sp_flags: Subprogram.DISPFlags, |
| 8028 | raw: []const u8, |
| 8029 | |
| 8030 | const ValueData = struct { |
| 8031 | value: Value, |
| 8032 | function: Function.Index, |
| 8033 | }; |
| 8034 | }; |
| 8035 | }; |
| 8036 | fn format( |
| 8037 | data: FormatData, |
| 8038 | comptime fmt_str: []const u8, |
| 8039 | fmt_opts: std.fmt.FormatOptions, |
| 8040 | writer: anytype, |
| 8041 | ) @TypeOf(writer).Error!void { |
| 8042 | if (data.node == .none) return; |
| 8043 | |
| 8044 | const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S'; |
| 8045 | const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str; |
| 8046 | |
| 8047 | if (data.formatter.need_comma) try writer.writeAll(", "); |
| 8048 | defer data.formatter.need_comma = true; |
| 8049 | try writer.writeAll(data.prefix); |
| 8134 | 8050 | |
| 8135 | | pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { |
| 8136 | | switch (arch) { |
| 8137 | | .aarch64, .aarch64_be, .aarch64_32 => { |
| 8138 | | llvm.LLVMInitializeAArch64Target(); |
| 8139 | | llvm.LLVMInitializeAArch64TargetInfo(); |
| 8140 | | llvm.LLVMInitializeAArch64TargetMC(); |
| 8141 | | llvm.LLVMInitializeAArch64AsmPrinter(); |
| 8142 | | llvm.LLVMInitializeAArch64AsmParser(); |
| 8143 | | }, |
| 8144 | | .amdgcn => { |
| 8145 | | llvm.LLVMInitializeAMDGPUTarget(); |
| 8146 | | llvm.LLVMInitializeAMDGPUTargetInfo(); |
| 8147 | | llvm.LLVMInitializeAMDGPUTargetMC(); |
| 8148 | | llvm.LLVMInitializeAMDGPUAsmPrinter(); |
| 8149 | | llvm.LLVMInitializeAMDGPUAsmParser(); |
| 8150 | | }, |
| 8151 | | .thumb, .thumbeb, .arm, .armeb => { |
| 8152 | | llvm.LLVMInitializeARMTarget(); |
| 8153 | | llvm.LLVMInitializeARMTargetInfo(); |
| 8154 | | llvm.LLVMInitializeARMTargetMC(); |
| 8155 | | llvm.LLVMInitializeARMAsmPrinter(); |
| 8156 | | llvm.LLVMInitializeARMAsmParser(); |
| 8157 | | }, |
| 8158 | | .avr => { |
| 8159 | | llvm.LLVMInitializeAVRTarget(); |
| 8160 | | llvm.LLVMInitializeAVRTargetInfo(); |
| 8161 | | llvm.LLVMInitializeAVRTargetMC(); |
| 8162 | | llvm.LLVMInitializeAVRAsmPrinter(); |
| 8163 | | llvm.LLVMInitializeAVRAsmParser(); |
| 8164 | | }, |
| 8165 | | .bpfel, .bpfeb => { |
| 8166 | | llvm.LLVMInitializeBPFTarget(); |
| 8167 | | llvm.LLVMInitializeBPFTargetInfo(); |
| 8168 | | llvm.LLVMInitializeBPFTargetMC(); |
| 8169 | | llvm.LLVMInitializeBPFAsmPrinter(); |
| 8170 | | llvm.LLVMInitializeBPFAsmParser(); |
| 8171 | | }, |
| 8172 | | .hexagon => { |
| 8173 | | llvm.LLVMInitializeHexagonTarget(); |
| 8174 | | llvm.LLVMInitializeHexagonTargetInfo(); |
| 8175 | | llvm.LLVMInitializeHexagonTargetMC(); |
| 8176 | | llvm.LLVMInitializeHexagonAsmPrinter(); |
| 8177 | | llvm.LLVMInitializeHexagonAsmParser(); |
| 8178 | | }, |
| 8179 | | .lanai => { |
| 8180 | | llvm.LLVMInitializeLanaiTarget(); |
| 8181 | | llvm.LLVMInitializeLanaiTargetInfo(); |
| 8182 | | llvm.LLVMInitializeLanaiTargetMC(); |
| 8183 | | llvm.LLVMInitializeLanaiAsmPrinter(); |
| 8184 | | llvm.LLVMInitializeLanaiAsmParser(); |
| 8185 | | }, |
| 8186 | | .mips, .mipsel, .mips64, .mips64el => { |
| 8187 | | llvm.LLVMInitializeMipsTarget(); |
| 8188 | | llvm.LLVMInitializeMipsTargetInfo(); |
| 8189 | | llvm.LLVMInitializeMipsTargetMC(); |
| 8190 | | llvm.LLVMInitializeMipsAsmPrinter(); |
| 8191 | | llvm.LLVMInitializeMipsAsmParser(); |
| 8192 | | }, |
| 8193 | | .msp430 => { |
| 8194 | | llvm.LLVMInitializeMSP430Target(); |
| 8195 | | llvm.LLVMInitializeMSP430TargetInfo(); |
| 8196 | | llvm.LLVMInitializeMSP430TargetMC(); |
| 8197 | | llvm.LLVMInitializeMSP430AsmPrinter(); |
| 8198 | | llvm.LLVMInitializeMSP430AsmParser(); |
| 8199 | | }, |
| 8200 | | .nvptx, .nvptx64 => { |
| 8201 | | llvm.LLVMInitializeNVPTXTarget(); |
| 8202 | | llvm.LLVMInitializeNVPTXTargetInfo(); |
| 8203 | | llvm.LLVMInitializeNVPTXTargetMC(); |
| 8204 | | llvm.LLVMInitializeNVPTXAsmPrinter(); |
| 8205 | | // There is no LLVMInitializeNVPTXAsmParser function available. |
| 8206 | | }, |
| 8207 | | .powerpc, .powerpcle, .powerpc64, .powerpc64le => { |
| 8208 | | llvm.LLVMInitializePowerPCTarget(); |
| 8209 | | llvm.LLVMInitializePowerPCTargetInfo(); |
| 8210 | | llvm.LLVMInitializePowerPCTargetMC(); |
| 8211 | | llvm.LLVMInitializePowerPCAsmPrinter(); |
| 8212 | | llvm.LLVMInitializePowerPCAsmParser(); |
| 8213 | | }, |
| 8214 | | .riscv32, .riscv64 => { |
| 8215 | | llvm.LLVMInitializeRISCVTarget(); |
| 8216 | | llvm.LLVMInitializeRISCVTargetInfo(); |
| 8217 | | llvm.LLVMInitializeRISCVTargetMC(); |
| 8218 | | llvm.LLVMInitializeRISCVAsmPrinter(); |
| 8219 | | llvm.LLVMInitializeRISCVAsmParser(); |
| 8220 | | }, |
| 8221 | | .sparc, .sparc64, .sparcel => { |
| 8222 | | llvm.LLVMInitializeSparcTarget(); |
| 8223 | | llvm.LLVMInitializeSparcTargetInfo(); |
| 8224 | | llvm.LLVMInitializeSparcTargetMC(); |
| 8225 | | llvm.LLVMInitializeSparcAsmPrinter(); |
| 8226 | | llvm.LLVMInitializeSparcAsmParser(); |
| 8227 | | }, |
| 8228 | | .s390x => { |
| 8229 | | llvm.LLVMInitializeSystemZTarget(); |
| 8230 | | llvm.LLVMInitializeSystemZTargetInfo(); |
| 8231 | | llvm.LLVMInitializeSystemZTargetMC(); |
| 8232 | | llvm.LLVMInitializeSystemZAsmPrinter(); |
| 8233 | | llvm.LLVMInitializeSystemZAsmParser(); |
| 8234 | | }, |
| 8235 | | .wasm32, .wasm64 => { |
| 8236 | | llvm.LLVMInitializeWebAssemblyTarget(); |
| 8237 | | llvm.LLVMInitializeWebAssemblyTargetInfo(); |
| 8238 | | llvm.LLVMInitializeWebAssemblyTargetMC(); |
| 8239 | | llvm.LLVMInitializeWebAssemblyAsmPrinter(); |
| 8240 | | llvm.LLVMInitializeWebAssemblyAsmParser(); |
| 8241 | | }, |
| 8242 | | .x86, .x86_64 => { |
| 8243 | | llvm.LLVMInitializeX86Target(); |
| 8244 | | llvm.LLVMInitializeX86TargetInfo(); |
| 8245 | | llvm.LLVMInitializeX86TargetMC(); |
| 8246 | | llvm.LLVMInitializeX86AsmPrinter(); |
| 8247 | | llvm.LLVMInitializeX86AsmParser(); |
| 8248 | | }, |
| 8249 | | .xtensa => { |
| 8250 | | if (build_options.llvm_has_xtensa) { |
| 8251 | | llvm.LLVMInitializeXtensaTarget(); |
| 8252 | | llvm.LLVMInitializeXtensaTargetInfo(); |
| 8253 | | llvm.LLVMInitializeXtensaTargetMC(); |
| 8254 | | // There is no LLVMInitializeXtensaAsmPrinter function. |
| 8255 | | llvm.LLVMInitializeXtensaAsmParser(); |
| 8051 | const builder = data.formatter.builder; |
| 8052 | switch (data.node) { |
| 8053 | .none => unreachable, |
| 8054 | .@"inline" => |node| { |
| 8055 | const needed_comma = data.formatter.need_comma; |
| 8056 | defer data.formatter.need_comma = needed_comma; |
| 8057 | data.formatter.need_comma = false; |
| 8058 | |
| 8059 | const item = builder.metadata_items.get(@intFromEnum(node)); |
| 8060 | switch (item.tag) { |
| 8061 | .expression => { |
| 8062 | var extra = builder.metadataExtraDataTrail(Expression, item.data); |
| 8063 | const elements = extra.trail.next(extra.data.elements_len, u32, builder); |
| 8064 | try writer.writeAll("!DIExpression("); |
| 8065 | for (elements) |element| try format(.{ |
| 8066 | .formatter = data.formatter, |
| 8067 | .node = .{ .u64 = element }, |
| 8068 | }, "%", fmt_opts, writer); |
| 8069 | try writer.writeByte(')'); |
| 8070 | }, |
| 8071 | .constant => try Constant.format(.{ |
| 8072 | .constant = @enumFromInt(item.data), |
| 8073 | .builder = builder, |
| 8074 | }, recurse_fmt_str, fmt_opts, writer), |
| 8075 | else => unreachable, |
| 8076 | } |
| 8077 | }, |
| 8078 | .index => |node| try writer.print("!{d}", .{node}), |
| 8079 | inline .local_value, .local_metadata => |node, tag| try Value.format(.{ |
| 8080 | .value = node.value, |
| 8081 | .function = node.function, |
| 8082 | .builder = builder, |
| 8083 | }, switch (tag) { |
| 8084 | .local_value => recurse_fmt_str, |
| 8085 | .local_metadata => "%", |
| 8086 | else => unreachable, |
| 8087 | }, fmt_opts, writer), |
| 8088 | inline .local_inline, .local_index => |node, tag| { |
| 8089 | if (comptime std.mem.eql(u8, recurse_fmt_str, "%")) |
| 8090 | try writer.print("{%} ", .{Type.metadata.fmt(builder)}); |
| 8091 | try format(.{ |
| 8092 | .formatter = data.formatter, |
| 8093 | .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node), |
| 8094 | }, "%", fmt_opts, writer); |
| 8095 | }, |
| 8096 | .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{ |
| 8097 | node.fmt(builder), |
| 8098 | }), |
| 8099 | inline .bool, |
| 8100 | .u32, |
| 8101 | .u64, |
| 8102 | .di_flags, |
| 8103 | .sp_flags, |
| 8104 | => |node| try writer.print("{}", .{node}), |
| 8105 | .raw => |node| try writer.writeAll(node), |
| 8256 | 8106 | } |
| 8257 | | }, |
| 8258 | | .xcore => { |
| 8259 | | llvm.LLVMInitializeXCoreTarget(); |
| 8260 | | llvm.LLVMInitializeXCoreTargetInfo(); |
| 8261 | | llvm.LLVMInitializeXCoreTargetMC(); |
| 8262 | | llvm.LLVMInitializeXCoreAsmPrinter(); |
| 8263 | | // There is no LLVMInitializeXCoreAsmParser function. |
| 8264 | | }, |
| 8265 | | .m68k => { |
| 8266 | | if (build_options.llvm_has_m68k) { |
| 8267 | | llvm.LLVMInitializeM68kTarget(); |
| 8268 | | llvm.LLVMInitializeM68kTargetInfo(); |
| 8269 | | llvm.LLVMInitializeM68kTargetMC(); |
| 8270 | | llvm.LLVMInitializeM68kAsmPrinter(); |
| 8271 | | llvm.LLVMInitializeM68kAsmParser(); |
| 8107 | } |
| 8108 | inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) { |
| 8109 | Metadata => Allocator.Error, |
| 8110 | else => error{}, |
| 8111 | }!std.fmt.Formatter(format) { |
| 8112 | const Node = @TypeOf(node); |
| 8113 | const MaybeNode = switch (@typeInfo(Node)) { |
| 8114 | .Optional => Node, |
| 8115 | .Null => ?noreturn, |
| 8116 | else => ?Node, |
| 8117 | }; |
| 8118 | const Some = @typeInfo(MaybeNode).Optional.child; |
| 8119 | return .{ .data = .{ |
| 8120 | .formatter = formatter, |
| 8121 | .prefix = prefix, |
| 8122 | .node = if (@as(MaybeNode, node)) |some| switch (@typeInfo(Some)) { |
| 8123 | .Enum => |enum_info| switch (Some) { |
| 8124 | Metadata => switch (some) { |
| 8125 | .none => .none, |
| 8126 | else => try formatter.refUnwrapped(some.unwrap(formatter.builder)), |
| 8127 | }, |
| 8128 | MetadataString => .{ .string = some }, |
| 8129 | else => if (enum_info.is_exhaustive) |
| 8130 | .{ .raw = @tagName(some) } |
| 8131 | else |
| 8132 | @compileError("unknown type to format: " ++ @typeName(Node)), |
| 8133 | }, |
| 8134 | .EnumLiteral => .{ .raw = @tagName(some) }, |
| 8135 | .Bool => .{ .bool = some }, |
| 8136 | .Struct => switch (Some) { |
| 8137 | DIFlags => .{ .di_flags = some }, |
| 8138 | Subprogram.DISPFlags => .{ .sp_flags = some }, |
| 8139 | else => @compileError("unknown type to format: " ++ @typeName(Node)), |
| 8140 | }, |
| 8141 | .Int, .ComptimeInt => .{ .u64 = some }, |
| 8142 | .Pointer => .{ .raw = some }, |
| 8143 | else => @compileError("unknown type to format: " ++ @typeName(Node)), |
| 8144 | } else switch (@typeInfo(Node)) { |
| 8145 | .Optional, .Null => .none, |
| 8146 | else => unreachable, |
| 8147 | }, |
| 8148 | } }; |
| 8149 | } |
| 8150 | inline fn fmtLocal( |
| 8151 | formatter: *Formatter, |
| 8152 | prefix: []const u8, |
| 8153 | value: Value, |
| 8154 | function: Function.Index, |
| 8155 | ) Allocator.Error!std.fmt.Formatter(format) { |
| 8156 | return .{ .data = .{ |
| 8157 | .formatter = formatter, |
| 8158 | .prefix = prefix, |
| 8159 | .node = switch (value.unwrap()) { |
| 8160 | .instruction, .constant => .{ .local_value = .{ |
| 8161 | .value = value, |
| 8162 | .function = function, |
| 8163 | } }, |
| 8164 | .metadata => |metadata| if (value == .none) .none else node: { |
| 8165 | const unwrapped = metadata.unwrap(formatter.builder); |
| 8166 | break :node if (@intFromEnum(unwrapped) >= first_local_metadata) |
| 8167 | .{ .local_metadata = .{ |
| 8168 | .value = function.ptrConst(formatter.builder).debug_values[ |
| 8169 | @intFromEnum(unwrapped) - first_local_metadata |
| 8170 | ].toValue(), |
| 8171 | .function = function, |
| 8172 | } } |
| 8173 | else switch (try formatter.refUnwrapped(unwrapped)) { |
| 8174 | .@"inline" => |node| .{ .local_inline = node }, |
| 8175 | .index => |node| .{ .local_index = node }, |
| 8176 | else => unreachable, |
| 8177 | }; |
| 8178 | }, |
| 8179 | }, |
| 8180 | } }; |
| 8181 | } |
| 8182 | fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node { |
| 8183 | assert(node != .none); |
| 8184 | assert(@intFromEnum(node) < first_forward_reference); |
| 8185 | const builder = formatter.builder; |
| 8186 | const unwrapped_metadata = node.unwrap(builder); |
| 8187 | const tag = formatter.builder.metadata_items.items(.tag)[@intFromEnum(unwrapped_metadata)]; |
| 8188 | switch (tag) { |
| 8189 | .none => unreachable, |
| 8190 | .expression, .constant => return .{ .@"inline" = unwrapped_metadata }, |
| 8191 | else => { |
| 8192 | assert(!tag.isInline()); |
| 8193 | const gop = try formatter.map.getOrPutValue(builder.gpa, unwrapped_metadata, {}); |
| 8194 | return .{ .index = @intCast(gop.index) }; |
| 8195 | }, |
| 8272 | 8196 | } |
| 8273 | | }, |
| 8274 | | .csky => { |
| 8275 | | if (build_options.llvm_has_csky) { |
| 8276 | | llvm.LLVMInitializeCSKYTarget(); |
| 8277 | | llvm.LLVMInitializeCSKYTargetInfo(); |
| 8278 | | llvm.LLVMInitializeCSKYTargetMC(); |
| 8279 | | // There is no LLVMInitializeCSKYAsmPrinter function. |
| 8280 | | llvm.LLVMInitializeCSKYAsmParser(); |
| 8197 | } |
| 8198 | |
| 8199 | inline fn specialized( |
| 8200 | formatter: *Formatter, |
| 8201 | distinct: enum { @"!", @"distinct !" }, |
| 8202 | node: enum { |
| 8203 | DIFile, |
| 8204 | DICompileUnit, |
| 8205 | DISubprogram, |
| 8206 | DILexicalBlock, |
| 8207 | DILocation, |
| 8208 | DIBasicType, |
| 8209 | DICompositeType, |
| 8210 | DIDerivedType, |
| 8211 | DISubroutineType, |
| 8212 | DIEnumerator, |
| 8213 | DISubrange, |
| 8214 | DILocalVariable, |
| 8215 | DIGlobalVariable, |
| 8216 | DIGlobalVariableExpression, |
| 8217 | }, |
| 8218 | nodes: anytype, |
| 8219 | writer: anytype, |
| 8220 | ) !void { |
| 8221 | comptime var fmt_str: []const u8 = ""; |
| 8222 | const names = comptime std.meta.fieldNames(@TypeOf(nodes)); |
| 8223 | comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined; |
| 8224 | inline for (fields[0..2], .{ "distinct", "node" }) |*field, name| { |
| 8225 | fmt_str = fmt_str ++ "{[" ++ name ++ "]s}"; |
| 8226 | field.* = .{ |
| 8227 | .name = name, |
| 8228 | .type = []const u8, |
| 8229 | .default_value = null, |
| 8230 | .is_comptime = false, |
| 8231 | .alignment = 0, |
| 8232 | }; |
| 8281 | 8233 | } |
| 8282 | | }, |
| 8283 | | .ve => { |
| 8284 | | llvm.LLVMInitializeVETarget(); |
| 8285 | | llvm.LLVMInitializeVETargetInfo(); |
| 8286 | | llvm.LLVMInitializeVETargetMC(); |
| 8287 | | llvm.LLVMInitializeVEAsmPrinter(); |
| 8288 | | llvm.LLVMInitializeVEAsmParser(); |
| 8289 | | }, |
| 8290 | | .arc => { |
| 8291 | | if (build_options.llvm_has_arc) { |
| 8292 | | llvm.LLVMInitializeARCTarget(); |
| 8293 | | llvm.LLVMInitializeARCTargetInfo(); |
| 8294 | | llvm.LLVMInitializeARCTargetMC(); |
| 8295 | | llvm.LLVMInitializeARCAsmPrinter(); |
| 8296 | | // There is no LLVMInitializeARCAsmParser function. |
| 8234 | fmt_str = fmt_str ++ "("; |
| 8235 | inline for (fields[2..], names) |*field, name| { |
| 8236 | fmt_str = fmt_str ++ "{[" ++ name ++ "]S}"; |
| 8237 | field.* = .{ |
| 8238 | .name = name, |
| 8239 | .type = std.fmt.Formatter(format), |
| 8240 | .default_value = null, |
| 8241 | .is_comptime = false, |
| 8242 | .alignment = 0, |
| 8243 | }; |
| 8297 | 8244 | } |
| 8298 | | }, |
| 8245 | fmt_str = fmt_str ++ ")\n"; |
| 8246 | |
| 8247 | var fmt_args: @Type(.{ .Struct = .{ |
| 8248 | .layout = .Auto, |
| 8249 | .fields = &fields, |
| 8250 | .decls = &.{}, |
| 8251 | .is_tuple = false, |
| 8252 | } }) = undefined; |
| 8253 | fmt_args.distinct = @tagName(distinct); |
| 8254 | fmt_args.node = @tagName(node); |
| 8255 | inline for (names) |name| @field(fmt_args, name) = try formatter.fmt( |
| 8256 | name ++ ": ", |
| 8257 | @field(nodes, name), |
| 8258 | ); |
| 8259 | try writer.print(fmt_str, fmt_args); |
| 8260 | } |
| 8261 | }; |
| 8262 | }; |
| 8299 | 8263 | |
| 8300 | | // LLVM backends that have no initialization functions. |
| 8301 | | .tce, |
| 8302 | | .tcele, |
| 8303 | | .r600, |
| 8304 | | .le32, |
| 8305 | | .le64, |
| 8306 | | .amdil, |
| 8307 | | .amdil64, |
| 8308 | | .hsail, |
| 8309 | | .hsail64, |
| 8310 | | .shave, |
| 8311 | | .spir, |
| 8312 | | .spir64, |
| 8313 | | .kalimba, |
| 8314 | | .renderscript32, |
| 8315 | | .renderscript64, |
| 8316 | | .dxil, |
| 8317 | | .loongarch32, |
| 8318 | | .loongarch64, |
| 8319 | | => {}, |
| 8264 | pub fn init(options: Options) Allocator.Error!Builder { |
| 8265 | var self = Builder{ |
| 8266 | .gpa = options.allocator, |
| 8267 | .strip = options.strip, |
| 8268 | |
| 8269 | .source_filename = .none, |
| 8270 | .data_layout = .none, |
| 8271 | .target_triple = .none, |
| 8272 | .module_asm = .{}, |
| 8273 | |
| 8274 | .string_map = .{}, |
| 8275 | .string_indices = .{}, |
| 8276 | .string_bytes = .{}, |
| 8277 | |
| 8278 | .types = .{}, |
| 8279 | .next_unnamed_type = @enumFromInt(0), |
| 8280 | .next_unique_type_id = .{}, |
| 8281 | .type_map = .{}, |
| 8282 | .type_items = .{}, |
| 8283 | .type_extra = .{}, |
| 8284 | |
| 8285 | .attributes = .{}, |
| 8286 | .attributes_map = .{}, |
| 8287 | .attributes_indices = .{}, |
| 8288 | .attributes_extra = .{}, |
| 8289 | |
| 8290 | .function_attributes_set = .{}, |
| 8291 | |
| 8292 | .globals = .{}, |
| 8293 | .next_unnamed_global = @enumFromInt(0), |
| 8294 | .next_replaced_global = .none, |
| 8295 | .next_unique_global_id = .{}, |
| 8296 | .aliases = .{}, |
| 8297 | .variables = .{}, |
| 8298 | .functions = .{}, |
| 8299 | |
| 8300 | .constant_map = .{}, |
| 8301 | .constant_items = .{}, |
| 8302 | .constant_extra = .{}, |
| 8303 | .constant_limbs = .{}, |
| 8304 | |
| 8305 | .metadata_map = .{}, |
| 8306 | .metadata_items = .{}, |
| 8307 | .metadata_extra = .{}, |
| 8308 | .metadata_limbs = .{}, |
| 8309 | .metadata_forward_references = .{}, |
| 8310 | .metadata_named = .{}, |
| 8311 | .metadata_string_map = .{}, |
| 8312 | .metadata_string_indices = .{}, |
| 8313 | .metadata_string_bytes = .{}, |
| 8314 | }; |
| 8315 | errdefer self.deinit(); |
| 8316 | |
| 8317 | try self.string_indices.append(self.gpa, 0); |
| 8318 | assert(try self.string("") == .empty); |
| 8319 | |
| 8320 | if (options.name.len > 0) self.source_filename = try self.string(options.name); |
| 8321 | |
| 8322 | if (options.triple.len > 0) { |
| 8323 | self.target_triple = try self.string(options.triple); |
| 8324 | } |
| 8325 | |
| 8326 | { |
| 8327 | const static_len = @typeInfo(Type).Enum.fields.len - 1; |
| 8328 | try self.type_map.ensureTotalCapacity(self.gpa, static_len); |
| 8329 | try self.type_items.ensureTotalCapacity(self.gpa, static_len); |
| 8330 | inline for (@typeInfo(Type.Simple).Enum.fields) |simple_field| { |
| 8331 | const result = self.getOrPutTypeNoExtraAssumeCapacity( |
| 8332 | .{ .tag = .simple, .data = simple_field.value }, |
| 8333 | ); |
| 8334 | assert(result.new and result.type == @field(Type, simple_field.name)); |
| 8335 | } |
| 8336 | inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits| |
| 8337 | assert(self.intTypeAssumeCapacity(bits) == |
| 8338 | @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); |
| 8339 | inline for (.{ 0, 4 }) |addr_space_index| { |
| 8340 | const addr_space: AddrSpace = @enumFromInt(addr_space_index); |
| 8341 | assert(self.ptrTypeAssumeCapacity(addr_space) == |
| 8342 | @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space}))); |
| 8343 | } |
| 8344 | } |
| 8320 | 8345 | |
| 8321 | | .spu_2 => unreachable, // LLVM does not support this backend |
| 8322 | | .spirv32 => unreachable, // LLVM does not support this backend |
| 8323 | | .spirv64 => unreachable, // LLVM does not support this backend |
| 8346 | { |
| 8347 | try self.attributes_indices.append(self.gpa, 0); |
| 8348 | assert(try self.attrs(&.{}) == .none); |
| 8349 | assert(try self.fnAttrs(&.{}) == .none); |
| 8324 | 8350 | } |
| 8351 | |
| 8352 | assert(try self.intConst(.i1, 0) == .false); |
| 8353 | assert(try self.intConst(.i1, 1) == .true); |
| 8354 | assert(try self.intConst(.i32, 0) == .@"0"); |
| 8355 | assert(try self.intConst(.i32, 1) == .@"1"); |
| 8356 | assert(try self.noneConst(.token) == .none); |
| 8357 | if (!self.strip) assert(try self.debugNone() == .none); |
| 8358 | |
| 8359 | try self.metadata_string_indices.append(self.gpa, 0); |
| 8360 | assert(try self.metadataString("") == .none); |
| 8361 | |
| 8362 | return self; |
| 8363 | } |
| 8364 | |
| 8365 | pub fn deinit(self: *Builder) void { |
| 8366 | self.module_asm.deinit(self.gpa); |
| 8367 | |
| 8368 | self.string_map.deinit(self.gpa); |
| 8369 | self.string_indices.deinit(self.gpa); |
| 8370 | self.string_bytes.deinit(self.gpa); |
| 8371 | |
| 8372 | self.types.deinit(self.gpa); |
| 8373 | self.next_unique_type_id.deinit(self.gpa); |
| 8374 | self.type_map.deinit(self.gpa); |
| 8375 | self.type_items.deinit(self.gpa); |
| 8376 | self.type_extra.deinit(self.gpa); |
| 8377 | |
| 8378 | self.attributes.deinit(self.gpa); |
| 8379 | self.attributes_map.deinit(self.gpa); |
| 8380 | self.attributes_indices.deinit(self.gpa); |
| 8381 | self.attributes_extra.deinit(self.gpa); |
| 8382 | |
| 8383 | self.function_attributes_set.deinit(self.gpa); |
| 8384 | |
| 8385 | self.globals.deinit(self.gpa); |
| 8386 | self.next_unique_global_id.deinit(self.gpa); |
| 8387 | self.aliases.deinit(self.gpa); |
| 8388 | self.variables.deinit(self.gpa); |
| 8389 | for (self.functions.items) |*function| function.deinit(self.gpa); |
| 8390 | self.functions.deinit(self.gpa); |
| 8391 | |
| 8392 | self.constant_map.deinit(self.gpa); |
| 8393 | self.constant_items.deinit(self.gpa); |
| 8394 | self.constant_extra.deinit(self.gpa); |
| 8395 | self.constant_limbs.deinit(self.gpa); |
| 8396 | |
| 8397 | self.metadata_map.deinit(self.gpa); |
| 8398 | self.metadata_items.deinit(self.gpa); |
| 8399 | self.metadata_extra.deinit(self.gpa); |
| 8400 | self.metadata_limbs.deinit(self.gpa); |
| 8401 | self.metadata_forward_references.deinit(self.gpa); |
| 8402 | self.metadata_named.deinit(self.gpa); |
| 8403 | |
| 8404 | self.metadata_string_map.deinit(self.gpa); |
| 8405 | self.metadata_string_indices.deinit(self.gpa); |
| 8406 | self.metadata_string_bytes.deinit(self.gpa); |
| 8407 | |
| 8408 | self.* = undefined; |
| 8325 | 8409 | } |
| 8326 | 8410 | |
| 8327 | 8411 | pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { |
| ... | ... | @@ -8336,24 +8420,25 @@ pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { |
| 8336 | 8420 | pub fn finishModuleAsm(self: *Builder) Allocator.Error!void { |
| 8337 | 8421 | if (self.module_asm.getLastOrNull()) |last| if (last != '\n') |
| 8338 | 8422 | try self.module_asm.append(self.gpa, '\n'); |
| 8339 | | if (self.useLibLlvm()) |
| 8340 | | self.llvm.module.?.setModuleInlineAsm(self.module_asm.items.ptr, self.module_asm.items.len); |
| 8341 | 8423 | } |
| 8342 | 8424 | |
| 8343 | 8425 | pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String { |
| 8344 | | try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1); |
| 8426 | try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len); |
| 8345 | 8427 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 8346 | 8428 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8347 | 8429 | |
| 8348 | 8430 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); |
| 8349 | 8431 | if (!gop.found_existing) { |
| 8350 | 8432 | self.string_bytes.appendSliceAssumeCapacity(bytes); |
| 8351 | | self.string_bytes.appendAssumeCapacity(0); |
| 8352 | 8433 | self.string_indices.appendAssumeCapacity(@intCast(self.string_bytes.items.len)); |
| 8353 | 8434 | } |
| 8354 | 8435 | return String.fromIndex(gop.index); |
| 8355 | 8436 | } |
| 8356 | 8437 | |
| 8438 | pub fn stringNull(self: *Builder, bytes: [:0]const u8) Allocator.Error!String { |
| 8439 | return self.string(bytes[0 .. bytes.len + 1]); |
| 8440 | } |
| 8441 | |
| 8357 | 8442 | pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String { |
| 8358 | 8443 | return String.fromIndex( |
| 8359 | 8444 | self.string_map.getIndexAdapted(bytes, String.Adapter{ .builder = self }) orelse return null, |
| ... | ... | @@ -8362,16 +8447,25 @@ pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String { |
| 8362 | 8447 | |
| 8363 | 8448 | pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!String { |
| 8364 | 8449 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8365 | | try self.string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str ++ .{0}, fmt_args))); |
| 8450 | try self.string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args))); |
| 8366 | 8451 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 8367 | 8452 | return self.fmtAssumeCapacity(fmt_str, fmt_args); |
| 8368 | 8453 | } |
| 8369 | 8454 | |
| 8370 | 8455 | pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String { |
| 8371 | | const start = self.string_bytes.items.len; |
| 8372 | | self.string_bytes.writer(self.gpa).print(fmt_str ++ .{0}, fmt_args) catch unreachable; |
| 8373 | | const bytes: []const u8 = self.string_bytes.items[start .. self.string_bytes.items.len - 1]; |
| 8456 | self.string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable; |
| 8457 | return self.trailingStringAssumeCapacity(); |
| 8458 | } |
| 8459 | |
| 8460 | pub fn trailingString(self: *Builder) Allocator.Error!String { |
| 8461 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 8462 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8463 | return self.trailingStringAssumeCapacity(); |
| 8464 | } |
| 8374 | 8465 | |
| 8466 | pub fn trailingStringAssumeCapacity(self: *Builder) String { |
| 8467 | const start = self.string_indices.getLast(); |
| 8468 | const bytes: []const u8 = self.string_bytes.items[start..]; |
| 8375 | 8469 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); |
| 8376 | 8470 | if (gop.found_existing) { |
| 8377 | 8471 | self.string_bytes.shrinkRetainingCapacity(start); |
| ... | ... | @@ -8435,7 +8529,7 @@ pub fn structType( |
| 8435 | 8529 | pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type { |
| 8436 | 8530 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8437 | 8531 | if (name.slice(self)) |id| { |
| 8438 | | const count: usize = comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)}); |
| 8532 | const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); |
| 8439 | 8533 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); |
| 8440 | 8534 | } |
| 8441 | 8535 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | ... | @@ -8449,98 +8543,17 @@ pub fn namedTypeSetBody( |
| 8449 | 8543 | self: *Builder, |
| 8450 | 8544 | named_type: Type, |
| 8451 | 8545 | body_type: Type, |
| 8452 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!void { |
| 8546 | ) void { |
| 8453 | 8547 | const named_item = self.type_items.items[@intFromEnum(named_type)]; |
| 8454 | 8548 | self.type_extra.items[named_item.data + std.meta.fieldIndex(Type.NamedStructure, "body").?] = |
| 8455 | 8549 | @intFromEnum(body_type); |
| 8456 | | if (self.useLibLlvm()) { |
| 8457 | | const body_item = self.type_items.items[@intFromEnum(body_type)]; |
| 8458 | | var body_extra = self.typeExtraDataTrail(Type.Structure, body_item.data); |
| 8459 | | const body_fields = body_extra.trail.next(body_extra.data.fields_len, Type, self); |
| 8460 | | const llvm_fields = try self.gpa.alloc(*llvm.Type, body_fields.len); |
| 8461 | | defer self.gpa.free(llvm_fields); |
| 8462 | | for (llvm_fields, body_fields) |*llvm_field, body_field| llvm_field.* = body_field.toLlvm(self); |
| 8463 | | self.llvm.types.items[@intFromEnum(named_type)].structSetBody( |
| 8464 | | llvm_fields.ptr, |
| 8465 | | @intCast(llvm_fields.len), |
| 8466 | | switch (body_item.tag) { |
| 8467 | | .structure => .False, |
| 8468 | | .packed_structure => .True, |
| 8469 | | else => unreachable, |
| 8470 | | }, |
| 8471 | | ); |
| 8472 | | } |
| 8473 | 8550 | } |
| 8474 | 8551 | |
| 8475 | 8552 | pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Index { |
| 8476 | 8553 | try self.attributes.ensureUnusedCapacity(self.gpa, 1); |
| 8477 | | if (self.useLibLlvm()) try self.llvm.attributes.ensureUnusedCapacity(self.gpa, 1); |
| 8478 | 8554 | |
| 8479 | 8555 | const gop = self.attributes.getOrPutAssumeCapacity(attribute.toStorage()); |
| 8480 | | if (!gop.found_existing) { |
| 8481 | | gop.value_ptr.* = {}; |
| 8482 | | if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) { |
| 8483 | | else => llvm_attr: { |
| 8484 | | const llvm_kind_id = attribute.getKind().toLlvm(self); |
| 8485 | | if (llvm_kind_id.* == 0) { |
| 8486 | | const name = @tagName(attribute); |
| 8487 | | llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len); |
| 8488 | | assert(llvm_kind_id.* != 0); |
| 8489 | | } |
| 8490 | | break :llvm_attr switch (attribute) { |
| 8491 | | else => switch (attribute) { |
| 8492 | | inline else => |value| self.llvm.context.createEnumAttribute( |
| 8493 | | llvm_kind_id.*, |
| 8494 | | switch (@TypeOf(value)) { |
| 8495 | | void => 0, |
| 8496 | | u32 => value, |
| 8497 | | Attribute.FpClass, |
| 8498 | | Attribute.AllocKind, |
| 8499 | | Attribute.Memory, |
| 8500 | | => @as(u32, @bitCast(value)), |
| 8501 | | Alignment => value.toByteUnits() orelse 0, |
| 8502 | | Attribute.AllocSize, |
| 8503 | | Attribute.VScaleRange, |
| 8504 | | => @bitCast(value.toLlvm()), |
| 8505 | | Attribute.UwTable => @intFromEnum(value), |
| 8506 | | else => @compileError( |
| 8507 | | "bad payload type: " ++ @typeName(@TypeOf(value)), |
| 8508 | | ), |
| 8509 | | }, |
| 8510 | | ), |
| 8511 | | .byval, |
| 8512 | | .byref, |
| 8513 | | .preallocated, |
| 8514 | | .inalloca, |
| 8515 | | .sret, |
| 8516 | | .elementtype, |
| 8517 | | .string, |
| 8518 | | .none, |
| 8519 | | => unreachable, |
| 8520 | | }, |
| 8521 | | .byval, |
| 8522 | | .byref, |
| 8523 | | .preallocated, |
| 8524 | | .inalloca, |
| 8525 | | .sret, |
| 8526 | | .elementtype, |
| 8527 | | => |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)), |
| 8528 | | .string, .none => unreachable, |
| 8529 | | }; |
| 8530 | | }, |
| 8531 | | .string => |string_attr| llvm_attr: { |
| 8532 | | const kind = string_attr.kind.slice(self).?; |
| 8533 | | const value = string_attr.value.slice(self).?; |
| 8534 | | break :llvm_attr self.llvm.context.createStringAttribute( |
| 8535 | | kind.ptr, |
| 8536 | | @intCast(kind.len), |
| 8537 | | value.ptr, |
| 8538 | | @intCast(value.len), |
| 8539 | | ); |
| 8540 | | }, |
| 8541 | | .none => unreachable, |
| 8542 | | }); |
| 8543 | | } |
| 8556 | if (!gop.found_existing) gop.value_ptr.* = {}; |
| 8544 | 8557 | return @enumFromInt(gop.index); |
| 8545 | 8558 | } |
| 8546 | 8559 | |
| ... | ... | @@ -8557,12 +8570,16 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr |
| 8557 | 8570 | } |
| 8558 | 8571 | |
| 8559 | 8572 | pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes { |
| 8560 | | return @enumFromInt(try self.attrGeneric(@ptrCast( |
| 8573 | try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1); |
| 8574 | const function_attributes: FunctionAttributes = @enumFromInt(try self.attrGeneric(@ptrCast( |
| 8561 | 8575 | fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last| |
| 8562 | 8576 | last + 1 |
| 8563 | 8577 | else |
| 8564 | 8578 | 0], |
| 8565 | 8579 | ))); |
| 8580 | |
| 8581 | _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes); |
| 8582 | return function_attributes; |
| 8566 | 8583 | } |
| 8567 | 8584 | |
| 8568 | 8585 | pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index { |
| ... | ... | @@ -8586,7 +8603,6 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo |
| 8586 | 8603 | global_gop.value_ptr.* = global; |
| 8587 | 8604 | const global_index: Global.Index = @enumFromInt(global_gop.index); |
| 8588 | 8605 | global_index.updateDsoLocal(self); |
| 8589 | | global_index.updateName(self); |
| 8590 | 8606 | return global_index; |
| 8591 | 8607 | } |
| 8592 | 8608 | |
| ... | ... | @@ -8622,12 +8638,6 @@ pub fn addAliasAssumeCapacity( |
| 8622 | 8638 | addr_space: AddrSpace, |
| 8623 | 8639 | aliasee: Constant, |
| 8624 | 8640 | ) Alias.Index { |
| 8625 | | if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(self.llvm.module.?.addAlias( |
| 8626 | | ty.toLlvm(self), |
| 8627 | | @intFromEnum(addr_space), |
| 8628 | | aliasee.toLlvm(self), |
| 8629 | | name.slice(self).?, |
| 8630 | | )); |
| 8631 | 8641 | const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len); |
| 8632 | 8642 | self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ |
| 8633 | 8643 | .addr_space = addr_space, |
| ... | ... | @@ -8656,13 +8666,6 @@ pub fn addVariableAssumeCapacity( |
| 8656 | 8666 | name: String, |
| 8657 | 8667 | addr_space: AddrSpace, |
| 8658 | 8668 | ) Variable.Index { |
| 8659 | | if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity( |
| 8660 | | self.llvm.module.?.addGlobalInAddressSpace( |
| 8661 | | ty.toLlvm(self), |
| 8662 | | name.slice(self).?, |
| 8663 | | @intFromEnum(addr_space), |
| 8664 | | ), |
| 8665 | | ); |
| 8666 | 8669 | const variable_index: Variable.Index = @enumFromInt(self.variables.items.len); |
| 8667 | 8670 | self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ |
| 8668 | 8671 | .addr_space = addr_space, |
| ... | ... | @@ -8692,13 +8695,6 @@ pub fn addFunctionAssumeCapacity( |
| 8692 | 8695 | addr_space: AddrSpace, |
| 8693 | 8696 | ) Function.Index { |
| 8694 | 8697 | assert(ty.isFunction(self)); |
| 8695 | | if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity( |
| 8696 | | self.llvm.module.?.addFunctionInAddressSpace( |
| 8697 | | name.slice(self).?, |
| 8698 | | ty.toLlvm(self), |
| 8699 | | @intFromEnum(addr_space), |
| 8700 | | ), |
| 8701 | | ); |
| 8702 | 8698 | const function_index: Function.Index = @enumFromInt(self.functions.items.len); |
| 8703 | 8699 | self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ |
| 8704 | 8700 | .addr_space = addr_space, |
| ... | ... | @@ -8714,7 +8710,6 @@ pub fn getIntrinsic( |
| 8714 | 8710 | overload: []const Type, |
| 8715 | 8711 | ) Allocator.Error!Function.Index { |
| 8716 | 8712 | const ExpectedContents = extern union { |
| 8717 | | name: [expected_intrinsic_name_len]u8, |
| 8718 | 8713 | attrs: extern struct { |
| 8719 | 8714 | params: [expected_args_len]Type, |
| 8720 | 8715 | fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes, |
| ... | ... | @@ -8727,12 +8722,10 @@ pub fn getIntrinsic( |
| 8727 | 8722 | const allocator = stack.get(); |
| 8728 | 8723 | |
| 8729 | 8724 | const name = name: { |
| 8730 | | var buffer = std.ArrayList(u8).init(allocator); |
| 8731 | | defer buffer.deinit(); |
| 8732 | | |
| 8733 | | try buffer.writer().print("llvm.{s}", .{@tagName(id)}); |
| 8734 | | for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)}); |
| 8735 | | break :name try self.string(buffer.items); |
| 8725 | const writer = self.string_bytes.writer(self.gpa); |
| 8726 | try writer.print("llvm.{s}", .{@tagName(id)}); |
| 8727 | for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)}); |
| 8728 | break :name try self.trailingString(); |
| 8736 | 8729 | }; |
| 8737 | 8730 | if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; |
| 8738 | 8731 | |
| ... | ... | @@ -8826,7 +8819,6 @@ pub fn bigIntConst(self: *Builder, ty: Type, value: std.math.big.int.Const) Allo |
| 8826 | 8819 | try self.constant_map.ensureUnusedCapacity(self.gpa, 1); |
| 8827 | 8820 | try self.constant_items.ensureUnusedCapacity(self.gpa, 1); |
| 8828 | 8821 | try self.constant_limbs.ensureUnusedCapacity(self.gpa, Constant.Integer.limbs + value.limbs.len); |
| 8829 | | if (self.useLibLlvm()) try self.llvm.constants.ensureUnusedCapacity(self.gpa, 1); |
| 8830 | 8822 | return self.bigIntConstAssumeCapacity(ty, value); |
| 8831 | 8823 | } |
| 8832 | 8824 | |
| ... | ... | @@ -8977,16 +8969,6 @@ pub fn stringValue(self: *Builder, val: String) Allocator.Error!Value { |
| 8977 | 8969 | return (try self.stringConst(val)).toValue(); |
| 8978 | 8970 | } |
| 8979 | 8971 | |
| 8980 | | pub fn stringNullConst(self: *Builder, val: String) Allocator.Error!Constant { |
| 8981 | | try self.ensureUnusedTypeCapacity(1, Type.Array, 0); |
| 8982 | | try self.ensureUnusedConstantCapacity(1, NoExtra, 0); |
| 8983 | | return self.stringNullConstAssumeCapacity(val); |
| 8984 | | } |
| 8985 | | |
| 8986 | | pub fn stringNullValue(self: *Builder, val: String) Allocator.Error!Value { |
| 8987 | | return (try self.stringNullConst(val)).toValue(); |
| 8988 | | } |
| 8989 | | |
| 8990 | 8972 | pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.Error!Constant { |
| 8991 | 8973 | try self.ensureUnusedConstantCapacity(1, Constant.Aggregate, vals.len); |
| 8992 | 8974 | return self.vectorConstAssumeCapacity(ty, vals); |
| ... | ... | @@ -9244,72 +9226,20 @@ pub fn asmValue( |
| 9244 | 9226 | return (try self.asmConst(ty, info, assembly, constraints)).toValue(); |
| 9245 | 9227 | } |
| 9246 | 9228 | |
| 9247 | | pub fn verify(self: *Builder) error{}!bool { |
| 9248 | | if (self.useLibLlvm()) { |
| 9249 | | var error_message: [*:0]const u8 = undefined; |
| 9250 | | // verifyModule always allocs the error_message even if there is no error |
| 9251 | | defer llvm.disposeMessage(error_message); |
| 9252 | | |
| 9253 | | if (self.llvm.module.?.verify(.ReturnStatus, &error_message).toBool()) { |
| 9254 | | log.err("failed verification of LLVM module:\n{s}\n", .{error_message}); |
| 9255 | | return false; |
| 9256 | | } |
| 9257 | | } |
| 9258 | | return true; |
| 9259 | | } |
| 9260 | | |
| 9261 | | pub fn writeBitcodeToFile(self: *Builder, path: []const u8) Allocator.Error!bool { |
| 9262 | | const path_z = try self.gpa.dupeZ(u8, path); |
| 9263 | | defer self.gpa.free(path_z); |
| 9264 | | return self.writeBitcodeToFileZ(path_z); |
| 9265 | | } |
| 9266 | | |
| 9267 | | pub fn writeBitcodeToFileZ(self: *Builder, path: [*:0]const u8) bool { |
| 9268 | | if (self.useLibLlvm()) { |
| 9269 | | const error_code = self.llvm.module.?.writeBitcodeToFile(path); |
| 9270 | | if (error_code != 0) { |
| 9271 | | log.err("failed dumping LLVM module to \"{s}\": {d}", .{ path, error_code }); |
| 9272 | | return false; |
| 9273 | | } |
| 9274 | | } else { |
| 9275 | | log.err("writing bitcode without libllvm not implemented", .{}); |
| 9276 | | return false; |
| 9277 | | } |
| 9278 | | return true; |
| 9279 | | } |
| 9280 | | |
| 9281 | 9229 | pub fn dump(self: *Builder) void { |
| 9282 | | if (self.useLibLlvm()) |
| 9283 | | self.llvm.module.?.dump() |
| 9284 | | else |
| 9285 | | self.print(std.io.getStdErr().writer()) catch {}; |
| 9230 | self.print(std.io.getStdErr().writer()) catch {}; |
| 9286 | 9231 | } |
| 9287 | 9232 | |
| 9288 | 9233 | pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool { |
| 9289 | | const path_z = try self.gpa.dupeZ(u8, path); |
| 9290 | | defer self.gpa.free(path_z); |
| 9291 | | return self.printToFileZ(path_z); |
| 9292 | | } |
| 9293 | | |
| 9294 | | pub fn printToFileZ(self: *Builder, path: [*:0]const u8) bool { |
| 9295 | | if (self.useLibLlvm()) { |
| 9296 | | var error_message: [*:0]const u8 = undefined; |
| 9297 | | if (self.llvm.module.?.printModuleToFile(path, &error_message).toBool()) { |
| 9298 | | defer llvm.disposeMessage(error_message); |
| 9299 | | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, error_message }); |
| 9300 | | return false; |
| 9301 | | } |
| 9302 | | } else { |
| 9303 | | var file = std.fs.cwd().createFileZ(path, .{}) catch |err| { |
| 9304 | | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); |
| 9305 | | return false; |
| 9306 | | }; |
| 9307 | | defer file.close(); |
| 9308 | | self.print(file.writer()) catch |err| { |
| 9309 | | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); |
| 9310 | | return false; |
| 9311 | | }; |
| 9312 | | } |
| 9234 | var file = std.fs.cwd().createFile(path, .{}) catch |err| { |
| 9235 | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); |
| 9236 | return false; |
| 9237 | }; |
| 9238 | defer file.close(); |
| 9239 | self.print(file.writer()) catch |err| { |
| 9240 | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); |
| 9241 | return false; |
| 9242 | }; |
| 9313 | 9243 | return true; |
| 9314 | 9244 | } |
| 9315 | 9245 | |
| ... | ... | @@ -9324,9 +9254,11 @@ pub fn printUnbuffered( |
| 9324 | 9254 | writer: anytype, |
| 9325 | 9255 | ) (@TypeOf(writer).Error || Allocator.Error)!void { |
| 9326 | 9256 | var need_newline = false; |
| 9257 | var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined }; |
| 9258 | defer metadata_formatter.map.deinit(self.gpa); |
| 9327 | 9259 | |
| 9328 | 9260 | if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) { |
| 9329 | | if (need_newline) try writer.writeByte('\n'); |
| 9261 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9330 | 9262 | if (self.source_filename != .none) try writer.print( |
| 9331 | 9263 | \\; ModuleID = '{s}' |
| 9332 | 9264 | \\source_filename = {"} |
| ... | ... | @@ -9340,40 +9272,40 @@ pub fn printUnbuffered( |
| 9340 | 9272 | \\target triple = {"} |
| 9341 | 9273 | \\ |
| 9342 | 9274 | , .{self.target_triple.fmt(self)}); |
| 9343 | | need_newline = true; |
| 9344 | 9275 | } |
| 9345 | 9276 | |
| 9346 | 9277 | if (self.module_asm.items.len > 0) { |
| 9347 | | if (need_newline) try writer.writeByte('\n'); |
| 9278 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9348 | 9279 | var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n'); |
| 9349 | 9280 | while (line_it.next()) |line| { |
| 9350 | 9281 | try writer.writeAll("module asm "); |
| 9351 | 9282 | try printEscapedString(line, .always_quote, writer); |
| 9352 | 9283 | try writer.writeByte('\n'); |
| 9353 | 9284 | } |
| 9354 | | need_newline = true; |
| 9355 | 9285 | } |
| 9356 | 9286 | |
| 9357 | 9287 | if (self.types.count() > 0) { |
| 9358 | | if (need_newline) try writer.writeByte('\n'); |
| 9288 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9359 | 9289 | for (self.types.keys(), self.types.values()) |id, ty| try writer.print( |
| 9360 | 9290 | \\%{} = type {} |
| 9361 | 9291 | \\ |
| 9362 | 9292 | , .{ id.fmt(self), ty.fmt(self) }); |
| 9363 | | need_newline = true; |
| 9364 | 9293 | } |
| 9365 | 9294 | |
| 9366 | 9295 | if (self.variables.items.len > 0) { |
| 9367 | | if (need_newline) try writer.writeByte('\n'); |
| 9296 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9368 | 9297 | for (self.variables.items) |variable| { |
| 9369 | 9298 | if (variable.global.getReplacement(self) != .none) continue; |
| 9370 | 9299 | const global = variable.global.ptrConst(self); |
| 9300 | metadata_formatter.need_comma = true; |
| 9301 | defer metadata_formatter.need_comma = undefined; |
| 9371 | 9302 | try writer.print( |
| 9372 | | \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, } |
| 9303 | \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{} |
| 9373 | 9304 | \\ |
| 9374 | 9305 | , .{ |
| 9375 | 9306 | variable.global.fmt(self), |
| 9376 | | global.linkage, |
| 9307 | Linkage.fmtOptional(if (global.linkage == .external and |
| 9308 | variable.init != .no_init) null else global.linkage), |
| 9377 | 9309 | global.preemption, |
| 9378 | 9310 | global.visibility, |
| 9379 | 9311 | global.dll_storage_class, |
| ... | ... | @@ -9385,18 +9317,20 @@ pub fn printUnbuffered( |
| 9385 | 9317 | global.type.fmt(self), |
| 9386 | 9318 | variable.init.fmt(self), |
| 9387 | 9319 | variable.alignment, |
| 9320 | try metadata_formatter.fmt("!dbg ", global.dbg), |
| 9388 | 9321 | }); |
| 9389 | 9322 | } |
| 9390 | | need_newline = true; |
| 9391 | 9323 | } |
| 9392 | 9324 | |
| 9393 | 9325 | if (self.aliases.items.len > 0) { |
| 9394 | | if (need_newline) try writer.writeByte('\n'); |
| 9326 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9395 | 9327 | for (self.aliases.items) |alias| { |
| 9396 | 9328 | if (alias.global.getReplacement(self) != .none) continue; |
| 9397 | 9329 | const global = alias.global.ptrConst(self); |
| 9330 | metadata_formatter.need_comma = true; |
| 9331 | defer metadata_formatter.need_comma = undefined; |
| 9398 | 9332 | try writer.print( |
| 9399 | | \\{} ={}{}{}{}{ }{} alias {%}, {%} |
| 9333 | \\{} ={}{}{}{}{ }{} alias {%}, {%}{} |
| 9400 | 9334 | \\ |
| 9401 | 9335 | , .{ |
| 9402 | 9336 | alias.global.fmt(self), |
| ... | ... | @@ -9408,9 +9342,9 @@ pub fn printUnbuffered( |
| 9408 | 9342 | global.unnamed_addr, |
| 9409 | 9343 | global.type.fmt(self), |
| 9410 | 9344 | alias.aliasee.fmt(self), |
| 9345 | try metadata_formatter.fmt("!dbg ", global.dbg), |
| 9411 | 9346 | }); |
| 9412 | 9347 | } |
| 9413 | | need_newline = true; |
| 9414 | 9348 | } |
| 9415 | 9349 | |
| 9416 | 9350 | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; |
| ... | ... | @@ -9418,7 +9352,7 @@ pub fn printUnbuffered( |
| 9418 | 9352 | |
| 9419 | 9353 | for (0.., self.functions.items) |function_i, function| { |
| 9420 | 9354 | if (function.global.getReplacement(self) != .none) continue; |
| 9421 | | if (need_newline) try writer.writeByte('\n'); |
| 9355 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9422 | 9356 | const function_index: Function.Index = @enumFromInt(function_i); |
| 9423 | 9357 | const global = function.global.ptrConst(self); |
| 9424 | 9358 | const params_len = global.type.functionParameters(self).len; |
| ... | ... | @@ -9464,13 +9398,23 @@ pub fn printUnbuffered( |
| 9464 | 9398 | if (function_attributes != .none) try writer.print(" #{d}", .{ |
| 9465 | 9399 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, |
| 9466 | 9400 | }); |
| 9467 | | try writer.print("{ }", .{function.alignment}); |
| 9401 | { |
| 9402 | metadata_formatter.need_comma = false; |
| 9403 | defer metadata_formatter.need_comma = undefined; |
| 9404 | try writer.print("{ }{}", .{ |
| 9405 | function.alignment, |
| 9406 | try metadata_formatter.fmt(" !dbg ", global.dbg), |
| 9407 | }); |
| 9408 | } |
| 9468 | 9409 | if (function.instructions.len > 0) { |
| 9469 | 9410 | var block_incoming_len: u32 = undefined; |
| 9470 | 9411 | try writer.writeAll(" {\n"); |
| 9412 | var dbg: Metadata = .none; |
| 9471 | 9413 | for (params_len..function.instructions.len) |instruction_i| { |
| 9472 | 9414 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); |
| 9473 | 9415 | const instruction = function.instructions.get(@intFromEnum(instruction_index)); |
| 9416 | if (function.debug_locations.get(instruction_index)) |debug_location| |
| 9417 | dbg = debug_location; |
| 9474 | 9418 | switch (instruction.tag) { |
| 9475 | 9419 | .add, |
| 9476 | 9420 | .@"add nsw", |
| ... | ... | @@ -9555,7 +9499,7 @@ pub fn printUnbuffered( |
| 9555 | 9499 | .xor, |
| 9556 | 9500 | => |tag| { |
| 9557 | 9501 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); |
| 9558 | | try writer.print(" %{} = {s} {%}, {}\n", .{ |
| 9502 | try writer.print(" %{} = {s} {%}, {}", .{ |
| 9559 | 9503 | instruction_index.name(&function).fmt(self), |
| 9560 | 9504 | @tagName(tag), |
| 9561 | 9505 | extra.lhs.fmt(function_index, self), |
| ... | ... | @@ -9577,7 +9521,7 @@ pub fn printUnbuffered( |
| 9577 | 9521 | .zext, |
| 9578 | 9522 | => |tag| { |
| 9579 | 9523 | const extra = function.extraData(Function.Instruction.Cast, instruction.data); |
| 9580 | | try writer.print(" %{} = {s} {%} to {%}\n", .{ |
| 9524 | try writer.print(" %{} = {s} {%} to {%}", .{ |
| 9581 | 9525 | instruction_index.name(&function).fmt(self), |
| 9582 | 9526 | @tagName(tag), |
| 9583 | 9527 | extra.val.fmt(function_index, self), |
| ... | ... | @@ -9588,11 +9532,14 @@ pub fn printUnbuffered( |
| 9588 | 9532 | .@"alloca inalloca", |
| 9589 | 9533 | => |tag| { |
| 9590 | 9534 | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); |
| 9591 | | try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{ |
| 9535 | try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{ |
| 9592 | 9536 | instruction_index.name(&function).fmt(self), |
| 9593 | 9537 | @tagName(tag), |
| 9594 | 9538 | extra.type.fmt(self), |
| 9595 | | extra.len.fmt(function_index, self), |
| 9539 | Value.fmt(switch (extra.len) { |
| 9540 | .@"1" => .none, |
| 9541 | else => extra.len, |
| 9542 | }, function_index, self), |
| 9596 | 9543 | extra.info.alignment, |
| 9597 | 9544 | extra.info.addr_space, |
| 9598 | 9545 | }); |
| ... | ... | @@ -9601,7 +9548,7 @@ pub fn printUnbuffered( |
| 9601 | 9548 | .atomicrmw => |tag| { |
| 9602 | 9549 | const extra = |
| 9603 | 9550 | function.extraData(Function.Instruction.AtomicRmw, instruction.data); |
| 9604 | | try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{ |
| 9551 | try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{ |
| 9605 | 9552 | instruction_index.name(&function).fmt(self), |
| 9606 | 9553 | @tagName(tag), |
| 9607 | 9554 | extra.info.access_kind, |
| ... | ... | @@ -9619,16 +9566,17 @@ pub fn printUnbuffered( |
| 9619 | 9566 | if (@intFromEnum(instruction_index) > params_len) |
| 9620 | 9567 | try writer.writeByte('\n'); |
| 9621 | 9568 | try writer.print("{}:\n", .{name.fmt(self)}); |
| 9569 | continue; |
| 9622 | 9570 | }, |
| 9623 | 9571 | .br => |tag| { |
| 9624 | 9572 | const target: Function.Block.Index = @enumFromInt(instruction.data); |
| 9625 | | try writer.print(" {s} {%}\n", .{ |
| 9573 | try writer.print(" {s} {%}", .{ |
| 9626 | 9574 | @tagName(tag), target.toInst(&function).fmt(function_index, self), |
| 9627 | 9575 | }); |
| 9628 | 9576 | }, |
| 9629 | 9577 | .br_cond => { |
| 9630 | 9578 | const extra = function.extraData(Function.Instruction.BrCond, instruction.data); |
| 9631 | | try writer.print(" br {%}, {%}, {%}\n", .{ |
| 9579 | try writer.print(" br {%}, {%}, {%}", .{ |
| 9632 | 9580 | extra.cond.fmt(function_index, self), |
| 9633 | 9581 | extra.then.toInst(&function).fmt(function_index, self), |
| 9634 | 9582 | extra.@"else".toInst(&function).fmt(function_index, self), |
| ... | ... | @@ -9668,10 +9616,12 @@ pub fn printUnbuffered( |
| 9668 | 9616 | }); |
| 9669 | 9617 | for (0.., args) |arg_index, arg| { |
| 9670 | 9618 | if (arg_index > 0) try writer.writeAll(", "); |
| 9671 | | try writer.print("{%}{} {}", .{ |
| 9619 | metadata_formatter.need_comma = false; |
| 9620 | defer metadata_formatter.need_comma = undefined; |
| 9621 | try writer.print("{%}{}{}", .{ |
| 9672 | 9622 | arg.typeOf(function_index, self).fmt(self), |
| 9673 | 9623 | extra.data.attributes.param(arg_index, self).fmt(self), |
| 9674 | | arg.fmt(function_index, self), |
| 9624 | try metadata_formatter.fmtLocal(" ", arg, function_index), |
| 9675 | 9625 | }); |
| 9676 | 9626 | } |
| 9677 | 9627 | try writer.writeByte(')'); |
| ... | ... | @@ -9683,14 +9633,13 @@ pub fn printUnbuffered( |
| 9683 | 9633 | {}, |
| 9684 | 9634 | )).index, |
| 9685 | 9635 | }); |
| 9686 | | try writer.writeByte('\n'); |
| 9687 | 9636 | }, |
| 9688 | 9637 | .cmpxchg, |
| 9689 | 9638 | .@"cmpxchg weak", |
| 9690 | 9639 | => |tag| { |
| 9691 | 9640 | const extra = |
| 9692 | 9641 | function.extraData(Function.Instruction.CmpXchg, instruction.data); |
| 9693 | | try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{ |
| 9642 | try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{ |
| 9694 | 9643 | instruction_index.name(&function).fmt(self), |
| 9695 | 9644 | @tagName(tag), |
| 9696 | 9645 | extra.info.access_kind, |
| ... | ... | @@ -9706,7 +9655,7 @@ pub fn printUnbuffered( |
| 9706 | 9655 | .extractelement => |tag| { |
| 9707 | 9656 | const extra = |
| 9708 | 9657 | function.extraData(Function.Instruction.ExtractElement, instruction.data); |
| 9709 | | try writer.print(" %{} = {s} {%}, {%}\n", .{ |
| 9658 | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 9710 | 9659 | instruction_index.name(&function).fmt(self), |
| 9711 | 9660 | @tagName(tag), |
| 9712 | 9661 | extra.val.fmt(function_index, self), |
| ... | ... | @@ -9725,7 +9674,6 @@ pub fn printUnbuffered( |
| 9725 | 9674 | extra.data.val.fmt(function_index, self), |
| 9726 | 9675 | }); |
| 9727 | 9676 | for (indices) |index| try writer.print(", {d}", .{index}); |
| 9728 | | try writer.writeByte('\n'); |
| 9729 | 9677 | }, |
| 9730 | 9678 | .fence => |tag| { |
| 9731 | 9679 | const info: MemoryAccessInfo = @bitCast(instruction.data); |
| ... | ... | @@ -9739,7 +9687,7 @@ pub fn printUnbuffered( |
| 9739 | 9687 | .@"fneg fast", |
| 9740 | 9688 | => |tag| { |
| 9741 | 9689 | const val: Value = @enumFromInt(instruction.data); |
| 9742 | | try writer.print(" %{} = {s} {%}\n", .{ |
| 9690 | try writer.print(" %{} = {s} {%}", .{ |
| 9743 | 9691 | instruction_index.name(&function).fmt(self), |
| 9744 | 9692 | @tagName(tag), |
| 9745 | 9693 | val.fmt(function_index, self), |
| ... | ... | @@ -9762,12 +9710,11 @@ pub fn printUnbuffered( |
| 9762 | 9710 | for (indices) |index| try writer.print(", {%}", .{ |
| 9763 | 9711 | index.fmt(function_index, self), |
| 9764 | 9712 | }); |
| 9765 | | try writer.writeByte('\n'); |
| 9766 | 9713 | }, |
| 9767 | 9714 | .insertelement => |tag| { |
| 9768 | 9715 | const extra = |
| 9769 | 9716 | function.extraData(Function.Instruction.InsertElement, instruction.data); |
| 9770 | | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 9717 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ |
| 9771 | 9718 | instruction_index.name(&function).fmt(self), |
| 9772 | 9719 | @tagName(tag), |
| 9773 | 9720 | extra.val.fmt(function_index, self), |
| ... | ... | @@ -9786,13 +9733,12 @@ pub fn printUnbuffered( |
| 9786 | 9733 | extra.data.elem.fmt(function_index, self), |
| 9787 | 9734 | }); |
| 9788 | 9735 | for (indices) |index| try writer.print(", {d}", .{index}); |
| 9789 | | try writer.writeByte('\n'); |
| 9790 | 9736 | }, |
| 9791 | 9737 | .load, |
| 9792 | 9738 | .@"load atomic", |
| 9793 | 9739 | => |tag| { |
| 9794 | 9740 | const extra = function.extraData(Function.Instruction.Load, instruction.data); |
| 9795 | | try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{ |
| 9741 | try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{ |
| 9796 | 9742 | instruction_index.name(&function).fmt(self), |
| 9797 | 9743 | @tagName(tag), |
| 9798 | 9744 | extra.info.access_kind, |
| ... | ... | @@ -9822,23 +9768,22 @@ pub fn printUnbuffered( |
| 9822 | 9768 | incoming_block.toInst(&function).fmt(function_index, self), |
| 9823 | 9769 | }); |
| 9824 | 9770 | } |
| 9825 | | try writer.writeByte('\n'); |
| 9826 | 9771 | }, |
| 9827 | 9772 | .ret => |tag| { |
| 9828 | 9773 | const val: Value = @enumFromInt(instruction.data); |
| 9829 | | try writer.print(" {s} {%}\n", .{ |
| 9774 | try writer.print(" {s} {%}", .{ |
| 9830 | 9775 | @tagName(tag), |
| 9831 | 9776 | val.fmt(function_index, self), |
| 9832 | 9777 | }); |
| 9833 | 9778 | }, |
| 9834 | 9779 | .@"ret void", |
| 9835 | 9780 | .@"unreachable", |
| 9836 | | => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), |
| 9781 | => |tag| try writer.print(" {s}", .{@tagName(tag)}), |
| 9837 | 9782 | .select, |
| 9838 | 9783 | .@"select fast", |
| 9839 | 9784 | => |tag| { |
| 9840 | 9785 | const extra = function.extraData(Function.Instruction.Select, instruction.data); |
| 9841 | | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 9786 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ |
| 9842 | 9787 | instruction_index.name(&function).fmt(self), |
| 9843 | 9788 | @tagName(tag), |
| 9844 | 9789 | extra.cond.fmt(function_index, self), |
| ... | ... | @@ -9849,7 +9794,7 @@ pub fn printUnbuffered( |
| 9849 | 9794 | .shufflevector => |tag| { |
| 9850 | 9795 | const extra = |
| 9851 | 9796 | function.extraData(Function.Instruction.ShuffleVector, instruction.data); |
| 9852 | | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 9797 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ |
| 9853 | 9798 | instruction_index.name(&function).fmt(self), |
| 9854 | 9799 | @tagName(tag), |
| 9855 | 9800 | extra.lhs.fmt(function_index, self), |
| ... | ... | @@ -9861,7 +9806,7 @@ pub fn printUnbuffered( |
| 9861 | 9806 | .@"store atomic", |
| 9862 | 9807 | => |tag| { |
| 9863 | 9808 | const extra = function.extraData(Function.Instruction.Store, instruction.data); |
| 9864 | | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{ |
| 9809 | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{ |
| 9865 | 9810 | @tagName(tag), |
| 9866 | 9811 | extra.info.access_kind, |
| 9867 | 9812 | extra.val.fmt(function_index, self), |
| ... | ... | @@ -9889,11 +9834,11 @@ pub fn printUnbuffered( |
| 9889 | 9834 | case_block.toInst(&function).fmt(function_index, self), |
| 9890 | 9835 | }, |
| 9891 | 9836 | ); |
| 9892 | | try writer.writeAll(" ]\n"); |
| 9837 | try writer.writeAll(" ]"); |
| 9893 | 9838 | }, |
| 9894 | 9839 | .va_arg => |tag| { |
| 9895 | 9840 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); |
| 9896 | | try writer.print(" %{} = {s} {%}, {%}\n", .{ |
| 9841 | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 9897 | 9842 | instruction_index.name(&function).fmt(self), |
| 9898 | 9843 | @tagName(tag), |
| 9899 | 9844 | extra.list.fmt(function_index, self), |
| ... | ... | @@ -9901,11 +9846,13 @@ pub fn printUnbuffered( |
| 9901 | 9846 | }); |
| 9902 | 9847 | }, |
| 9903 | 9848 | } |
| 9849 | metadata_formatter.need_comma = true; |
| 9850 | defer metadata_formatter.need_comma = undefined; |
| 9851 | try writer.print("{}\n", .{try metadata_formatter.fmt("!dbg ", dbg)}); |
| 9904 | 9852 | } |
| 9905 | 9853 | try writer.writeByte('}'); |
| 9906 | 9854 | } |
| 9907 | 9855 | try writer.writeByte('\n'); |
| 9908 | | need_newline = true; |
| 9909 | 9856 | } |
| 9910 | 9857 | |
| 9911 | 9858 | if (attribute_groups.count() > 0) { |
| ... | ... | @@ -9915,12 +9862,375 @@ pub fn printUnbuffered( |
| 9915 | 9862 | \\attributes #{d} = {{{#"} }} |
| 9916 | 9863 | \\ |
| 9917 | 9864 | , .{ attribute_group_index, attribute_group.fmt(self) }); |
| 9918 | | need_newline = true; |
| 9919 | 9865 | } |
| 9920 | | } |
| 9921 | 9866 | |
| 9922 | | pub inline fn useLibLlvm(self: *const Builder) bool { |
| 9923 | | return build_options.have_llvm and self.use_lib_llvm; |
| 9867 | if (self.metadata_named.count() > 0) { |
| 9868 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9869 | for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| { |
| 9870 | const elements: []const Metadata = |
| 9871 | @ptrCast(self.metadata_extra.items[data.index..][0..data.len]); |
| 9872 | try writer.writeByte('!'); |
| 9873 | try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer); |
| 9874 | try writer.writeAll(" = !{"); |
| 9875 | metadata_formatter.need_comma = false; |
| 9876 | defer metadata_formatter.need_comma = undefined; |
| 9877 | for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)}); |
| 9878 | try writer.writeAll("}\n"); |
| 9879 | } |
| 9880 | } |
| 9881 | |
| 9882 | if (metadata_formatter.map.count() > 0) { |
| 9883 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 9884 | var metadata_index: usize = 0; |
| 9885 | while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) { |
| 9886 | @setEvalBranchQuota(10_000); |
| 9887 | const metadata_item = |
| 9888 | self.metadata_items.get(@intFromEnum(metadata_formatter.map.keys()[metadata_index])); |
| 9889 | try writer.print("!{} = ", .{metadata_index}); |
| 9890 | metadata_formatter.need_comma = false; |
| 9891 | defer metadata_formatter.need_comma = undefined; |
| 9892 | switch (metadata_item.tag) { |
| 9893 | .none, .expression, .constant => unreachable, |
| 9894 | .file => { |
| 9895 | const extra = self.metadataExtraData(Metadata.File, metadata_item.data); |
| 9896 | try metadata_formatter.specialized(.@"!", .DIFile, .{ |
| 9897 | .filename = extra.filename, |
| 9898 | .directory = extra.directory, |
| 9899 | .checksumkind = null, |
| 9900 | .checksum = null, |
| 9901 | .source = null, |
| 9902 | }, writer); |
| 9903 | }, |
| 9904 | .compile_unit, |
| 9905 | .@"compile_unit optimized", |
| 9906 | => |kind| { |
| 9907 | const extra = self.metadataExtraData(Metadata.CompileUnit, metadata_item.data); |
| 9908 | try metadata_formatter.specialized(.@"distinct !", .DICompileUnit, .{ |
| 9909 | .language = .DW_LANG_C99, |
| 9910 | .file = extra.file, |
| 9911 | .producer = extra.producer, |
| 9912 | .isOptimized = switch (kind) { |
| 9913 | .compile_unit => false, |
| 9914 | .@"compile_unit optimized" => true, |
| 9915 | else => unreachable, |
| 9916 | }, |
| 9917 | .flags = null, |
| 9918 | .runtimeVersion = 0, |
| 9919 | .splitDebugFilename = null, |
| 9920 | .emissionKind = .FullDebug, |
| 9921 | .enums = extra.enums, |
| 9922 | .retainedTypes = null, |
| 9923 | .globals = extra.globals, |
| 9924 | .imports = null, |
| 9925 | .macros = null, |
| 9926 | .dwoId = null, |
| 9927 | .splitDebugInlining = false, |
| 9928 | .debugInfoForProfiling = null, |
| 9929 | .nameTableKind = null, |
| 9930 | .rangesBaseAddress = null, |
| 9931 | .sysroot = null, |
| 9932 | .sdk = null, |
| 9933 | }, writer); |
| 9934 | }, |
| 9935 | .subprogram, |
| 9936 | .@"subprogram local", |
| 9937 | .@"subprogram definition", |
| 9938 | .@"subprogram local definition", |
| 9939 | .@"subprogram optimized", |
| 9940 | .@"subprogram optimized local", |
| 9941 | .@"subprogram optimized definition", |
| 9942 | .@"subprogram optimized local definition", |
| 9943 | => |kind| { |
| 9944 | const extra = self.metadataExtraData(Metadata.Subprogram, metadata_item.data); |
| 9945 | try metadata_formatter.specialized(.@"distinct !", .DISubprogram, .{ |
| 9946 | .name = extra.name, |
| 9947 | .linkageName = extra.linkage_name, |
| 9948 | .scope = extra.file, |
| 9949 | .file = extra.file, |
| 9950 | .line = extra.line, |
| 9951 | .type = extra.ty, |
| 9952 | .scopeLine = extra.scope_line, |
| 9953 | .containingType = null, |
| 9954 | .virtualIndex = null, |
| 9955 | .thisAdjustment = null, |
| 9956 | .flags = extra.di_flags, |
| 9957 | .spFlags = @as(Metadata.Subprogram.DISPFlags, @bitCast(@as(u32, @as(u3, @intCast( |
| 9958 | @intFromEnum(kind) - @intFromEnum(Metadata.Tag.subprogram), |
| 9959 | ))) << 2)), |
| 9960 | .unit = extra.compile_unit, |
| 9961 | .templateParams = null, |
| 9962 | .declaration = null, |
| 9963 | .retainedNodes = null, |
| 9964 | .thrownTypes = null, |
| 9965 | .annotations = null, |
| 9966 | .targetFuncName = null, |
| 9967 | }, writer); |
| 9968 | }, |
| 9969 | .lexical_block => { |
| 9970 | const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data); |
| 9971 | try metadata_formatter.specialized(.@"distinct !", .DILexicalBlock, .{ |
| 9972 | .scope = extra.scope, |
| 9973 | .file = extra.file, |
| 9974 | .line = extra.line, |
| 9975 | .column = extra.column, |
| 9976 | }, writer); |
| 9977 | }, |
| 9978 | .location => { |
| 9979 | const extra = self.metadataExtraData(Metadata.Location, metadata_item.data); |
| 9980 | try metadata_formatter.specialized(.@"!", .DILocation, .{ |
| 9981 | .line = extra.line, |
| 9982 | .column = extra.column, |
| 9983 | .scope = extra.scope, |
| 9984 | .inlinedAt = extra.inlined_at, |
| 9985 | .isImplicitCode = false, |
| 9986 | }, writer); |
| 9987 | }, |
| 9988 | .basic_bool_type, |
| 9989 | .basic_unsigned_type, |
| 9990 | .basic_signed_type, |
| 9991 | .basic_float_type, |
| 9992 | => |kind| { |
| 9993 | const extra = self.metadataExtraData(Metadata.BasicType, metadata_item.data); |
| 9994 | try metadata_formatter.specialized(.@"!", .DIBasicType, .{ |
| 9995 | .tag = null, |
| 9996 | .name = switch (extra.name) { |
| 9997 | .none => null, |
| 9998 | else => extra.name, |
| 9999 | }, |
| 10000 | .size = extra.bitSize(), |
| 10001 | .@"align" = null, |
| 10002 | .encoding = @as(enum { |
| 10003 | DW_ATE_boolean, |
| 10004 | DW_ATE_unsigned, |
| 10005 | DW_ATE_signed, |
| 10006 | DW_ATE_float, |
| 10007 | }, switch (kind) { |
| 10008 | .basic_bool_type => .DW_ATE_boolean, |
| 10009 | .basic_unsigned_type => .DW_ATE_unsigned, |
| 10010 | .basic_signed_type => .DW_ATE_signed, |
| 10011 | .basic_float_type => .DW_ATE_float, |
| 10012 | else => unreachable, |
| 10013 | }), |
| 10014 | .flags = null, |
| 10015 | }, writer); |
| 10016 | }, |
| 10017 | .composite_struct_type, |
| 10018 | .composite_union_type, |
| 10019 | .composite_enumeration_type, |
| 10020 | .composite_array_type, |
| 10021 | .composite_vector_type, |
| 10022 | => |kind| { |
| 10023 | const extra = self.metadataExtraData(Metadata.CompositeType, metadata_item.data); |
| 10024 | try metadata_formatter.specialized(.@"!", .DICompositeType, .{ |
| 10025 | .tag = @as(enum { |
| 10026 | DW_TAG_structure_type, |
| 10027 | DW_TAG_union_type, |
| 10028 | DW_TAG_enumeration_type, |
| 10029 | DW_TAG_array_type, |
| 10030 | }, switch (kind) { |
| 10031 | .composite_struct_type => .DW_TAG_structure_type, |
| 10032 | .composite_union_type => .DW_TAG_union_type, |
| 10033 | .composite_enumeration_type => .DW_TAG_enumeration_type, |
| 10034 | .composite_array_type, .composite_vector_type => .DW_TAG_array_type, |
| 10035 | else => unreachable, |
| 10036 | }), |
| 10037 | .name = switch (extra.name) { |
| 10038 | .none => null, |
| 10039 | else => extra.name, |
| 10040 | }, |
| 10041 | .scope = extra.scope, |
| 10042 | .file = null, |
| 10043 | .line = null, |
| 10044 | .baseType = extra.underlying_type, |
| 10045 | .size = extra.bitSize(), |
| 10046 | .@"align" = extra.bitAlign(), |
| 10047 | .offset = null, |
| 10048 | .flags = null, |
| 10049 | .elements = extra.fields_tuple, |
| 10050 | .runtimeLang = null, |
| 10051 | .vtableHolder = null, |
| 10052 | .templateParams = null, |
| 10053 | .identifier = null, |
| 10054 | .discriminator = null, |
| 10055 | .dataLocation = null, |
| 10056 | .associated = null, |
| 10057 | .allocated = null, |
| 10058 | .rank = null, |
| 10059 | .annotations = null, |
| 10060 | }, writer); |
| 10061 | }, |
| 10062 | .derived_pointer_type, |
| 10063 | .derived_member_type, |
| 10064 | => |kind| { |
| 10065 | const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data); |
| 10066 | try metadata_formatter.specialized(.@"!", .DIDerivedType, .{ |
| 10067 | .tag = @as(enum { |
| 10068 | DW_TAG_pointer_type, |
| 10069 | DW_TAG_member, |
| 10070 | }, switch (kind) { |
| 10071 | .derived_pointer_type => .DW_TAG_pointer_type, |
| 10072 | .derived_member_type => .DW_TAG_member, |
| 10073 | else => unreachable, |
| 10074 | }), |
| 10075 | .name = switch (extra.name) { |
| 10076 | .none => null, |
| 10077 | else => extra.name, |
| 10078 | }, |
| 10079 | .scope = extra.scope, |
| 10080 | .file = null, |
| 10081 | .line = null, |
| 10082 | .baseType = extra.underlying_type, |
| 10083 | .size = extra.bitSize(), |
| 10084 | .@"align" = extra.bitAlign(), |
| 10085 | .offset = switch (extra.bitOffset()) { |
| 10086 | 0 => null, |
| 10087 | else => |bit_offset| bit_offset, |
| 10088 | }, |
| 10089 | .flags = null, |
| 10090 | .extraData = null, |
| 10091 | .dwarfAddressSpace = null, |
| 10092 | .annotations = null, |
| 10093 | }, writer); |
| 10094 | }, |
| 10095 | .subroutine_type => { |
| 10096 | const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data); |
| 10097 | try metadata_formatter.specialized(.@"!", .DISubroutineType, .{ |
| 10098 | .flags = null, |
| 10099 | .cc = null, |
| 10100 | .types = extra.types_tuple, |
| 10101 | }, writer); |
| 10102 | }, |
| 10103 | .enumerator_unsigned, |
| 10104 | .enumerator_signed_positive, |
| 10105 | .enumerator_signed_negative, |
| 10106 | => |kind| { |
| 10107 | const extra = self.metadataExtraData(Metadata.Enumerator, metadata_item.data); |
| 10108 | |
| 10109 | const ExpectedContents = extern struct { |
| 10110 | string: [(64 * 8 / std.math.log2(10)) + 2]u8, |
| 10111 | limbs: [ |
| 10112 | std.math.big.int.calcToStringLimbsBufferLen( |
| 10113 | 64 / @sizeOf(std.math.big.Limb), |
| 10114 | 10, |
| 10115 | ) |
| 10116 | ]std.math.big.Limb, |
| 10117 | }; |
| 10118 | var stack align(@alignOf(ExpectedContents)) = |
| 10119 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10120 | const allocator = stack.get(); |
| 10121 | |
| 10122 | const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len]; |
| 10123 | const bigint: std.math.big.int.Const = .{ |
| 10124 | .limbs = limbs, |
| 10125 | .positive = switch (kind) { |
| 10126 | .enumerator_unsigned, |
| 10127 | .enumerator_signed_positive, |
| 10128 | => true, |
| 10129 | .enumerator_signed_negative => false, |
| 10130 | else => unreachable, |
| 10131 | }, |
| 10132 | }; |
| 10133 | const str = try bigint.toStringAlloc(allocator, 10, undefined); |
| 10134 | defer allocator.free(str); |
| 10135 | |
| 10136 | try metadata_formatter.specialized(.@"!", .DIEnumerator, .{ |
| 10137 | .name = extra.name, |
| 10138 | .value = str, |
| 10139 | .isUnsigned = switch (kind) { |
| 10140 | .enumerator_unsigned => true, |
| 10141 | .enumerator_signed_positive, .enumerator_signed_negative => false, |
| 10142 | else => unreachable, |
| 10143 | }, |
| 10144 | }, writer); |
| 10145 | }, |
| 10146 | .subrange => { |
| 10147 | const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data); |
| 10148 | try metadata_formatter.specialized(.@"!", .DISubrange, .{ |
| 10149 | .count = extra.count, |
| 10150 | .lowerBound = extra.lower_bound, |
| 10151 | .upperBound = null, |
| 10152 | .stride = null, |
| 10153 | }, writer); |
| 10154 | }, |
| 10155 | .tuple => { |
| 10156 | var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data); |
| 10157 | const elements = extra.trail.next(extra.data.elements_len, Metadata, self); |
| 10158 | try writer.writeAll("!{"); |
| 10159 | for (elements) |element| try writer.print("{[element]%}", .{ |
| 10160 | .element = try metadata_formatter.fmt("", element), |
| 10161 | }); |
| 10162 | try writer.writeAll("}\n"); |
| 10163 | }, |
| 10164 | .module_flag => { |
| 10165 | const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data); |
| 10166 | try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{ |
| 10167 | .behavior = try metadata_formatter.fmt("", extra.behavior), |
| 10168 | .name = try metadata_formatter.fmt("", extra.name), |
| 10169 | .constant = try metadata_formatter.fmt("", extra.constant), |
| 10170 | }); |
| 10171 | }, |
| 10172 | .local_var => { |
| 10173 | const extra = self.metadataExtraData(Metadata.LocalVar, metadata_item.data); |
| 10174 | try metadata_formatter.specialized(.@"!", .DILocalVariable, .{ |
| 10175 | .name = extra.name, |
| 10176 | .arg = null, |
| 10177 | .scope = extra.scope, |
| 10178 | .file = extra.file, |
| 10179 | .line = extra.line, |
| 10180 | .type = extra.ty, |
| 10181 | .flags = null, |
| 10182 | .@"align" = null, |
| 10183 | .annotations = null, |
| 10184 | }, writer); |
| 10185 | }, |
| 10186 | .parameter => { |
| 10187 | const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data); |
| 10188 | try metadata_formatter.specialized(.@"!", .DILocalVariable, .{ |
| 10189 | .name = extra.name, |
| 10190 | .arg = extra.arg_no, |
| 10191 | .scope = extra.scope, |
| 10192 | .file = extra.file, |
| 10193 | .line = extra.line, |
| 10194 | .type = extra.ty, |
| 10195 | .flags = null, |
| 10196 | .@"align" = null, |
| 10197 | .annotations = null, |
| 10198 | }, writer); |
| 10199 | }, |
| 10200 | .global_var, |
| 10201 | .@"global_var local", |
| 10202 | => |kind| { |
| 10203 | const extra = self.metadataExtraData(Metadata.GlobalVar, metadata_item.data); |
| 10204 | try metadata_formatter.specialized(.@"distinct !", .DIGlobalVariable, .{ |
| 10205 | .name = extra.name, |
| 10206 | .linkageName = extra.linkage_name, |
| 10207 | .scope = extra.scope, |
| 10208 | .file = extra.file, |
| 10209 | .line = extra.line, |
| 10210 | .type = extra.ty, |
| 10211 | .isLocal = switch (kind) { |
| 10212 | .global_var => false, |
| 10213 | .@"global_var local" => true, |
| 10214 | else => unreachable, |
| 10215 | }, |
| 10216 | .isDefinition = true, |
| 10217 | .declaration = null, |
| 10218 | .templateParams = null, |
| 10219 | .@"align" = null, |
| 10220 | .annotations = null, |
| 10221 | }, writer); |
| 10222 | }, |
| 10223 | .global_var_expression => { |
| 10224 | const extra = |
| 10225 | self.metadataExtraData(Metadata.GlobalVarExpression, metadata_item.data); |
| 10226 | try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{ |
| 10227 | .@"var" = extra.variable, |
| 10228 | .expr = extra.expression, |
| 10229 | }, writer); |
| 10230 | }, |
| 10231 | } |
| 10232 | } |
| 10233 | } |
| 9924 | 10234 | } |
| 9925 | 10235 | |
| 9926 | 10236 | const NoExtra = struct {}; |
| ... | ... | @@ -9954,10 +10264,9 @@ fn printEscapedString( |
| 9954 | 10264 | } |
| 9955 | 10265 | |
| 9956 | 10266 | fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void { |
| 9957 | | if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1); |
| 9958 | 10267 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 9959 | 10268 | if (name.slice(self)) |id| { |
| 9960 | | const count: usize = comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)}); |
| 10269 | const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); |
| 9961 | 10270 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); |
| 9962 | 10271 | } |
| 9963 | 10272 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | ... | @@ -9970,7 +10279,7 @@ fn fnTypeAssumeCapacity( |
| 9970 | 10279 | ret: Type, |
| 9971 | 10280 | params: []const Type, |
| 9972 | 10281 | comptime kind: Type.Function.Kind, |
| 9973 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Type { |
| 10282 | ) Type { |
| 9974 | 10283 | const tag: Type.Tag = switch (kind) { |
| 9975 | 10284 | .normal => .function, |
| 9976 | 10285 | .vararg => .vararg_function, |
| ... | ... | @@ -10007,20 +10316,6 @@ fn fnTypeAssumeCapacity( |
| 10007 | 10316 | }), |
| 10008 | 10317 | }); |
| 10009 | 10318 | self.type_extra.appendSliceAssumeCapacity(@ptrCast(params)); |
| 10010 | | if (self.useLibLlvm()) { |
| 10011 | | const llvm_params = try self.gpa.alloc(*llvm.Type, params.len); |
| 10012 | | defer self.gpa.free(llvm_params); |
| 10013 | | for (llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(self); |
| 10014 | | self.llvm.types.appendAssumeCapacity(llvm.functionType( |
| 10015 | | ret.toLlvm(self), |
| 10016 | | llvm_params.ptr, |
| 10017 | | @intCast(llvm_params.len), |
| 10018 | | switch (kind) { |
| 10019 | | .normal => .False, |
| 10020 | | .vararg => .True, |
| 10021 | | }, |
| 10022 | | )); |
| 10023 | | } |
| 10024 | 10319 | } |
| 10025 | 10320 | return @enumFromInt(gop.index); |
| 10026 | 10321 | } |
| ... | ... | @@ -10028,8 +10323,6 @@ fn fnTypeAssumeCapacity( |
| 10028 | 10323 | fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type { |
| 10029 | 10324 | assert(bits > 0); |
| 10030 | 10325 | const result = self.getOrPutTypeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits }); |
| 10031 | | if (self.useLibLlvm() and result.new) |
| 10032 | | self.llvm.types.appendAssumeCapacity(self.llvm.context.intType(bits)); |
| 10033 | 10326 | return result.type; |
| 10034 | 10327 | } |
| 10035 | 10328 | |
| ... | ... | @@ -10037,8 +10330,6 @@ fn ptrTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type { |
| 10037 | 10330 | const result = self.getOrPutTypeNoExtraAssumeCapacity( |
| 10038 | 10331 | .{ .tag = .pointer, .data = @intFromEnum(addr_space) }, |
| 10039 | 10332 | ); |
| 10040 | | if (self.useLibLlvm() and result.new) |
| 10041 | | self.llvm.types.appendAssumeCapacity(self.llvm.context.pointerType(@intFromEnum(addr_space))); |
| 10042 | 10333 | return result.type; |
| 10043 | 10334 | } |
| 10044 | 10335 | |
| ... | ... | @@ -10076,10 +10367,6 @@ fn vectorTypeAssumeCapacity( |
| 10076 | 10367 | .tag = tag, |
| 10077 | 10368 | .data = self.addTypeExtraAssumeCapacity(data), |
| 10078 | 10369 | }); |
| 10079 | | if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity(switch (kind) { |
| 10080 | | .normal => &llvm.Type.vectorType, |
| 10081 | | .scalable => &llvm.Type.scalableVectorType, |
| 10082 | | }(child.toLlvm(self), @intCast(len))); |
| 10083 | 10370 | } |
| 10084 | 10371 | return @enumFromInt(gop.index); |
| 10085 | 10372 | } |
| ... | ... | @@ -10109,9 +10396,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type { |
| 10109 | 10396 | .tag = .small_array, |
| 10110 | 10397 | .data = self.addTypeExtraAssumeCapacity(data), |
| 10111 | 10398 | }); |
| 10112 | | if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity( |
| 10113 | | child.toLlvm(self).arrayType2(len), |
| 10114 | | ); |
| 10115 | 10399 | } |
| 10116 | 10400 | return @enumFromInt(gop.index); |
| 10117 | 10401 | } else { |
| ... | ... | @@ -10142,9 +10426,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type { |
| 10142 | 10426 | .tag = .array, |
| 10143 | 10427 | .data = self.addTypeExtraAssumeCapacity(data), |
| 10144 | 10428 | }); |
| 10145 | | if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity( |
| 10146 | | child.toLlvm(self).arrayType2(len), |
| 10147 | | ); |
| 10148 | 10429 | } |
| 10149 | 10430 | return @enumFromInt(gop.index); |
| 10150 | 10431 | } |
| ... | ... | @@ -10154,7 +10435,7 @@ fn structTypeAssumeCapacity( |
| 10154 | 10435 | self: *Builder, |
| 10155 | 10436 | comptime kind: Type.Structure.Kind, |
| 10156 | 10437 | fields: []const Type, |
| 10157 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Type { |
| 10438 | ) Type { |
| 10158 | 10439 | const tag: Type.Tag = switch (kind) { |
| 10159 | 10440 | .normal => .structure, |
| 10160 | 10441 | .@"packed" => .packed_structure, |
| ... | ... | @@ -10186,25 +10467,6 @@ fn structTypeAssumeCapacity( |
| 10186 | 10467 | }), |
| 10187 | 10468 | }); |
| 10188 | 10469 | self.type_extra.appendSliceAssumeCapacity(@ptrCast(fields)); |
| 10189 | | if (self.useLibLlvm()) { |
| 10190 | | const ExpectedContents = [expected_fields_len]*llvm.Type; |
| 10191 | | var stack align(@alignOf(ExpectedContents)) = |
| 10192 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10193 | | const allocator = stack.get(); |
| 10194 | | |
| 10195 | | const llvm_fields = try allocator.alloc(*llvm.Type, fields.len); |
| 10196 | | defer allocator.free(llvm_fields); |
| 10197 | | for (llvm_fields, fields) |*llvm_field, field| llvm_field.* = field.toLlvm(self); |
| 10198 | | |
| 10199 | | self.llvm.types.appendAssumeCapacity(self.llvm.context.structType( |
| 10200 | | llvm_fields.ptr, |
| 10201 | | @intCast(llvm_fields.len), |
| 10202 | | switch (kind) { |
| 10203 | | .normal => .False, |
| 10204 | | .@"packed" => .True, |
| 10205 | | }, |
| 10206 | | )); |
| 10207 | | } |
| 10208 | 10470 | } |
| 10209 | 10471 | return @enumFromInt(gop.index); |
| 10210 | 10472 | } |
| ... | ... | @@ -10246,9 +10508,6 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type { |
| 10246 | 10508 | }); |
| 10247 | 10509 | const result: Type = @enumFromInt(gop.index); |
| 10248 | 10510 | type_gop.value_ptr.* = result; |
| 10249 | | if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity( |
| 10250 | | self.llvm.context.structCreateNamed(id.slice(self) orelse ""), |
| 10251 | | ); |
| 10252 | 10511 | return result; |
| 10253 | 10512 | } |
| 10254 | 10513 | |
| ... | ... | @@ -10271,7 +10530,6 @@ fn ensureUnusedTypeCapacity( |
| 10271 | 10530 | self.gpa, |
| 10272 | 10531 | count * (@typeInfo(Extra).Struct.fields.len + trail_len), |
| 10273 | 10532 | ); |
| 10274 | | if (self.useLibLlvm()) try self.llvm.types.ensureUnusedCapacity(self.gpa, count); |
| 10275 | 10533 | } |
| 10276 | 10534 | |
| 10277 | 10535 | fn getOrPutTypeNoExtraAssumeCapacity(self: *Builder, item: Type.Item) struct { new: bool, type: Type } { |
| ... | ... | @@ -10305,7 +10563,7 @@ fn addTypeExtraAssumeCapacity(self: *Builder, extra: anytype) Type.Item.ExtraInd |
| 10305 | 10563 | self.type_extra.appendAssumeCapacity(switch (field.type) { |
| 10306 | 10564 | u32 => value, |
| 10307 | 10565 | String, Type => @intFromEnum(value), |
| 10308 | | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 10566 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 10309 | 10567 | }); |
| 10310 | 10568 | } |
| 10311 | 10569 | return result; |
| ... | ... | @@ -10388,10 +10646,7 @@ fn bigIntConstAssumeCapacity( |
| 10388 | 10646 | assert(type_item.tag == .integer); |
| 10389 | 10647 | const bits = type_item.data; |
| 10390 | 10648 | |
| 10391 | | const ExpectedContents = extern struct { |
| 10392 | | limbs: [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb, |
| 10393 | | llvm_limbs: if (build_options.have_llvm) [64 / @sizeOf(u64)]u64 else void, |
| 10394 | | }; |
| 10649 | const ExpectedContents = [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb; |
| 10395 | 10650 | var stack align(@alignOf(ExpectedContents)) = |
| 10396 | 10651 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10397 | 10652 | const allocator = stack.get(); |
| ... | ... | @@ -10448,44 +10703,6 @@ fn bigIntConstAssumeCapacity( |
| 10448 | 10703 | @ptrCast(self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs)); |
| 10449 | 10704 | extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) }; |
| 10450 | 10705 | self.constant_limbs.appendSliceAssumeCapacity(canonical_value.limbs); |
| 10451 | | if (self.useLibLlvm()) { |
| 10452 | | const llvm_type = ty.toLlvm(self); |
| 10453 | | if (canonical_value.to(c_longlong)) |small| { |
| 10454 | | self.llvm.constants.appendAssumeCapacity(llvm_type.constInt(@bitCast(small), .True)); |
| 10455 | | } else |_| if (canonical_value.to(c_ulonglong)) |small| { |
| 10456 | | self.llvm.constants.appendAssumeCapacity(llvm_type.constInt(small, .False)); |
| 10457 | | } else |_| { |
| 10458 | | const llvm_limbs = try allocator.alloc(u64, std.math.divCeil( |
| 10459 | | usize, |
| 10460 | | if (canonical_value.positive) canonical_value.bitCountAbs() else bits, |
| 10461 | | @bitSizeOf(u64), |
| 10462 | | ) catch unreachable); |
| 10463 | | defer allocator.free(llvm_limbs); |
| 10464 | | var limb_index: usize = 0; |
| 10465 | | var borrow: std.math.big.Limb = 0; |
| 10466 | | for (llvm_limbs) |*result_limb| { |
| 10467 | | var llvm_limb: u64 = 0; |
| 10468 | | inline for (0..Constant.Integer.limbs) |shift| { |
| 10469 | | const limb = if (limb_index < canonical_value.limbs.len) |
| 10470 | | canonical_value.limbs[limb_index] |
| 10471 | | else |
| 10472 | | 0; |
| 10473 | | limb_index += 1; |
| 10474 | | llvm_limb |= @as(u64, limb) << shift * @bitSizeOf(std.math.big.Limb); |
| 10475 | | } |
| 10476 | | if (!canonical_value.positive) { |
| 10477 | | const overflow = @subWithOverflow(borrow, llvm_limb); |
| 10478 | | llvm_limb = overflow[0]; |
| 10479 | | borrow -%= overflow[1]; |
| 10480 | | assert(borrow == 0 or borrow == std.math.maxInt(std.math.big.Limb)); |
| 10481 | | } |
| 10482 | | result_limb.* = llvm_limb; |
| 10483 | | } |
| 10484 | | self.llvm.constants.appendAssumeCapacity( |
| 10485 | | llvm_type.constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), llvm_limbs.ptr), |
| 10486 | | ); |
| 10487 | | } |
| 10488 | | } |
| 10489 | 10706 | } |
| 10490 | 10707 | return @enumFromInt(gop.index); |
| 10491 | 10708 | } |
| ... | ... | @@ -10494,13 +10711,6 @@ fn halfConstAssumeCapacity(self: *Builder, val: f16) Constant { |
| 10494 | 10711 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10495 | 10712 | .{ .tag = .half, .data = @as(u16, @bitCast(val)) }, |
| 10496 | 10713 | ); |
| 10497 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity( |
| 10498 | | if (std.math.isSignalNan(val)) |
| 10499 | | Type.i16.toLlvm(self).constInt(@as(u16, @bitCast(val)), .False) |
| 10500 | | .constBitCast(Type.half.toLlvm(self)) |
| 10501 | | else |
| 10502 | | Type.half.toLlvm(self).constReal(val), |
| 10503 | | ); |
| 10504 | 10714 | return result.constant; |
| 10505 | 10715 | } |
| 10506 | 10716 | |
| ... | ... | @@ -10509,16 +10719,6 @@ fn bfloatConstAssumeCapacity(self: *Builder, val: f32) Constant { |
| 10509 | 10719 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10510 | 10720 | .{ .tag = .bfloat, .data = @bitCast(val) }, |
| 10511 | 10721 | ); |
| 10512 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity( |
| 10513 | | if (std.math.isSignalNan(val)) |
| 10514 | | Type.i16.toLlvm(self).constInt(@as(u32, @bitCast(val)) >> 16, .False) |
| 10515 | | .constBitCast(Type.bfloat.toLlvm(self)) |
| 10516 | | else |
| 10517 | | Type.bfloat.toLlvm(self).constReal(val), |
| 10518 | | ); |
| 10519 | | |
| 10520 | | if (self.useLibLlvm() and result.new) |
| 10521 | | self.llvm.constants.appendAssumeCapacity(Type.bfloat.toLlvm(self).constReal(val)); |
| 10522 | 10722 | return result.constant; |
| 10523 | 10723 | } |
| 10524 | 10724 | |
| ... | ... | @@ -10526,13 +10726,6 @@ fn floatConstAssumeCapacity(self: *Builder, val: f32) Constant { |
| 10526 | 10726 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10527 | 10727 | .{ .tag = .float, .data = @bitCast(val) }, |
| 10528 | 10728 | ); |
| 10529 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity( |
| 10530 | | if (std.math.isSignalNan(val)) |
| 10531 | | Type.i32.toLlvm(self).constInt(@as(u32, @bitCast(val)), .False) |
| 10532 | | .constBitCast(Type.float.toLlvm(self)) |
| 10533 | | else |
| 10534 | | Type.float.toLlvm(self).constReal(val), |
| 10535 | | ); |
| 10536 | 10729 | return result.constant; |
| 10537 | 10730 | } |
| 10538 | 10731 | |
| ... | ... | @@ -10563,13 +10756,6 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant { |
| 10563 | 10756 | .hi = @intCast(@as(u64, @bitCast(val)) >> 32), |
| 10564 | 10757 | }), |
| 10565 | 10758 | }); |
| 10566 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 10567 | | if (std.math.isSignalNan(val)) |
| 10568 | | Type.i64.toLlvm(self).constInt(@as(u64, @bitCast(val)), .False) |
| 10569 | | .constBitCast(Type.double.toLlvm(self)) |
| 10570 | | else |
| 10571 | | Type.double.toLlvm(self).constReal(val), |
| 10572 | | ); |
| 10573 | 10759 | } |
| 10574 | 10760 | return @enumFromInt(gop.index); |
| 10575 | 10761 | } |
| ... | ... | @@ -10604,17 +10790,6 @@ fn fp128ConstAssumeCapacity(self: *Builder, val: f128) Constant { |
| 10604 | 10790 | .hi_hi = @intCast(@as(u128, @bitCast(val)) >> 96), |
| 10605 | 10791 | }), |
| 10606 | 10792 | }); |
| 10607 | | if (self.useLibLlvm()) { |
| 10608 | | const llvm_limbs = [_]u64{ |
| 10609 | | @truncate(@as(u128, @bitCast(val))), |
| 10610 | | @intCast(@as(u128, @bitCast(val)) >> 64), |
| 10611 | | }; |
| 10612 | | self.llvm.constants.appendAssumeCapacity( |
| 10613 | | Type.i128.toLlvm(self) |
| 10614 | | .constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), &llvm_limbs) |
| 10615 | | .constBitCast(Type.fp128.toLlvm(self)), |
| 10616 | | ); |
| 10617 | | } |
| 10618 | 10793 | } |
| 10619 | 10794 | return @enumFromInt(gop.index); |
| 10620 | 10795 | } |
| ... | ... | @@ -10648,17 +10823,6 @@ fn x86_fp80ConstAssumeCapacity(self: *Builder, val: f80) Constant { |
| 10648 | 10823 | .hi = @intCast(@as(u80, @bitCast(val)) >> 64), |
| 10649 | 10824 | }), |
| 10650 | 10825 | }); |
| 10651 | | if (self.useLibLlvm()) { |
| 10652 | | const llvm_limbs = [_]u64{ |
| 10653 | | @truncate(@as(u80, @bitCast(val))), |
| 10654 | | @intCast(@as(u80, @bitCast(val)) >> 64), |
| 10655 | | }; |
| 10656 | | self.llvm.constants.appendAssumeCapacity( |
| 10657 | | Type.i80.toLlvm(self) |
| 10658 | | .constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), &llvm_limbs) |
| 10659 | | .constBitCast(Type.x86_fp80.toLlvm(self)), |
| 10660 | | ); |
| 10661 | | } |
| 10662 | 10826 | } |
| 10663 | 10827 | return @enumFromInt(gop.index); |
| 10664 | 10828 | } |
| ... | ... | @@ -10693,14 +10857,6 @@ fn ppc_fp128ConstAssumeCapacity(self: *Builder, val: [2]f64) Constant { |
| 10693 | 10857 | .hi_hi = @intCast(@as(u64, @bitCast(val[1])) >> 32), |
| 10694 | 10858 | }), |
| 10695 | 10859 | }); |
| 10696 | | if (self.useLibLlvm()) { |
| 10697 | | const llvm_limbs: [2]u64 = @bitCast(val); |
| 10698 | | self.llvm.constants.appendAssumeCapacity( |
| 10699 | | Type.i128.toLlvm(self) |
| 10700 | | .constIntOfArbitraryPrecision(@intCast(llvm_limbs.len), &llvm_limbs) |
| 10701 | | .constBitCast(Type.ppc_fp128.toLlvm(self)), |
| 10702 | | ); |
| 10703 | | } |
| 10704 | 10860 | } |
| 10705 | 10861 | return @enumFromInt(gop.index); |
| 10706 | 10862 | } |
| ... | ... | @@ -10710,8 +10866,6 @@ fn nullConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10710 | 10866 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10711 | 10867 | .{ .tag = .null, .data = @intFromEnum(ty) }, |
| 10712 | 10868 | ); |
| 10713 | | if (self.useLibLlvm() and result.new) |
| 10714 | | self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).constNull()); |
| 10715 | 10869 | return result.constant; |
| 10716 | 10870 | } |
| 10717 | 10871 | |
| ... | ... | @@ -10720,16 +10874,10 @@ fn noneConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10720 | 10874 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10721 | 10875 | .{ .tag = .none, .data = @intFromEnum(ty) }, |
| 10722 | 10876 | ); |
| 10723 | | if (self.useLibLlvm() and result.new) |
| 10724 | | self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).constNull()); |
| 10725 | 10877 | return result.constant; |
| 10726 | 10878 | } |
| 10727 | 10879 | |
| 10728 | | fn structConstAssumeCapacity( |
| 10729 | | self: *Builder, |
| 10730 | | ty: Type, |
| 10731 | | vals: []const Constant, |
| 10732 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { |
| 10880 | fn structConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant { |
| 10733 | 10881 | const type_item = self.type_items.items[@intFromEnum(ty)]; |
| 10734 | 10882 | var extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) { |
| 10735 | 10883 | .structure, .packed_structure => type_item.data, |
| ... | ... | @@ -10756,28 +10904,10 @@ fn structConstAssumeCapacity( |
| 10756 | 10904 | else => unreachable, |
| 10757 | 10905 | }; |
| 10758 | 10906 | const result = self.getOrPutConstantAggregateAssumeCapacity(tag, ty, vals); |
| 10759 | | if (self.useLibLlvm() and result.new) { |
| 10760 | | const ExpectedContents = [expected_fields_len]*llvm.Value; |
| 10761 | | var stack align(@alignOf(ExpectedContents)) = |
| 10762 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10763 | | const allocator = stack.get(); |
| 10764 | | |
| 10765 | | const llvm_vals = try allocator.alloc(*llvm.Value, vals.len); |
| 10766 | | defer allocator.free(llvm_vals); |
| 10767 | | for (llvm_vals, vals) |*llvm_val, val| llvm_val.* = val.toLlvm(self); |
| 10768 | | |
| 10769 | | self.llvm.constants.appendAssumeCapacity( |
| 10770 | | ty.toLlvm(self).constNamedStruct(llvm_vals.ptr, @intCast(llvm_vals.len)), |
| 10771 | | ); |
| 10772 | | } |
| 10773 | 10907 | return result.constant; |
| 10774 | 10908 | } |
| 10775 | 10909 | |
| 10776 | | fn arrayConstAssumeCapacity( |
| 10777 | | self: *Builder, |
| 10778 | | ty: Type, |
| 10779 | | vals: []const Constant, |
| 10780 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { |
| 10910 | fn arrayConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant { |
| 10781 | 10911 | const type_item = self.type_items.items[@intFromEnum(ty)]; |
| 10782 | 10912 | const type_extra: struct { len: u64, child: Type } = switch (type_item.tag) { |
| 10783 | 10913 | inline .small_array, .array => |kind| extra: { |
| ... | ... | @@ -10798,20 +10928,6 @@ fn arrayConstAssumeCapacity( |
| 10798 | 10928 | } else return self.zeroInitConstAssumeCapacity(ty); |
| 10799 | 10929 | |
| 10800 | 10930 | const result = self.getOrPutConstantAggregateAssumeCapacity(.array, ty, vals); |
| 10801 | | if (self.useLibLlvm() and result.new) { |
| 10802 | | const ExpectedContents = [expected_fields_len]*llvm.Value; |
| 10803 | | var stack align(@alignOf(ExpectedContents)) = |
| 10804 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10805 | | const allocator = stack.get(); |
| 10806 | | |
| 10807 | | const llvm_vals = try allocator.alloc(*llvm.Value, vals.len); |
| 10808 | | defer allocator.free(llvm_vals); |
| 10809 | | for (llvm_vals, vals) |*llvm_val, val| llvm_val.* = val.toLlvm(self); |
| 10810 | | |
| 10811 | | self.llvm.constants.appendAssumeCapacity( |
| 10812 | | type_extra.child.toLlvm(self).constArray2(llvm_vals.ptr, llvm_vals.len), |
| 10813 | | ); |
| 10814 | | } |
| 10815 | 10931 | return result.constant; |
| 10816 | 10932 | } |
| 10817 | 10933 | |
| ... | ... | @@ -10822,30 +10938,10 @@ fn stringConstAssumeCapacity(self: *Builder, val: String) Constant { |
| 10822 | 10938 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10823 | 10939 | .{ .tag = .string, .data = @intFromEnum(val) }, |
| 10824 | 10940 | ); |
| 10825 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity( |
| 10826 | | self.llvm.context.constString(slice.ptr, @intCast(slice.len), .True), |
| 10827 | | ); |
| 10828 | | return result.constant; |
| 10829 | | } |
| 10830 | | |
| 10831 | | fn stringNullConstAssumeCapacity(self: *Builder, val: String) Constant { |
| 10832 | | const slice = val.slice(self).?; |
| 10833 | | const ty = self.arrayTypeAssumeCapacity(slice.len + 1, .i8); |
| 10834 | | if (std.mem.allEqual(u8, slice, 0)) return self.zeroInitConstAssumeCapacity(ty); |
| 10835 | | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10836 | | .{ .tag = .string_null, .data = @intFromEnum(val) }, |
| 10837 | | ); |
| 10838 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity( |
| 10839 | | self.llvm.context.constString(slice.ptr, @intCast(slice.len + 1), .True), |
| 10840 | | ); |
| 10841 | 10941 | return result.constant; |
| 10842 | 10942 | } |
| 10843 | 10943 | |
| 10844 | | fn vectorConstAssumeCapacity( |
| 10845 | | self: *Builder, |
| 10846 | | ty: Type, |
| 10847 | | vals: []const Constant, |
| 10848 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { |
| 10944 | fn vectorConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant { |
| 10849 | 10945 | assert(ty.isVector(self)); |
| 10850 | 10946 | assert(ty.vectorLen(self) == vals.len); |
| 10851 | 10947 | for (vals) |val| assert(ty.childType(self) == val.typeOf(self)); |
| ... | ... | @@ -10858,28 +10954,10 @@ fn vectorConstAssumeCapacity( |
| 10858 | 10954 | } else return self.zeroInitConstAssumeCapacity(ty); |
| 10859 | 10955 | |
| 10860 | 10956 | const result = self.getOrPutConstantAggregateAssumeCapacity(.vector, ty, vals); |
| 10861 | | if (self.useLibLlvm() and result.new) { |
| 10862 | | const ExpectedContents = [expected_fields_len]*llvm.Value; |
| 10863 | | var stack align(@alignOf(ExpectedContents)) = |
| 10864 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10865 | | const allocator = stack.get(); |
| 10866 | | |
| 10867 | | const llvm_vals = try allocator.alloc(*llvm.Value, vals.len); |
| 10868 | | defer allocator.free(llvm_vals); |
| 10869 | | for (llvm_vals, vals) |*llvm_val, val| llvm_val.* = val.toLlvm(self); |
| 10870 | | |
| 10871 | | self.llvm.constants.appendAssumeCapacity( |
| 10872 | | llvm.constVector(llvm_vals.ptr, @intCast(llvm_vals.len)), |
| 10873 | | ); |
| 10874 | | } |
| 10875 | 10957 | return result.constant; |
| 10876 | 10958 | } |
| 10877 | 10959 | |
| 10878 | | fn splatConstAssumeCapacity( |
| 10879 | | self: *Builder, |
| 10880 | | ty: Type, |
| 10881 | | val: Constant, |
| 10882 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { |
| 10960 | fn splatConstAssumeCapacity(self: *Builder, ty: Type, val: Constant) Constant { |
| 10883 | 10961 | assert(ty.scalarType(self) == val.typeOf(self)); |
| 10884 | 10962 | |
| 10885 | 10963 | if (!ty.isVector(self)) return val; |
| ... | ... | @@ -10909,20 +10987,6 @@ fn splatConstAssumeCapacity( |
| 10909 | 10987 | .tag = .splat, |
| 10910 | 10988 | .data = self.addConstantExtraAssumeCapacity(data), |
| 10911 | 10989 | }); |
| 10912 | | if (self.useLibLlvm()) { |
| 10913 | | const ExpectedContents = [expected_fields_len]*llvm.Value; |
| 10914 | | var stack align(@alignOf(ExpectedContents)) = |
| 10915 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10916 | | const allocator = stack.get(); |
| 10917 | | |
| 10918 | | const llvm_vals = try allocator.alloc(*llvm.Value, ty.vectorLen(self)); |
| 10919 | | defer allocator.free(llvm_vals); |
| 10920 | | @memset(llvm_vals, val.toLlvm(self)); |
| 10921 | | |
| 10922 | | self.llvm.constants.appendAssumeCapacity( |
| 10923 | | llvm.constVector(llvm_vals.ptr, @intCast(llvm_vals.len)), |
| 10924 | | ); |
| 10925 | | } |
| 10926 | 10990 | } |
| 10927 | 10991 | return @enumFromInt(gop.index); |
| 10928 | 10992 | } |
| ... | ... | @@ -10964,8 +11028,6 @@ fn zeroInitConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10964 | 11028 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10965 | 11029 | .{ .tag = .zeroinitializer, .data = @intFromEnum(ty) }, |
| 10966 | 11030 | ); |
| 10967 | | if (self.useLibLlvm() and result.new) |
| 10968 | | self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).constNull()); |
| 10969 | 11031 | return result.constant; |
| 10970 | 11032 | } |
| 10971 | 11033 | |
| ... | ... | @@ -10981,8 +11043,6 @@ fn undefConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10981 | 11043 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10982 | 11044 | .{ .tag = .undef, .data = @intFromEnum(ty) }, |
| 10983 | 11045 | ); |
| 10984 | | if (self.useLibLlvm() and result.new) |
| 10985 | | self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).getUndef()); |
| 10986 | 11046 | return result.constant; |
| 10987 | 11047 | } |
| 10988 | 11048 | |
| ... | ... | @@ -10998,8 +11058,6 @@ fn poisonConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10998 | 11058 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10999 | 11059 | .{ .tag = .poison, .data = @intFromEnum(ty) }, |
| 11000 | 11060 | ); |
| 11001 | | if (self.useLibLlvm() and result.new) |
| 11002 | | self.llvm.constants.appendAssumeCapacity(ty.toLlvm(self).getPoison()); |
| 11003 | 11061 | return result.constant; |
| 11004 | 11062 | } |
| 11005 | 11063 | |
| ... | ... | @@ -11032,9 +11090,6 @@ fn blockAddrConstAssumeCapacity( |
| 11032 | 11090 | .tag = .blockaddress, |
| 11033 | 11091 | .data = self.addConstantExtraAssumeCapacity(data), |
| 11034 | 11092 | }); |
| 11035 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 11036 | | function.toLlvm(self).blockAddress(block.toValue(self, function).toLlvm(self, function)), |
| 11037 | | ); |
| 11038 | 11093 | } |
| 11039 | 11094 | return @enumFromInt(gop.index); |
| 11040 | 11095 | } |
| ... | ... | @@ -11043,7 +11098,6 @@ fn dsoLocalEquivalentConstAssumeCapacity(self: *Builder, function: Function.Inde |
| 11043 | 11098 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 11044 | 11099 | .{ .tag = .dso_local_equivalent, .data = @intFromEnum(function) }, |
| 11045 | 11100 | ); |
| 11046 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(undefined); |
| 11047 | 11101 | return result.constant; |
| 11048 | 11102 | } |
| 11049 | 11103 | |
| ... | ... | @@ -11051,7 +11105,6 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant { |
| 11051 | 11105 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 11052 | 11106 | .{ .tag = .no_cfi, .data = @intFromEnum(function) }, |
| 11053 | 11107 | ); |
| 11054 | | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(undefined); |
| 11055 | 11108 | return result.constant; |
| 11056 | 11109 | } |
| 11057 | 11110 | |
| ... | ... | @@ -11141,22 +11194,6 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: |
| 11141 | 11194 | .tag = tag, |
| 11142 | 11195 | .data = self.addConstantExtraAssumeCapacity(data.cast), |
| 11143 | 11196 | }); |
| 11144 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(switch (tag) { |
| 11145 | | .trunc => &llvm.Value.constTrunc, |
| 11146 | | .zext => &llvm.Value.constZExt, |
| 11147 | | .sext => &llvm.Value.constSExt, |
| 11148 | | .fptrunc => &llvm.Value.constFPTrunc, |
| 11149 | | .fpext => &llvm.Value.constFPExt, |
| 11150 | | .fptoui => &llvm.Value.constFPToUI, |
| 11151 | | .fptosi => &llvm.Value.constFPToSI, |
| 11152 | | .uitofp => &llvm.Value.constUIToFP, |
| 11153 | | .sitofp => &llvm.Value.constSIToFP, |
| 11154 | | .ptrtoint => &llvm.Value.constPtrToInt, |
| 11155 | | .inttoptr => &llvm.Value.constIntToPtr, |
| 11156 | | .bitcast => &llvm.Value.constBitCast, |
| 11157 | | .addrspacecast => &llvm.Value.constAddrSpaceCast, |
| 11158 | | else => unreachable, |
| 11159 | | }(val.toLlvm(self), ty.toLlvm(self))); |
| 11160 | 11197 | } |
| 11161 | 11198 | return @enumFromInt(gop.index); |
| 11162 | 11199 | } |
| ... | ... | @@ -11168,7 +11205,7 @@ fn gepConstAssumeCapacity( |
| 11168 | 11205 | base: Constant, |
| 11169 | 11206 | inrange: ?u16, |
| 11170 | 11207 | indices: []const Constant, |
| 11171 | | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { |
| 11208 | ) Constant { |
| 11172 | 11209 | const tag: Constant.Tag = switch (kind) { |
| 11173 | 11210 | .normal => .getelementptr, |
| 11174 | 11211 | .inbounds => .@"getelementptr inbounds", |
| ... | ... | @@ -11249,21 +11286,6 @@ fn gepConstAssumeCapacity( |
| 11249 | 11286 | }), |
| 11250 | 11287 | }); |
| 11251 | 11288 | self.constant_extra.appendSliceAssumeCapacity(@ptrCast(indices)); |
| 11252 | | if (self.useLibLlvm()) { |
| 11253 | | const ExpectedContents = [expected_gep_indices_len]*llvm.Value; |
| 11254 | | var stack align(@alignOf(ExpectedContents)) = |
| 11255 | | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 11256 | | const allocator = stack.get(); |
| 11257 | | |
| 11258 | | const llvm_indices = try allocator.alloc(*llvm.Value, indices.len); |
| 11259 | | defer allocator.free(llvm_indices); |
| 11260 | | for (llvm_indices, indices) |*llvm_index, index| llvm_index.* = index.toLlvm(self); |
| 11261 | | |
| 11262 | | self.llvm.constants.appendAssumeCapacity(switch (kind) { |
| 11263 | | .normal => &llvm.Type.constGEP, |
| 11264 | | .inbounds => &llvm.Type.constInBoundsGEP, |
| 11265 | | }(ty.toLlvm(self), base.toLlvm(self), llvm_indices.ptr, @intCast(llvm_indices.len))); |
| 11266 | | } |
| 11267 | 11289 | } |
| 11268 | 11290 | return @enumFromInt(gop.index); |
| 11269 | 11291 | } |
| ... | ... | @@ -11298,9 +11320,6 @@ fn icmpConstAssumeCapacity( |
| 11298 | 11320 | .tag = .icmp, |
| 11299 | 11321 | .data = self.addConstantExtraAssumeCapacity(data), |
| 11300 | 11322 | }); |
| 11301 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 11302 | | llvm.constICmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)), |
| 11303 | | ); |
| 11304 | 11323 | } |
| 11305 | 11324 | return @enumFromInt(gop.index); |
| 11306 | 11325 | } |
| ... | ... | @@ -11335,9 +11354,6 @@ fn fcmpConstAssumeCapacity( |
| 11335 | 11354 | .tag = .fcmp, |
| 11336 | 11355 | .data = self.addConstantExtraAssumeCapacity(data), |
| 11337 | 11356 | }); |
| 11338 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 11339 | | llvm.constFCmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)), |
| 11340 | | ); |
| 11341 | 11357 | } |
| 11342 | 11358 | return @enumFromInt(gop.index); |
| 11343 | 11359 | } |
| ... | ... | @@ -11371,9 +11387,6 @@ fn extractElementConstAssumeCapacity( |
| 11371 | 11387 | .tag = .extractelement, |
| 11372 | 11388 | .data = self.addConstantExtraAssumeCapacity(data), |
| 11373 | 11389 | }); |
| 11374 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 11375 | | val.toLlvm(self).constExtractElement(index.toLlvm(self)), |
| 11376 | | ); |
| 11377 | 11390 | } |
| 11378 | 11391 | return @enumFromInt(gop.index); |
| 11379 | 11392 | } |
| ... | ... | @@ -11408,9 +11421,6 @@ fn insertElementConstAssumeCapacity( |
| 11408 | 11421 | .tag = .insertelement, |
| 11409 | 11422 | .data = self.addConstantExtraAssumeCapacity(data), |
| 11410 | 11423 | }); |
| 11411 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 11412 | | val.toLlvm(self).constInsertElement(elem.toLlvm(self), index.toLlvm(self)), |
| 11413 | | ); |
| 11414 | 11424 | } |
| 11415 | 11425 | return @enumFromInt(gop.index); |
| 11416 | 11426 | } |
| ... | ... | @@ -11449,9 +11459,6 @@ fn shuffleVectorConstAssumeCapacity( |
| 11449 | 11459 | .tag = .shufflevector, |
| 11450 | 11460 | .data = self.addConstantExtraAssumeCapacity(data), |
| 11451 | 11461 | }); |
| 11452 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 11453 | | lhs.toLlvm(self).constShuffleVector(rhs.toLlvm(self), mask.toLlvm(self)), |
| 11454 | | ); |
| 11455 | 11462 | } |
| 11456 | 11463 | return @enumFromInt(gop.index); |
| 11457 | 11464 | } |
| ... | ... | @@ -11506,18 +11513,6 @@ fn binConstAssumeCapacity( |
| 11506 | 11513 | .tag = tag, |
| 11507 | 11514 | .data = self.addConstantExtraAssumeCapacity(data.extra), |
| 11508 | 11515 | }); |
| 11509 | | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(switch (tag) { |
| 11510 | | .add => &llvm.Value.constAdd, |
| 11511 | | .sub => &llvm.Value.constSub, |
| 11512 | | .mul => &llvm.Value.constMul, |
| 11513 | | .shl => &llvm.Value.constShl, |
| 11514 | | .lshr => &llvm.Value.constLShr, |
| 11515 | | .ashr => &llvm.Value.constAShr, |
| 11516 | | .@"and" => &llvm.Value.constAnd, |
| 11517 | | .@"or" => &llvm.Value.constOr, |
| 11518 | | .xor => &llvm.Value.constXor, |
| 11519 | | else => unreachable, |
| 11520 | | }(lhs.toLlvm(self), rhs.toLlvm(self))); |
| 11521 | 11516 | } |
| 11522 | 11517 | return @enumFromInt(gop.index); |
| 11523 | 11518 | } |
| ... | ... | @@ -11560,21 +11555,6 @@ fn asmConstAssumeCapacity( |
| 11560 | 11555 | .tag = data.tag, |
| 11561 | 11556 | .data = self.addConstantExtraAssumeCapacity(data.extra), |
| 11562 | 11557 | }); |
| 11563 | | if (self.useLibLlvm()) { |
| 11564 | | const assembly_slice = assembly.slice(self).?; |
| 11565 | | const constraints_slice = constraints.slice(self).?; |
| 11566 | | self.llvm.constants.appendAssumeCapacity(llvm.getInlineAsm( |
| 11567 | | ty.toLlvm(self), |
| 11568 | | assembly_slice.ptr, |
| 11569 | | assembly_slice.len, |
| 11570 | | constraints_slice.ptr, |
| 11571 | | constraints_slice.len, |
| 11572 | | llvm.Bool.fromBool(info.sideeffect), |
| 11573 | | llvm.Bool.fromBool(info.alignstack), |
| 11574 | | if (info.inteldialect) .Intel else .ATT, |
| 11575 | | llvm.Bool.fromBool(info.unwind), |
| 11576 | | )); |
| 11577 | | } |
| 11578 | 11558 | } |
| 11579 | 11559 | return @enumFromInt(gop.index); |
| 11580 | 11560 | } |
| ... | ... | @@ -11591,7 +11571,6 @@ fn ensureUnusedConstantCapacity( |
| 11591 | 11571 | self.gpa, |
| 11592 | 11572 | count * (@typeInfo(Extra).Struct.fields.len + trail_len), |
| 11593 | 11573 | ); |
| 11594 | | if (self.useLibLlvm()) try self.llvm.constants.ensureUnusedCapacity(self.gpa, count); |
| 11595 | 11574 | } |
| 11596 | 11575 | |
| 11597 | 11576 | fn getOrPutConstantNoExtraAssumeCapacity( |
| ... | ... | @@ -11722,15 +11701,3260 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite |
| 11722 | 11701 | return self.constantExtraDataTrail(T, index).data; |
| 11723 | 11702 | } |
| 11724 | 11703 | |
| 11725 | | const assert = std.debug.assert; |
| 11726 | | const build_options = @import("build_options"); |
| 11727 | | const builtin = @import("builtin"); |
| 11728 | | const llvm = if (build_options.have_llvm) |
| 11729 | | @import("bindings.zig") |
| 11730 | | else |
| 11731 | | @compileError("LLVM unavailable"); |
| 11732 | | const log = std.log.scoped(.llvm); |
| 11733 | | const std = @import("std"); |
| 11704 | fn ensureUnusedMetadataCapacity( |
| 11705 | self: *Builder, |
| 11706 | count: usize, |
| 11707 | comptime Extra: type, |
| 11708 | trail_len: usize, |
| 11709 | ) Allocator.Error!void { |
| 11710 | try self.metadata_map.ensureUnusedCapacity(self.gpa, count); |
| 11711 | try self.metadata_items.ensureUnusedCapacity(self.gpa, count); |
| 11712 | try self.metadata_extra.ensureUnusedCapacity( |
| 11713 | self.gpa, |
| 11714 | count * (@typeInfo(Extra).Struct.fields.len + trail_len), |
| 11715 | ); |
| 11716 | } |
| 11734 | 11717 | |
| 11735 | | const Allocator = std.mem.Allocator; |
| 11736 | | const Builder = @This(); |
| 11718 | fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.ExtraIndex { |
| 11719 | const result: Metadata.Item.ExtraIndex = @intCast(self.metadata_extra.items.len); |
| 11720 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { |
| 11721 | const value = @field(extra, field.name); |
| 11722 | self.metadata_extra.appendAssumeCapacity(switch (field.type) { |
| 11723 | u32 => value, |
| 11724 | MetadataString, Metadata, Variable.Index, Value => @intFromEnum(value), |
| 11725 | Metadata.DIFlags => @bitCast(value), |
| 11726 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 11727 | }); |
| 11728 | } |
| 11729 | return result; |
| 11730 | } |
| 11731 | |
| 11732 | const MetadataExtraDataTrail = struct { |
| 11733 | index: Metadata.Item.ExtraIndex, |
| 11734 | |
| 11735 | fn nextMut(self: *MetadataExtraDataTrail, len: u32, comptime Item: type, builder: *Builder) []Item { |
| 11736 | const items: []Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]); |
| 11737 | self.index += @intCast(len); |
| 11738 | return items; |
| 11739 | } |
| 11740 | |
| 11741 | fn next( |
| 11742 | self: *MetadataExtraDataTrail, |
| 11743 | len: u32, |
| 11744 | comptime Item: type, |
| 11745 | builder: *const Builder, |
| 11746 | ) []const Item { |
| 11747 | const items: []const Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]); |
| 11748 | self.index += @intCast(len); |
| 11749 | return items; |
| 11750 | } |
| 11751 | }; |
| 11752 | |
| 11753 | fn metadataExtraDataTrail( |
| 11754 | self: *const Builder, |
| 11755 | comptime T: type, |
| 11756 | index: Metadata.Item.ExtraIndex, |
| 11757 | ) struct { data: T, trail: MetadataExtraDataTrail } { |
| 11758 | var result: T = undefined; |
| 11759 | const fields = @typeInfo(T).Struct.fields; |
| 11760 | inline for (fields, self.metadata_extra.items[index..][0..fields.len]) |field, value| |
| 11761 | @field(result, field.name) = switch (field.type) { |
| 11762 | u32 => value, |
| 11763 | MetadataString, Metadata, Variable.Index, Value => @enumFromInt(value), |
| 11764 | Metadata.DIFlags => @bitCast(value), |
| 11765 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 11766 | }; |
| 11767 | return .{ |
| 11768 | .data = result, |
| 11769 | .trail = .{ .index = index + @as(Metadata.Item.ExtraIndex, @intCast(fields.len)) }, |
| 11770 | }; |
| 11771 | } |
| 11772 | |
| 11773 | fn metadataExtraData(self: *const Builder, comptime T: type, index: Metadata.Item.ExtraIndex) T { |
| 11774 | return self.metadataExtraDataTrail(T, index).data; |
| 11775 | } |
| 11776 | |
| 11777 | pub fn metadataString(self: *Builder, bytes: []const u8) Allocator.Error!MetadataString { |
| 11778 | try self.metadata_string_bytes.ensureUnusedCapacity(self.gpa, bytes.len); |
| 11779 | try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 11780 | try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1); |
| 11781 | |
| 11782 | const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted( |
| 11783 | bytes, |
| 11784 | MetadataString.Adapter{ .builder = self }, |
| 11785 | ); |
| 11786 | if (!gop.found_existing) { |
| 11787 | self.metadata_string_bytes.appendSliceAssumeCapacity(bytes); |
| 11788 | self.metadata_string_indices.appendAssumeCapacity(@intCast(self.metadata_string_bytes.items.len)); |
| 11789 | } |
| 11790 | return @enumFromInt(gop.index); |
| 11791 | } |
| 11792 | |
| 11793 | pub fn metadataStringFromString(self: *Builder, str: String) Allocator.Error!MetadataString { |
| 11794 | if (str == .none or str == .empty) return MetadataString.none; |
| 11795 | return try self.metadataString(str.slice(self).?); |
| 11796 | } |
| 11797 | |
| 11798 | pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!MetadataString { |
| 11799 | try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1); |
| 11800 | try self.metadata_string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args))); |
| 11801 | try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 11802 | return self.metadataStringFmtAssumeCapacity(fmt_str, fmt_args); |
| 11803 | } |
| 11804 | |
| 11805 | pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString { |
| 11806 | self.metadata_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable; |
| 11807 | return self.trailingMetadataStringAssumeCapacity(); |
| 11808 | } |
| 11809 | |
| 11810 | pub fn trailingMetadataString(self: *Builder) Allocator.Error!MetadataString { |
| 11811 | try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 11812 | try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1); |
| 11813 | return self.trailingMetadataStringAssumeCapacity(); |
| 11814 | } |
| 11815 | |
| 11816 | pub fn trailingMetadataStringAssumeCapacity(self: *Builder) MetadataString { |
| 11817 | const start = self.metadata_string_indices.getLast(); |
| 11818 | const bytes: []const u8 = self.metadata_string_bytes.items[start..]; |
| 11819 | const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); |
| 11820 | if (gop.found_existing) { |
| 11821 | self.metadata_string_bytes.shrinkRetainingCapacity(start); |
| 11822 | } else { |
| 11823 | self.metadata_string_indices.appendAssumeCapacity(@intCast(self.metadata_string_bytes.items.len)); |
| 11824 | } |
| 11825 | return @enumFromInt(gop.index); |
| 11826 | } |
| 11827 | |
| 11828 | pub fn debugNamed(self: *Builder, name: MetadataString, operands: []const Metadata) Allocator.Error!void { |
| 11829 | try self.metadata_extra.ensureUnusedCapacity(self.gpa, operands.len); |
| 11830 | try self.metadata_named.ensureUnusedCapacity(self.gpa, 1); |
| 11831 | self.debugNamedAssumeCapacity(name, operands); |
| 11832 | } |
| 11833 | |
| 11834 | fn debugNone(self: *Builder) Allocator.Error!Metadata { |
| 11835 | try self.ensureUnusedMetadataCapacity(1, NoExtra, 0); |
| 11836 | return self.debugNoneAssumeCapacity(); |
| 11837 | } |
| 11838 | |
| 11839 | pub fn debugFile( |
| 11840 | self: *Builder, |
| 11841 | filename: MetadataString, |
| 11842 | directory: MetadataString, |
| 11843 | ) Allocator.Error!Metadata { |
| 11844 | try self.ensureUnusedMetadataCapacity(1, Metadata.File, 0); |
| 11845 | return self.debugFileAssumeCapacity(filename, directory); |
| 11846 | } |
| 11847 | |
| 11848 | pub fn debugCompileUnit( |
| 11849 | self: *Builder, |
| 11850 | file: Metadata, |
| 11851 | producer: MetadataString, |
| 11852 | enums: Metadata, |
| 11853 | globals: Metadata, |
| 11854 | options: Metadata.CompileUnit.Options, |
| 11855 | ) Allocator.Error!Metadata { |
| 11856 | try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0); |
| 11857 | return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, options); |
| 11858 | } |
| 11859 | |
| 11860 | pub fn debugSubprogram( |
| 11861 | self: *Builder, |
| 11862 | file: Metadata, |
| 11863 | name: MetadataString, |
| 11864 | linkage_name: MetadataString, |
| 11865 | line: u32, |
| 11866 | scope_line: u32, |
| 11867 | ty: Metadata, |
| 11868 | options: Metadata.Subprogram.Options, |
| 11869 | compile_unit: Metadata, |
| 11870 | ) Allocator.Error!Metadata { |
| 11871 | try self.ensureUnusedMetadataCapacity(1, Metadata.Subprogram, 0); |
| 11872 | return self.debugSubprogramAssumeCapacity( |
| 11873 | file, |
| 11874 | name, |
| 11875 | linkage_name, |
| 11876 | line, |
| 11877 | scope_line, |
| 11878 | ty, |
| 11879 | options, |
| 11880 | compile_unit, |
| 11881 | ); |
| 11882 | } |
| 11883 | |
| 11884 | pub fn debugLexicalBlock(self: *Builder, scope: Metadata, file: Metadata, line: u32, column: u32) Allocator.Error!Metadata { |
| 11885 | try self.ensureUnusedMetadataCapacity(1, Metadata.LexicalBlock, 0); |
| 11886 | return self.debugLexicalBlockAssumeCapacity(scope, file, line, column); |
| 11887 | } |
| 11888 | |
| 11889 | pub fn debugLocation(self: *Builder, line: u32, column: u32, scope: Metadata, inlined_at: Metadata) Allocator.Error!Metadata { |
| 11890 | try self.ensureUnusedMetadataCapacity(1, Metadata.Location, 0); |
| 11891 | return self.debugLocationAssumeCapacity(line, column, scope, inlined_at); |
| 11892 | } |
| 11893 | |
| 11894 | pub fn debugBoolType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { |
| 11895 | try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); |
| 11896 | return self.debugBoolTypeAssumeCapacity(name, size_in_bits); |
| 11897 | } |
| 11898 | |
| 11899 | pub fn debugUnsignedType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { |
| 11900 | try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); |
| 11901 | return self.debugUnsignedTypeAssumeCapacity(name, size_in_bits); |
| 11902 | } |
| 11903 | |
| 11904 | pub fn debugSignedType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { |
| 11905 | try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); |
| 11906 | return self.debugSignedTypeAssumeCapacity(name, size_in_bits); |
| 11907 | } |
| 11908 | |
| 11909 | pub fn debugFloatType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { |
| 11910 | try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); |
| 11911 | return self.debugFloatTypeAssumeCapacity(name, size_in_bits); |
| 11912 | } |
| 11913 | |
| 11914 | pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata { |
| 11915 | try self.metadata_forward_references.ensureUnusedCapacity(self.gpa, 1); |
| 11916 | return self.debugForwardReferenceAssumeCapacity(); |
| 11917 | } |
| 11918 | |
| 11919 | pub fn debugStructType( |
| 11920 | self: *Builder, |
| 11921 | name: MetadataString, |
| 11922 | file: Metadata, |
| 11923 | scope: Metadata, |
| 11924 | line: u32, |
| 11925 | underlying_type: Metadata, |
| 11926 | size_in_bits: u64, |
| 11927 | align_in_bits: u64, |
| 11928 | fields_tuple: Metadata, |
| 11929 | ) Allocator.Error!Metadata { |
| 11930 | try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); |
| 11931 | return self.debugStructTypeAssumeCapacity( |
| 11932 | name, |
| 11933 | file, |
| 11934 | scope, |
| 11935 | line, |
| 11936 | underlying_type, |
| 11937 | size_in_bits, |
| 11938 | align_in_bits, |
| 11939 | fields_tuple, |
| 11940 | ); |
| 11941 | } |
| 11942 | |
| 11943 | pub fn debugUnionType( |
| 11944 | self: *Builder, |
| 11945 | name: MetadataString, |
| 11946 | file: Metadata, |
| 11947 | scope: Metadata, |
| 11948 | line: u32, |
| 11949 | underlying_type: Metadata, |
| 11950 | size_in_bits: u64, |
| 11951 | align_in_bits: u64, |
| 11952 | fields_tuple: Metadata, |
| 11953 | ) Allocator.Error!Metadata { |
| 11954 | try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); |
| 11955 | return self.debugUnionTypeAssumeCapacity( |
| 11956 | name, |
| 11957 | file, |
| 11958 | scope, |
| 11959 | line, |
| 11960 | underlying_type, |
| 11961 | size_in_bits, |
| 11962 | align_in_bits, |
| 11963 | fields_tuple, |
| 11964 | ); |
| 11965 | } |
| 11966 | |
| 11967 | pub fn debugEnumerationType( |
| 11968 | self: *Builder, |
| 11969 | name: MetadataString, |
| 11970 | file: Metadata, |
| 11971 | scope: Metadata, |
| 11972 | line: u32, |
| 11973 | underlying_type: Metadata, |
| 11974 | size_in_bits: u64, |
| 11975 | align_in_bits: u64, |
| 11976 | fields_tuple: Metadata, |
| 11977 | ) Allocator.Error!Metadata { |
| 11978 | try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); |
| 11979 | return self.debugEnumerationTypeAssumeCapacity( |
| 11980 | name, |
| 11981 | file, |
| 11982 | scope, |
| 11983 | line, |
| 11984 | underlying_type, |
| 11985 | size_in_bits, |
| 11986 | align_in_bits, |
| 11987 | fields_tuple, |
| 11988 | ); |
| 11989 | } |
| 11990 | |
| 11991 | pub fn debugArrayType( |
| 11992 | self: *Builder, |
| 11993 | name: MetadataString, |
| 11994 | file: Metadata, |
| 11995 | scope: Metadata, |
| 11996 | line: u32, |
| 11997 | underlying_type: Metadata, |
| 11998 | size_in_bits: u64, |
| 11999 | align_in_bits: u64, |
| 12000 | fields_tuple: Metadata, |
| 12001 | ) Allocator.Error!Metadata { |
| 12002 | try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); |
| 12003 | return self.debugArrayTypeAssumeCapacity( |
| 12004 | name, |
| 12005 | file, |
| 12006 | scope, |
| 12007 | line, |
| 12008 | underlying_type, |
| 12009 | size_in_bits, |
| 12010 | align_in_bits, |
| 12011 | fields_tuple, |
| 12012 | ); |
| 12013 | } |
| 12014 | |
| 12015 | pub fn debugVectorType( |
| 12016 | self: *Builder, |
| 12017 | name: MetadataString, |
| 12018 | file: Metadata, |
| 12019 | scope: Metadata, |
| 12020 | line: u32, |
| 12021 | underlying_type: Metadata, |
| 12022 | size_in_bits: u64, |
| 12023 | align_in_bits: u64, |
| 12024 | fields_tuple: Metadata, |
| 12025 | ) Allocator.Error!Metadata { |
| 12026 | try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); |
| 12027 | return self.debugVectorTypeAssumeCapacity( |
| 12028 | name, |
| 12029 | file, |
| 12030 | scope, |
| 12031 | line, |
| 12032 | underlying_type, |
| 12033 | size_in_bits, |
| 12034 | align_in_bits, |
| 12035 | fields_tuple, |
| 12036 | ); |
| 12037 | } |
| 12038 | |
| 12039 | pub fn debugPointerType( |
| 12040 | self: *Builder, |
| 12041 | name: MetadataString, |
| 12042 | file: Metadata, |
| 12043 | scope: Metadata, |
| 12044 | line: u32, |
| 12045 | underlying_type: Metadata, |
| 12046 | size_in_bits: u64, |
| 12047 | align_in_bits: u64, |
| 12048 | offset_in_bits: u64, |
| 12049 | ) Allocator.Error!Metadata { |
| 12050 | try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); |
| 12051 | return self.debugPointerTypeAssumeCapacity( |
| 12052 | name, |
| 12053 | file, |
| 12054 | scope, |
| 12055 | line, |
| 12056 | underlying_type, |
| 12057 | size_in_bits, |
| 12058 | align_in_bits, |
| 12059 | offset_in_bits, |
| 12060 | ); |
| 12061 | } |
| 12062 | |
| 12063 | pub fn debugMemberType( |
| 12064 | self: *Builder, |
| 12065 | name: MetadataString, |
| 12066 | file: Metadata, |
| 12067 | scope: Metadata, |
| 12068 | line: u32, |
| 12069 | underlying_type: Metadata, |
| 12070 | size_in_bits: u64, |
| 12071 | align_in_bits: u64, |
| 12072 | offset_in_bits: u64, |
| 12073 | ) Allocator.Error!Metadata { |
| 12074 | try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); |
| 12075 | return self.debugMemberTypeAssumeCapacity( |
| 12076 | name, |
| 12077 | file, |
| 12078 | scope, |
| 12079 | line, |
| 12080 | underlying_type, |
| 12081 | size_in_bits, |
| 12082 | align_in_bits, |
| 12083 | offset_in_bits, |
| 12084 | ); |
| 12085 | } |
| 12086 | |
| 12087 | pub fn debugSubroutineType( |
| 12088 | self: *Builder, |
| 12089 | types_tuple: Metadata, |
| 12090 | ) Allocator.Error!Metadata { |
| 12091 | try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0); |
| 12092 | return self.debugSubroutineTypeAssumeCapacity(types_tuple); |
| 12093 | } |
| 12094 | |
| 12095 | pub fn debugEnumerator( |
| 12096 | self: *Builder, |
| 12097 | name: MetadataString, |
| 12098 | unsigned: bool, |
| 12099 | bit_width: u32, |
| 12100 | value: std.math.big.int.Const, |
| 12101 | ) Allocator.Error!Metadata { |
| 12102 | assert(!(unsigned and !value.positive)); |
| 12103 | try self.ensureUnusedMetadataCapacity(1, Metadata.Enumerator, 0); |
| 12104 | try self.metadata_limbs.ensureUnusedCapacity(self.gpa, value.limbs.len); |
| 12105 | return self.debugEnumeratorAssumeCapacity(name, unsigned, bit_width, value); |
| 12106 | } |
| 12107 | |
| 12108 | pub fn debugSubrange( |
| 12109 | self: *Builder, |
| 12110 | lower_bound: Metadata, |
| 12111 | count: Metadata, |
| 12112 | ) Allocator.Error!Metadata { |
| 12113 | try self.ensureUnusedMetadataCapacity(1, Metadata.Subrange, 0); |
| 12114 | return self.debugSubrangeAssumeCapacity(lower_bound, count); |
| 12115 | } |
| 12116 | |
| 12117 | pub fn debugExpression( |
| 12118 | self: *Builder, |
| 12119 | elements: []const u32, |
| 12120 | ) Allocator.Error!Metadata { |
| 12121 | try self.ensureUnusedMetadataCapacity(1, Metadata.Expression, elements.len * @sizeOf(u32)); |
| 12122 | return self.debugExpressionAssumeCapacity(elements); |
| 12123 | } |
| 12124 | |
| 12125 | pub fn debugTuple( |
| 12126 | self: *Builder, |
| 12127 | elements: []const Metadata, |
| 12128 | ) Allocator.Error!Metadata { |
| 12129 | try self.ensureUnusedMetadataCapacity(1, Metadata.Tuple, elements.len * @sizeOf(Metadata)); |
| 12130 | return self.debugTupleAssumeCapacity(elements); |
| 12131 | } |
| 12132 | |
| 12133 | pub fn debugModuleFlag( |
| 12134 | self: *Builder, |
| 12135 | behavior: Metadata, |
| 12136 | name: MetadataString, |
| 12137 | constant: Metadata, |
| 12138 | ) Allocator.Error!Metadata { |
| 12139 | try self.ensureUnusedMetadataCapacity(1, Metadata.ModuleFlag, 0); |
| 12140 | return self.debugModuleFlagAssumeCapacity(behavior, name, constant); |
| 12141 | } |
| 12142 | |
| 12143 | pub fn debugLocalVar( |
| 12144 | self: *Builder, |
| 12145 | name: MetadataString, |
| 12146 | file: Metadata, |
| 12147 | scope: Metadata, |
| 12148 | line: u32, |
| 12149 | ty: Metadata, |
| 12150 | ) Allocator.Error!Metadata { |
| 12151 | try self.ensureUnusedMetadataCapacity(1, Metadata.LocalVar, 0); |
| 12152 | return self.debugLocalVarAssumeCapacity(name, file, scope, line, ty); |
| 12153 | } |
| 12154 | |
| 12155 | pub fn debugParameter( |
| 12156 | self: *Builder, |
| 12157 | name: MetadataString, |
| 12158 | file: Metadata, |
| 12159 | scope: Metadata, |
| 12160 | line: u32, |
| 12161 | ty: Metadata, |
| 12162 | arg_no: u32, |
| 12163 | ) Allocator.Error!Metadata { |
| 12164 | try self.ensureUnusedMetadataCapacity(1, Metadata.Parameter, 0); |
| 12165 | return self.debugParameterAssumeCapacity(name, file, scope, line, ty, arg_no); |
| 12166 | } |
| 12167 | |
| 12168 | pub fn debugGlobalVar( |
| 12169 | self: *Builder, |
| 12170 | name: MetadataString, |
| 12171 | linkage_name: MetadataString, |
| 12172 | file: Metadata, |
| 12173 | scope: Metadata, |
| 12174 | line: u32, |
| 12175 | ty: Metadata, |
| 12176 | variable: Variable.Index, |
| 12177 | options: Metadata.GlobalVar.Options, |
| 12178 | ) Allocator.Error!Metadata { |
| 12179 | try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVar, 0); |
| 12180 | return self.debugGlobalVarAssumeCapacity( |
| 12181 | name, |
| 12182 | linkage_name, |
| 12183 | file, |
| 12184 | scope, |
| 12185 | line, |
| 12186 | ty, |
| 12187 | variable, |
| 12188 | options, |
| 12189 | ); |
| 12190 | } |
| 12191 | |
| 12192 | pub fn debugGlobalVarExpression( |
| 12193 | self: *Builder, |
| 12194 | variable: Metadata, |
| 12195 | expression: Metadata, |
| 12196 | ) Allocator.Error!Metadata { |
| 12197 | try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVarExpression, 0); |
| 12198 | return self.debugGlobalVarExpressionAssumeCapacity(variable, expression); |
| 12199 | } |
| 12200 | |
| 12201 | pub fn debugConstant(self: *Builder, value: Constant) Allocator.Error!Metadata { |
| 12202 | try self.ensureUnusedMetadataCapacity(1, NoExtra, 0); |
| 12203 | return self.debugConstantAssumeCapacity(value); |
| 12204 | } |
| 12205 | |
| 12206 | pub fn debugForwardReferenceSetType(self: *Builder, fwd_ref: Metadata, ty: Metadata) void { |
| 12207 | assert( |
| 12208 | @intFromEnum(fwd_ref) >= Metadata.first_forward_reference and |
| 12209 | @intFromEnum(fwd_ref) <= Metadata.first_local_metadata, |
| 12210 | ); |
| 12211 | const index = @intFromEnum(fwd_ref) - Metadata.first_forward_reference; |
| 12212 | self.metadata_forward_references.items[index] = ty; |
| 12213 | } |
| 12214 | |
| 12215 | fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata { |
| 12216 | const Key = struct { |
| 12217 | tag: Metadata.Tag, |
| 12218 | value: @TypeOf(value), |
| 12219 | }; |
| 12220 | const Adapter = struct { |
| 12221 | builder: *const Builder, |
| 12222 | pub fn hash(_: @This(), key: Key) u32 { |
| 12223 | var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag))); |
| 12224 | inline for (std.meta.fields(@TypeOf(value))) |field| { |
| 12225 | hasher.update(std.mem.asBytes(&@field(key.value, field.name))); |
| 12226 | } |
| 12227 | return @truncate(hasher.final()); |
| 12228 | } |
| 12229 | |
| 12230 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 12231 | if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; |
| 12232 | const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; |
| 12233 | const rhs_extra = ctx.builder.metadataExtraData(@TypeOf(value), rhs_data); |
| 12234 | return std.meta.eql(lhs_key.value, rhs_extra); |
| 12235 | } |
| 12236 | }; |
| 12237 | |
| 12238 | const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( |
| 12239 | Key{ .tag = tag, .value = value }, |
| 12240 | Adapter{ .builder = self }, |
| 12241 | ); |
| 12242 | |
| 12243 | if (!gop.found_existing) { |
| 12244 | gop.key_ptr.* = {}; |
| 12245 | gop.value_ptr.* = {}; |
| 12246 | self.metadata_items.appendAssumeCapacity(.{ |
| 12247 | .tag = tag, |
| 12248 | .data = self.addMetadataExtraAssumeCapacity(value), |
| 12249 | }); |
| 12250 | } |
| 12251 | return @enumFromInt(gop.index); |
| 12252 | } |
| 12253 | |
| 12254 | fn metadataDistinctAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata { |
| 12255 | const Key = struct { tag: Metadata.Tag, index: Metadata }; |
| 12256 | const Adapter = struct { |
| 12257 | pub fn hash(_: @This(), key: Key) u32 { |
| 12258 | return @truncate(std.hash.Wyhash.hash( |
| 12259 | std.hash.uint32(@intFromEnum(key.tag)), |
| 12260 | std.mem.asBytes(&key.index), |
| 12261 | )); |
| 12262 | } |
| 12263 | |
| 12264 | pub fn eql(_: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 12265 | return @intFromEnum(lhs_key.index) == rhs_index; |
| 12266 | } |
| 12267 | }; |
| 12268 | |
| 12269 | const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( |
| 12270 | Key{ .tag = tag, .index = @enumFromInt(self.metadata_map.count()) }, |
| 12271 | Adapter{}, |
| 12272 | ); |
| 12273 | |
| 12274 | if (!gop.found_existing) { |
| 12275 | gop.key_ptr.* = {}; |
| 12276 | gop.value_ptr.* = {}; |
| 12277 | self.metadata_items.appendAssumeCapacity(.{ |
| 12278 | .tag = tag, |
| 12279 | .data = self.addMetadataExtraAssumeCapacity(value), |
| 12280 | }); |
| 12281 | } |
| 12282 | return @enumFromInt(gop.index); |
| 12283 | } |
| 12284 | |
| 12285 | fn debugNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []const Metadata) void { |
| 12286 | assert(!self.strip); |
| 12287 | assert(name != .none); |
| 12288 | const extra_index: u32 = @intCast(self.metadata_extra.items.len); |
| 12289 | self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands)); |
| 12290 | |
| 12291 | const gop = self.metadata_named.getOrPutAssumeCapacity(name); |
| 12292 | gop.value_ptr.* = .{ |
| 12293 | .index = extra_index, |
| 12294 | .len = @intCast(operands.len), |
| 12295 | }; |
| 12296 | } |
| 12297 | |
| 12298 | pub fn debugNoneAssumeCapacity(self: *Builder) Metadata { |
| 12299 | assert(!self.strip); |
| 12300 | return self.metadataSimpleAssumeCapacity(.none, .{}); |
| 12301 | } |
| 12302 | |
| 12303 | fn debugFileAssumeCapacity( |
| 12304 | self: *Builder, |
| 12305 | filename: MetadataString, |
| 12306 | directory: MetadataString, |
| 12307 | ) Metadata { |
| 12308 | assert(!self.strip); |
| 12309 | return self.metadataSimpleAssumeCapacity(.file, Metadata.File{ |
| 12310 | .filename = filename, |
| 12311 | .directory = directory, |
| 12312 | }); |
| 12313 | } |
| 12314 | |
| 12315 | pub fn debugCompileUnitAssumeCapacity( |
| 12316 | self: *Builder, |
| 12317 | file: Metadata, |
| 12318 | producer: MetadataString, |
| 12319 | enums: Metadata, |
| 12320 | globals: Metadata, |
| 12321 | options: Metadata.CompileUnit.Options, |
| 12322 | ) Metadata { |
| 12323 | assert(!self.strip); |
| 12324 | return self.metadataDistinctAssumeCapacity( |
| 12325 | if (options.optimized) .@"compile_unit optimized" else .compile_unit, |
| 12326 | Metadata.CompileUnit{ |
| 12327 | .file = file, |
| 12328 | .producer = producer, |
| 12329 | .enums = enums, |
| 12330 | .globals = globals, |
| 12331 | }, |
| 12332 | ); |
| 12333 | } |
| 12334 | |
| 12335 | fn debugSubprogramAssumeCapacity( |
| 12336 | self: *Builder, |
| 12337 | file: Metadata, |
| 12338 | name: MetadataString, |
| 12339 | linkage_name: MetadataString, |
| 12340 | line: u32, |
| 12341 | scope_line: u32, |
| 12342 | ty: Metadata, |
| 12343 | options: Metadata.Subprogram.Options, |
| 12344 | compile_unit: Metadata, |
| 12345 | ) Metadata { |
| 12346 | assert(!self.strip); |
| 12347 | const tag: Metadata.Tag = @enumFromInt(@intFromEnum(Metadata.Tag.subprogram) + |
| 12348 | @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))); |
| 12349 | return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{ |
| 12350 | .file = file, |
| 12351 | .name = name, |
| 12352 | .linkage_name = linkage_name, |
| 12353 | .line = line, |
| 12354 | .scope_line = scope_line, |
| 12355 | .ty = ty, |
| 12356 | .di_flags = options.di_flags, |
| 12357 | .compile_unit = compile_unit, |
| 12358 | }); |
| 12359 | } |
| 12360 | |
| 12361 | fn debugLexicalBlockAssumeCapacity(self: *Builder, scope: Metadata, file: Metadata, line: u32, column: u32) Metadata { |
| 12362 | assert(!self.strip); |
| 12363 | return self.metadataSimpleAssumeCapacity(.lexical_block, Metadata.LexicalBlock{ |
| 12364 | .scope = scope, |
| 12365 | .file = file, |
| 12366 | .line = line, |
| 12367 | .column = column, |
| 12368 | }); |
| 12369 | } |
| 12370 | |
| 12371 | fn debugLocationAssumeCapacity(self: *Builder, line: u32, column: u32, scope: Metadata, inlined_at: Metadata) Metadata { |
| 12372 | assert(!self.strip); |
| 12373 | return self.metadataSimpleAssumeCapacity(.location, Metadata.Location{ |
| 12374 | .line = line, |
| 12375 | .column = column, |
| 12376 | .scope = scope, |
| 12377 | .inlined_at = inlined_at, |
| 12378 | }); |
| 12379 | } |
| 12380 | |
| 12381 | fn debugBoolTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { |
| 12382 | assert(!self.strip); |
| 12383 | return self.metadataSimpleAssumeCapacity(.basic_bool_type, Metadata.BasicType{ |
| 12384 | .name = name, |
| 12385 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12386 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12387 | }); |
| 12388 | } |
| 12389 | |
| 12390 | fn debugUnsignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { |
| 12391 | assert(!self.strip); |
| 12392 | return self.metadataSimpleAssumeCapacity(.basic_unsigned_type, Metadata.BasicType{ |
| 12393 | .name = name, |
| 12394 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12395 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12396 | }); |
| 12397 | } |
| 12398 | |
| 12399 | fn debugSignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { |
| 12400 | assert(!self.strip); |
| 12401 | return self.metadataSimpleAssumeCapacity(.basic_signed_type, Metadata.BasicType{ |
| 12402 | .name = name, |
| 12403 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12404 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12405 | }); |
| 12406 | } |
| 12407 | |
| 12408 | fn debugFloatTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { |
| 12409 | assert(!self.strip); |
| 12410 | return self.metadataSimpleAssumeCapacity(.basic_float_type, Metadata.BasicType{ |
| 12411 | .name = name, |
| 12412 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12413 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12414 | }); |
| 12415 | } |
| 12416 | |
| 12417 | fn debugForwardReferenceAssumeCapacity(self: *Builder) Metadata { |
| 12418 | assert(!self.strip); |
| 12419 | const index = Metadata.first_forward_reference + self.metadata_forward_references.items.len; |
| 12420 | self.metadata_forward_references.appendAssumeCapacity(.none); |
| 12421 | return @enumFromInt(index); |
| 12422 | } |
| 12423 | |
| 12424 | fn debugStructTypeAssumeCapacity( |
| 12425 | self: *Builder, |
| 12426 | name: MetadataString, |
| 12427 | file: Metadata, |
| 12428 | scope: Metadata, |
| 12429 | line: u32, |
| 12430 | underlying_type: Metadata, |
| 12431 | size_in_bits: u64, |
| 12432 | align_in_bits: u64, |
| 12433 | fields_tuple: Metadata, |
| 12434 | ) Metadata { |
| 12435 | assert(!self.strip); |
| 12436 | return self.debugCompositeTypeAssumeCapacity( |
| 12437 | .composite_struct_type, |
| 12438 | name, |
| 12439 | file, |
| 12440 | scope, |
| 12441 | line, |
| 12442 | underlying_type, |
| 12443 | size_in_bits, |
| 12444 | align_in_bits, |
| 12445 | fields_tuple, |
| 12446 | ); |
| 12447 | } |
| 12448 | |
| 12449 | fn debugUnionTypeAssumeCapacity( |
| 12450 | self: *Builder, |
| 12451 | name: MetadataString, |
| 12452 | file: Metadata, |
| 12453 | scope: Metadata, |
| 12454 | line: u32, |
| 12455 | underlying_type: Metadata, |
| 12456 | size_in_bits: u64, |
| 12457 | align_in_bits: u64, |
| 12458 | fields_tuple: Metadata, |
| 12459 | ) Metadata { |
| 12460 | assert(!self.strip); |
| 12461 | return self.debugCompositeTypeAssumeCapacity( |
| 12462 | .composite_union_type, |
| 12463 | name, |
| 12464 | file, |
| 12465 | scope, |
| 12466 | line, |
| 12467 | underlying_type, |
| 12468 | size_in_bits, |
| 12469 | align_in_bits, |
| 12470 | fields_tuple, |
| 12471 | ); |
| 12472 | } |
| 12473 | |
| 12474 | fn debugEnumerationTypeAssumeCapacity( |
| 12475 | self: *Builder, |
| 12476 | name: MetadataString, |
| 12477 | file: Metadata, |
| 12478 | scope: Metadata, |
| 12479 | line: u32, |
| 12480 | underlying_type: Metadata, |
| 12481 | size_in_bits: u64, |
| 12482 | align_in_bits: u64, |
| 12483 | fields_tuple: Metadata, |
| 12484 | ) Metadata { |
| 12485 | assert(!self.strip); |
| 12486 | return self.debugCompositeTypeAssumeCapacity( |
| 12487 | .composite_enumeration_type, |
| 12488 | name, |
| 12489 | file, |
| 12490 | scope, |
| 12491 | line, |
| 12492 | underlying_type, |
| 12493 | size_in_bits, |
| 12494 | align_in_bits, |
| 12495 | fields_tuple, |
| 12496 | ); |
| 12497 | } |
| 12498 | |
| 12499 | fn debugArrayTypeAssumeCapacity( |
| 12500 | self: *Builder, |
| 12501 | name: MetadataString, |
| 12502 | file: Metadata, |
| 12503 | scope: Metadata, |
| 12504 | line: u32, |
| 12505 | underlying_type: Metadata, |
| 12506 | size_in_bits: u64, |
| 12507 | align_in_bits: u64, |
| 12508 | fields_tuple: Metadata, |
| 12509 | ) Metadata { |
| 12510 | assert(!self.strip); |
| 12511 | return self.debugCompositeTypeAssumeCapacity( |
| 12512 | .composite_array_type, |
| 12513 | name, |
| 12514 | file, |
| 12515 | scope, |
| 12516 | line, |
| 12517 | underlying_type, |
| 12518 | size_in_bits, |
| 12519 | align_in_bits, |
| 12520 | fields_tuple, |
| 12521 | ); |
| 12522 | } |
| 12523 | |
| 12524 | fn debugVectorTypeAssumeCapacity( |
| 12525 | self: *Builder, |
| 12526 | name: MetadataString, |
| 12527 | file: Metadata, |
| 12528 | scope: Metadata, |
| 12529 | line: u32, |
| 12530 | underlying_type: Metadata, |
| 12531 | size_in_bits: u64, |
| 12532 | align_in_bits: u64, |
| 12533 | fields_tuple: Metadata, |
| 12534 | ) Metadata { |
| 12535 | assert(!self.strip); |
| 12536 | return self.debugCompositeTypeAssumeCapacity( |
| 12537 | .composite_vector_type, |
| 12538 | name, |
| 12539 | file, |
| 12540 | scope, |
| 12541 | line, |
| 12542 | underlying_type, |
| 12543 | size_in_bits, |
| 12544 | align_in_bits, |
| 12545 | fields_tuple, |
| 12546 | ); |
| 12547 | } |
| 12548 | |
| 12549 | fn debugCompositeTypeAssumeCapacity( |
| 12550 | self: *Builder, |
| 12551 | tag: Metadata.Tag, |
| 12552 | name: MetadataString, |
| 12553 | file: Metadata, |
| 12554 | scope: Metadata, |
| 12555 | line: u32, |
| 12556 | underlying_type: Metadata, |
| 12557 | size_in_bits: u64, |
| 12558 | align_in_bits: u64, |
| 12559 | fields_tuple: Metadata, |
| 12560 | ) Metadata { |
| 12561 | assert(!self.strip); |
| 12562 | return self.metadataSimpleAssumeCapacity(tag, Metadata.CompositeType{ |
| 12563 | .name = name, |
| 12564 | .file = file, |
| 12565 | .scope = scope, |
| 12566 | .line = line, |
| 12567 | .underlying_type = underlying_type, |
| 12568 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12569 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12570 | .align_in_bits_lo = @truncate(align_in_bits), |
| 12571 | .align_in_bits_hi = @truncate(align_in_bits >> 32), |
| 12572 | .fields_tuple = fields_tuple, |
| 12573 | }); |
| 12574 | } |
| 12575 | |
| 12576 | fn debugPointerTypeAssumeCapacity( |
| 12577 | self: *Builder, |
| 12578 | name: MetadataString, |
| 12579 | file: Metadata, |
| 12580 | scope: Metadata, |
| 12581 | line: u32, |
| 12582 | underlying_type: Metadata, |
| 12583 | size_in_bits: u64, |
| 12584 | align_in_bits: u64, |
| 12585 | offset_in_bits: u64, |
| 12586 | ) Metadata { |
| 12587 | assert(!self.strip); |
| 12588 | return self.metadataSimpleAssumeCapacity(.derived_pointer_type, Metadata.DerivedType{ |
| 12589 | .name = name, |
| 12590 | .file = file, |
| 12591 | .scope = scope, |
| 12592 | .line = line, |
| 12593 | .underlying_type = underlying_type, |
| 12594 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12595 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12596 | .align_in_bits_lo = @truncate(align_in_bits), |
| 12597 | .align_in_bits_hi = @truncate(align_in_bits >> 32), |
| 12598 | .offset_in_bits_lo = @truncate(offset_in_bits), |
| 12599 | .offset_in_bits_hi = @truncate(offset_in_bits >> 32), |
| 12600 | }); |
| 12601 | } |
| 12602 | |
| 12603 | fn debugMemberTypeAssumeCapacity( |
| 12604 | self: *Builder, |
| 12605 | name: MetadataString, |
| 12606 | file: Metadata, |
| 12607 | scope: Metadata, |
| 12608 | line: u32, |
| 12609 | underlying_type: Metadata, |
| 12610 | size_in_bits: u64, |
| 12611 | align_in_bits: u64, |
| 12612 | offset_in_bits: u64, |
| 12613 | ) Metadata { |
| 12614 | assert(!self.strip); |
| 12615 | return self.metadataSimpleAssumeCapacity(.derived_member_type, Metadata.DerivedType{ |
| 12616 | .name = name, |
| 12617 | .file = file, |
| 12618 | .scope = scope, |
| 12619 | .line = line, |
| 12620 | .underlying_type = underlying_type, |
| 12621 | .size_in_bits_lo = @truncate(size_in_bits), |
| 12622 | .size_in_bits_hi = @truncate(size_in_bits >> 32), |
| 12623 | .align_in_bits_lo = @truncate(align_in_bits), |
| 12624 | .align_in_bits_hi = @truncate(align_in_bits >> 32), |
| 12625 | .offset_in_bits_lo = @truncate(offset_in_bits), |
| 12626 | .offset_in_bits_hi = @truncate(offset_in_bits >> 32), |
| 12627 | }); |
| 12628 | } |
| 12629 | |
| 12630 | fn debugSubroutineTypeAssumeCapacity( |
| 12631 | self: *Builder, |
| 12632 | types_tuple: Metadata, |
| 12633 | ) Metadata { |
| 12634 | assert(!self.strip); |
| 12635 | return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{ |
| 12636 | .types_tuple = types_tuple, |
| 12637 | }); |
| 12638 | } |
| 12639 | |
| 12640 | fn debugEnumeratorAssumeCapacity( |
| 12641 | self: *Builder, |
| 12642 | name: MetadataString, |
| 12643 | unsigned: bool, |
| 12644 | bit_width: u32, |
| 12645 | value: std.math.big.int.Const, |
| 12646 | ) Metadata { |
| 12647 | assert(!self.strip); |
| 12648 | const Key = struct { |
| 12649 | tag: Metadata.Tag, |
| 12650 | name: MetadataString, |
| 12651 | bit_width: u32, |
| 12652 | value: std.math.big.int.Const, |
| 12653 | }; |
| 12654 | const Adapter = struct { |
| 12655 | builder: *const Builder, |
| 12656 | pub fn hash(_: @This(), key: Key) u32 { |
| 12657 | var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag))); |
| 12658 | hasher.update(std.mem.asBytes(&key.name)); |
| 12659 | hasher.update(std.mem.asBytes(&key.bit_width)); |
| 12660 | hasher.update(std.mem.sliceAsBytes(key.value.limbs)); |
| 12661 | return @truncate(hasher.final()); |
| 12662 | } |
| 12663 | |
| 12664 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 12665 | if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; |
| 12666 | const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; |
| 12667 | const rhs_extra = ctx.builder.metadataExtraData(Metadata.Enumerator, rhs_data); |
| 12668 | const limbs = ctx.builder.metadata_limbs |
| 12669 | .items[rhs_extra.limbs_index..][0..rhs_extra.limbs_len]; |
| 12670 | const rhs_value = std.math.big.int.Const{ |
| 12671 | .limbs = limbs, |
| 12672 | .positive = lhs_key.value.positive, |
| 12673 | }; |
| 12674 | return lhs_key.name == rhs_extra.name and |
| 12675 | lhs_key.bit_width == rhs_extra.bit_width and |
| 12676 | lhs_key.value.eql(rhs_value); |
| 12677 | } |
| 12678 | }; |
| 12679 | |
| 12680 | const tag: Metadata.Tag = if (unsigned) |
| 12681 | .enumerator_unsigned |
| 12682 | else if (value.positive) |
| 12683 | .enumerator_signed_positive |
| 12684 | else |
| 12685 | .enumerator_signed_negative; |
| 12686 | |
| 12687 | assert(!(tag == .enumerator_unsigned and !value.positive)); |
| 12688 | |
| 12689 | const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( |
| 12690 | Key{ |
| 12691 | .tag = tag, |
| 12692 | .name = name, |
| 12693 | .bit_width = bit_width, |
| 12694 | .value = value, |
| 12695 | }, |
| 12696 | Adapter{ .builder = self }, |
| 12697 | ); |
| 12698 | |
| 12699 | if (!gop.found_existing) { |
| 12700 | gop.key_ptr.* = {}; |
| 12701 | gop.value_ptr.* = {}; |
| 12702 | self.metadata_items.appendAssumeCapacity(.{ |
| 12703 | .tag = tag, |
| 12704 | .data = self.addMetadataExtraAssumeCapacity(Metadata.Enumerator{ |
| 12705 | .name = name, |
| 12706 | .bit_width = bit_width, |
| 12707 | .limbs_index = @intCast(self.metadata_limbs.items.len), |
| 12708 | .limbs_len = @intCast(value.limbs.len), |
| 12709 | }), |
| 12710 | }); |
| 12711 | self.metadata_limbs.appendSliceAssumeCapacity(value.limbs); |
| 12712 | } |
| 12713 | return @enumFromInt(gop.index); |
| 12714 | } |
| 12715 | |
| 12716 | fn debugSubrangeAssumeCapacity( |
| 12717 | self: *Builder, |
| 12718 | lower_bound: Metadata, |
| 12719 | count: Metadata, |
| 12720 | ) Metadata { |
| 12721 | assert(!self.strip); |
| 12722 | return self.metadataSimpleAssumeCapacity(.subrange, Metadata.Subrange{ |
| 12723 | .lower_bound = lower_bound, |
| 12724 | .count = count, |
| 12725 | }); |
| 12726 | } |
| 12727 | |
| 12728 | fn debugExpressionAssumeCapacity( |
| 12729 | self: *Builder, |
| 12730 | elements: []const u32, |
| 12731 | ) Metadata { |
| 12732 | assert(!self.strip); |
| 12733 | const Key = struct { |
| 12734 | elements: []const u32, |
| 12735 | }; |
| 12736 | const Adapter = struct { |
| 12737 | builder: *const Builder, |
| 12738 | pub fn hash(_: @This(), key: Key) u32 { |
| 12739 | var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.expression))); |
| 12740 | hasher.update(std.mem.sliceAsBytes(key.elements)); |
| 12741 | return @truncate(hasher.final()); |
| 12742 | } |
| 12743 | |
| 12744 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 12745 | if (Metadata.Tag.expression != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; |
| 12746 | const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; |
| 12747 | var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Expression, rhs_data); |
| 12748 | return std.mem.eql( |
| 12749 | u32, |
| 12750 | lhs_key.elements, |
| 12751 | rhs_extra.trail.next(rhs_extra.data.elements_len, u32, ctx.builder), |
| 12752 | ); |
| 12753 | } |
| 12754 | }; |
| 12755 | |
| 12756 | const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( |
| 12757 | Key{ .elements = elements }, |
| 12758 | Adapter{ .builder = self }, |
| 12759 | ); |
| 12760 | |
| 12761 | if (!gop.found_existing) { |
| 12762 | gop.key_ptr.* = {}; |
| 12763 | gop.value_ptr.* = {}; |
| 12764 | self.metadata_items.appendAssumeCapacity(.{ |
| 12765 | .tag = .expression, |
| 12766 | .data = self.addMetadataExtraAssumeCapacity(Metadata.Expression{ |
| 12767 | .elements_len = @intCast(elements.len), |
| 12768 | }), |
| 12769 | }); |
| 12770 | self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements)); |
| 12771 | } |
| 12772 | return @enumFromInt(gop.index); |
| 12773 | } |
| 12774 | |
| 12775 | fn debugTupleAssumeCapacity( |
| 12776 | self: *Builder, |
| 12777 | elements: []const Metadata, |
| 12778 | ) Metadata { |
| 12779 | assert(!self.strip); |
| 12780 | const Key = struct { |
| 12781 | elements: []const Metadata, |
| 12782 | }; |
| 12783 | const Adapter = struct { |
| 12784 | builder: *const Builder, |
| 12785 | pub fn hash(_: @This(), key: Key) u32 { |
| 12786 | var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.tuple))); |
| 12787 | hasher.update(std.mem.sliceAsBytes(key.elements)); |
| 12788 | return @truncate(hasher.final()); |
| 12789 | } |
| 12790 | |
| 12791 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 12792 | if (Metadata.Tag.tuple != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; |
| 12793 | const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; |
| 12794 | var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Tuple, rhs_data); |
| 12795 | return std.mem.eql( |
| 12796 | Metadata, |
| 12797 | lhs_key.elements, |
| 12798 | rhs_extra.trail.next(rhs_extra.data.elements_len, Metadata, ctx.builder), |
| 12799 | ); |
| 12800 | } |
| 12801 | }; |
| 12802 | |
| 12803 | const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( |
| 12804 | Key{ .elements = elements }, |
| 12805 | Adapter{ .builder = self }, |
| 12806 | ); |
| 12807 | |
| 12808 | if (!gop.found_existing) { |
| 12809 | gop.key_ptr.* = {}; |
| 12810 | gop.value_ptr.* = {}; |
| 12811 | self.metadata_items.appendAssumeCapacity(.{ |
| 12812 | .tag = .tuple, |
| 12813 | .data = self.addMetadataExtraAssumeCapacity(Metadata.Tuple{ |
| 12814 | .elements_len = @intCast(elements.len), |
| 12815 | }), |
| 12816 | }); |
| 12817 | self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements)); |
| 12818 | } |
| 12819 | return @enumFromInt(gop.index); |
| 12820 | } |
| 12821 | |
| 12822 | fn debugModuleFlagAssumeCapacity( |
| 12823 | self: *Builder, |
| 12824 | behavior: Metadata, |
| 12825 | name: MetadataString, |
| 12826 | constant: Metadata, |
| 12827 | ) Metadata { |
| 12828 | assert(!self.strip); |
| 12829 | return self.metadataSimpleAssumeCapacity(.module_flag, Metadata.ModuleFlag{ |
| 12830 | .behavior = behavior, |
| 12831 | .name = name, |
| 12832 | .constant = constant, |
| 12833 | }); |
| 12834 | } |
| 12835 | |
| 12836 | fn debugLocalVarAssumeCapacity( |
| 12837 | self: *Builder, |
| 12838 | name: MetadataString, |
| 12839 | file: Metadata, |
| 12840 | scope: Metadata, |
| 12841 | line: u32, |
| 12842 | ty: Metadata, |
| 12843 | ) Metadata { |
| 12844 | assert(!self.strip); |
| 12845 | return self.metadataSimpleAssumeCapacity(.local_var, Metadata.LocalVar{ |
| 12846 | .name = name, |
| 12847 | .file = file, |
| 12848 | .scope = scope, |
| 12849 | .line = line, |
| 12850 | .ty = ty, |
| 12851 | }); |
| 12852 | } |
| 12853 | |
| 12854 | fn debugParameterAssumeCapacity( |
| 12855 | self: *Builder, |
| 12856 | name: MetadataString, |
| 12857 | file: Metadata, |
| 12858 | scope: Metadata, |
| 12859 | line: u32, |
| 12860 | ty: Metadata, |
| 12861 | arg_no: u32, |
| 12862 | ) Metadata { |
| 12863 | assert(!self.strip); |
| 12864 | return self.metadataSimpleAssumeCapacity(.parameter, Metadata.Parameter{ |
| 12865 | .name = name, |
| 12866 | .file = file, |
| 12867 | .scope = scope, |
| 12868 | .line = line, |
| 12869 | .ty = ty, |
| 12870 | .arg_no = arg_no, |
| 12871 | }); |
| 12872 | } |
| 12873 | |
| 12874 | fn debugGlobalVarAssumeCapacity( |
| 12875 | self: *Builder, |
| 12876 | name: MetadataString, |
| 12877 | linkage_name: MetadataString, |
| 12878 | file: Metadata, |
| 12879 | scope: Metadata, |
| 12880 | line: u32, |
| 12881 | ty: Metadata, |
| 12882 | variable: Variable.Index, |
| 12883 | options: Metadata.GlobalVar.Options, |
| 12884 | ) Metadata { |
| 12885 | assert(!self.strip); |
| 12886 | return self.metadataDistinctAssumeCapacity( |
| 12887 | if (options.local) .@"global_var local" else .global_var, |
| 12888 | Metadata.GlobalVar{ |
| 12889 | .name = name, |
| 12890 | .linkage_name = linkage_name, |
| 12891 | .file = file, |
| 12892 | .scope = scope, |
| 12893 | .line = line, |
| 12894 | .ty = ty, |
| 12895 | .variable = variable, |
| 12896 | }, |
| 12897 | ); |
| 12898 | } |
| 12899 | |
| 12900 | fn debugGlobalVarExpressionAssumeCapacity( |
| 12901 | self: *Builder, |
| 12902 | variable: Metadata, |
| 12903 | expression: Metadata, |
| 12904 | ) Metadata { |
| 12905 | assert(!self.strip); |
| 12906 | return self.metadataSimpleAssumeCapacity(.global_var_expression, Metadata.GlobalVarExpression{ |
| 12907 | .variable = variable, |
| 12908 | .expression = expression, |
| 12909 | }); |
| 12910 | } |
| 12911 | |
| 12912 | fn debugConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata { |
| 12913 | assert(!self.strip); |
| 12914 | const Adapter = struct { |
| 12915 | builder: *const Builder, |
| 12916 | pub fn hash(_: @This(), key: Constant) u32 { |
| 12917 | var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.constant))); |
| 12918 | hasher.update(std.mem.asBytes(&key)); |
| 12919 | return @truncate(hasher.final()); |
| 12920 | } |
| 12921 | |
| 12922 | pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool { |
| 12923 | if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; |
| 12924 | const rhs_data: Constant = @enumFromInt(ctx.builder.metadata_items.items(.data)[rhs_index]); |
| 12925 | return rhs_data == lhs_key; |
| 12926 | } |
| 12927 | }; |
| 12928 | |
| 12929 | const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( |
| 12930 | constant, |
| 12931 | Adapter{ .builder = self }, |
| 12932 | ); |
| 12933 | |
| 12934 | if (!gop.found_existing) { |
| 12935 | gop.key_ptr.* = {}; |
| 12936 | gop.value_ptr.* = {}; |
| 12937 | self.metadata_items.appendAssumeCapacity(.{ |
| 12938 | .tag = .constant, |
| 12939 | .data = @intFromEnum(constant), |
| 12940 | }); |
| 12941 | } |
| 12942 | return @enumFromInt(gop.index); |
| 12943 | } |
| 12944 | |
| 12945 | pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]const u32 { |
| 12946 | const BitcodeWriter = bitcode_writer.BitcodeWriter(&.{ Type, FunctionAttributes }); |
| 12947 | var bitcode = BitcodeWriter.init(allocator, .{ |
| 12948 | std.math.log2_int_ceil(usize, self.type_items.items.len), |
| 12949 | std.math.log2_int_ceil(usize, 1 + self.function_attributes_set.count()), |
| 12950 | }); |
| 12951 | errdefer bitcode.deinit(); |
| 12952 | |
| 12953 | // Write LLVM IR magic |
| 12954 | try bitcode.writeBits(ir.MAGIC, 32); |
| 12955 | |
| 12956 | var record: std.ArrayListUnmanaged(u64) = .{}; |
| 12957 | defer record.deinit(self.gpa); |
| 12958 | |
| 12959 | // IDENTIFICATION_BLOCK |
| 12960 | { |
| 12961 | const Identification = ir.Identification; |
| 12962 | var identification_block = try bitcode.enterTopBlock(Identification); |
| 12963 | |
| 12964 | const producer = try std.fmt.allocPrint(self.gpa, "zig {d}.{d}.{d}", .{ |
| 12965 | build_options.semver.major, |
| 12966 | build_options.semver.minor, |
| 12967 | build_options.semver.patch, |
| 12968 | }); |
| 12969 | defer self.gpa.free(producer); |
| 12970 | |
| 12971 | try identification_block.writeAbbrev(Identification.Version{ .string = producer }); |
| 12972 | try identification_block.writeAbbrev(Identification.Epoch{ .epoch = 0 }); |
| 12973 | |
| 12974 | try identification_block.end(); |
| 12975 | } |
| 12976 | |
| 12977 | // MODULE_BLOCK |
| 12978 | { |
| 12979 | const Module = ir.Module; |
| 12980 | var module_block = try bitcode.enterTopBlock(Module); |
| 12981 | |
| 12982 | try module_block.writeAbbrev(Module.Version{}); |
| 12983 | |
| 12984 | if (self.target_triple.slice(self)) |triple| { |
| 12985 | try module_block.writeAbbrev(Module.String{ |
| 12986 | .code = 2, |
| 12987 | .string = triple, |
| 12988 | }); |
| 12989 | } |
| 12990 | |
| 12991 | if (self.data_layout.slice(self)) |data_layout| { |
| 12992 | try module_block.writeAbbrev(Module.String{ |
| 12993 | .code = 3, |
| 12994 | .string = data_layout, |
| 12995 | }); |
| 12996 | } |
| 12997 | |
| 12998 | if (self.source_filename.slice(self)) |source_filename| { |
| 12999 | try module_block.writeAbbrev(Module.String{ |
| 13000 | .code = 16, |
| 13001 | .string = source_filename, |
| 13002 | }); |
| 13003 | } |
| 13004 | |
| 13005 | if (self.module_asm.items.len != 0) { |
| 13006 | try module_block.writeAbbrev(Module.String{ |
| 13007 | .code = 4, |
| 13008 | .string = self.module_asm.items, |
| 13009 | }); |
| 13010 | } |
| 13011 | |
| 13012 | // TYPE_BLOCK |
| 13013 | { |
| 13014 | var type_block = try module_block.enterSubBlock(ir.Type); |
| 13015 | |
| 13016 | try type_block.writeAbbrev(ir.Type.NumEntry{ .num = @intCast(self.type_items.items.len) }); |
| 13017 | |
| 13018 | for (self.type_items.items, 0..) |item, i| { |
| 13019 | const ty: Type = @enumFromInt(i); |
| 13020 | |
| 13021 | switch (item.tag) { |
| 13022 | .simple => try type_block.writeAbbrev(ir.Type.Simple{ .code = @truncate(item.data) }), |
| 13023 | .integer => try type_block.writeAbbrev(ir.Type.Integer{ .width = item.data }), |
| 13024 | .structure, |
| 13025 | .packed_structure, |
| 13026 | => |kind| { |
| 13027 | const is_packed = switch (kind) { |
| 13028 | .structure => false, |
| 13029 | .packed_structure => true, |
| 13030 | else => unreachable, |
| 13031 | }; |
| 13032 | var extra = self.typeExtraDataTrail(Type.Structure, item.data); |
| 13033 | try type_block.writeAbbrev(ir.Type.StructAnon{ |
| 13034 | .is_packed = is_packed, |
| 13035 | .types = extra.trail.next(extra.data.fields_len, Type, self), |
| 13036 | }); |
| 13037 | }, |
| 13038 | .named_structure => { |
| 13039 | const extra = self.typeExtraData(Type.NamedStructure, item.data); |
| 13040 | try type_block.writeAbbrev(ir.Type.StructName{ |
| 13041 | .string = extra.id.slice(self).?, |
| 13042 | }); |
| 13043 | |
| 13044 | switch (extra.body) { |
| 13045 | .none => try type_block.writeAbbrev(ir.Type.Opaque{}), |
| 13046 | else => { |
| 13047 | const real_struct = self.type_items.items[@intFromEnum(extra.body)]; |
| 13048 | const is_packed: bool = switch (real_struct.tag) { |
| 13049 | .structure => false, |
| 13050 | .packed_structure => true, |
| 13051 | else => unreachable, |
| 13052 | }; |
| 13053 | |
| 13054 | var real_extra = self.typeExtraDataTrail(Type.Structure, real_struct.data); |
| 13055 | try type_block.writeAbbrev(ir.Type.StructNamed{ |
| 13056 | .is_packed = is_packed, |
| 13057 | .types = real_extra.trail.next(real_extra.data.fields_len, Type, self), |
| 13058 | }); |
| 13059 | }, |
| 13060 | } |
| 13061 | }, |
| 13062 | .array, |
| 13063 | .small_array, |
| 13064 | => try type_block.writeAbbrev(ir.Type.Array{ |
| 13065 | .len = ty.aggregateLen(self), |
| 13066 | .child = ty.childType(self), |
| 13067 | }), |
| 13068 | .vector, |
| 13069 | .scalable_vector, |
| 13070 | => try type_block.writeAbbrev(ir.Type.Vector{ |
| 13071 | .len = ty.aggregateLen(self), |
| 13072 | .child = ty.childType(self), |
| 13073 | }), |
| 13074 | .pointer => try type_block.writeAbbrev(ir.Type.Pointer{ |
| 13075 | .addr_space = ty.pointerAddrSpace(self), |
| 13076 | }), |
| 13077 | .target => { |
| 13078 | var extra = self.typeExtraDataTrail(Type.Target, item.data); |
| 13079 | try type_block.writeAbbrev(ir.Type.StructName{ |
| 13080 | .string = extra.data.name.slice(self).?, |
| 13081 | }); |
| 13082 | |
| 13083 | const types = extra.trail.next(extra.data.types_len, Type, self); |
| 13084 | const ints = extra.trail.next(extra.data.ints_len, u32, self); |
| 13085 | |
| 13086 | try type_block.writeAbbrev(ir.Type.Target{ |
| 13087 | .num_types = extra.data.types_len, |
| 13088 | .types = types, |
| 13089 | .ints = ints, |
| 13090 | }); |
| 13091 | }, |
| 13092 | .function, .vararg_function => |kind| { |
| 13093 | const is_vararg = switch (kind) { |
| 13094 | .function => false, |
| 13095 | .vararg_function => true, |
| 13096 | else => unreachable, |
| 13097 | }; |
| 13098 | var extra = self.typeExtraDataTrail(Type.Function, item.data); |
| 13099 | try type_block.writeAbbrev(ir.Type.Function{ |
| 13100 | .is_vararg = is_vararg, |
| 13101 | .return_type = extra.data.ret, |
| 13102 | .param_types = extra.trail.next(extra.data.params_len, Type, self), |
| 13103 | }); |
| 13104 | }, |
| 13105 | } |
| 13106 | } |
| 13107 | |
| 13108 | try type_block.end(); |
| 13109 | } |
| 13110 | |
| 13111 | var attributes_set: std.AutoArrayHashMapUnmanaged(struct { |
| 13112 | attributes: Attributes, |
| 13113 | index: u32, |
| 13114 | }, void) = .{}; |
| 13115 | defer attributes_set.deinit(self.gpa); |
| 13116 | |
| 13117 | // PARAMATTR_GROUP_BLOCK |
| 13118 | { |
| 13119 | const ParamattrGroup = ir.ParamattrGroup; |
| 13120 | |
| 13121 | var paramattr_group_block = try module_block.enterSubBlock(ParamattrGroup); |
| 13122 | |
| 13123 | for (self.function_attributes_set.keys()) |func_attributes| { |
| 13124 | for (func_attributes.slice(self), 0..) |attributes, i| { |
| 13125 | const attributes_slice = attributes.slice(self); |
| 13126 | if (attributes_slice.len == 0) continue; |
| 13127 | |
| 13128 | const attr_gop = try attributes_set.getOrPut(self.gpa, .{ |
| 13129 | .attributes = attributes, |
| 13130 | .index = @intCast(i), |
| 13131 | }); |
| 13132 | |
| 13133 | if (attr_gop.found_existing) continue; |
| 13134 | |
| 13135 | record.clearRetainingCapacity(); |
| 13136 | try record.ensureUnusedCapacity(self.gpa, 2); |
| 13137 | |
| 13138 | record.appendAssumeCapacity(attr_gop.index); |
| 13139 | record.appendAssumeCapacity(switch (i) { |
| 13140 | 0 => 0xffffffff, |
| 13141 | else => i - 1, |
| 13142 | }); |
| 13143 | |
| 13144 | for (attributes_slice) |attr_index| { |
| 13145 | const kind = attr_index.getKind(self); |
| 13146 | switch (attr_index.toAttribute(self)) { |
| 13147 | .zeroext, |
| 13148 | .signext, |
| 13149 | .inreg, |
| 13150 | .@"noalias", |
| 13151 | .nocapture, |
| 13152 | .nofree, |
| 13153 | .nest, |
| 13154 | .returned, |
| 13155 | .nonnull, |
| 13156 | .swiftself, |
| 13157 | .swiftasync, |
| 13158 | .swifterror, |
| 13159 | .immarg, |
| 13160 | .noundef, |
| 13161 | .allocalign, |
| 13162 | .allocptr, |
| 13163 | .readnone, |
| 13164 | .readonly, |
| 13165 | .writeonly, |
| 13166 | .alwaysinline, |
| 13167 | .builtin, |
| 13168 | .cold, |
| 13169 | .convergent, |
| 13170 | .disable_sanitizer_information, |
| 13171 | .fn_ret_thunk_extern, |
| 13172 | .hot, |
| 13173 | .inlinehint, |
| 13174 | .jumptable, |
| 13175 | .minsize, |
| 13176 | .naked, |
| 13177 | .nobuiltin, |
| 13178 | .nocallback, |
| 13179 | .noduplicate, |
| 13180 | .noimplicitfloat, |
| 13181 | .@"noinline", |
| 13182 | .nomerge, |
| 13183 | .nonlazybind, |
| 13184 | .noprofile, |
| 13185 | .skipprofile, |
| 13186 | .noredzone, |
| 13187 | .noreturn, |
| 13188 | .norecurse, |
| 13189 | .willreturn, |
| 13190 | .nosync, |
| 13191 | .nounwind, |
| 13192 | .nosanitize_bounds, |
| 13193 | .nosanitize_coverage, |
| 13194 | .null_pointer_is_valid, |
| 13195 | .optforfuzzing, |
| 13196 | .optnone, |
| 13197 | .optsize, |
| 13198 | .returns_twice, |
| 13199 | .safestack, |
| 13200 | .sanitize_address, |
| 13201 | .sanitize_memory, |
| 13202 | .sanitize_thread, |
| 13203 | .sanitize_hwaddress, |
| 13204 | .sanitize_memtag, |
| 13205 | .speculative_load_hardening, |
| 13206 | .speculatable, |
| 13207 | .ssp, |
| 13208 | .sspstrong, |
| 13209 | .sspreq, |
| 13210 | .strictfp, |
| 13211 | .nocf_check, |
| 13212 | .shadowcallstack, |
| 13213 | .mustprogress, |
| 13214 | .no_sanitize_address, |
| 13215 | .no_sanitize_hwaddress, |
| 13216 | .sanitize_address_dyninit, |
| 13217 | => { |
| 13218 | try record.ensureUnusedCapacity(self.gpa, 2); |
| 13219 | record.appendAssumeCapacity(0); |
| 13220 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13221 | }, |
| 13222 | .byval, |
| 13223 | .byref, |
| 13224 | .preallocated, |
| 13225 | .inalloca, |
| 13226 | .sret, |
| 13227 | .elementtype, |
| 13228 | => |ty| { |
| 13229 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13230 | record.appendAssumeCapacity(6); |
| 13231 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13232 | record.appendAssumeCapacity(@intFromEnum(ty)); |
| 13233 | }, |
| 13234 | .@"align", |
| 13235 | .alignstack, |
| 13236 | => |alignment| { |
| 13237 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13238 | record.appendAssumeCapacity(1); |
| 13239 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13240 | record.appendAssumeCapacity(alignment.toByteUnits() orelse 0); |
| 13241 | }, |
| 13242 | .dereferenceable, |
| 13243 | .dereferenceable_or_null, |
| 13244 | => |size| { |
| 13245 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13246 | record.appendAssumeCapacity(1); |
| 13247 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13248 | record.appendAssumeCapacity(size); |
| 13249 | }, |
| 13250 | .nofpclass => |fpclass| { |
| 13251 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13252 | record.appendAssumeCapacity(1); |
| 13253 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13254 | record.appendAssumeCapacity(@as(u32, @bitCast(fpclass))); |
| 13255 | }, |
| 13256 | .allockind => |allockind| { |
| 13257 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13258 | record.appendAssumeCapacity(1); |
| 13259 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13260 | record.appendAssumeCapacity(@as(u32, @bitCast(allockind))); |
| 13261 | }, |
| 13262 | |
| 13263 | .allocsize => |allocsize| { |
| 13264 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13265 | record.appendAssumeCapacity(1); |
| 13266 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13267 | record.appendAssumeCapacity(@bitCast(allocsize.toLlvm())); |
| 13268 | }, |
| 13269 | .memory => |memory| { |
| 13270 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13271 | record.appendAssumeCapacity(1); |
| 13272 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13273 | record.appendAssumeCapacity(@as(u32, @bitCast(memory))); |
| 13274 | }, |
| 13275 | .uwtable => |uwtable| if (uwtable != .none) { |
| 13276 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13277 | record.appendAssumeCapacity(1); |
| 13278 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13279 | record.appendAssumeCapacity(@intFromEnum(uwtable)); |
| 13280 | }, |
| 13281 | .vscale_range => |vscale_range| { |
| 13282 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13283 | record.appendAssumeCapacity(1); |
| 13284 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13285 | record.appendAssumeCapacity(@bitCast(vscale_range.toLlvm())); |
| 13286 | }, |
| 13287 | .string => |string_attr| { |
| 13288 | const string_attr_kind_slice = string_attr.kind.slice(self).?; |
| 13289 | const string_attr_value_slice = if (string_attr.value != .none) |
| 13290 | string_attr.value.slice(self).? |
| 13291 | else |
| 13292 | null; |
| 13293 | |
| 13294 | try record.ensureUnusedCapacity( |
| 13295 | self.gpa, |
| 13296 | 2 + string_attr_kind_slice.len + if (string_attr_value_slice) |slice| slice.len + 1 else 0, |
| 13297 | ); |
| 13298 | record.appendAssumeCapacity(if (string_attr.value == .none) 3 else 4); |
| 13299 | for (string_attr.kind.slice(self).?) |c| { |
| 13300 | record.appendAssumeCapacity(c); |
| 13301 | } |
| 13302 | record.appendAssumeCapacity(0); |
| 13303 | if (string_attr_value_slice) |slice| { |
| 13304 | for (slice) |c| { |
| 13305 | record.appendAssumeCapacity(c); |
| 13306 | } |
| 13307 | record.appendAssumeCapacity(0); |
| 13308 | } |
| 13309 | }, |
| 13310 | .none => unreachable, |
| 13311 | } |
| 13312 | } |
| 13313 | |
| 13314 | try paramattr_group_block.writeUnabbrev(3, record.items); |
| 13315 | } |
| 13316 | } |
| 13317 | |
| 13318 | try paramattr_group_block.end(); |
| 13319 | } |
| 13320 | |
| 13321 | // PARAMATTR_BLOCK |
| 13322 | { |
| 13323 | const Paramattr = ir.Paramattr; |
| 13324 | var paramattr_block = try module_block.enterSubBlock(Paramattr); |
| 13325 | |
| 13326 | for (self.function_attributes_set.keys()) |func_attributes| { |
| 13327 | const func_attributes_slice = func_attributes.slice(self); |
| 13328 | record.clearRetainingCapacity(); |
| 13329 | try record.ensureUnusedCapacity(self.gpa, func_attributes_slice.len); |
| 13330 | for (func_attributes_slice, 0..) |attributes, i| { |
| 13331 | const attributes_slice = attributes.slice(self); |
| 13332 | if (attributes_slice.len == 0) continue; |
| 13333 | |
| 13334 | const group_index = attributes_set.getIndex(.{ |
| 13335 | .attributes = attributes, |
| 13336 | .index = @intCast(i), |
| 13337 | }).?; |
| 13338 | record.appendAssumeCapacity(@intCast(group_index)); |
| 13339 | } |
| 13340 | |
| 13341 | try paramattr_block.writeAbbrev(Paramattr.Entry{ .group_indices = record.items }); |
| 13342 | } |
| 13343 | |
| 13344 | try paramattr_block.end(); |
| 13345 | } |
| 13346 | |
| 13347 | var globals: std.AutoArrayHashMapUnmanaged(Global.Index, void) = .{}; |
| 13348 | defer globals.deinit(self.gpa); |
| 13349 | try globals.ensureUnusedCapacity( |
| 13350 | self.gpa, |
| 13351 | self.variables.items.len + |
| 13352 | self.functions.items.len + |
| 13353 | self.aliases.items.len, |
| 13354 | ); |
| 13355 | |
| 13356 | for (self.variables.items) |variable| { |
| 13357 | if (variable.global.getReplacement(self) != .none) continue; |
| 13358 | |
| 13359 | globals.putAssumeCapacity(variable.global, {}); |
| 13360 | } |
| 13361 | |
| 13362 | for (self.functions.items) |function| { |
| 13363 | if (function.global.getReplacement(self) != .none) continue; |
| 13364 | |
| 13365 | globals.putAssumeCapacity(function.global, {}); |
| 13366 | } |
| 13367 | |
| 13368 | for (self.aliases.items) |alias| { |
| 13369 | if (alias.global.getReplacement(self) != .none) continue; |
| 13370 | |
| 13371 | globals.putAssumeCapacity(alias.global, {}); |
| 13372 | } |
| 13373 | |
| 13374 | const ConstantAdapter = struct { |
| 13375 | const ConstantAdapter = @This(); |
| 13376 | builder: *const Builder, |
| 13377 | globals: *const std.AutoArrayHashMapUnmanaged(Global.Index, void), |
| 13378 | |
| 13379 | pub fn get(adapter: @This(), param: anytype, comptime field_name: []const u8) @TypeOf(param) { |
| 13380 | _ = field_name; |
| 13381 | return switch (@TypeOf(param)) { |
| 13382 | Constant => @enumFromInt(adapter.getConstantIndex(param)), |
| 13383 | else => param, |
| 13384 | }; |
| 13385 | } |
| 13386 | |
| 13387 | pub fn getConstantIndex(adapter: ConstantAdapter, constant: Constant) u32 { |
| 13388 | return switch (constant.unwrap()) { |
| 13389 | .constant => |c| c + adapter.numGlobals(), |
| 13390 | .global => |global| @intCast(adapter.globals.getIndex(global.unwrap(adapter.builder)).?), |
| 13391 | }; |
| 13392 | } |
| 13393 | |
| 13394 | pub fn numConstants(adapter: ConstantAdapter) u32 { |
| 13395 | return @intCast(adapter.globals.count() + adapter.builder.constant_items.len); |
| 13396 | } |
| 13397 | |
| 13398 | pub fn numGlobals(adapter: ConstantAdapter) u32 { |
| 13399 | return @intCast(adapter.globals.count()); |
| 13400 | } |
| 13401 | }; |
| 13402 | |
| 13403 | const constant_adapter = ConstantAdapter{ |
| 13404 | .builder = self, |
| 13405 | .globals = &globals, |
| 13406 | }; |
| 13407 | |
| 13408 | // Globals |
| 13409 | { |
| 13410 | var section_map: std.AutoArrayHashMapUnmanaged(String, void) = .{}; |
| 13411 | defer section_map.deinit(self.gpa); |
| 13412 | try section_map.ensureUnusedCapacity(self.gpa, globals.count()); |
| 13413 | |
| 13414 | for (self.variables.items) |variable| { |
| 13415 | if (variable.global.getReplacement(self) != .none) continue; |
| 13416 | |
| 13417 | const section = blk: { |
| 13418 | if (variable.section == .none) break :blk 0; |
| 13419 | const gop = section_map.getOrPutAssumeCapacity(variable.section); |
| 13420 | if (!gop.found_existing) { |
| 13421 | try module_block.writeAbbrev(Module.String{ |
| 13422 | .code = 5, |
| 13423 | .string = variable.section.slice(self).?, |
| 13424 | }); |
| 13425 | } |
| 13426 | break :blk gop.index + 1; |
| 13427 | }; |
| 13428 | |
| 13429 | const initid = if (variable.init == .no_init) |
| 13430 | 0 |
| 13431 | else |
| 13432 | (constant_adapter.getConstantIndex(variable.init) + 1); |
| 13433 | |
| 13434 | const strtab = variable.global.strtab(self); |
| 13435 | |
| 13436 | const global = variable.global.ptrConst(self); |
| 13437 | try module_block.writeAbbrev(Module.Variable{ |
| 13438 | .strtab_offset = strtab.offset, |
| 13439 | .strtab_size = strtab.size, |
| 13440 | .type_index = global.type, |
| 13441 | .is_const = .{ |
| 13442 | .is_const = switch (variable.mutability) { |
| 13443 | .global => false, |
| 13444 | .constant => true, |
| 13445 | }, |
| 13446 | .addr_space = global.addr_space, |
| 13447 | }, |
| 13448 | .initid = initid, |
| 13449 | .linkage = global.linkage, |
| 13450 | .alignment = variable.alignment.toLlvm(), |
| 13451 | .section = section, |
| 13452 | .visibility = global.visibility, |
| 13453 | .thread_local = variable.thread_local, |
| 13454 | .unnamed_addr = global.unnamed_addr, |
| 13455 | .externally_initialized = global.externally_initialized, |
| 13456 | .dllstorageclass = global.dll_storage_class, |
| 13457 | .preemption = global.preemption, |
| 13458 | }); |
| 13459 | } |
| 13460 | |
| 13461 | for (self.functions.items) |func| { |
| 13462 | if (func.global.getReplacement(self) != .none) continue; |
| 13463 | |
| 13464 | const section = blk: { |
| 13465 | if (func.section == .none) break :blk 0; |
| 13466 | const gop = section_map.getOrPutAssumeCapacity(func.section); |
| 13467 | if (!gop.found_existing) { |
| 13468 | try module_block.writeAbbrev(Module.String{ |
| 13469 | .code = 5, |
| 13470 | .string = func.section.slice(self).?, |
| 13471 | }); |
| 13472 | } |
| 13473 | break :blk gop.index + 1; |
| 13474 | }; |
| 13475 | |
| 13476 | const paramattr_index = if (self.function_attributes_set.getIndex(func.attributes)) |index| |
| 13477 | index + 1 |
| 13478 | else |
| 13479 | 0; |
| 13480 | |
| 13481 | const strtab = func.global.strtab(self); |
| 13482 | |
| 13483 | const global = func.global.ptrConst(self); |
| 13484 | try module_block.writeAbbrev(Module.Function{ |
| 13485 | .strtab_offset = strtab.offset, |
| 13486 | .strtab_size = strtab.size, |
| 13487 | .type_index = global.type, |
| 13488 | .call_conv = func.call_conv, |
| 13489 | .is_proto = func.instructions.len == 0, |
| 13490 | .linkage = global.linkage, |
| 13491 | .paramattr = paramattr_index, |
| 13492 | .alignment = func.alignment.toLlvm(), |
| 13493 | .section = section, |
| 13494 | .visibility = global.visibility, |
| 13495 | .unnamed_addr = global.unnamed_addr, |
| 13496 | .dllstorageclass = global.dll_storage_class, |
| 13497 | .preemption = global.preemption, |
| 13498 | .addr_space = global.addr_space, |
| 13499 | }); |
| 13500 | } |
| 13501 | |
| 13502 | for (self.aliases.items) |alias| { |
| 13503 | if (alias.global.getReplacement(self) != .none) continue; |
| 13504 | |
| 13505 | const strtab = alias.global.strtab(self); |
| 13506 | |
| 13507 | const global = alias.global.ptrConst(self); |
| 13508 | try module_block.writeAbbrev(Module.Alias{ |
| 13509 | .strtab_offset = strtab.offset, |
| 13510 | .strtab_size = strtab.size, |
| 13511 | .type_index = global.type, |
| 13512 | .addr_space = global.addr_space, |
| 13513 | .aliasee = constant_adapter.getConstantIndex(alias.aliasee), |
| 13514 | .linkage = global.linkage, |
| 13515 | .visibility = global.visibility, |
| 13516 | .thread_local = alias.thread_local, |
| 13517 | .unnamed_addr = global.unnamed_addr, |
| 13518 | .dllstorageclass = global.dll_storage_class, |
| 13519 | .preemption = global.preemption, |
| 13520 | }); |
| 13521 | } |
| 13522 | } |
| 13523 | |
| 13524 | // CONSTANTS_BLOCK |
| 13525 | { |
| 13526 | const Constants = ir.Constants; |
| 13527 | var constants_block = try module_block.enterSubBlock(Constants); |
| 13528 | |
| 13529 | var current_type: Type = .none; |
| 13530 | const tags = self.constant_items.items(.tag); |
| 13531 | const datas = self.constant_items.items(.data); |
| 13532 | for (0..self.constant_items.len) |index| { |
| 13533 | record.clearRetainingCapacity(); |
| 13534 | const constant: Constant = @enumFromInt(index); |
| 13535 | const constant_type = constant.typeOf(self); |
| 13536 | if (constant_type != current_type) { |
| 13537 | try constants_block.writeAbbrev(Constants.SetType{ .type_id = constant_type }); |
| 13538 | current_type = constant_type; |
| 13539 | } |
| 13540 | const data = datas[index]; |
| 13541 | switch (tags[index]) { |
| 13542 | .null, |
| 13543 | .zeroinitializer, |
| 13544 | .none, |
| 13545 | => try constants_block.writeAbbrev(Constants.Null{}), |
| 13546 | .undef => try constants_block.writeAbbrev(Constants.Undef{}), |
| 13547 | .poison => try constants_block.writeAbbrev(Constants.Poison{}), |
| 13548 | .positive_integer, |
| 13549 | .negative_integer, |
| 13550 | => |tag| { |
| 13551 | const extra: *align(@alignOf(std.math.big.Limb)) Constant.Integer = |
| 13552 | @ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]); |
| 13553 | const limbs = self.constant_limbs |
| 13554 | .items[data + Constant.Integer.limbs ..][0..extra.limbs_len]; |
| 13555 | const bigint: std.math.big.int.Const = .{ |
| 13556 | .limbs = limbs, |
| 13557 | .positive = tag == .positive_integer, |
| 13558 | }; |
| 13559 | |
| 13560 | const bit_count = extra.type.scalarBits(self); |
| 13561 | if (bit_count <= 64) { |
| 13562 | const val = bigint.to(i64) catch unreachable; |
| 13563 | const emit_val = if (tag == .positive_integer) |
| 13564 | @shlWithOverflow(val, 1)[0] |
| 13565 | else |
| 13566 | (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1); |
| 13567 | try constants_block.writeAbbrev(Constants.Integer{ .value = @bitCast(emit_val) }); |
| 13568 | } else { |
| 13569 | const word_count = std.mem.alignForward(u24, bit_count, 64) / 64; |
| 13570 | try record.ensureUnusedCapacity(self.gpa, word_count); |
| 13571 | const buffer: [*]u8 = @ptrCast(record.items.ptr); |
| 13572 | bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little); |
| 13573 | |
| 13574 | const signed_buffer: [*]i64 = @ptrCast(record.items.ptr); |
| 13575 | for (signed_buffer[0..word_count], 0..) |val, i| { |
| 13576 | signed_buffer[i] = if (val >= 0) |
| 13577 | @shlWithOverflow(val, 1)[0] |
| 13578 | else |
| 13579 | (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1); |
| 13580 | } |
| 13581 | |
| 13582 | try constants_block.writeUnabbrev(5, record.items.ptr[0..word_count]); |
| 13583 | } |
| 13584 | }, |
| 13585 | .half, |
| 13586 | .bfloat, |
| 13587 | => try constants_block.writeAbbrev(Constants.Half{ .value = @truncate(data) }), |
| 13588 | .float => try constants_block.writeAbbrev(Constants.Float{ .value = data }), |
| 13589 | .double => { |
| 13590 | const extra = self.constantExtraData(Constant.Double, data); |
| 13591 | try constants_block.writeAbbrev(Constants.Double{ |
| 13592 | .value = (@as(u64, extra.hi) << 32) | extra.lo, |
| 13593 | }); |
| 13594 | }, |
| 13595 | .x86_fp80 => { |
| 13596 | const extra = self.constantExtraData(Constant.Fp80, data); |
| 13597 | try constants_block.writeAbbrev(Constants.Fp80{ |
| 13598 | .hi = @as(u64, extra.hi) << 48 | @as(u64, extra.lo_hi) << 16 | |
| 13599 | extra.lo_lo >> 16, |
| 13600 | .lo = @truncate(extra.lo_lo), |
| 13601 | }); |
| 13602 | }, |
| 13603 | .fp128, |
| 13604 | .ppc_fp128, |
| 13605 | => { |
| 13606 | const extra = self.constantExtraData(Constant.Fp128, data); |
| 13607 | try constants_block.writeAbbrev(Constants.Fp128{ |
| 13608 | .lo = @as(u64, extra.lo_hi) << 32 | @as(u64, extra.lo_lo), |
| 13609 | .hi = @as(u64, extra.hi_hi) << 32 | @as(u64, extra.hi_lo), |
| 13610 | }); |
| 13611 | }, |
| 13612 | .array, |
| 13613 | .vector, |
| 13614 | .structure, |
| 13615 | .packed_structure, |
| 13616 | => { |
| 13617 | var extra = self.constantExtraDataTrail(Constant.Aggregate, data); |
| 13618 | const len: u32 = @intCast(extra.data.type.aggregateLen(self)); |
| 13619 | const values = extra.trail.next(len, Constant, self); |
| 13620 | |
| 13621 | try constants_block.writeAbbrevAdapted( |
| 13622 | Constants.Aggregate{ .values = values }, |
| 13623 | constant_adapter, |
| 13624 | ); |
| 13625 | }, |
| 13626 | .splat => { |
| 13627 | const ConstantsWriter = @TypeOf(constants_block); |
| 13628 | const extra = self.constantExtraData(Constant.Splat, data); |
| 13629 | const vector_len = extra.type.vectorLen(self); |
| 13630 | const c = constant_adapter.getConstantIndex(extra.value); |
| 13631 | |
| 13632 | try bitcode.writeBits( |
| 13633 | ConstantsWriter.abbrevId(Constants.Aggregate), |
| 13634 | ConstantsWriter.abbrev_len, |
| 13635 | ); |
| 13636 | try bitcode.writeVBR(vector_len, 6); |
| 13637 | for (0..vector_len) |_| { |
| 13638 | try bitcode.writeBits(c, Constants.Aggregate.ops[1].array_fixed); |
| 13639 | } |
| 13640 | }, |
| 13641 | .string => { |
| 13642 | const str: String = @enumFromInt(data); |
| 13643 | if (str == .none) { |
| 13644 | try constants_block.writeAbbrev(Constants.Null{}); |
| 13645 | } else { |
| 13646 | const slice = str.slice(self).?; |
| 13647 | if (slice.len > 0 and slice[slice.len - 1] == 0) |
| 13648 | try constants_block.writeAbbrev(Constants.CString{ .string = slice[0 .. slice.len - 1] }) |
| 13649 | else |
| 13650 | try constants_block.writeAbbrev(Constants.String{ .string = slice }); |
| 13651 | } |
| 13652 | }, |
| 13653 | .bitcast, |
| 13654 | .inttoptr, |
| 13655 | .ptrtoint, |
| 13656 | .fptosi, |
| 13657 | .fptoui, |
| 13658 | .sitofp, |
| 13659 | .uitofp, |
| 13660 | .addrspacecast, |
| 13661 | .fptrunc, |
| 13662 | .trunc, |
| 13663 | .fpext, |
| 13664 | .sext, |
| 13665 | .zext, |
| 13666 | => |tag| { |
| 13667 | const extra = self.constantExtraData(Constant.Cast, data); |
| 13668 | try constants_block.writeAbbrevAdapted(Constants.Cast{ |
| 13669 | .type_index = extra.type, |
| 13670 | .val = extra.val, |
| 13671 | .opcode = tag.toCastOpcode(), |
| 13672 | }, constant_adapter); |
| 13673 | }, |
| 13674 | .add, |
| 13675 | .@"add nsw", |
| 13676 | .@"add nuw", |
| 13677 | .sub, |
| 13678 | .@"sub nsw", |
| 13679 | .@"sub nuw", |
| 13680 | .mul, |
| 13681 | .@"mul nsw", |
| 13682 | .@"mul nuw", |
| 13683 | .shl, |
| 13684 | .lshr, |
| 13685 | .ashr, |
| 13686 | .@"and", |
| 13687 | .@"or", |
| 13688 | .xor, |
| 13689 | => |tag| { |
| 13690 | const extra = self.constantExtraData(Constant.Binary, data); |
| 13691 | try constants_block.writeAbbrevAdapted(Constants.Binary{ |
| 13692 | .opcode = tag.toBinaryOpcode(), |
| 13693 | .lhs = extra.lhs, |
| 13694 | .rhs = extra.rhs, |
| 13695 | }, constant_adapter); |
| 13696 | }, |
| 13697 | .icmp, |
| 13698 | .fcmp, |
| 13699 | => { |
| 13700 | const extra = self.constantExtraData(Constant.Compare, data); |
| 13701 | try constants_block.writeAbbrevAdapted(Constants.Cmp{ |
| 13702 | .ty = extra.lhs.typeOf(self), |
| 13703 | .lhs = extra.lhs, |
| 13704 | .rhs = extra.rhs, |
| 13705 | .pred = extra.cond, |
| 13706 | }, constant_adapter); |
| 13707 | }, |
| 13708 | .extractelement => { |
| 13709 | const extra = self.constantExtraData(Constant.ExtractElement, data); |
| 13710 | try constants_block.writeAbbrevAdapted(Constants.ExtractElement{ |
| 13711 | .val_type = extra.val.typeOf(self), |
| 13712 | .val = extra.val, |
| 13713 | .index_type = extra.index.typeOf(self), |
| 13714 | .index = extra.index, |
| 13715 | }, constant_adapter); |
| 13716 | }, |
| 13717 | .insertelement => { |
| 13718 | const extra = self.constantExtraData(Constant.InsertElement, data); |
| 13719 | try constants_block.writeAbbrevAdapted(Constants.InsertElement{ |
| 13720 | .val = extra.val, |
| 13721 | .elem = extra.elem, |
| 13722 | .index_type = extra.index.typeOf(self), |
| 13723 | .index = extra.index, |
| 13724 | }, constant_adapter); |
| 13725 | }, |
| 13726 | .shufflevector => { |
| 13727 | const extra = self.constantExtraData(Constant.ShuffleVector, data); |
| 13728 | const ty = constant.typeOf(self); |
| 13729 | const lhs_type = extra.lhs.typeOf(self); |
| 13730 | // Check if instruction is widening, truncating or not |
| 13731 | if (ty == lhs_type) { |
| 13732 | try constants_block.writeAbbrevAdapted(Constants.ShuffleVector{ |
| 13733 | .lhs = extra.lhs, |
| 13734 | .rhs = extra.rhs, |
| 13735 | .mask = extra.mask, |
| 13736 | }, constant_adapter); |
| 13737 | } else { |
| 13738 | try constants_block.writeAbbrevAdapted(Constants.ShuffleVectorEx{ |
| 13739 | .ty = ty, |
| 13740 | .lhs = extra.lhs, |
| 13741 | .rhs = extra.rhs, |
| 13742 | .mask = extra.mask, |
| 13743 | }, constant_adapter); |
| 13744 | } |
| 13745 | }, |
| 13746 | .getelementptr, |
| 13747 | .@"getelementptr inbounds", |
| 13748 | => |tag| { |
| 13749 | var extra = self.constantExtraDataTrail(Constant.GetElementPtr, data); |
| 13750 | const indices = extra.trail.next(extra.data.info.indices_len, Constant, self); |
| 13751 | try record.ensureUnusedCapacity(self.gpa, 1 + 2 + 2 * indices.len); |
| 13752 | |
| 13753 | record.appendAssumeCapacity(@intFromEnum(extra.data.type)); |
| 13754 | |
| 13755 | record.appendAssumeCapacity(@intFromEnum(extra.data.base.typeOf(self))); |
| 13756 | record.appendAssumeCapacity(constant_adapter.getConstantIndex(extra.data.base)); |
| 13757 | |
| 13758 | for (indices) |i| { |
| 13759 | record.appendAssumeCapacity(@intFromEnum(i.typeOf(self))); |
| 13760 | record.appendAssumeCapacity(constant_adapter.getConstantIndex(i)); |
| 13761 | } |
| 13762 | |
| 13763 | try constants_block.writeUnabbrev(switch (tag) { |
| 13764 | .getelementptr => 12, |
| 13765 | .@"getelementptr inbounds" => 20, |
| 13766 | else => unreachable, |
| 13767 | }, record.items); |
| 13768 | }, |
| 13769 | .@"asm", |
| 13770 | .@"asm sideeffect", |
| 13771 | .@"asm alignstack", |
| 13772 | .@"asm sideeffect alignstack", |
| 13773 | .@"asm inteldialect", |
| 13774 | .@"asm sideeffect inteldialect", |
| 13775 | .@"asm alignstack inteldialect", |
| 13776 | .@"asm sideeffect alignstack inteldialect", |
| 13777 | .@"asm unwind", |
| 13778 | .@"asm sideeffect unwind", |
| 13779 | .@"asm alignstack unwind", |
| 13780 | .@"asm sideeffect alignstack unwind", |
| 13781 | .@"asm inteldialect unwind", |
| 13782 | .@"asm sideeffect inteldialect unwind", |
| 13783 | .@"asm alignstack inteldialect unwind", |
| 13784 | .@"asm sideeffect alignstack inteldialect unwind", |
| 13785 | => |tag| { |
| 13786 | const extra = self.constantExtraData(Constant.Assembly, data); |
| 13787 | |
| 13788 | const assembly_slice = extra.assembly.slice(self).?; |
| 13789 | const constraints_slice = extra.constraints.slice(self).?; |
| 13790 | |
| 13791 | try record.ensureUnusedCapacity(self.gpa, 4 + assembly_slice.len + constraints_slice.len); |
| 13792 | |
| 13793 | record.appendAssumeCapacity(@intFromEnum(extra.type)); |
| 13794 | record.appendAssumeCapacity(switch (tag) { |
| 13795 | .@"asm" => 0, |
| 13796 | .@"asm sideeffect" => 0b0001, |
| 13797 | .@"asm sideeffect alignstack" => 0b0011, |
| 13798 | .@"asm sideeffect inteldialect" => 0b0101, |
| 13799 | .@"asm sideeffect alignstack inteldialect" => 0b0111, |
| 13800 | .@"asm sideeffect unwind" => 0b1001, |
| 13801 | .@"asm sideeffect alignstack unwind" => 0b1011, |
| 13802 | .@"asm sideeffect inteldialect unwind" => 0b1101, |
| 13803 | .@"asm sideeffect alignstack inteldialect unwind" => 0b1111, |
| 13804 | .@"asm alignstack" => 0b0010, |
| 13805 | .@"asm inteldialect" => 0b0100, |
| 13806 | .@"asm alignstack inteldialect" => 0b0110, |
| 13807 | .@"asm unwind" => 0b1000, |
| 13808 | .@"asm alignstack unwind" => 0b1010, |
| 13809 | .@"asm inteldialect unwind" => 0b1100, |
| 13810 | .@"asm alignstack inteldialect unwind" => 0b1110, |
| 13811 | else => unreachable, |
| 13812 | }); |
| 13813 | |
| 13814 | record.appendAssumeCapacity(assembly_slice.len); |
| 13815 | for (assembly_slice) |c| record.appendAssumeCapacity(c); |
| 13816 | |
| 13817 | record.appendAssumeCapacity(constraints_slice.len); |
| 13818 | for (constraints_slice) |c| record.appendAssumeCapacity(c); |
| 13819 | |
| 13820 | try constants_block.writeUnabbrev(30, record.items); |
| 13821 | }, |
| 13822 | .blockaddress => { |
| 13823 | const extra = self.constantExtraData(Constant.BlockAddress, data); |
| 13824 | try constants_block.writeAbbrev(Constants.BlockAddress{ |
| 13825 | .type_id = extra.function.typeOf(self), |
| 13826 | .function = constant_adapter.getConstantIndex(extra.function.toConst(self)), |
| 13827 | .block = @intFromEnum(extra.block), |
| 13828 | }); |
| 13829 | }, |
| 13830 | .dso_local_equivalent, |
| 13831 | .no_cfi, |
| 13832 | => |tag| { |
| 13833 | const function: Function.Index = @enumFromInt(data); |
| 13834 | try constants_block.writeAbbrev(Constants.DsoLocalEquivalentOrNoCfi{ |
| 13835 | .code = switch (tag) { |
| 13836 | .dso_local_equivalent => 27, |
| 13837 | .no_cfi => 29, |
| 13838 | else => unreachable, |
| 13839 | }, |
| 13840 | .type_id = function.typeOf(self), |
| 13841 | .function = constant_adapter.getConstantIndex(function.toConst(self)), |
| 13842 | }); |
| 13843 | }, |
| 13844 | } |
| 13845 | } |
| 13846 | |
| 13847 | try constants_block.end(); |
| 13848 | } |
| 13849 | |
| 13850 | // METADATA_KIND_BLOCK |
| 13851 | if (!self.strip) { |
| 13852 | const MetadataKindBlock = ir.MetadataKindBlock; |
| 13853 | var metadata_kind_block = try module_block.enterSubBlock(MetadataKindBlock); |
| 13854 | |
| 13855 | inline for (@typeInfo(ir.MetadataKind).Enum.fields) |field| { |
| 13856 | try metadata_kind_block.writeAbbrev(MetadataKindBlock.Kind{ |
| 13857 | .id = field.value, |
| 13858 | .name = field.name, |
| 13859 | }); |
| 13860 | } |
| 13861 | |
| 13862 | try metadata_kind_block.end(); |
| 13863 | } |
| 13864 | |
| 13865 | const MetadataAdapter = struct { |
| 13866 | builder: *const Builder, |
| 13867 | constant_adapter: ConstantAdapter, |
| 13868 | |
| 13869 | pub fn init( |
| 13870 | builder: *const Builder, |
| 13871 | const_adapter: ConstantAdapter, |
| 13872 | ) @This() { |
| 13873 | return .{ |
| 13874 | .builder = builder, |
| 13875 | .constant_adapter = const_adapter, |
| 13876 | }; |
| 13877 | } |
| 13878 | |
| 13879 | pub fn get(adapter: @This(), value: anytype, comptime field_name: []const u8) @TypeOf(value) { |
| 13880 | _ = field_name; |
| 13881 | const Ty = @TypeOf(value); |
| 13882 | return switch (Ty) { |
| 13883 | Metadata => @enumFromInt(adapter.getMetadataIndex(value)), |
| 13884 | MetadataString => @enumFromInt(adapter.getMetadataStringIndex(value)), |
| 13885 | Constant => @enumFromInt(adapter.constant_adapter.getConstantIndex(value)), |
| 13886 | else => value, |
| 13887 | }; |
| 13888 | } |
| 13889 | |
| 13890 | pub fn getMetadataIndex(adapter: @This(), metadata: Metadata) u32 { |
| 13891 | if (metadata == .none) return 0; |
| 13892 | return @intCast(adapter.builder.metadata_string_map.count() + |
| 13893 | @intFromEnum(metadata.unwrap(adapter.builder)) - 1); |
| 13894 | } |
| 13895 | |
| 13896 | pub fn getMetadataStringIndex(_: @This(), metadata_string: MetadataString) u32 { |
| 13897 | return @intFromEnum(metadata_string); |
| 13898 | } |
| 13899 | }; |
| 13900 | |
| 13901 | const metadata_adapter = MetadataAdapter.init(self, constant_adapter); |
| 13902 | |
| 13903 | // METADATA_BLOCK |
| 13904 | if (!self.strip) { |
| 13905 | const MetadataBlock = ir.MetadataBlock; |
| 13906 | var metadata_block = try module_block.enterSubBlock(MetadataBlock); |
| 13907 | |
| 13908 | const MetadataBlockWriter = @TypeOf(metadata_block); |
| 13909 | |
| 13910 | // Emit all MetadataStrings |
| 13911 | { |
| 13912 | const strings_offset, const strings_size = blk: { |
| 13913 | var strings_offset: u32 = 0; |
| 13914 | var strings_size: u32 = 0; |
| 13915 | for (1..self.metadata_string_map.count()) |metadata_string_index| { |
| 13916 | const metadata_string: MetadataString = @enumFromInt(metadata_string_index); |
| 13917 | const slice = metadata_string.slice(self); |
| 13918 | strings_offset += bitcode.bitsVBR(@as(u32, @intCast(slice.len)), 6); |
| 13919 | strings_size += @intCast(slice.len * 8); |
| 13920 | } |
| 13921 | break :blk .{ |
| 13922 | std.mem.alignForward(u32, strings_offset, 32) / 8, |
| 13923 | std.mem.alignForward(u32, strings_size, 32) / 8, |
| 13924 | }; |
| 13925 | }; |
| 13926 | |
| 13927 | try bitcode.writeBits( |
| 13928 | comptime MetadataBlockWriter.abbrevId(MetadataBlock.Strings), |
| 13929 | MetadataBlockWriter.abbrev_len, |
| 13930 | ); |
| 13931 | |
| 13932 | try bitcode.writeVBR(@as(u32, @intCast(self.metadata_string_map.count() - 1)), 6); |
| 13933 | try bitcode.writeVBR(strings_offset, 6); |
| 13934 | |
| 13935 | try bitcode.writeVBR(strings_size + strings_offset, 6); |
| 13936 | |
| 13937 | try bitcode.alignTo32(); |
| 13938 | |
| 13939 | for (1..self.metadata_string_map.count()) |metadata_string_index| { |
| 13940 | const metadata_string: MetadataString = @enumFromInt(metadata_string_index); |
| 13941 | const slice = metadata_string.slice(self); |
| 13942 | try bitcode.writeVBR(@as(u32, @intCast(slice.len)), 6); |
| 13943 | } |
| 13944 | |
| 13945 | try bitcode.alignTo32(); |
| 13946 | |
| 13947 | for (1..self.metadata_string_map.count()) |metadata_string_index| { |
| 13948 | const metadata_string: MetadataString = @enumFromInt(metadata_string_index); |
| 13949 | const slice = metadata_string.slice(self); |
| 13950 | for (slice) |c| { |
| 13951 | try bitcode.writeBits(c, 8); |
| 13952 | } |
| 13953 | } |
| 13954 | |
| 13955 | try bitcode.alignTo32(); |
| 13956 | } |
| 13957 | |
| 13958 | for ( |
| 13959 | self.metadata_items.items(.tag)[1..], |
| 13960 | self.metadata_items.items(.data)[1..], |
| 13961 | ) |tag, data| { |
| 13962 | switch (tag) { |
| 13963 | .none => unreachable, |
| 13964 | .file => { |
| 13965 | const extra = self.metadataExtraData(Metadata.File, data); |
| 13966 | |
| 13967 | try metadata_block.writeAbbrevAdapted(MetadataBlock.File{ |
| 13968 | .filename = extra.filename, |
| 13969 | .directory = extra.directory, |
| 13970 | }, metadata_adapter); |
| 13971 | }, |
| 13972 | .compile_unit, |
| 13973 | .@"compile_unit optimized", |
| 13974 | => |kind| { |
| 13975 | const extra = self.metadataExtraData(Metadata.CompileUnit, data); |
| 13976 | try metadata_block.writeAbbrevAdapted(MetadataBlock.CompileUnit{ |
| 13977 | .file = extra.file, |
| 13978 | .producer = extra.producer, |
| 13979 | .is_optimized = switch (kind) { |
| 13980 | .compile_unit => false, |
| 13981 | .@"compile_unit optimized" => true, |
| 13982 | else => unreachable, |
| 13983 | }, |
| 13984 | .enums = extra.enums, |
| 13985 | .globals = extra.globals, |
| 13986 | }, metadata_adapter); |
| 13987 | }, |
| 13988 | .subprogram, |
| 13989 | .@"subprogram local", |
| 13990 | .@"subprogram definition", |
| 13991 | .@"subprogram local definition", |
| 13992 | .@"subprogram optimized", |
| 13993 | .@"subprogram optimized local", |
| 13994 | .@"subprogram optimized definition", |
| 13995 | .@"subprogram optimized local definition", |
| 13996 | => |kind| { |
| 13997 | const extra = self.metadataExtraData(Metadata.Subprogram, data); |
| 13998 | |
| 13999 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Subprogram{ |
| 14000 | .scope = extra.file, |
| 14001 | .name = extra.name, |
| 14002 | .linkage_name = extra.linkage_name, |
| 14003 | .file = extra.file, |
| 14004 | .line = extra.line, |
| 14005 | .ty = extra.ty, |
| 14006 | .scope_line = extra.scope_line, |
| 14007 | .sp_flags = @bitCast(@as(u32, @as(u3, @intCast( |
| 14008 | @intFromEnum(kind) - @intFromEnum(Metadata.Tag.subprogram), |
| 14009 | ))) << 2), |
| 14010 | .flags = extra.di_flags, |
| 14011 | .compile_unit = extra.compile_unit, |
| 14012 | }, metadata_adapter); |
| 14013 | }, |
| 14014 | .lexical_block => { |
| 14015 | const extra = self.metadataExtraData(Metadata.LexicalBlock, data); |
| 14016 | try metadata_block.writeAbbrevAdapted(MetadataBlock.LexicalBlock{ |
| 14017 | .scope = extra.scope, |
| 14018 | .file = extra.file, |
| 14019 | .line = extra.line, |
| 14020 | .column = extra.column, |
| 14021 | }, metadata_adapter); |
| 14022 | }, |
| 14023 | .location => { |
| 14024 | const extra = self.metadataExtraData(Metadata.Location, data); |
| 14025 | assert(extra.scope != .none); |
| 14026 | try metadata_block.writeAbbrev(MetadataBlock.Location{ |
| 14027 | .line = extra.line, |
| 14028 | .column = extra.column, |
| 14029 | .scope = metadata_adapter.getMetadataIndex(extra.scope) - 1, |
| 14030 | .inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(extra.inlined_at)), |
| 14031 | }); |
| 14032 | }, |
| 14033 | .basic_bool_type, |
| 14034 | .basic_unsigned_type, |
| 14035 | .basic_signed_type, |
| 14036 | .basic_float_type, |
| 14037 | => |kind| { |
| 14038 | const extra = self.metadataExtraData(Metadata.BasicType, data); |
| 14039 | try metadata_block.writeAbbrevAdapted(MetadataBlock.BasicType{ |
| 14040 | .name = extra.name, |
| 14041 | .size_in_bits = extra.bitSize(), |
| 14042 | .encoding = switch (kind) { |
| 14043 | .basic_bool_type => DW.ATE.boolean, |
| 14044 | .basic_unsigned_type => DW.ATE.unsigned, |
| 14045 | .basic_signed_type => DW.ATE.signed, |
| 14046 | .basic_float_type => DW.ATE.float, |
| 14047 | else => unreachable, |
| 14048 | }, |
| 14049 | }, metadata_adapter); |
| 14050 | }, |
| 14051 | .composite_struct_type, |
| 14052 | .composite_union_type, |
| 14053 | .composite_enumeration_type, |
| 14054 | .composite_array_type, |
| 14055 | .composite_vector_type, |
| 14056 | => |kind| { |
| 14057 | const extra = self.metadataExtraData(Metadata.CompositeType, data); |
| 14058 | |
| 14059 | try metadata_block.writeAbbrevAdapted(MetadataBlock.CompositeType{ |
| 14060 | .tag = switch (kind) { |
| 14061 | .composite_struct_type => DW.TAG.structure_type, |
| 14062 | .composite_union_type => DW.TAG.union_type, |
| 14063 | .composite_enumeration_type => DW.TAG.enumeration_type, |
| 14064 | .composite_array_type, .composite_vector_type => DW.TAG.array_type, |
| 14065 | else => unreachable, |
| 14066 | }, |
| 14067 | .name = extra.name, |
| 14068 | .file = extra.file, |
| 14069 | .line = extra.line, |
| 14070 | .scope = extra.scope, |
| 14071 | .underlying_type = extra.underlying_type, |
| 14072 | .size_in_bits = extra.bitSize(), |
| 14073 | .align_in_bits = extra.bitAlign(), |
| 14074 | .flags = if (kind == .composite_vector_type) .{ .Vector = true } else .{}, |
| 14075 | .elements = extra.fields_tuple, |
| 14076 | }, metadata_adapter); |
| 14077 | }, |
| 14078 | .derived_pointer_type, |
| 14079 | .derived_member_type, |
| 14080 | => |kind| { |
| 14081 | const extra = self.metadataExtraData(Metadata.DerivedType, data); |
| 14082 | try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{ |
| 14083 | .tag = switch (kind) { |
| 14084 | .derived_pointer_type => DW.TAG.pointer_type, |
| 14085 | .derived_member_type => DW.TAG.member, |
| 14086 | else => unreachable, |
| 14087 | }, |
| 14088 | .name = extra.name, |
| 14089 | .file = extra.file, |
| 14090 | .line = extra.line, |
| 14091 | .scope = extra.scope, |
| 14092 | .underlying_type = extra.underlying_type, |
| 14093 | .size_in_bits = extra.bitSize(), |
| 14094 | .align_in_bits = extra.bitAlign(), |
| 14095 | .offset_in_bits = extra.bitOffset(), |
| 14096 | }, metadata_adapter); |
| 14097 | }, |
| 14098 | .subroutine_type => { |
| 14099 | const extra = self.metadataExtraData(Metadata.SubroutineType, data); |
| 14100 | |
| 14101 | try metadata_block.writeAbbrevAdapted(MetadataBlock.SubroutineType{ |
| 14102 | .types = extra.types_tuple, |
| 14103 | }, metadata_adapter); |
| 14104 | }, |
| 14105 | .enumerator_unsigned, |
| 14106 | .enumerator_signed_positive, |
| 14107 | .enumerator_signed_negative, |
| 14108 | => |kind| { |
| 14109 | const positive = switch (kind) { |
| 14110 | .enumerator_unsigned, |
| 14111 | .enumerator_signed_positive, |
| 14112 | => true, |
| 14113 | .enumerator_signed_negative => false, |
| 14114 | else => unreachable, |
| 14115 | }; |
| 14116 | |
| 14117 | const unsigned = switch (kind) { |
| 14118 | .enumerator_unsigned => true, |
| 14119 | .enumerator_signed_positive, |
| 14120 | .enumerator_signed_negative, |
| 14121 | => false, |
| 14122 | else => unreachable, |
| 14123 | }; |
| 14124 | |
| 14125 | const extra = self.metadataExtraData(Metadata.Enumerator, data); |
| 14126 | |
| 14127 | const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len]; |
| 14128 | |
| 14129 | const bigint: std.math.big.int.Const = .{ |
| 14130 | .limbs = limbs, |
| 14131 | .positive = positive, |
| 14132 | }; |
| 14133 | |
| 14134 | if (extra.bit_width <= 64) { |
| 14135 | const val = bigint.to(i64) catch unreachable; |
| 14136 | const emit_val = if (positive) |
| 14137 | @shlWithOverflow(val, 1)[0] |
| 14138 | else |
| 14139 | (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1); |
| 14140 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{ |
| 14141 | .flags = .{ |
| 14142 | .unsigned = unsigned, |
| 14143 | .bigint = false, |
| 14144 | }, |
| 14145 | .bit_width = extra.bit_width, |
| 14146 | .name = extra.name, |
| 14147 | .value = @bitCast(emit_val), |
| 14148 | }, metadata_adapter); |
| 14149 | } else { |
| 14150 | const word_count = std.mem.alignForward(u32, extra.bit_width, 64) / 64; |
| 14151 | try record.ensureUnusedCapacity(self.gpa, 3 + word_count); |
| 14152 | |
| 14153 | const flags: MetadataBlock.Enumerator.Flags = .{ |
| 14154 | .unsigned = unsigned, |
| 14155 | .bigint = true, |
| 14156 | }; |
| 14157 | |
| 14158 | const FlagsInt = @typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?; |
| 14159 | |
| 14160 | const flags_int: FlagsInt = @bitCast(flags); |
| 14161 | |
| 14162 | record.appendAssumeCapacity(@intCast(flags_int)); |
| 14163 | record.appendAssumeCapacity(@intCast(extra.bit_width)); |
| 14164 | record.appendAssumeCapacity(metadata_adapter.getMetadataStringIndex(extra.name)); |
| 14165 | |
| 14166 | const buffer: [*]u8 = @ptrCast(record.items.ptr); |
| 14167 | bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little); |
| 14168 | |
| 14169 | const signed_buffer: [*]i64 = @ptrCast(record.items.ptr); |
| 14170 | for (signed_buffer[0..word_count], 0..) |val, i| { |
| 14171 | signed_buffer[i] = if (val >= 0) |
| 14172 | @shlWithOverflow(val, 1)[0] |
| 14173 | else |
| 14174 | (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1); |
| 14175 | } |
| 14176 | |
| 14177 | try metadata_block.writeUnabbrev( |
| 14178 | MetadataBlock.Enumerator.id, |
| 14179 | record.items.ptr[0..(3 + word_count)], |
| 14180 | ); |
| 14181 | } |
| 14182 | }, |
| 14183 | .subrange => { |
| 14184 | const extra = self.metadataExtraData(Metadata.Subrange, data); |
| 14185 | |
| 14186 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Subrange{ |
| 14187 | .count = extra.count, |
| 14188 | .lower_bound = extra.lower_bound, |
| 14189 | }, metadata_adapter); |
| 14190 | }, |
| 14191 | .expression => { |
| 14192 | var extra = self.metadataExtraDataTrail(Metadata.Expression, data); |
| 14193 | |
| 14194 | const elements = extra.trail.next(extra.data.elements_len, u32, self); |
| 14195 | |
| 14196 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Expression{ |
| 14197 | .elements = elements, |
| 14198 | }, metadata_adapter); |
| 14199 | }, |
| 14200 | .tuple => { |
| 14201 | var extra = self.metadataExtraDataTrail(Metadata.Tuple, data); |
| 14202 | |
| 14203 | const elements = extra.trail.next(extra.data.elements_len, Metadata, self); |
| 14204 | |
| 14205 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Node{ |
| 14206 | .elements = elements, |
| 14207 | }, metadata_adapter); |
| 14208 | }, |
| 14209 | .module_flag => { |
| 14210 | const extra = self.metadataExtraData(Metadata.ModuleFlag, data); |
| 14211 | try metadata_block.writeAbbrev(MetadataBlock.Node{ |
| 14212 | .elements = &.{ |
| 14213 | @enumFromInt(metadata_adapter.getMetadataIndex(extra.behavior)), |
| 14214 | @enumFromInt(metadata_adapter.getMetadataStringIndex(extra.name)), |
| 14215 | @enumFromInt(metadata_adapter.getMetadataIndex(extra.constant)), |
| 14216 | }, |
| 14217 | }); |
| 14218 | }, |
| 14219 | .local_var => { |
| 14220 | const extra = self.metadataExtraData(Metadata.LocalVar, data); |
| 14221 | try metadata_block.writeAbbrevAdapted(MetadataBlock.LocalVar{ |
| 14222 | .scope = extra.scope, |
| 14223 | .name = extra.name, |
| 14224 | .file = extra.file, |
| 14225 | .line = extra.line, |
| 14226 | .ty = extra.ty, |
| 14227 | }, metadata_adapter); |
| 14228 | }, |
| 14229 | .parameter => { |
| 14230 | const extra = self.metadataExtraData(Metadata.Parameter, data); |
| 14231 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Parameter{ |
| 14232 | .scope = extra.scope, |
| 14233 | .name = extra.name, |
| 14234 | .file = extra.file, |
| 14235 | .line = extra.line, |
| 14236 | .ty = extra.ty, |
| 14237 | .arg = extra.arg_no, |
| 14238 | }, metadata_adapter); |
| 14239 | }, |
| 14240 | .global_var, |
| 14241 | .@"global_var local", |
| 14242 | => |kind| { |
| 14243 | const extra = self.metadataExtraData(Metadata.GlobalVar, data); |
| 14244 | try metadata_block.writeAbbrevAdapted(MetadataBlock.GlobalVar{ |
| 14245 | .scope = extra.scope, |
| 14246 | .name = extra.name, |
| 14247 | .linkage_name = extra.linkage_name, |
| 14248 | .file = extra.file, |
| 14249 | .line = extra.line, |
| 14250 | .ty = extra.ty, |
| 14251 | .local = kind == .@"global_var local", |
| 14252 | }, metadata_adapter); |
| 14253 | }, |
| 14254 | .global_var_expression => { |
| 14255 | const extra = self.metadataExtraData(Metadata.GlobalVarExpression, data); |
| 14256 | try metadata_block.writeAbbrevAdapted(MetadataBlock.GlobalVarExpression{ |
| 14257 | .variable = extra.variable, |
| 14258 | .expression = extra.expression, |
| 14259 | }, metadata_adapter); |
| 14260 | }, |
| 14261 | .constant => { |
| 14262 | const constant: Constant = @enumFromInt(data); |
| 14263 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{ |
| 14264 | .ty = constant.typeOf(self), |
| 14265 | .constant = constant, |
| 14266 | }, metadata_adapter); |
| 14267 | }, |
| 14268 | } |
| 14269 | record.clearRetainingCapacity(); |
| 14270 | } |
| 14271 | |
| 14272 | // Write named metadata |
| 14273 | for (self.metadata_named.keys(), self.metadata_named.values()) |name, operands| { |
| 14274 | const slice = name.slice(self); |
| 14275 | try metadata_block.writeAbbrev(MetadataBlock.Name{ |
| 14276 | .name = slice, |
| 14277 | }); |
| 14278 | |
| 14279 | const elements = self.metadata_extra.items[operands.index..][0..operands.len]; |
| 14280 | for (elements) |*e| { |
| 14281 | e.* = metadata_adapter.getMetadataIndex(@enumFromInt(e.*)) - 1; |
| 14282 | } |
| 14283 | |
| 14284 | try metadata_block.writeAbbrev(MetadataBlock.NamedNode{ |
| 14285 | .elements = @ptrCast(elements), |
| 14286 | }); |
| 14287 | } |
| 14288 | |
| 14289 | // Write global attached metadata |
| 14290 | { |
| 14291 | for (globals.keys()) |global| { |
| 14292 | const global_ptr = global.ptrConst(self); |
| 14293 | if (global_ptr.dbg == .none) continue; |
| 14294 | |
| 14295 | switch (global_ptr.kind) { |
| 14296 | .function => |f| if (f.ptrConst(self).instructions.len != 0) continue, |
| 14297 | else => {}, |
| 14298 | } |
| 14299 | |
| 14300 | try metadata_block.writeAbbrev(MetadataBlock.GlobalDeclAttachment{ |
| 14301 | .value = @enumFromInt(constant_adapter.getConstantIndex(global.toConst())), |
| 14302 | .kind = ir.MetadataKind.dbg, |
| 14303 | .metadata = @enumFromInt(metadata_adapter.getMetadataIndex(global_ptr.dbg) - 1), |
| 14304 | }); |
| 14305 | } |
| 14306 | } |
| 14307 | |
| 14308 | try metadata_block.end(); |
| 14309 | } |
| 14310 | |
| 14311 | // FUNCTION_BLOCKS |
| 14312 | { |
| 14313 | const FunctionAdapter = struct { |
| 14314 | constant_adapter: ConstantAdapter, |
| 14315 | metadata_adapter: MetadataAdapter, |
| 14316 | func: *const Function, |
| 14317 | instruction_index: u32 = 0, |
| 14318 | |
| 14319 | pub fn init( |
| 14320 | const_adapter: ConstantAdapter, |
| 14321 | meta_adapter: MetadataAdapter, |
| 14322 | func: *const Function, |
| 14323 | ) @This() { |
| 14324 | return .{ |
| 14325 | .constant_adapter = const_adapter, |
| 14326 | .metadata_adapter = meta_adapter, |
| 14327 | .func = func, |
| 14328 | .instruction_index = 0, |
| 14329 | }; |
| 14330 | } |
| 14331 | |
| 14332 | pub fn get(adapter: @This(), value: anytype, comptime field_name: []const u8) @TypeOf(value) { |
| 14333 | _ = field_name; |
| 14334 | const Ty = @TypeOf(value); |
| 14335 | return switch (Ty) { |
| 14336 | Value => @enumFromInt(adapter.getOffsetValueIndex(value)), |
| 14337 | Constant => @enumFromInt(adapter.getOffsetConstantIndex(value)), |
| 14338 | FunctionAttributes => @enumFromInt(switch (value) { |
| 14339 | .none => 0, |
| 14340 | else => 1 + adapter.constant_adapter.builder.function_attributes_set.getIndex(value).?, |
| 14341 | }), |
| 14342 | else => value, |
| 14343 | }; |
| 14344 | } |
| 14345 | |
| 14346 | pub fn getValueIndex(adapter: @This(), value: Value) u32 { |
| 14347 | return @intCast(switch (value.unwrap()) { |
| 14348 | .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(), |
| 14349 | .constant => |constant| adapter.constant_adapter.getConstantIndex(constant), |
| 14350 | .metadata => |metadata| if (!adapter.metadata_adapter.builder.strip) blk: { |
| 14351 | const real_metadata = metadata.unwrap(adapter.metadata_adapter.builder); |
| 14352 | if (@intFromEnum(real_metadata) < Metadata.first_local_metadata) |
| 14353 | break :blk adapter.metadata_adapter.getMetadataIndex(real_metadata) - 1; |
| 14354 | |
| 14355 | return @intCast(@intFromEnum(metadata) - |
| 14356 | Metadata.first_local_metadata + |
| 14357 | adapter.metadata_adapter.builder.metadata_string_map.count() - 1 + |
| 14358 | adapter.metadata_adapter.builder.metadata_map.count() - 1); |
| 14359 | } else unreachable, |
| 14360 | }); |
| 14361 | } |
| 14362 | |
| 14363 | pub fn getOffsetValueIndex(adapter: @This(), value: Value) u32 { |
| 14364 | return @subWithOverflow(adapter.offset(), adapter.getValueIndex(value))[0]; |
| 14365 | } |
| 14366 | |
| 14367 | pub fn getOffsetValueSignedIndex(adapter: @This(), value: Value) i32 { |
| 14368 | const signed_offset: i32 = @intCast(adapter.offset()); |
| 14369 | const signed_value: i32 = @intCast(adapter.getValueIndex(value)); |
| 14370 | return signed_offset - signed_value; |
| 14371 | } |
| 14372 | |
| 14373 | pub fn getOffsetConstantIndex(adapter: @This(), constant: Constant) u32 { |
| 14374 | return adapter.offset() - adapter.constant_adapter.getConstantIndex(constant); |
| 14375 | } |
| 14376 | |
| 14377 | pub fn offset(adapter: @This()) u32 { |
| 14378 | return @as( |
| 14379 | Function.Instruction.Index, |
| 14380 | @enumFromInt(adapter.instruction_index), |
| 14381 | ).valueIndex(adapter.func) + adapter.firstInstr(); |
| 14382 | } |
| 14383 | |
| 14384 | fn firstInstr(adapter: @This()) u32 { |
| 14385 | return adapter.constant_adapter.numConstants(); |
| 14386 | } |
| 14387 | |
| 14388 | pub fn next(adapter: *@This()) void { |
| 14389 | adapter.instruction_index += 1; |
| 14390 | } |
| 14391 | }; |
| 14392 | |
| 14393 | for (self.functions.items, 0..) |func, func_index| { |
| 14394 | const FunctionBlock = ir.FunctionBlock; |
| 14395 | if (func.global.getReplacement(self) != .none) continue; |
| 14396 | |
| 14397 | if (func.instructions.len == 0) continue; |
| 14398 | |
| 14399 | var function_block = try module_block.enterSubBlock(FunctionBlock); |
| 14400 | |
| 14401 | try function_block.writeAbbrev(FunctionBlock.DeclareBlocks{ .num_blocks = func.blocks.len }); |
| 14402 | |
| 14403 | var adapter = FunctionAdapter.init(constant_adapter, metadata_adapter, &func); |
| 14404 | |
| 14405 | // Emit function level metadata block |
| 14406 | if (!self.strip and func.debug_values.len != 0) { |
| 14407 | const MetadataBlock = ir.FunctionMetadataBlock; |
| 14408 | var metadata_block = try function_block.enterSubBlock(MetadataBlock); |
| 14409 | |
| 14410 | for (func.debug_values) |value| { |
| 14411 | try metadata_block.writeAbbrev(MetadataBlock.Value{ |
| 14412 | .ty = value.typeOf(@enumFromInt(func_index), self), |
| 14413 | .value = @enumFromInt(adapter.getValueIndex(value.toValue())), |
| 14414 | }); |
| 14415 | } |
| 14416 | |
| 14417 | try metadata_block.end(); |
| 14418 | } |
| 14419 | |
| 14420 | const tags = func.instructions.items(.tag); |
| 14421 | const datas = func.instructions.items(.data); |
| 14422 | |
| 14423 | var has_location = false; |
| 14424 | |
| 14425 | var block_incoming_len: u32 = undefined; |
| 14426 | for (0..func.instructions.len) |instr_index| { |
| 14427 | const tag = tags[instr_index]; |
| 14428 | |
| 14429 | record.clearRetainingCapacity(); |
| 14430 | |
| 14431 | switch (tag) { |
| 14432 | .block => block_incoming_len = datas[instr_index], |
| 14433 | .arg => {}, |
| 14434 | .@"unreachable" => try function_block.writeAbbrev(FunctionBlock.Unreachable{}), |
| 14435 | .call, |
| 14436 | .@"musttail call", |
| 14437 | .@"notail call", |
| 14438 | .@"tail call", |
| 14439 | => |kind| { |
| 14440 | var extra = func.extraDataTrail(Function.Instruction.Call, datas[instr_index]); |
| 14441 | |
| 14442 | const call_conv = extra.data.info.call_conv; |
| 14443 | const args = extra.trail.next(extra.data.args_len, Value, &func); |
| 14444 | try function_block.writeAbbrevAdapted(FunctionBlock.Call{ |
| 14445 | .attributes = extra.data.attributes, |
| 14446 | .call_type = switch (kind) { |
| 14447 | .call => .{ .call_conv = call_conv }, |
| 14448 | .@"tail call" => .{ .tail = true, .call_conv = call_conv }, |
| 14449 | .@"musttail call" => .{ .must_tail = true, .call_conv = call_conv }, |
| 14450 | .@"notail call" => .{ .no_tail = true, .call_conv = call_conv }, |
| 14451 | else => unreachable, |
| 14452 | }, |
| 14453 | .type_id = extra.data.ty, |
| 14454 | .callee = extra.data.callee, |
| 14455 | .args = args, |
| 14456 | }, adapter); |
| 14457 | }, |
| 14458 | .@"call fast", |
| 14459 | .@"musttail call fast", |
| 14460 | .@"notail call fast", |
| 14461 | .@"tail call fast", |
| 14462 | => |kind| { |
| 14463 | var extra = func.extraDataTrail(Function.Instruction.Call, datas[instr_index]); |
| 14464 | |
| 14465 | const call_conv = extra.data.info.call_conv; |
| 14466 | const args = extra.trail.next(extra.data.args_len, Value, &func); |
| 14467 | try function_block.writeAbbrevAdapted(FunctionBlock.CallFast{ |
| 14468 | .attributes = extra.data.attributes, |
| 14469 | .call_type = switch (kind) { |
| 14470 | .call => .{ .call_conv = call_conv }, |
| 14471 | .@"tail call" => .{ .tail = true, .call_conv = call_conv }, |
| 14472 | .@"musttail call" => .{ .must_tail = true, .call_conv = call_conv }, |
| 14473 | .@"notail call" => .{ .no_tail = true, .call_conv = call_conv }, |
| 14474 | else => unreachable, |
| 14475 | }, |
| 14476 | .fast_math = .{}, |
| 14477 | .type_id = extra.data.ty, |
| 14478 | .callee = extra.data.callee, |
| 14479 | .args = args, |
| 14480 | }, adapter); |
| 14481 | }, |
| 14482 | .add, |
| 14483 | .@"add nsw", |
| 14484 | .@"add nuw", |
| 14485 | .@"add nuw nsw", |
| 14486 | .@"and", |
| 14487 | .fadd, |
| 14488 | .fdiv, |
| 14489 | .fmul, |
| 14490 | .mul, |
| 14491 | .@"mul nsw", |
| 14492 | .@"mul nuw", |
| 14493 | .@"mul nuw nsw", |
| 14494 | .frem, |
| 14495 | .fsub, |
| 14496 | .sdiv, |
| 14497 | .@"sdiv exact", |
| 14498 | .sub, |
| 14499 | .@"sub nsw", |
| 14500 | .@"sub nuw", |
| 14501 | .@"sub nuw nsw", |
| 14502 | .udiv, |
| 14503 | .@"udiv exact", |
| 14504 | .xor, |
| 14505 | .shl, |
| 14506 | .@"shl nsw", |
| 14507 | .@"shl nuw", |
| 14508 | .@"shl nuw nsw", |
| 14509 | .lshr, |
| 14510 | .@"lshr exact", |
| 14511 | .@"or", |
| 14512 | .urem, |
| 14513 | .srem, |
| 14514 | .ashr, |
| 14515 | .@"ashr exact", |
| 14516 | => |kind| { |
| 14517 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 14518 | try function_block.writeAbbrev(FunctionBlock.Binary{ |
| 14519 | .opcode = kind.toBinaryOpcode(), |
| 14520 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14521 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14522 | }); |
| 14523 | }, |
| 14524 | .@"fadd fast", |
| 14525 | .@"fdiv fast", |
| 14526 | .@"fmul fast", |
| 14527 | .@"frem fast", |
| 14528 | .@"fsub fast", |
| 14529 | => |kind| { |
| 14530 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 14531 | try function_block.writeAbbrev(FunctionBlock.BinaryFast{ |
| 14532 | .opcode = kind.toBinaryOpcode(), |
| 14533 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14534 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14535 | .fast_math = .{}, |
| 14536 | }); |
| 14537 | }, |
| 14538 | .alloca, |
| 14539 | .@"alloca inalloca", |
| 14540 | => |kind| { |
| 14541 | const extra = func.extraData(Function.Instruction.Alloca, datas[instr_index]); |
| 14542 | const alignment = extra.info.alignment.toLlvm(); |
| 14543 | try function_block.writeAbbrev(FunctionBlock.Alloca{ |
| 14544 | .inst_type = extra.type, |
| 14545 | .len_type = extra.len.typeOf(@enumFromInt(func_index), self), |
| 14546 | .len_value = adapter.getValueIndex(extra.len), |
| 14547 | .flags = .{ |
| 14548 | .align_lower = @truncate(alignment), |
| 14549 | .inalloca = kind == .@"alloca inalloca", |
| 14550 | .explicit_type = true, |
| 14551 | .swift_error = false, |
| 14552 | .align_upper = @truncate(alignment << 5), |
| 14553 | }, |
| 14554 | }); |
| 14555 | }, |
| 14556 | .bitcast, |
| 14557 | .inttoptr, |
| 14558 | .ptrtoint, |
| 14559 | .fptosi, |
| 14560 | .fptoui, |
| 14561 | .sitofp, |
| 14562 | .uitofp, |
| 14563 | .addrspacecast, |
| 14564 | .fptrunc, |
| 14565 | .trunc, |
| 14566 | .fpext, |
| 14567 | .sext, |
| 14568 | .zext, |
| 14569 | => |kind| { |
| 14570 | const extra = func.extraData(Function.Instruction.Cast, datas[instr_index]); |
| 14571 | try function_block.writeAbbrev(FunctionBlock.Cast{ |
| 14572 | .val = adapter.getOffsetValueIndex(extra.val), |
| 14573 | .type_index = extra.type, |
| 14574 | .opcode = kind.toCastOpcode(), |
| 14575 | }); |
| 14576 | }, |
| 14577 | .@"fcmp false", |
| 14578 | .@"fcmp oeq", |
| 14579 | .@"fcmp oge", |
| 14580 | .@"fcmp ogt", |
| 14581 | .@"fcmp ole", |
| 14582 | .@"fcmp olt", |
| 14583 | .@"fcmp one", |
| 14584 | .@"fcmp ord", |
| 14585 | .@"fcmp true", |
| 14586 | .@"fcmp ueq", |
| 14587 | .@"fcmp uge", |
| 14588 | .@"fcmp ugt", |
| 14589 | .@"fcmp ule", |
| 14590 | .@"fcmp ult", |
| 14591 | .@"fcmp une", |
| 14592 | .@"fcmp uno", |
| 14593 | .@"icmp eq", |
| 14594 | .@"icmp ne", |
| 14595 | .@"icmp sge", |
| 14596 | .@"icmp sgt", |
| 14597 | .@"icmp sle", |
| 14598 | .@"icmp slt", |
| 14599 | .@"icmp uge", |
| 14600 | .@"icmp ugt", |
| 14601 | .@"icmp ule", |
| 14602 | .@"icmp ult", |
| 14603 | => |kind| { |
| 14604 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 14605 | try function_block.writeAbbrev(FunctionBlock.Cmp{ |
| 14606 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14607 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14608 | .pred = kind.toCmpPredicate(), |
| 14609 | }); |
| 14610 | }, |
| 14611 | .@"fcmp fast false", |
| 14612 | .@"fcmp fast oeq", |
| 14613 | .@"fcmp fast oge", |
| 14614 | .@"fcmp fast ogt", |
| 14615 | .@"fcmp fast ole", |
| 14616 | .@"fcmp fast olt", |
| 14617 | .@"fcmp fast one", |
| 14618 | .@"fcmp fast ord", |
| 14619 | .@"fcmp fast true", |
| 14620 | .@"fcmp fast ueq", |
| 14621 | .@"fcmp fast uge", |
| 14622 | .@"fcmp fast ugt", |
| 14623 | .@"fcmp fast ule", |
| 14624 | .@"fcmp fast ult", |
| 14625 | .@"fcmp fast une", |
| 14626 | .@"fcmp fast uno", |
| 14627 | => |kind| { |
| 14628 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 14629 | try function_block.writeAbbrev(FunctionBlock.CmpFast{ |
| 14630 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14631 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14632 | .pred = kind.toCmpPredicate(), |
| 14633 | .fast_math = .{}, |
| 14634 | }); |
| 14635 | }, |
| 14636 | .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{ |
| 14637 | .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])), |
| 14638 | }), |
| 14639 | .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{ |
| 14640 | .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])), |
| 14641 | .fast_math = .{}, |
| 14642 | }), |
| 14643 | .extractvalue => { |
| 14644 | var extra = func.extraDataTrail(Function.Instruction.ExtractValue, datas[instr_index]); |
| 14645 | const indices = extra.trail.next(extra.data.indices_len, u32, &func); |
| 14646 | try function_block.writeAbbrev(FunctionBlock.ExtractValue{ |
| 14647 | .val = adapter.getOffsetValueIndex(extra.data.val), |
| 14648 | .indices = indices, |
| 14649 | }); |
| 14650 | }, |
| 14651 | .insertvalue => { |
| 14652 | var extra = func.extraDataTrail(Function.Instruction.InsertValue, datas[instr_index]); |
| 14653 | const indices = extra.trail.next(extra.data.indices_len, u32, &func); |
| 14654 | try function_block.writeAbbrev(FunctionBlock.InsertValue{ |
| 14655 | .val = adapter.getOffsetValueIndex(extra.data.val), |
| 14656 | .elem = adapter.getOffsetValueIndex(extra.data.elem), |
| 14657 | .indices = indices, |
| 14658 | }); |
| 14659 | }, |
| 14660 | .extractelement => { |
| 14661 | const extra = func.extraData(Function.Instruction.ExtractElement, datas[instr_index]); |
| 14662 | try function_block.writeAbbrev(FunctionBlock.ExtractElement{ |
| 14663 | .val = adapter.getOffsetValueIndex(extra.val), |
| 14664 | .index = adapter.getOffsetValueIndex(extra.index), |
| 14665 | }); |
| 14666 | }, |
| 14667 | .insertelement => { |
| 14668 | const extra = func.extraData(Function.Instruction.InsertElement, datas[instr_index]); |
| 14669 | try function_block.writeAbbrev(FunctionBlock.InsertElement{ |
| 14670 | .val = adapter.getOffsetValueIndex(extra.val), |
| 14671 | .elem = adapter.getOffsetValueIndex(extra.elem), |
| 14672 | .index = adapter.getOffsetValueIndex(extra.index), |
| 14673 | }); |
| 14674 | }, |
| 14675 | .select => { |
| 14676 | const extra = func.extraData(Function.Instruction.Select, datas[instr_index]); |
| 14677 | try function_block.writeAbbrev(FunctionBlock.Select{ |
| 14678 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14679 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14680 | .cond = adapter.getOffsetValueIndex(extra.cond), |
| 14681 | }); |
| 14682 | }, |
| 14683 | .@"select fast" => { |
| 14684 | const extra = func.extraData(Function.Instruction.Select, datas[instr_index]); |
| 14685 | try function_block.writeAbbrev(FunctionBlock.SelectFast{ |
| 14686 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14687 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14688 | .cond = adapter.getOffsetValueIndex(extra.cond), |
| 14689 | .fast_math = .{}, |
| 14690 | }); |
| 14691 | }, |
| 14692 | .shufflevector => { |
| 14693 | const extra = func.extraData(Function.Instruction.ShuffleVector, datas[instr_index]); |
| 14694 | try function_block.writeAbbrev(FunctionBlock.ShuffleVector{ |
| 14695 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 14696 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 14697 | .mask = adapter.getOffsetValueIndex(extra.mask), |
| 14698 | }); |
| 14699 | }, |
| 14700 | .getelementptr, |
| 14701 | .@"getelementptr inbounds", |
| 14702 | => |kind| { |
| 14703 | var extra = func.extraDataTrail(Function.Instruction.GetElementPtr, datas[instr_index]); |
| 14704 | const indices = extra.trail.next(extra.data.indices_len, Value, &func); |
| 14705 | try function_block.writeAbbrevAdapted( |
| 14706 | FunctionBlock.GetElementPtr{ |
| 14707 | .is_inbounds = kind == .@"getelementptr inbounds", |
| 14708 | .type_index = extra.data.type, |
| 14709 | .base = extra.data.base, |
| 14710 | .indices = indices, |
| 14711 | }, |
| 14712 | adapter, |
| 14713 | ); |
| 14714 | }, |
| 14715 | .load => { |
| 14716 | const extra = func.extraData(Function.Instruction.Load, datas[instr_index]); |
| 14717 | try function_block.writeAbbrev(FunctionBlock.Load{ |
| 14718 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 14719 | .ty = extra.type, |
| 14720 | .alignment = extra.info.alignment.toLlvm(), |
| 14721 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 14722 | }); |
| 14723 | }, |
| 14724 | .@"load atomic" => { |
| 14725 | const extra = func.extraData(Function.Instruction.Load, datas[instr_index]); |
| 14726 | try function_block.writeAbbrev(FunctionBlock.LoadAtomic{ |
| 14727 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 14728 | .ty = extra.type, |
| 14729 | .alignment = extra.info.alignment.toLlvm(), |
| 14730 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 14731 | .success_ordering = extra.info.success_ordering, |
| 14732 | .sync_scope = extra.info.sync_scope, |
| 14733 | }); |
| 14734 | }, |
| 14735 | .store => { |
| 14736 | const extra = func.extraData(Function.Instruction.Store, datas[instr_index]); |
| 14737 | try function_block.writeAbbrev(FunctionBlock.Store{ |
| 14738 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 14739 | .val = adapter.getOffsetValueIndex(extra.val), |
| 14740 | .alignment = extra.info.alignment.toLlvm(), |
| 14741 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 14742 | }); |
| 14743 | }, |
| 14744 | .@"store atomic" => { |
| 14745 | const extra = func.extraData(Function.Instruction.Store, datas[instr_index]); |
| 14746 | try function_block.writeAbbrev(FunctionBlock.StoreAtomic{ |
| 14747 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 14748 | .val = adapter.getOffsetValueIndex(extra.val), |
| 14749 | .alignment = extra.info.alignment.toLlvm(), |
| 14750 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 14751 | .success_ordering = extra.info.success_ordering, |
| 14752 | .sync_scope = extra.info.sync_scope, |
| 14753 | }); |
| 14754 | }, |
| 14755 | .br => { |
| 14756 | try function_block.writeAbbrev(FunctionBlock.BrUnconditional{ |
| 14757 | .block = datas[instr_index], |
| 14758 | }); |
| 14759 | }, |
| 14760 | .br_cond => { |
| 14761 | const extra = func.extraData(Function.Instruction.BrCond, datas[instr_index]); |
| 14762 | try function_block.writeAbbrev(FunctionBlock.BrConditional{ |
| 14763 | .then_block = @intFromEnum(extra.then), |
| 14764 | .else_block = @intFromEnum(extra.@"else"), |
| 14765 | .condition = adapter.getOffsetValueIndex(extra.cond), |
| 14766 | }); |
| 14767 | }, |
| 14768 | .@"switch" => { |
| 14769 | var extra = func.extraDataTrail(Function.Instruction.Switch, datas[instr_index]); |
| 14770 | |
| 14771 | try record.ensureUnusedCapacity(self.gpa, 3 + extra.data.cases_len * 2); |
| 14772 | |
| 14773 | // Conditional type |
| 14774 | record.appendAssumeCapacity(@intFromEnum(extra.data.val.typeOf(@enumFromInt(func_index), self))); |
| 14775 | |
| 14776 | // Conditional |
| 14777 | record.appendAssumeCapacity(adapter.getOffsetValueIndex(extra.data.val)); |
| 14778 | |
| 14779 | // Default block |
| 14780 | record.appendAssumeCapacity(@intFromEnum(extra.data.default)); |
| 14781 | |
| 14782 | const vals = extra.trail.next(extra.data.cases_len, Constant, &func); |
| 14783 | const blocks = extra.trail.next(extra.data.cases_len, Function.Block.Index, &func); |
| 14784 | for (vals, blocks) |val, block| { |
| 14785 | record.appendAssumeCapacity(adapter.constant_adapter.getConstantIndex(val)); |
| 14786 | record.appendAssumeCapacity(@intFromEnum(block)); |
| 14787 | } |
| 14788 | |
| 14789 | try function_block.writeUnabbrev(12, record.items); |
| 14790 | }, |
| 14791 | .va_arg => { |
| 14792 | const extra = func.extraData(Function.Instruction.VaArg, datas[instr_index]); |
| 14793 | try function_block.writeAbbrev(FunctionBlock.VaArg{ |
| 14794 | .list_type = extra.list.typeOf(@enumFromInt(func_index), self), |
| 14795 | .list = adapter.getOffsetValueIndex(extra.list), |
| 14796 | .type = extra.type, |
| 14797 | }); |
| 14798 | }, |
| 14799 | .phi, |
| 14800 | .@"phi fast", |
| 14801 | => |kind| { |
| 14802 | var extra = func.extraDataTrail(Function.Instruction.Phi, datas[instr_index]); |
| 14803 | const vals = extra.trail.next(block_incoming_len, Value, &func); |
| 14804 | const blocks = extra.trail.next(block_incoming_len, Function.Block.Index, &func); |
| 14805 | |
| 14806 | try record.ensureUnusedCapacity( |
| 14807 | self.gpa, |
| 14808 | 1 + block_incoming_len * 2 + @intFromBool(kind == .@"phi fast"), |
| 14809 | ); |
| 14810 | |
| 14811 | record.appendAssumeCapacity(@intFromEnum(extra.data.type)); |
| 14812 | |
| 14813 | for (vals, blocks) |val, block| { |
| 14814 | const offset_value = adapter.getOffsetValueSignedIndex(val); |
| 14815 | const abs_value: u32 = @intCast(@abs(offset_value)); |
| 14816 | const signed_vbr = if (offset_value > 0) abs_value << 1 else ((abs_value << 1) | 1); |
| 14817 | record.appendAssumeCapacity(signed_vbr); |
| 14818 | record.appendAssumeCapacity(@intFromEnum(block)); |
| 14819 | } |
| 14820 | |
| 14821 | if (kind == .@"phi fast") record.appendAssumeCapacity(@as(u8, @bitCast(FastMath{}))); |
| 14822 | |
| 14823 | try function_block.writeUnabbrev(16, record.items); |
| 14824 | }, |
| 14825 | .ret => try function_block.writeAbbrev(FunctionBlock.Ret{ |
| 14826 | .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])), |
| 14827 | }), |
| 14828 | .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}), |
| 14829 | .atomicrmw => { |
| 14830 | const extra = func.extraData(Function.Instruction.AtomicRmw, datas[instr_index]); |
| 14831 | try function_block.writeAbbrev(FunctionBlock.AtomicRmw{ |
| 14832 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 14833 | .val = adapter.getOffsetValueIndex(extra.val), |
| 14834 | .operation = extra.info.atomic_rmw_operation, |
| 14835 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 14836 | .success_ordering = extra.info.success_ordering, |
| 14837 | .sync_scope = extra.info.sync_scope, |
| 14838 | .alignment = extra.info.alignment.toLlvm(), |
| 14839 | }); |
| 14840 | }, |
| 14841 | .cmpxchg, |
| 14842 | .@"cmpxchg weak", |
| 14843 | => |kind| { |
| 14844 | const extra = func.extraData(Function.Instruction.CmpXchg, datas[instr_index]); |
| 14845 | |
| 14846 | try function_block.writeAbbrev(FunctionBlock.CmpXchg{ |
| 14847 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 14848 | .cmp = adapter.getOffsetValueIndex(extra.cmp), |
| 14849 | .new = adapter.getOffsetValueIndex(extra.new), |
| 14850 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 14851 | .success_ordering = extra.info.success_ordering, |
| 14852 | .sync_scope = extra.info.sync_scope, |
| 14853 | .failure_ordering = extra.info.failure_ordering, |
| 14854 | .is_weak = kind == .@"cmpxchg weak", |
| 14855 | .alignment = extra.info.alignment.toLlvm(), |
| 14856 | }); |
| 14857 | }, |
| 14858 | .fence => { |
| 14859 | const info: MemoryAccessInfo = @bitCast(datas[instr_index]); |
| 14860 | try function_block.writeAbbrev(FunctionBlock.Fence{ |
| 14861 | .ordering = info.success_ordering, |
| 14862 | .sync_scope = info.sync_scope, |
| 14863 | }); |
| 14864 | }, |
| 14865 | } |
| 14866 | |
| 14867 | if (!self.strip) { |
| 14868 | if (func.debug_locations.get(@enumFromInt(instr_index))) |debug_location| { |
| 14869 | if (debug_location != .none) { |
| 14870 | const location = self.metadata_items.get(@intFromEnum(debug_location)); |
| 14871 | assert(location.tag == .location); |
| 14872 | const extra = self.metadataExtraData(Metadata.Location, location.data); |
| 14873 | try function_block.writeAbbrev(FunctionBlock.DebugLoc{ |
| 14874 | .line = extra.line, |
| 14875 | .column = extra.column, |
| 14876 | .scope = @enumFromInt(metadata_adapter.getMetadataIndex(extra.scope)), |
| 14877 | .inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(extra.inlined_at)), |
| 14878 | .is_implicit = false, |
| 14879 | }); |
| 14880 | has_location = true; |
| 14881 | } else { |
| 14882 | has_location = false; |
| 14883 | } |
| 14884 | } else if (has_location) { |
| 14885 | try function_block.writeAbbrev(FunctionBlock.DebugLocAgain{}); |
| 14886 | } |
| 14887 | } |
| 14888 | |
| 14889 | adapter.next(); |
| 14890 | } |
| 14891 | |
| 14892 | // VALUE_SYMTAB |
| 14893 | if (!self.strip) { |
| 14894 | const ValueSymbolTable = ir.FunctionValueSymbolTable; |
| 14895 | |
| 14896 | var value_symtab_block = try function_block.enterSubBlock(ValueSymbolTable); |
| 14897 | |
| 14898 | for (func.blocks, 0..) |block, block_index| { |
| 14899 | const name = block.instruction.name(&func); |
| 14900 | |
| 14901 | if (name == .none or name == .empty) continue; |
| 14902 | |
| 14903 | try value_symtab_block.writeAbbrev(ValueSymbolTable.BlockEntry{ |
| 14904 | .value_id = @intCast(block_index), |
| 14905 | .string = name.slice(self).?, |
| 14906 | }); |
| 14907 | } |
| 14908 | |
| 14909 | // TODO: Emit non block entries if the builder ever starts assigning names to non blocks |
| 14910 | |
| 14911 | try value_symtab_block.end(); |
| 14912 | } |
| 14913 | |
| 14914 | // METADATA_ATTACHMENT_BLOCK |
| 14915 | if (!self.strip) blk: { |
| 14916 | const dbg = func.global.ptrConst(self).dbg; |
| 14917 | |
| 14918 | if (dbg == .none) break :blk; |
| 14919 | |
| 14920 | const MetadataAttachmentBlock = ir.MetadataAttachmentBlock; |
| 14921 | var metadata_attach_block = try function_block.enterSubBlock(MetadataAttachmentBlock); |
| 14922 | |
| 14923 | try metadata_attach_block.writeAbbrev(MetadataAttachmentBlock.AttachmentSingle{ |
| 14924 | .kind = ir.MetadataKind.dbg, |
| 14925 | .metadata = @enumFromInt(metadata_adapter.getMetadataIndex(dbg) - 1), |
| 14926 | }); |
| 14927 | |
| 14928 | try metadata_attach_block.end(); |
| 14929 | } |
| 14930 | |
| 14931 | try function_block.end(); |
| 14932 | } |
| 14933 | } |
| 14934 | |
| 14935 | try module_block.end(); |
| 14936 | } |
| 14937 | |
| 14938 | // STRTAB_BLOCK |
| 14939 | { |
| 14940 | const Strtab = ir.Strtab; |
| 14941 | var strtab_block = try bitcode.enterTopBlock(Strtab); |
| 14942 | |
| 14943 | try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.string_bytes.items }); |
| 14944 | |
| 14945 | try strtab_block.end(); |
| 14946 | } |
| 14947 | |
| 14948 | return bitcode.toSlice(); |
| 14949 | } |
| 14950 | |
| 14951 | const Allocator = std.mem.Allocator; |
| 14952 | const assert = std.debug.assert; |
| 14953 | const bitcode_writer = @import("bitcode_writer.zig"); |
| 14954 | const build_options = @import("build_options"); |
| 14955 | const Builder = @This(); |
| 14956 | const builtin = @import("builtin"); |
| 14957 | const DW = std.dwarf; |
| 14958 | const ir = @import("ir.zig"); |
| 14959 | const log = std.log.scoped(.llvm); |
| 14960 | const std = @import("std"); |