| ... | @@ -1,21 +1,6 @@ | ... | @@ -1,21 +1,6 @@ |
| 1 | gpa: Allocator, | 1 | gpa: Allocator, |
| 2 | use_lib_llvm: bool, | | |
| 3 | strip: bool, | 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 | source_filename: String, | 4 | source_filename: String, |
| 20 | data_layout: String, | 5 | data_layout: String, |
| 21 | target_triple: String, | 6 | target_triple: String, |
| ... | @@ -37,6 +22,8 @@ attributes_map: std.AutoArrayHashMapUnmanaged(void, void), | ... | @@ -37,6 +22,8 @@ attributes_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 37 | attributes_indices: std.ArrayListUnmanaged(u32), | 22 | attributes_indices: std.ArrayListUnmanaged(u32), |
| 38 | attributes_extra: std.ArrayListUnmanaged(u32), | 23 | attributes_extra: std.ArrayListUnmanaged(u32), |
| 39 | | 24 | |
| | 25 | function_attributes_set: std.AutoArrayHashMapUnmanaged(FunctionAttributes, void), |
| | 26 | |
| 40 | globals: std.AutoArrayHashMapUnmanaged(String, Global), | 27 | globals: std.AutoArrayHashMapUnmanaged(String, Global), |
| 41 | next_unnamed_global: String, | 28 | next_unnamed_global: String, |
| 42 | next_replaced_global: String, | 29 | next_replaced_global: String, |
| ... | @@ -50,17 +37,29 @@ constant_items: std.MultiArrayList(Constant.Item), | ... | @@ -50,17 +37,29 @@ constant_items: std.MultiArrayList(Constant.Item), |
| 50 | constant_extra: std.ArrayListUnmanaged(u32), | 37 | constant_extra: std.ArrayListUnmanaged(u32), |
| 51 | constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb), | 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 | pub const expected_args_len = 16; | 54 | pub const expected_args_len = 16; |
| 54 | pub const expected_attrs_len = 16; | 55 | pub const expected_attrs_len = 16; |
| 55 | pub const expected_fields_len = 32; | 56 | pub const expected_fields_len = 32; |
| 56 | pub const expected_gep_indices_len = 8; | 57 | pub const expected_gep_indices_len = 8; |
| 57 | pub const expected_cases_len = 8; | 58 | pub const expected_cases_len = 8; |
| 58 | pub const expected_incoming_len = 8; | 59 | pub const expected_incoming_len = 8; |
| 59 | pub const expected_intrinsic_name_len = 64; | | |
| 60 | | 60 | |
| 61 | pub const Options = struct { | 61 | pub const Options = struct { |
| 62 | allocator: Allocator, | 62 | allocator: Allocator, |
| 63 | use_lib_llvm: bool = false, | | |
| 64 | strip: bool = true, | 63 | strip: bool = true, |
| 65 | name: []const u8 = &.{}, | 64 | name: []const u8 = &.{}, |
| 66 | target: std.Target = builtin.target, | 65 | target: std.Target = builtin.target, |
| ... | @@ -77,11 +76,11 @@ pub const String = enum(u32) { | ... | @@ -77,11 +76,11 @@ pub const String = enum(u32) { |
| 77 | return self.toIndex() == null; | 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 | const index = self.toIndex() orelse return null; | 80 | const index = self.toIndex() orelse return null; |
| 82 | const start = b.string_indices.items[index]; | 81 | const start = builder.string_indices.items[index]; |
| 83 | const end = b.string_indices.items[index + 1]; | 82 | const end = builder.string_indices.items[index + 1]; |
| 84 | return b.string_bytes.items[start .. end - 1 :0]; | 83 | return builder.string_bytes.items[start..end]; |
| 85 | } | 84 | } |
| 86 | | 85 | |
| 87 | const FormatData = struct { | 86 | const FormatData = struct { |
| ... | @@ -94,17 +93,21 @@ pub const String = enum(u32) { | ... | @@ -94,17 +93,21 @@ pub const String = enum(u32) { |
| 94 | _: std.fmt.FormatOptions, | 93 | _: std.fmt.FormatOptions, |
| 95 | writer: anytype, | 94 | writer: anytype, |
| 96 | ) @TypeOf(writer).Error!void { | 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 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); | 97 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); |
| 99 | assert(data.string != .none); | 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 | return writer.print("{d}", .{@intFromEnum(data.string)}); | 100 | return writer.print("{d}", .{@intFromEnum(data.string)}); |
| 102 | try printEscapedString(sentinel_slice[0 .. sentinel_slice.len + comptime @intFromBool( | 101 | if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_| |
| 103 | std.mem.indexOfScalar(u8, fmt_str, '@') != null, | 102 | return writer.writeAll(string_slice); |
| 104 | )], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| | 103 | try printEscapedString( |
| 105 | .always_quote | 104 | string_slice, |
| 106 | else | 105 | if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| |
| 107 | .quote_unless_valid_identifier, writer); | 106 | .always_quote |
| | 107 | else |
| | 108 | .quote_unless_valid_identifier, |
| | 109 | writer, |
| | 110 | ); |
| 108 | } | 111 | } |
| 109 | pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) { | 112 | pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) { |
| 110 | return .{ .data = .{ .string = self, .builder = builder } }; | 113 | return .{ .data = .{ .string = self, .builder = builder } }; |
| ... | @@ -130,6 +133,72 @@ pub const String = enum(u32) { | ... | @@ -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 | pub const Type = enum(u32) { | 202 | pub const Type = enum(u32) { |
| 134 | void, | 203 | void, |
| 135 | half, | 204 | half, |
| ... | @@ -178,20 +247,20 @@ pub const Type = enum(u32) { | ... | @@ -178,20 +247,20 @@ pub const Type = enum(u32) { |
| 178 | named_structure, | 247 | named_structure, |
| 179 | }; | 248 | }; |
| 180 | | 249 | |
| 181 | pub const Simple = enum { | 250 | pub const Simple = enum(u5) { |
| 182 | void, | 251 | void = 2, |
| 183 | half, | 252 | half = 10, |
| 184 | bfloat, | 253 | bfloat = 23, |
| 185 | float, | 254 | float = 3, |
| 186 | double, | 255 | double = 4, |
| 187 | fp128, | 256 | fp128 = 14, |
| 188 | x86_fp80, | 257 | x86_fp80 = 13, |
| 189 | ppc_fp128, | 258 | ppc_fp128 = 15, |
| 190 | x86_amx, | 259 | x86_amx = 24, |
| 191 | x86_mmx, | 260 | x86_mmx = 17, |
| 192 | label, | 261 | label = 5, |
| 193 | token, | 262 | token = 22, |
| 194 | metadata, | 263 | metadata = 16, |
| 195 | }; | 264 | }; |
| 196 | | 265 | |
| 197 | pub const Function = struct { | 266 | pub const Function = struct { |
| ... | @@ -579,7 +648,6 @@ pub const Type = enum(u32) { | ... | @@ -579,7 +648,6 @@ pub const Type = enum(u32) { |
| 579 | var visited: IsSizedVisited = .{}; | 648 | var visited: IsSizedVisited = .{}; |
| 580 | defer visited.deinit(builder.gpa); | 649 | defer visited.deinit(builder.gpa); |
| 581 | const result = try self.isSizedVisited(&visited, builder); | 650 | const result = try self.isSizedVisited(&visited, builder); |
| 582 | if (builder.useLibLlvm()) assert(result == self.toLlvm(builder).isSized().toBool()); | | |
| 583 | return result; | 651 | return result; |
| 584 | } | 652 | } |
| 585 | | 653 | |
| ... | @@ -766,11 +834,6 @@ pub const Type = enum(u32) { | ... | @@ -766,11 +834,6 @@ pub const Type = enum(u32) { |
| 766 | return .{ .data = .{ .type = self, .builder = builder } }; | 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 | const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void); | 837 | const IsSizedVisited = std.AutoHashMapUnmanaged(Type, void); |
| 775 | fn isSizedVisited( | 838 | fn isSizedVisited( |
| 776 | self: Type, | 839 | self: Type, |
| ... | @@ -1051,14 +1114,21 @@ pub const Attribute = union(Kind) { | ... | @@ -1051,14 +1114,21 @@ pub const Attribute = union(Kind) { |
| 1051 | .no_sanitize_hwaddress, | 1114 | .no_sanitize_hwaddress, |
| 1052 | .sanitize_address_dyninit, | 1115 | .sanitize_address_dyninit, |
| 1053 | => |kind| { | 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 | comptime assert(std.mem.eql(u8, @tagName(kind), field.name)); | 1124 | comptime assert(std.mem.eql(u8, @tagName(kind), field.name)); |
| 1056 | return @unionInit(Attribute, field.name, switch (field.type) { | 1125 | return @unionInit(Attribute, field.name, switch (field.type) { |
| 1057 | void => {}, | 1126 | void => {}, |
| 1058 | u32 => storage.value, | 1127 | u32 => storage.value, |
| 1059 | Alignment, String, Type, UwTable => @enumFromInt(storage.value), | 1128 | Alignment, String, Type, UwTable => @enumFromInt(storage.value), |
| 1060 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), | 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 | .string, .none => unreachable, | 1134 | .string, .none => unreachable, |
| ... | @@ -1246,109 +1316,104 @@ pub const Attribute = union(Kind) { | ... | @@ -1246,109 +1316,104 @@ pub const Attribute = union(Kind) { |
| 1246 | fn toStorage(self: Index, builder: *const Builder) Storage { | 1316 | fn toStorage(self: Index, builder: *const Builder) Storage { |
| 1247 | return builder.attributes.keys()[@intFromEnum(self)]; | 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 | pub const Kind = enum(u32) { | 1321 | pub const Kind = enum(u32) { |
| 1257 | // Parameter Attributes | 1322 | // Parameter Attributes |
| 1258 | zeroext, | 1323 | zeroext = 34, |
| 1259 | signext, | 1324 | signext = 24, |
| 1260 | inreg, | 1325 | inreg = 5, |
| 1261 | byval, | 1326 | byval = 3, |
| 1262 | byref, | 1327 | byref = 69, |
| 1263 | preallocated, | 1328 | preallocated = 65, |
| 1264 | inalloca, | 1329 | inalloca = 38, |
| 1265 | sret, | 1330 | sret = 29, // TODO: ? |
| 1266 | elementtype, | 1331 | elementtype = 77, |
| 1267 | @"align", | 1332 | @"align" = 1, |
| 1268 | @"noalias", | 1333 | @"noalias" = 9, |
| 1269 | nocapture, | 1334 | nocapture = 11, |
| 1270 | nofree, | 1335 | nofree = 62, |
| 1271 | nest, | 1336 | nest = 8, |
| 1272 | returned, | 1337 | returned = 22, |
| 1273 | nonnull, | 1338 | nonnull = 39, |
| 1274 | dereferenceable, | 1339 | dereferenceable = 41, |
| 1275 | dereferenceable_or_null, | 1340 | dereferenceable_or_null = 42, |
| 1276 | swiftself, | 1341 | swiftself = 46, |
| 1277 | swiftasync, | 1342 | swiftasync = 75, |
| 1278 | swifterror, | 1343 | swifterror = 47, |
| 1279 | immarg, | 1344 | immarg = 60, |
| 1280 | noundef, | 1345 | noundef = 68, |
| 1281 | nofpclass, | 1346 | nofpclass = 87, |
| 1282 | alignstack, | 1347 | alignstack = 25, |
| 1283 | allocalign, | 1348 | allocalign = 80, |
| 1284 | allocptr, | 1349 | allocptr = 81, |
| 1285 | readnone, | 1350 | readnone = 20, |
| 1286 | readonly, | 1351 | readonly = 21, |
| 1287 | writeonly, | 1352 | writeonly = 52, |
| 1288 | | 1353 | |
| 1289 | // Function Attributes | 1354 | // Function Attributes |
| 1290 | //alignstack, | 1355 | //alignstack, |
| 1291 | allockind, | 1356 | allockind = 82, |
| 1292 | allocsize, | 1357 | allocsize = 51, |
| 1293 | alwaysinline, | 1358 | alwaysinline = 2, |
| 1294 | builtin, | 1359 | builtin = 35, |
| 1295 | cold, | 1360 | cold = 36, |
| 1296 | convergent, | 1361 | convergent = 43, |
| 1297 | disable_sanitizer_information, | 1362 | disable_sanitizer_information = 78, |
| 1298 | fn_ret_thunk_extern, | 1363 | fn_ret_thunk_extern = 84, |
| 1299 | hot, | 1364 | hot = 72, |
| 1300 | inlinehint, | 1365 | inlinehint = 4, |
| 1301 | jumptable, | 1366 | jumptable = 40, |
| 1302 | memory, | 1367 | memory = 86, |
| 1303 | minsize, | 1368 | minsize = 6, |
| 1304 | naked, | 1369 | naked = 7, |
| 1305 | nobuiltin, | 1370 | nobuiltin = 10, |
| 1306 | nocallback, | 1371 | nocallback = 71, |
| 1307 | noduplicate, | 1372 | noduplicate = 12, |
| 1308 | //nofree, | 1373 | //nofree, |
| 1309 | noimplicitfloat, | 1374 | noimplicitfloat = 13, |
| 1310 | @"noinline", | 1375 | @"noinline" = 14, |
| 1311 | nomerge, | 1376 | nomerge = 66, |
| 1312 | nonlazybind, | 1377 | nonlazybind = 15, |
| 1313 | noprofile, | 1378 | noprofile = 73, |
| 1314 | skipprofile, | 1379 | skipprofile = 85, |
| 1315 | noredzone, | 1380 | noredzone = 16, |
| 1316 | noreturn, | 1381 | noreturn = 17, |
| 1317 | norecurse, | 1382 | norecurse = 48, |
| 1318 | willreturn, | 1383 | willreturn = 61, |
| 1319 | nosync, | 1384 | nosync = 63, |
| 1320 | nounwind, | 1385 | nounwind = 18, |
| 1321 | nosanitize_bounds, | 1386 | nosanitize_bounds = 79, |
| 1322 | nosanitize_coverage, | 1387 | nosanitize_coverage = 76, |
| 1323 | null_pointer_is_valid, | 1388 | null_pointer_is_valid = 67, |
| 1324 | optforfuzzing, | 1389 | optforfuzzing = 57, |
| 1325 | optnone, | 1390 | optnone = 37, |
| 1326 | optsize, | 1391 | optsize = 19, |
| 1327 | //preallocated, | 1392 | //preallocated, |
| 1328 | returns_twice, | 1393 | returns_twice = 23, |
| 1329 | safestack, | 1394 | safestack = 44, |
| 1330 | sanitize_address, | 1395 | sanitize_address = 30, |
| 1331 | sanitize_memory, | 1396 | sanitize_memory = 32, |
| 1332 | sanitize_thread, | 1397 | sanitize_thread = 31, |
| 1333 | sanitize_hwaddress, | 1398 | sanitize_hwaddress = 55, |
| 1334 | sanitize_memtag, | 1399 | sanitize_memtag = 64, |
| 1335 | speculative_load_hardening, | 1400 | speculative_load_hardening = 59, |
| 1336 | speculatable, | 1401 | speculatable = 53, |
| 1337 | ssp, | 1402 | ssp = 26, |
| 1338 | sspstrong, | 1403 | sspstrong = 28, |
| 1339 | sspreq, | 1404 | sspreq = 27, |
| 1340 | strictfp, | 1405 | strictfp = 54, |
| 1341 | uwtable, | 1406 | uwtable = 33, |
| 1342 | nocf_check, | 1407 | nocf_check = 56, |
| 1343 | shadowcallstack, | 1408 | shadowcallstack = 58, |
| 1344 | mustprogress, | 1409 | mustprogress = 70, |
| 1345 | vscale_range, | 1410 | vscale_range = 74, |
| 1346 | | 1411 | |
| 1347 | // Global Attributes | 1412 | // Global Attributes |
| 1348 | no_sanitize_address, | 1413 | no_sanitize_address = 100, |
| 1349 | no_sanitize_hwaddress, | 1414 | no_sanitize_hwaddress = 101, |
| 1350 | //sanitize_memtag, | 1415 | //sanitize_memtag, |
| 1351 | sanitize_address_dyninit, | 1416 | sanitize_address_dyninit = 102, |
| 1352 | | 1417 | |
| 1353 | string = std.math.maxInt(u31), | 1418 | string = std.math.maxInt(u31), |
| 1354 | none = std.math.maxInt(u32), | 1419 | none = std.math.maxInt(u32), |
| ... | @@ -1368,11 +1433,6 @@ pub const Attribute = union(Kind) { | ... | @@ -1368,11 +1433,6 @@ pub const Attribute = union(Kind) { |
| 1368 | const str: String = @enumFromInt(@intFromEnum(self)); | 1433 | const str: String = @enumFromInt(@intFromEnum(self)); |
| 1369 | return if (str.isAnon()) null else str; | 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 | pub const FpClass = packed struct(u32) { | 1438 | pub const FpClass = packed struct(u32) { |
| ... | @@ -1494,12 +1554,12 @@ pub const Attribute = union(Kind) { | ... | @@ -1494,12 +1554,12 @@ pub const Attribute = union(Kind) { |
| 1494 | | 1554 | |
| 1495 | fn toStorage(self: Attribute) Storage { | 1555 | fn toStorage(self: Attribute) Storage { |
| 1496 | return switch (self) { | 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 | void => 0, | 1558 | void => 0, |
| 1499 | u32 => value, | 1559 | u32 => value, |
| 1500 | Alignment, String, Type, UwTable => @intFromEnum(value), | 1560 | Alignment, String, Type, UwTable => @intFromEnum(value), |
| 1501 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), | 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 | .string => |string_attr| .{ | 1564 | .string => |string_attr| .{ |
| 1505 | .kind = Kind.fromString(string_attr.kind), | 1565 | .kind = Kind.fromString(string_attr.kind), |
| ... | @@ -1709,18 +1769,18 @@ pub const FunctionAttributes = enum(u32) { | ... | @@ -1709,18 +1769,18 @@ pub const FunctionAttributes = enum(u32) { |
| 1709 | } | 1769 | } |
| 1710 | }; | 1770 | }; |
| 1711 | | 1771 | |
| 1712 | pub const Linkage = enum { | 1772 | pub const Linkage = enum(u4) { |
| 1713 | private, | 1773 | private = 9, |
| 1714 | internal, | 1774 | internal = 3, |
| 1715 | weak, | 1775 | weak = 1, |
| 1716 | weak_odr, | 1776 | weak_odr = 10, |
| 1717 | linkonce, | 1777 | linkonce = 4, |
| 1718 | linkonce_odr, | 1778 | linkonce_odr = 11, |
| 1719 | available_externally, | 1779 | available_externally = 12, |
| 1720 | appending, | 1780 | appending = 2, |
| 1721 | common, | 1781 | common = 8, |
| 1722 | extern_weak, | 1782 | extern_weak = 7, |
| 1723 | external, | 1783 | external = 0, |
| 1724 | | 1784 | |
| 1725 | pub fn format( | 1785 | pub fn format( |
| 1726 | self: Linkage, | 1786 | self: Linkage, |
| ... | @@ -1731,20 +1791,16 @@ pub const Linkage = enum { | ... | @@ -1731,20 +1791,16 @@ pub const Linkage = enum { |
| 1731 | if (self != .external) try writer.print(" {s}", .{@tagName(self)}); | 1791 | if (self != .external) try writer.print(" {s}", .{@tagName(self)}); |
| 1732 | } | 1792 | } |
| 1733 | | 1793 | |
| 1734 | fn toLlvm(self: Linkage) llvm.Linkage { | 1794 | fn formatOptional( |
| 1735 | return switch (self) { | 1795 | data: ?Linkage, |
| 1736 | .private => .Private, | 1796 | comptime _: []const u8, |
| 1737 | .internal => .Internal, | 1797 | _: std.fmt.FormatOptions, |
| 1738 | .weak => .WeakAny, | 1798 | writer: anytype, |
| 1739 | .weak_odr => .WeakODR, | 1799 | ) @TypeOf(writer).Error!void { |
| 1740 | .linkonce => .LinkOnceAny, | 1800 | if (data) |linkage| try writer.print(" {s}", .{@tagName(linkage)}); |
| 1741 | .linkonce_odr => .LinkOnceODR, | 1801 | } |
| 1742 | .available_externally => .AvailableExternally, | 1802 | pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) { |
| 1743 | .appending => .Appending, | 1803 | return .{ .data = self }; |
| 1744 | .common => .Common, | | |
| 1745 | .extern_weak => .ExternalWeak, | | |
| 1746 | .external => .External, | | |
| 1747 | }; | | |
| 1748 | } | 1804 | } |
| 1749 | }; | 1805 | }; |
| 1750 | | 1806 | |
| ... | @@ -1763,10 +1819,10 @@ pub const Preemption = enum { | ... | @@ -1763,10 +1819,10 @@ pub const Preemption = enum { |
| 1763 | } | 1819 | } |
| 1764 | }; | 1820 | }; |
| 1765 | | 1821 | |
| 1766 | pub const Visibility = enum { | 1822 | pub const Visibility = enum(u2) { |
| 1767 | default, | 1823 | default = 0, |
| 1768 | hidden, | 1824 | hidden = 1, |
| 1769 | protected, | 1825 | protected = 2, |
| 1770 | | 1826 | |
| 1771 | pub fn format( | 1827 | pub fn format( |
| 1772 | self: Visibility, | 1828 | self: Visibility, |
| ... | @@ -1776,20 +1832,12 @@ pub const Visibility = enum { | ... | @@ -1776,20 +1832,12 @@ pub const Visibility = enum { |
| 1776 | ) @TypeOf(writer).Error!void { | 1832 | ) @TypeOf(writer).Error!void { |
| 1777 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); | 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 { | 1837 | pub const DllStorageClass = enum(u2) { |
| 1790 | default, | 1838 | default = 0, |
| 1791 | dllimport, | 1839 | dllimport = 1, |
| 1792 | dllexport, | 1840 | dllexport = 2, |
| 1793 | | 1841 | |
| 1794 | pub fn format( | 1842 | pub fn format( |
| 1795 | self: DllStorageClass, | 1843 | self: DllStorageClass, |
| ... | @@ -1799,22 +1847,14 @@ pub const DllStorageClass = enum { | ... | @@ -1799,22 +1847,14 @@ pub const DllStorageClass = enum { |
| 1799 | ) @TypeOf(writer).Error!void { | 1847 | ) @TypeOf(writer).Error!void { |
| 1800 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); | 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 { | 1852 | pub const ThreadLocal = enum(u3) { |
| 1813 | default, | 1853 | default = 0, |
| 1814 | generaldynamic, | 1854 | generaldynamic = 1, |
| 1815 | localdynamic, | 1855 | localdynamic = 2, |
| 1816 | initialexec, | 1856 | initialexec = 3, |
| 1817 | localexec, | 1857 | localexec = 4, |
| 1818 | | 1858 | |
| 1819 | pub fn format( | 1859 | pub fn format( |
| 1820 | self: ThreadLocal, | 1860 | self: ThreadLocal, |
| ... | @@ -1826,24 +1866,14 @@ pub const ThreadLocal = enum { | ... | @@ -1826,24 +1866,14 @@ pub const ThreadLocal = enum { |
| 1826 | try writer.print("{s}thread_local", .{prefix}); | 1866 | try writer.print("{s}thread_local", .{prefix}); |
| 1827 | if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)}); | 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 | pub const Mutability = enum { global, constant }; | 1871 | pub const Mutability = enum { global, constant }; |
| 1842 | | 1872 | |
| 1843 | pub const UnnamedAddr = enum { | 1873 | pub const UnnamedAddr = enum(u2) { |
| 1844 | default, | 1874 | default = 0, |
| 1845 | unnamed_addr, | 1875 | unnamed_addr = 1, |
| 1846 | local_unnamed_addr, | 1876 | local_unnamed_addr = 2, |
| 1847 | | 1877 | |
| 1848 | pub fn format( | 1878 | pub fn format( |
| 1849 | self: UnnamedAddr, | 1879 | self: UnnamedAddr, |
| ... | @@ -1971,6 +2001,10 @@ pub const Alignment = enum(u6) { | ... | @@ -1971,6 +2001,10 @@ pub const Alignment = enum(u6) { |
| 1971 | return if (self == .default) null else @as(u64, 1) << @intFromEnum(self); | 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 | pub fn format( | 2008 | pub fn format( |
| 1975 | self: Alignment, | 2009 | self: Alignment, |
| 1976 | comptime prefix: []const u8, | 2010 | comptime prefix: []const u8, |
| ... | @@ -2100,11 +2134,6 @@ pub const CallConv = enum(u10) { | ... | @@ -2100,11 +2134,6 @@ pub const CallConv = enum(u10) { |
| 2100 | _ => try writer.print(" cc{d}", .{@intFromEnum(self)}), | 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 | pub const Global = struct { | 2139 | pub const Global = struct { |
| ... | @@ -2117,6 +2146,7 @@ pub const Global = struct { | ... | @@ -2117,6 +2146,7 @@ pub const Global = struct { |
| 2117 | externally_initialized: ExternallyInitialized = .default, | 2146 | externally_initialized: ExternallyInitialized = .default, |
| 2118 | type: Type, | 2147 | type: Type, |
| 2119 | partition: String = .none, | 2148 | partition: String = .none, |
| | 2149 | dbg: Metadata = .none, |
| 2120 | kind: union(enum) { | 2150 | kind: union(enum) { |
| 2121 | alias: Alias.Index, | 2151 | alias: Alias.Index, |
| 2122 | variable: Variable.Index, | 2152 | variable: Variable.Index, |
| ... | @@ -2153,6 +2183,18 @@ pub const Global = struct { | ... | @@ -2153,6 +2183,18 @@ pub const Global = struct { |
| 2153 | return builder.globals.keys()[@intFromEnum(self.unwrap(builder))]; | 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 | pub fn typeOf(self: Index, builder: *const Builder) Type { | 2198 | pub fn typeOf(self: Index, builder: *const Builder) Type { |
| 2157 | return self.ptrConst(builder).type; | 2199 | return self.ptrConst(builder).type; |
| 2158 | } | 2200 | } |
| ... | @@ -2162,32 +2204,25 @@ pub const Global = struct { | ... | @@ -2162,32 +2204,25 @@ pub const Global = struct { |
| 2162 | } | 2204 | } |
| 2163 | | 2205 | |
| 2164 | pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void { | 2206 | pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void { |
| 2165 | if (builder.useLibLlvm()) self.toLlvm(builder).setLinkage(linkage.toLlvm()); | | |
| 2166 | self.ptr(builder).linkage = linkage; | 2207 | self.ptr(builder).linkage = linkage; |
| 2167 | self.updateDsoLocal(builder); | 2208 | self.updateDsoLocal(builder); |
| 2168 | } | 2209 | } |
| 2169 | | 2210 | |
| 2170 | pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void { | 2211 | pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void { |
| 2171 | if (builder.useLibLlvm()) self.toLlvm(builder).setVisibility(visibility.toLlvm()); | | |
| 2172 | self.ptr(builder).visibility = visibility; | 2212 | self.ptr(builder).visibility = visibility; |
| 2173 | self.updateDsoLocal(builder); | 2213 | self.updateDsoLocal(builder); |
| 2174 | } | 2214 | } |
| 2175 | | 2215 | |
| 2176 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { | 2216 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { |
| 2177 | if (builder.useLibLlvm()) self.toLlvm(builder).setDLLStorageClass(class.toLlvm()); | | |
| 2178 | self.ptr(builder).dll_storage_class = class; | 2217 | self.ptr(builder).dll_storage_class = class; |
| 2179 | } | 2218 | } |
| 2180 | | 2219 | |
| 2181 | pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void { | 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 | self.ptr(builder).unnamed_addr = unnamed_addr; | 2221 | self.ptr(builder).unnamed_addr = unnamed_addr; |
| 2186 | } | 2222 | } |
| 2187 | | 2223 | |
| 2188 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | 2224 | pub fn setDebugMetadata(self: Index, dbg: Metadata, builder: *Builder) void { |
| 2189 | assert(builder.useLibLlvm()); | 2225 | self.ptr(builder).dbg = dbg; |
| 2190 | return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))]; | | |
| 2191 | } | 2226 | } |
| 2192 | | 2227 | |
| 2193 | const FormatData = struct { | 2228 | const FormatData = struct { |
| ... | @@ -2220,13 +2255,10 @@ pub const Global = struct { | ... | @@ -2220,13 +2255,10 @@ pub const Global = struct { |
| 2220 | | 2255 | |
| 2221 | pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void { | 2256 | pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void { |
| 2222 | try builder.ensureUnusedGlobalCapacity(.empty); | 2257 | try builder.ensureUnusedGlobalCapacity(.empty); |
| 2223 | if (builder.useLibLlvm()) | | |
| 2224 | try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1); | | |
| 2225 | self.replaceAssumeCapacity(other, builder); | 2258 | self.replaceAssumeCapacity(other, builder); |
| 2226 | } | 2259 | } |
| 2227 | | 2260 | |
| 2228 | pub fn delete(self: Index, builder: *Builder) void { | 2261 | pub fn delete(self: Index, builder: *Builder) void { |
| 2229 | if (builder.useLibLlvm()) self.toLlvm(builder).eraseGlobalValue(); | | |
| 2230 | self.ptr(builder).kind = .{ .replaced = .none }; | 2262 | self.ptr(builder).kind = .{ .replaced = .none }; |
| 2231 | } | 2263 | } |
| 2232 | | 2264 | |
| ... | @@ -2254,12 +2286,8 @@ pub const Global = struct { | ... | @@ -2254,12 +2286,8 @@ pub const Global = struct { |
| 2254 | const old_name = self.name(builder); | 2286 | const old_name = self.name(builder); |
| 2255 | if (new_name == old_name) return; | 2287 | if (new_name == old_name) return; |
| 2256 | const index = @intFromEnum(self.unwrap(builder)); | 2288 | const index = @intFromEnum(self.unwrap(builder)); |
| 2257 | if (builder.useLibLlvm()) | | |
| 2258 | builder.llvm.globals.appendAssumeCapacity(builder.llvm.globals.items[index]); | | |
| 2259 | _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); | 2289 | _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); |
| 2260 | if (builder.useLibLlvm()) _ = builder.llvm.globals.pop(); | | |
| 2261 | builder.globals.swapRemoveAt(index); | 2290 | builder.globals.swapRemoveAt(index); |
| 2262 | self.updateName(builder); | | |
| 2263 | if (!old_name.isAnon()) return; | 2291 | if (!old_name.isAnon()) return; |
| 2264 | builder.next_unnamed_global = @enumFromInt(@intFromEnum(builder.next_unnamed_global) - 1); | 2292 | builder.next_unnamed_global = @enumFromInt(@intFromEnum(builder.next_unnamed_global) - 1); |
| 2265 | if (builder.next_unnamed_global == old_name) return; | 2293 | if (builder.next_unnamed_global == old_name) return; |
| ... | @@ -2272,23 +2300,10 @@ pub const Global = struct { | ... | @@ -2272,23 +2300,10 @@ pub const Global = struct { |
| 2272 | self.renameAssumeCapacity(other_name, builder); | 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 | fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { | 2303 | fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { |
| 2283 | if (self.eql(other, builder)) return; | 2304 | if (self.eql(other, builder)) return; |
| 2284 | builder.next_replaced_global = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1); | 2305 | builder.next_replaced_global = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1); |
| 2285 | self.renameAssumeCapacity(builder.next_replaced_global, builder); | 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 | self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; | 2307 | self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; |
| 2293 | } | 2308 | } |
| 2294 | | 2309 | |
| ... | @@ -2345,13 +2360,8 @@ pub const Alias = struct { | ... | @@ -2345,13 +2360,8 @@ pub const Alias = struct { |
| 2345 | } | 2360 | } |
| 2346 | | 2361 | |
| 2347 | pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void { | 2362 | pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void { |
| 2348 | if (builder.useLibLlvm()) self.toLlvm(builder).setAliasee(aliasee.toLlvm(builder)); | | |
| 2349 | self.ptr(builder).aliasee = aliasee; | 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,14 +2414,10 @@ pub const Variable = struct { |
| 2404 | } | 2414 | } |
| 2405 | | 2415 | |
| 2406 | pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void { | 2416 | pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void { |
| 2407 | if (builder.useLibLlvm()) self.toLlvm(builder).setThreadLocalMode(thread_local.toLlvm()); | | |
| 2408 | self.ptr(builder).thread_local = thread_local; | 2417 | self.ptr(builder).thread_local = thread_local; |
| 2409 | } | 2418 | } |
| 2410 | | 2419 | |
| 2411 | pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void { | 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 | self.ptr(builder).mutability = mutability; | 2421 | self.ptr(builder).mutability = mutability; |
| 2416 | } | 2422 | } |
| 2417 | | 2423 | |
| ... | @@ -2424,67 +2430,25 @@ pub const Variable = struct { | ... | @@ -2424,67 +2430,25 @@ pub const Variable = struct { |
| 2424 | const variable = self.ptrConst(builder); | 2430 | const variable = self.ptrConst(builder); |
| 2425 | const global = variable.global.ptr(builder); | 2431 | const global = variable.global.ptr(builder); |
| 2426 | const initializer_type = initializer.typeOf(builder); | 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 | global.type = initializer_type; | 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 | self.ptr(builder).init = initializer; | 2435 | self.ptr(builder).init = initializer; |
| 2467 | } | 2436 | } |
| 2468 | | 2437 | |
| 2469 | pub fn setSection(self: Index, section: String, builder: *Builder) void { | 2438 | pub fn setSection(self: Index, section: String, builder: *Builder) void { |
| 2470 | if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?); | | |
| 2471 | self.ptr(builder).section = section; | 2439 | self.ptr(builder).section = section; |
| 2472 | } | 2440 | } |
| 2473 | | 2441 | |
| 2474 | pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void { | 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 | self.ptr(builder).alignment = alignment; | 2443 | self.ptr(builder).alignment = alignment; |
| 2478 | } | 2444 | } |
| 2479 | | 2445 | |
| 2480 | pub fn getAlignment(self: Index, builder: *Builder) Alignment { | 2446 | pub fn getAlignment(self: Index, builder: *Builder) Alignment { |
| 2481 | if (builder.useLibLlvm()) | | |
| 2482 | return Alignment.fromByteUnits(self.toLlvm(builder).getAlignment()); | | |
| 2483 | return self.ptr(builder).alignment; | 2447 | return self.ptr(builder).alignment; |
| 2484 | } | 2448 | } |
| 2485 | | 2449 | |
| 2486 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | 2450 | pub fn setGlobalVariableExpression(self: Index, expression: Metadata, builder: *Builder) void { |
| 2487 | return self.ptrConst(builder).global.toLlvm(builder); | 2451 | self.ptrConst(builder).global.setDebugMetadata(expression, builder); |
| 2488 | } | 2452 | } |
| 2489 | }; | 2453 | }; |
| 2490 | }; | 2454 | }; |
| ... | @@ -2633,6 +2597,10 @@ pub const Intrinsic = enum { | ... | @@ -2633,6 +2597,10 @@ pub const Intrinsic = enum { |
| 2633 | @"threadlocal.address", | 2597 | @"threadlocal.address", |
| 2634 | vscale, | 2598 | vscale, |
| 2635 | | 2599 | |
| | 2600 | // Debug |
| | 2601 | @"dbg.declare", |
| | 2602 | @"dbg.value", |
| | 2603 | |
| 2636 | // AMDGPU | 2604 | // AMDGPU |
| 2637 | @"amdgcn.workitem.id.x", | 2605 | @"amdgcn.workitem.id.x", |
| 2638 | @"amdgcn.workitem.id.y", | 2606 | @"amdgcn.workitem.id.y", |
| ... | @@ -3727,6 +3695,25 @@ pub const Intrinsic = enum { | ... | @@ -3727,6 +3695,25 @@ pub const Intrinsic = enum { |
| 3727 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | 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 | .@"amdgcn.workitem.id.x" = .{ | 3717 | .@"amdgcn.workitem.id.x" = .{ |
| 3731 | .ret_len = 1, | 3718 | .ret_len = 1, |
| 3732 | .params = &.{ | 3719 | .params = &.{ |
| ... | @@ -3809,7 +3796,9 @@ pub const Function = struct { | ... | @@ -3809,7 +3796,9 @@ pub const Function = struct { |
| 3809 | blocks: []const Block = &.{}, | 3796 | blocks: []const Block = &.{}, |
| 3810 | instructions: std.MultiArrayList(Instruction) = .{}, | 3797 | instructions: std.MultiArrayList(Instruction) = .{}, |
| 3811 | names: [*]const String = &[0]String{}, | 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 | extra: []const u32 = &.{}, | 3802 | extra: []const u32 = &.{}, |
| 3814 | | 3803 | |
| 3815 | pub const Index = enum(u32) { | 3804 | pub const Index = enum(u32) { |
| ... | @@ -3853,7 +3842,6 @@ pub const Function = struct { | ... | @@ -3853,7 +3842,6 @@ pub const Function = struct { |
| 3853 | } | 3842 | } |
| 3854 | | 3843 | |
| 3855 | pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void { | 3844 | pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void { |
| 3856 | if (builder.useLibLlvm()) self.toLlvm(builder).setFunctionCallConv(call_conv.toLlvm()); | | |
| 3857 | self.ptr(builder).call_conv = call_conv; | 3845 | self.ptr(builder).call_conv = call_conv; |
| 3858 | } | 3846 | } |
| 3859 | | 3847 | |
| ... | @@ -3862,94 +3850,19 @@ pub const Function = struct { | ... | @@ -3862,94 +3850,19 @@ pub const Function = struct { |
| 3862 | new_function_attributes: FunctionAttributes, | 3850 | new_function_attributes: FunctionAttributes, |
| 3863 | builder: *Builder, | 3851 | builder: *Builder, |
| 3864 | ) void { | 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 | self.ptr(builder).attributes = new_function_attributes; | 3853 | self.ptr(builder).attributes = new_function_attributes; |
| 3938 | } | 3854 | } |
| 3939 | | 3855 | |
| 3940 | pub fn setSection(self: Index, section: String, builder: *Builder) void { | 3856 | pub fn setSection(self: Index, section: String, builder: *Builder) void { |
| 3941 | if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?); | | |
| 3942 | self.ptr(builder).section = section; | 3857 | self.ptr(builder).section = section; |
| 3943 | } | 3858 | } |
| 3944 | | 3859 | |
| 3945 | pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void { | 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 | self.ptr(builder).alignment = alignment; | 3861 | self.ptr(builder).alignment = alignment; |
| 3949 | } | 3862 | } |
| 3950 | | 3863 | |
| 3951 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | 3864 | pub fn setSubprogram(self: Index, subprogram: Metadata, builder: *Builder) void { |
| 3952 | return self.ptrConst(builder).global.toLlvm(builder); | 3865 | self.ptrConst(builder).global.setDebugMetadata(subprogram, builder); |
| 3953 | } | 3866 | } |
| 3954 | }; | 3867 | }; |
| 3955 | | 3868 | |
| ... | @@ -4098,6 +4011,143 @@ pub const Function = struct { | ... | @@ -4098,6 +4011,143 @@ pub const Function = struct { |
| 4098 | va_arg, | 4011 | va_arg, |
| 4099 | xor, | 4012 | xor, |
| 4100 | zext, | 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 | pub const Index = enum(u32) { | 4153 | pub const Index = enum(u32) { |
| ... | @@ -4108,6 +4158,10 @@ pub const Function = struct { | ... | @@ -4108,6 +4158,10 @@ pub const Function = struct { |
| 4108 | return function.names[@intFromEnum(self)]; | 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 | pub fn toValue(self: Instruction.Index) Value { | 4165 | pub fn toValue(self: Instruction.Index) Value { |
| 4112 | return @enumFromInt(@intFromEnum(self)); | 4166 | return @enumFromInt(@intFromEnum(self)); |
| 4113 | } | 4167 | } |
| ... | @@ -4136,6 +4190,7 @@ pub const Function = struct { | ... | @@ -4136,6 +4190,7 @@ pub const Function = struct { |
| 4136 | .@"store atomic", | 4190 | .@"store atomic", |
| 4137 | .@"switch", | 4191 | .@"switch", |
| 4138 | .@"unreachable", | 4192 | .@"unreachable", |
| | 4193 | .block, |
| 4139 | => false, | 4194 | => false, |
| 4140 | .call, | 4195 | .call, |
| 4141 | .@"call fast", | 4196 | .@"call fast", |
| ... | @@ -4240,7 +4295,7 @@ pub const Function = struct { | ... | @@ -4240,7 +4295,7 @@ pub const Function = struct { |
| 4240 | => wip.builder.structTypeAssumeCapacity(.normal, &.{ | 4295 | => wip.builder.structTypeAssumeCapacity(.normal, &.{ |
| 4241 | wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip), | 4296 | wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip), |
| 4242 | .i1, | 4297 | .i1, |
| 4243 | }) catch unreachable, | 4298 | }), |
| 4244 | .extractelement => wip.extraData(ExtractElement, instruction.data) | 4299 | .extractelement => wip.extraData(ExtractElement, instruction.data) |
| 4245 | .val.typeOfWip(wip).childType(wip.builder), | 4300 | .val.typeOfWip(wip).childType(wip.builder), |
| 4246 | .extractvalue => { | 4301 | .extractvalue => { |
| ... | @@ -4427,7 +4482,7 @@ pub const Function = struct { | ... | @@ -4427,7 +4482,7 @@ pub const Function = struct { |
| 4427 | function.extraData(CmpXchg, instruction.data) | 4482 | function.extraData(CmpXchg, instruction.data) |
| 4428 | .cmp.typeOf(function_index, builder), | 4483 | .cmp.typeOf(function_index, builder), |
| 4429 | .i1, | 4484 | .i1, |
| 4430 | }) catch unreachable, | 4485 | }), |
| 4431 | .extractelement => function.extraData(ExtractElement, instruction.data) | 4486 | .extractelement => function.extraData(ExtractElement, instruction.data) |
| 4432 | .val.typeOf(function_index, builder).childType(builder), | 4487 | .val.typeOf(function_index, builder).childType(builder), |
| 4433 | .extractvalue => { | 4488 | .extractvalue => { |
| ... | @@ -4557,20 +4612,6 @@ pub const Function = struct { | ... | @@ -4557,20 +4612,6 @@ pub const Function = struct { |
| 4557 | ) std.fmt.Formatter(format) { | 4612 | ) std.fmt.Formatter(format) { |
| 4558 | return .{ .data = .{ .instruction = self, .function = function, .builder = builder } }; | 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 | pub const ExtraIndex = u32; | 4617 | pub const ExtraIndex = u32; |
| ... | @@ -4664,43 +4705,22 @@ pub const Function = struct { | ... | @@ -4664,43 +4705,22 @@ pub const Function = struct { |
| 4664 | val: Value, | 4705 | val: Value, |
| 4665 | | 4706 | |
| 4666 | pub const Operation = enum(u5) { | 4707 | pub const Operation = enum(u5) { |
| 4667 | xchg, | 4708 | xchg = 0, |
| 4668 | add, | 4709 | add = 1, |
| 4669 | sub, | 4710 | sub = 2, |
| 4670 | @"and", | 4711 | @"and" = 3, |
| 4671 | nand, | 4712 | nand = 4, |
| 4672 | @"or", | 4713 | @"or" = 5, |
| 4673 | xor, | 4714 | xor = 6, |
| 4674 | max, | 4715 | max = 7, |
| 4675 | min, | 4716 | min = 8, |
| 4676 | umax, | 4717 | umax = 9, |
| 4677 | umin, | 4718 | umin = 10, |
| 4678 | fadd, | 4719 | fadd = 11, |
| 4679 | fsub, | 4720 | fsub = 12, |
| 4680 | fmax, | 4721 | fmax = 13, |
| 4681 | fmin, | 4722 | fmin = 14, |
| 4682 | none = std.math.maxInt(u5), | 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,7 +4784,9 @@ pub const Function = struct { |
| 4764 | | 4784 | |
| 4765 | pub fn deinit(self: *Function, gpa: Allocator) void { | 4785 | pub fn deinit(self: *Function, gpa: Allocator) void { |
| 4766 | gpa.free(self.extra); | 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 | gpa.free(self.names[0..self.instructions.len]); | 4790 | gpa.free(self.names[0..self.instructions.len]); |
| 4769 | self.instructions.deinit(gpa); | 4791 | self.instructions.deinit(gpa); |
| 4770 | gpa.free(self.blocks); | 4792 | gpa.free(self.blocks); |
| ... | @@ -4822,7 +4844,7 @@ pub const Function = struct { | ... | @@ -4822,7 +4844,7 @@ pub const Function = struct { |
| 4822 | Instruction.Alloca.Info, | 4844 | Instruction.Alloca.Info, |
| 4823 | Instruction.Call.Info, | 4845 | Instruction.Call.Info, |
| 4824 | => @bitCast(value), | 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 | return .{ | 4849 | return .{ |
| 4828 | .data = result, | 4850 | .data = result, |
| ... | @@ -4838,16 +4860,14 @@ pub const Function = struct { | ... | @@ -4838,16 +4860,14 @@ pub const Function = struct { |
| 4838 | pub const WipFunction = struct { | 4860 | pub const WipFunction = struct { |
| 4839 | builder: *Builder, | 4861 | builder: *Builder, |
| 4840 | function: Function.Index, | 4862 | function: Function.Index, |
| 4841 | llvm: if (build_options.have_llvm) struct { | 4863 | last_debug_location: Metadata, |
| 4842 | builder: *llvm.Builder, | 4864 | current_debug_location: Metadata, |
| 4843 | blocks: std.ArrayListUnmanaged(*llvm.BasicBlock), | | |
| 4844 | instructions: std.ArrayListUnmanaged(*llvm.Value), | | |
| 4845 | } else void, | | |
| 4846 | cursor: Cursor, | 4865 | cursor: Cursor, |
| 4847 | blocks: std.ArrayListUnmanaged(Block), | 4866 | blocks: std.ArrayListUnmanaged(Block), |
| 4848 | instructions: std.MultiArrayList(Instruction), | 4867 | instructions: std.MultiArrayList(Instruction), |
| 4849 | names: std.ArrayListUnmanaged(String), | 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 | extra: std.ArrayListUnmanaged(u32), | 4871 | extra: std.ArrayListUnmanaged(u32), |
| 4852 | | 4872 | |
| 4853 | pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 }; | 4873 | pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 }; |
| ... | @@ -4873,35 +4893,23 @@ pub const WipFunction = struct { | ... | @@ -4873,35 +4893,23 @@ pub const WipFunction = struct { |
| 4873 | pub fn toInst(self: Index, function: *const Function) Instruction.Index { | 4893 | pub fn toInst(self: Index, function: *const Function) Instruction.Index { |
| 4874 | return function.blocks[@intFromEnum(self)].instruction; | 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 | pub const Instruction = Function.Instruction; | 4899 | pub const Instruction = Function.Instruction; |
| 4885 | | 4900 | |
| 4886 | pub fn init(builder: *Builder, function: Function.Index) Allocator.Error!WipFunction { | 4901 | pub fn init(builder: *Builder, function: Function.Index) Allocator.Error!WipFunction { |
| 4887 | if (builder.useLibLlvm()) { | 4902 | var self: WipFunction = .{ |
| 4888 | const llvm_function = function.toLlvm(builder); | | |
| 4889 | while (llvm_function.getFirstBasicBlock()) |bb| bb.deleteBasicBlock(); | | |
| 4890 | } | | |
| 4891 | | | |
| 4892 | var self = WipFunction{ | | |
| 4893 | .builder = builder, | 4903 | .builder = builder, |
| 4894 | .function = function, | 4904 | .function = function, |
| 4895 | .llvm = if (builder.useLibLlvm()) .{ | 4905 | .last_debug_location = .none, |
| 4896 | .builder = builder.llvm.context.createBuilder(), | 4906 | .current_debug_location = .none, |
| 4897 | .blocks = .{}, | | |
| 4898 | .instructions = .{}, | | |
| 4899 | } else undefined, | | |
| 4900 | .cursor = undefined, | 4907 | .cursor = undefined, |
| 4901 | .blocks = .{}, | 4908 | .blocks = .{}, |
| 4902 | .instructions = .{}, | 4909 | .instructions = .{}, |
| 4903 | .names = .{}, | 4910 | .names = .{}, |
| 4904 | .metadata = .{}, | 4911 | .debug_locations = .{}, |
| | 4912 | .debug_values = .{}, |
| 4905 | .extra = .{}, | 4913 | .extra = .{}, |
| 4906 | }; | 4914 | }; |
| 4907 | errdefer self.deinit(); | 4915 | errdefer self.deinit(); |
| ... | @@ -4909,15 +4917,14 @@ pub const WipFunction = struct { | ... | @@ -4909,15 +4917,14 @@ pub const WipFunction = struct { |
| 4909 | const params_len = function.typeOf(self.builder).functionParameters(self.builder).len; | 4917 | const params_len = function.typeOf(self.builder).functionParameters(self.builder).len; |
| 4910 | try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0); | 4918 | try self.ensureUnusedExtraCapacity(params_len, NoExtra, 0); |
| 4911 | try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len); | 4919 | try self.instructions.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 4912 | if (!self.builder.strip) try self.names.ensureUnusedCapacity(self.builder.gpa, params_len); | 4920 | if (!self.builder.strip) { |
| 4913 | if (self.builder.useLibLlvm()) | 4921 | try self.names.ensureUnusedCapacity(self.builder.gpa, params_len); |
| 4914 | try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, params_len); | 4922 | } |
| 4915 | for (0..params_len) |param_index| { | 4923 | for (0..params_len) |param_index| { |
| 4916 | self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) }); | 4924 | self.instructions.appendAssumeCapacity(.{ .tag = .arg, .data = @intCast(param_index) }); |
| 4917 | if (!self.builder.strip) self.names.appendAssumeCapacity(.empty); // TODO: param names | 4925 | if (!self.builder.strip) { |
| 4918 | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( | 4926 | self.names.appendAssumeCapacity(.empty); // TODO: param names |
| 4919 | function.toLlvm(self.builder).getParam(@intCast(param_index)), | 4927 | } |
| 4920 | ); | | |
| 4921 | } | 4928 | } |
| 4922 | | 4929 | |
| 4923 | return self; | 4930 | return self; |
| ... | @@ -4934,7 +4941,6 @@ pub const WipFunction = struct { | ... | @@ -4934,7 +4941,6 @@ pub const WipFunction = struct { |
| 4934 | | 4941 | |
| 4935 | pub fn block(self: *WipFunction, incoming: u32, name: []const u8) Allocator.Error!Block.Index { | 4942 | pub fn block(self: *WipFunction, incoming: u32, name: []const u8) Allocator.Error!Block.Index { |
| 4936 | try self.blocks.ensureUnusedCapacity(self.builder.gpa, 1); | 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 | const index: Block.Index = @enumFromInt(self.blocks.items.len); | 4945 | const index: Block.Index = @enumFromInt(self.blocks.items.len); |
| 4940 | const final_name = if (self.builder.strip) .empty else try self.builder.string(name); | 4946 | const final_name = if (self.builder.strip) .empty else try self.builder.string(name); |
| ... | @@ -4943,41 +4949,24 @@ pub const WipFunction = struct { | ... | @@ -4943,41 +4949,24 @@ pub const WipFunction = struct { |
| 4943 | .incoming = incoming, | 4949 | .incoming = incoming, |
| 4944 | .instructions = .{}, | 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 | return index; | 4952 | return index; |
| 4953 | } | 4953 | } |
| 4954 | | 4954 | |
| 4955 | pub fn ret(self: *WipFunction, val: Value) Allocator.Error!Instruction.Index { | 4955 | pub fn ret(self: *WipFunction, val: Value) Allocator.Error!Instruction.Index { |
| 4956 | assert(val.typeOfWip(self) == self.function.typeOf(self.builder).functionReturn(self.builder)); | 4956 | assert(val.typeOfWip(self) == self.function.typeOf(self.builder).functionReturn(self.builder)); |
| 4957 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | 4957 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 4958 | const instruction = try self.addInst(null, .{ .tag = .ret, .data = @intFromEnum(val) }); | 4958 | return 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; | | |
| 4963 | } | 4959 | } |
| 4964 | | 4960 | |
| 4965 | pub fn retVoid(self: *WipFunction) Allocator.Error!Instruction.Index { | 4961 | pub fn retVoid(self: *WipFunction) Allocator.Error!Instruction.Index { |
| 4966 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | 4962 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 4967 | const instruction = try self.addInst(null, .{ .tag = .@"ret void", .data = undefined }); | 4963 | return 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; | | |
| 4972 | } | 4964 | } |
| 4973 | | 4965 | |
| 4974 | pub fn br(self: *WipFunction, dest: Block.Index) Allocator.Error!Instruction.Index { | 4966 | pub fn br(self: *WipFunction, dest: Block.Index) Allocator.Error!Instruction.Index { |
| 4975 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | 4967 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 4976 | const instruction = try self.addInst(null, .{ .tag = .br, .data = @intFromEnum(dest) }); | 4968 | const instruction = try self.addInst(null, .{ .tag = .br, .data = @intFromEnum(dest) }); |
| 4977 | dest.ptr(self).branches += 1; | 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 | return instruction; | 4970 | return instruction; |
| 4982 | } | 4971 | } |
| 4983 | | 4972 | |
| ... | @@ -4999,9 +4988,6 @@ pub const WipFunction = struct { | ... | @@ -4999,9 +4988,6 @@ pub const WipFunction = struct { |
| 4999 | }); | 4988 | }); |
| 5000 | then.ptr(self).branches += 1; | 4989 | then.ptr(self).branches += 1; |
| 5001 | @"else".ptr(self).branches += 1; | 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 | return instruction; | 4991 | return instruction; |
| 5006 | } | 4992 | } |
| 5007 | | 4993 | |
| ... | @@ -5022,8 +5008,6 @@ pub const WipFunction = struct { | ... | @@ -5022,8 +5008,6 @@ pub const WipFunction = struct { |
| 5022 | extra.trail.nextMut(extra.data.cases_len, Block.Index, wip)[self.index] = dest; | 5008 | extra.trail.nextMut(extra.data.cases_len, Block.Index, wip)[self.index] = dest; |
| 5023 | self.index += 1; | 5009 | self.index += 1; |
| 5024 | dest.ptr(wip).branches += 1; | 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 | pub fn finish(self: WipSwitch, wip: *WipFunction) void { | 5013 | pub fn finish(self: WipSwitch, wip: *WipFunction) void { |
| ... | @@ -5050,18 +5034,12 @@ pub const WipFunction = struct { | ... | @@ -5050,18 +5034,12 @@ pub const WipFunction = struct { |
| 5050 | }); | 5034 | }); |
| 5051 | _ = self.extra.addManyAsSliceAssumeCapacity(cases_len * 2); | 5035 | _ = self.extra.addManyAsSliceAssumeCapacity(cases_len * 2); |
| 5052 | default.ptr(self).branches += 1; | 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 | return .{ .index = 0, .instruction = instruction }; | 5037 | return .{ .index = 0, .instruction = instruction }; |
| 5057 | } | 5038 | } |
| 5058 | | 5039 | |
| 5059 | pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index { | 5040 | pub fn @"unreachable"(self: *WipFunction) Allocator.Error!Instruction.Index { |
| 5060 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | 5041 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 5061 | const instruction = try self.addInst(null, .{ .tag = .@"unreachable", .data = undefined }); | 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 | return instruction; | 5043 | return instruction; |
| 5066 | } | 5044 | } |
| 5067 | | 5045 | |
| ... | @@ -5079,17 +5057,6 @@ pub const WipFunction = struct { | ... | @@ -5079,17 +5057,6 @@ pub const WipFunction = struct { |
| 5079 | } | 5057 | } |
| 5080 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | 5058 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| 5081 | const instruction = try self.addInst(name, .{ .tag = tag, .data = @intFromEnum(val) }); | 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 | return instruction.toValue(); | 5060 | return instruction.toValue(); |
| 5094 | } | 5061 | } |
| 5095 | | 5062 | |
| ... | @@ -5157,56 +5124,6 @@ pub const WipFunction = struct { | ... | @@ -5157,56 +5124,6 @@ pub const WipFunction = struct { |
| 5157 | .tag = tag, | 5124 | .tag = tag, |
| 5158 | .data = self.addExtraAssumeCapacity(Instruction.Binary{ .lhs = lhs, .rhs = rhs }), | 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 | return instruction.toValue(); | 5127 | return instruction.toValue(); |
| 5211 | } | 5128 | } |
| 5212 | | 5129 | |
| ... | @@ -5226,13 +5143,6 @@ pub const WipFunction = struct { | ... | @@ -5226,13 +5143,6 @@ pub const WipFunction = struct { |
| 5226 | .index = index, | 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 | return instruction.toValue(); | 5146 | return instruction.toValue(); |
| 5237 | } | 5147 | } |
| 5238 | | 5148 | |
| ... | @@ -5254,14 +5164,6 @@ pub const WipFunction = struct { | ... | @@ -5254,14 +5164,6 @@ pub const WipFunction = struct { |
| 5254 | .index = index, | 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 | return instruction.toValue(); | 5167 | return instruction.toValue(); |
| 5266 | } | 5168 | } |
| 5267 | | 5169 | |
| ... | @@ -5284,14 +5186,6 @@ pub const WipFunction = struct { | ... | @@ -5284,14 +5186,6 @@ pub const WipFunction = struct { |
| 5284 | .mask = mask, | 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 | return instruction.toValue(); | 5189 | return instruction.toValue(); |
| 5296 | } | 5190 | } |
| 5297 | | 5191 | |
| ... | @@ -5303,10 +5197,9 @@ pub const WipFunction = struct { | ... | @@ -5303,10 +5197,9 @@ pub const WipFunction = struct { |
| 5303 | ) Allocator.Error!Value { | 5197 | ) Allocator.Error!Value { |
| 5304 | const scalar_ty = try ty.changeLength(1, self.builder); | 5198 | const scalar_ty = try ty.changeLength(1, self.builder); |
| 5305 | const mask_ty = try ty.changeScalar(.i32, self.builder); | 5199 | const mask_ty = try ty.changeScalar(.i32, self.builder); |
| 5306 | const zero = try self.builder.intConst(.i32, 0); | | |
| 5307 | const poison = try self.builder.poisonValue(scalar_ty); | 5200 | const poison = try self.builder.poisonValue(scalar_ty); |
| 5308 | const mask = try self.builder.splatValue(mask_ty, zero); | 5201 | const mask = try self.builder.splatValue(mask_ty, .@"0"); |
| 5309 | const scalar = try self.insertElement(poison, elem, zero.toValue(), name); | 5202 | const scalar = try self.insertElement(poison, elem, .@"0", name); |
| 5310 | return self.shuffleVector(scalar, poison, mask, name); | 5203 | return self.shuffleVector(scalar, poison, mask, name); |
| 5311 | } | 5204 | } |
| 5312 | | 5205 | |
| ... | @@ -5327,13 +5220,6 @@ pub const WipFunction = struct { | ... | @@ -5327,13 +5220,6 @@ pub const WipFunction = struct { |
| 5327 | }), | 5220 | }), |
| 5328 | }); | 5221 | }); |
| 5329 | self.extra.appendSliceAssumeCapacity(indices); | 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 | return instruction.toValue(); | 5223 | return instruction.toValue(); |
| 5338 | } | 5224 | } |
| 5339 | | 5225 | |
| ... | @@ -5356,35 +5242,6 @@ pub const WipFunction = struct { | ... | @@ -5356,35 +5242,6 @@ pub const WipFunction = struct { |
| 5356 | }), | 5242 | }), |
| 5357 | }); | 5243 | }); |
| 5358 | self.extra.appendSliceAssumeCapacity(indices); | 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 | return instruction.toValue(); | 5245 | return instruction.toValue(); |
| 5389 | } | 5246 | } |
| 5390 | | 5247 | |
| ... | @@ -5420,19 +5277,13 @@ pub const WipFunction = struct { | ... | @@ -5420,19 +5277,13 @@ pub const WipFunction = struct { |
| 5420 | }, | 5277 | }, |
| 5421 | .data = self.addExtraAssumeCapacity(Instruction.Alloca{ | 5278 | .data = self.addExtraAssumeCapacity(Instruction.Alloca{ |
| 5422 | .type = ty, | 5279 | .type = ty, |
| 5423 | .len = len, | 5280 | .len = switch (len) { |
| | 5281 | .none => .@"1", |
| | 5282 | else => len, |
| | 5283 | }, |
| 5424 | .info = .{ .alignment = alignment, .addr_space = addr_space }, | 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 | return instruction.toValue(); | 5287 | return instruction.toValue(); |
| 5437 | } | 5288 | } |
| 5438 | | 5289 | |
| ... | @@ -5478,17 +5329,6 @@ pub const WipFunction = struct { | ... | @@ -5478,17 +5329,6 @@ pub const WipFunction = struct { |
| 5478 | .ptr = ptr, | 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 | return instruction.toValue(); | 5332 | return instruction.toValue(); |
| 5493 | } | 5333 | } |
| 5494 | | 5334 | |
| ... | @@ -5532,13 +5372,6 @@ pub const WipFunction = struct { | ... | @@ -5532,13 +5372,6 @@ pub const WipFunction = struct { |
| 5532 | .ptr = ptr, | 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 | return instruction; | 5375 | return instruction; |
| 5543 | } | 5376 | } |
| 5544 | | 5377 | |
| ... | @@ -5556,13 +5389,6 @@ pub const WipFunction = struct { | ... | @@ -5556,13 +5389,6 @@ pub const WipFunction = struct { |
| 5556 | .success_ordering = ordering, | 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 | return instruction; | 5392 | return instruction; |
| 5567 | } | 5393 | } |
| 5568 | | 5394 | |
| ... | @@ -5605,25 +5431,6 @@ pub const WipFunction = struct { | ... | @@ -5605,25 +5431,6 @@ pub const WipFunction = struct { |
| 5605 | .new = new, | 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 | return instruction.toValue(); | 5434 | return instruction.toValue(); |
| 5628 | } | 5435 | } |
| 5629 | | 5436 | |
| ... | @@ -5656,23 +5463,6 @@ pub const WipFunction = struct { | ... | @@ -5656,23 +5463,6 @@ pub const WipFunction = struct { |
| 5656 | .val = val, | 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 | return instruction.toValue(); | 5466 | return instruction.toValue(); |
| 5677 | } | 5467 | } |
| 5678 | | 5468 | |
| ... | @@ -5732,28 +5522,6 @@ pub const WipFunction = struct { | ... | @@ -5732,28 +5522,6 @@ pub const WipFunction = struct { |
| 5732 | }), | 5522 | }), |
| 5733 | }); | 5523 | }); |
| 5734 | self.extra.appendSliceAssumeCapacity(@ptrCast(indices)); | 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 | return instruction.toValue(); | 5525 | return instruction.toValue(); |
| 5758 | } | 5526 | } |
| 5759 | | 5527 | |
| ... | @@ -5765,9 +5533,7 @@ pub const WipFunction = struct { | ... | @@ -5765,9 +5533,7 @@ pub const WipFunction = struct { |
| 5765 | name: []const u8, | 5533 | name: []const u8, |
| 5766 | ) Allocator.Error!Value { | 5534 | ) Allocator.Error!Value { |
| 5767 | assert(ty.isStruct(self.builder)); | 5535 | assert(ty.isStruct(self.builder)); |
| 5768 | return self.gep(.inbounds, ty, base, &.{ | 5536 | return self.gep(.inbounds, ty, base, &.{ .@"0", try self.builder.intValue(.i32, index) }, name); |
| 5769 | try self.builder.intValue(.i32, 0), try self.builder.intValue(.i32, index), | | |
| 5770 | }, name); | | |
| 5771 | } | 5537 | } |
| 5772 | | 5538 | |
| 5773 | pub fn conv( | 5539 | pub fn conv( |
| ... | @@ -5815,22 +5581,6 @@ pub const WipFunction = struct { | ... | @@ -5815,22 +5581,6 @@ pub const WipFunction = struct { |
| 5815 | .type = ty, | 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 | return instruction.toValue(); | 5584 | return instruction.toValue(); |
| 5835 | } | 5585 | } |
| 5836 | | 5586 | |
| ... | @@ -5843,7 +5593,7 @@ pub const WipFunction = struct { | ... | @@ -5843,7 +5593,7 @@ pub const WipFunction = struct { |
| 5843 | ) Allocator.Error!Value { | 5593 | ) Allocator.Error!Value { |
| 5844 | return self.cmpTag(switch (cond) { | 5594 | return self.cmpTag(switch (cond) { |
| 5845 | inline else => |tag| @field(Instruction.Tag, "icmp " ++ @tagName(tag)), | 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 | pub fn fcmp( | 5599 | pub fn fcmp( |
| ... | @@ -5861,7 +5611,7 @@ pub const WipFunction = struct { | ... | @@ -5861,7 +5611,7 @@ pub const WipFunction = struct { |
| 5861 | .fast => "fast ", | 5611 | .fast => "fast ", |
| 5862 | } ++ @tagName(cond_tag)), | 5612 | } ++ @tagName(cond_tag)), |
| 5863 | }, | 5613 | }, |
| 5864 | }, @intFromEnum(cond), lhs, rhs, name); | 5614 | }, lhs, rhs, name); |
| 5865 | } | 5615 | } |
| 5866 | | 5616 | |
| 5867 | pub const WipPhi = struct { | 5617 | pub const WipPhi = struct { |
| ... | @@ -5877,7 +5627,7 @@ pub const WipFunction = struct { | ... | @@ -5877,7 +5627,7 @@ pub const WipFunction = struct { |
| 5877 | vals: []const Value, | 5627 | vals: []const Value, |
| 5878 | blocks: []const Block.Index, | 5628 | blocks: []const Block.Index, |
| 5879 | wip: *WipFunction, | 5629 | wip: *WipFunction, |
| 5880 | ) (if (build_options.have_llvm) Allocator.Error else error{})!void { | 5630 | ) void { |
| 5881 | const incoming_len = self.block.ptrConst(wip).incoming; | 5631 | const incoming_len = self.block.ptrConst(wip).incoming; |
| 5882 | assert(vals.len == incoming_len and blocks.len == incoming_len); | 5632 | assert(vals.len == incoming_len and blocks.len == incoming_len); |
| 5883 | const instruction = wip.instructions.get(@intFromEnum(self.instruction)); | 5633 | const instruction = wip.instructions.get(@intFromEnum(self.instruction)); |
| ... | @@ -5885,26 +5635,6 @@ pub const WipFunction = struct { | ... | @@ -5885,26 +5635,6 @@ pub const WipFunction = struct { |
| 5885 | for (vals) |val| assert(val.typeOfWip(wip) == extra.data.type); | 5635 | for (vals) |val| assert(val.typeOfWip(wip) == extra.data.type); |
| 5886 | @memcpy(extra.trail.nextMut(incoming_len, Value, wip), vals); | 5636 | @memcpy(extra.trail.nextMut(incoming_len, Value, wip), vals); |
| 5887 | @memcpy(extra.trail.nextMut(incoming_len, Block.Index, wip), blocks); | 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,53 +5700,6 @@ pub const WipFunction = struct { |
| 5970 | }), | 5700 | }), |
| 5971 | }); | 5701 | }); |
| 5972 | self.extra.appendSliceAssumeCapacity(@ptrCast(args)); | 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 | return instruction.toValue(); | 5703 | return instruction.toValue(); |
| 6021 | } | 5704 | } |
| 6022 | | 5705 | |
| ... | @@ -6117,16 +5800,25 @@ pub const WipFunction = struct { | ... | @@ -6117,16 +5800,25 @@ pub const WipFunction = struct { |
| 6117 | .type = ty, | 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 | return instruction.toValue(); | 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 | pub fn finish(self: *WipFunction) Allocator.Error!void { | 5822 | pub fn finish(self: *WipFunction) Allocator.Error!void { |
| 6131 | const gpa = self.builder.gpa; | 5823 | const gpa = self.builder.gpa; |
| 6132 | const function = self.function.ptr(self.builder); | 5824 | const function = self.function.ptr(self.builder); |
| ... | @@ -6146,6 +5838,7 @@ pub const WipFunction = struct { | ... | @@ -6146,6 +5838,7 @@ pub const WipFunction = struct { |
| 6146 | @intFromEnum(instruction) | 5838 | @intFromEnum(instruction) |
| 6147 | ].toValue(), | 5839 | ].toValue(), |
| 6148 | .constant => |constant| constant.toValue(), | 5840 | .constant => |constant| constant.toValue(), |
| | 5841 | .metadata => |metadata| metadata.toValue(), |
| 6149 | }; | 5842 | }; |
| 6150 | } | 5843 | } |
| 6151 | } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) }; | 5844 | } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) }; |
| ... | @@ -6154,9 +5847,15 @@ pub const WipFunction = struct { | ... | @@ -6154,9 +5847,15 @@ pub const WipFunction = struct { |
| 6154 | const names = try gpa.alloc(String, final_instructions_len); | 5847 | const names = try gpa.alloc(String, final_instructions_len); |
| 6155 | errdefer gpa.free(names); | 5848 | errdefer gpa.free(names); |
| 6156 | | 5849 | |
| 6157 | const metadata = | 5850 | const value_indices = try gpa.alloc(u32, final_instructions_len); |
| 6158 | if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len); | 5851 | errdefer gpa.free(value_indices); |
| 6159 | errdefer if (metadata) |new_metadata| gpa.free(new_metadata); | 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 | var wip_extra: struct { | 5860 | var wip_extra: struct { |
| 6162 | index: Instruction.ExtraIndex = 0, | 5861 | index: Instruction.ExtraIndex = 0, |
| ... | @@ -6179,7 +5878,7 @@ pub const WipFunction = struct { | ... | @@ -6179,7 +5878,7 @@ pub const WipFunction = struct { |
| 6179 | Instruction.Alloca.Info, | 5878 | Instruction.Alloca.Info, |
| 6180 | Instruction.Call.Info, | 5879 | Instruction.Call.Info, |
| 6181 | => @bitCast(value), | 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 | wip_extra.index += 1; | 5883 | wip_extra.index += 1; |
| 6185 | } | 5884 | } |
| ... | @@ -6210,8 +5909,10 @@ pub const WipFunction = struct { | ... | @@ -6210,8 +5909,10 @@ pub const WipFunction = struct { |
| 6210 | gpa.free(function.blocks); | 5909 | gpa.free(function.blocks); |
| 6211 | function.blocks = &.{}; | 5910 | function.blocks = &.{}; |
| 6212 | gpa.free(function.names[0..function.instructions.len]); | 5911 | gpa.free(function.names[0..function.instructions.len]); |
| 6213 | if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]); | 5912 | function.debug_locations.deinit(gpa); |
| 6214 | function.metadata = null; | 5913 | function.debug_locations = .{}; |
| | 5914 | gpa.free(function.debug_values); |
| | 5915 | function.debug_values = &.{}; |
| 6215 | gpa.free(function.extra); | 5916 | gpa.free(function.extra); |
| 6216 | function.extra = &.{}; | 5917 | function.extra = &.{}; |
| 6217 | | 5918 | |
| ... | @@ -6238,33 +5939,76 @@ pub const WipFunction = struct { | ... | @@ -6238,33 +5939,76 @@ pub const WipFunction = struct { |
| 6238 | | 5939 | |
| 6239 | var wip_name: struct { | 5940 | var wip_name: struct { |
| 6240 | next_name: String = @enumFromInt(0), | 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 { | 5945 | fn map(wip_name: *@This(), name: String, sep: []const u8) Allocator.Error!String { |
| 6243 | if (old_name != .empty) return old_name; | 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; | 5961 | while (true) { |
| 6246 | wip_name.next_name = @enumFromInt(@intFromEnum(new_name) + 1); | 5962 | gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1); |
| 6247 | return new_name; | 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 | for (0..params_len) |param_index| { | 5984 | for (0..params_len) |param_index| { |
| 6251 | const old_argument_index: Instruction.Index = @enumFromInt(param_index); | 5985 | const old_argument_index: Instruction.Index = @enumFromInt(param_index); |
| 6252 | const new_argument_index: Instruction.Index = @enumFromInt(function.instructions.len); | 5986 | const new_argument_index: Instruction.Index = @enumFromInt(function.instructions.len); |
| 6253 | const argument = self.instructions.get(@intFromEnum(old_argument_index)); | 5987 | const argument = self.instructions.get(@intFromEnum(old_argument_index)); |
| 6254 | assert(argument.tag == .arg); | 5988 | assert(argument.tag == .arg); |
| 6255 | assert(argument.data == param_index); | 5989 | assert(argument.data == param_index); |
| | 5990 | value_indices[function.instructions.len] = value_index; |
| | 5991 | value_index += 1; |
| 6256 | function.instructions.appendAssumeCapacity(argument); | 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 | if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)], | 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 | for (self.blocks.items) |current_block| { | 6004 | for (self.blocks.items) |current_block| { |
| 6262 | const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len); | 6005 | const new_block_index: Instruction.Index = @enumFromInt(function.instructions.len); |
| | 6006 | value_indices[function.instructions.len] = value_index; |
| 6263 | function.instructions.appendAssumeCapacity(.{ | 6007 | function.instructions.appendAssumeCapacity(.{ |
| 6264 | .tag = .block, | 6008 | .tag = .block, |
| 6265 | .data = current_block.incoming, | 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 | for (current_block.instructions.items) |old_instruction_index| { | 6012 | for (current_block.instructions.items) |old_instruction_index| { |
| 6269 | const new_instruction_index: Instruction.Index = | 6013 | const new_instruction_index: Instruction.Index = |
| 6270 | @enumFromInt(function.instructions.len); | 6014 | @enumFromInt(function.instructions.len); |
| ... | @@ -6565,10 +6309,21 @@ pub const WipFunction = struct { | ... | @@ -6565,10 +6309,21 @@ pub const WipFunction = struct { |
| 6565 | }, | 6309 | }, |
| 6566 | } | 6310 | } |
| 6567 | function.instructions.appendAssumeCapacity(instruction); | 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 | if (old_instruction_index.hasResultWip(self)) .empty else .none | 6313 | if (old_instruction_index.hasResultWip(self)) .empty else .none |
| 6570 | else | 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,28 +6331,25 @@ pub const WipFunction = struct { |
| 6576 | function.extra = wip_extra.finish(); | 6331 | function.extra = wip_extra.finish(); |
| 6577 | function.blocks = blocks; | 6332 | function.blocks = blocks; |
| 6578 | function.names = names.ptr; | 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 | pub fn deinit(self: *WipFunction) void { | 6339 | pub fn deinit(self: *WipFunction) void { |
| 6583 | self.extra.deinit(self.builder.gpa); | 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 | self.names.deinit(self.builder.gpa); | 6343 | self.names.deinit(self.builder.gpa); |
| 6586 | self.instructions.deinit(self.builder.gpa); | 6344 | self.instructions.deinit(self.builder.gpa); |
| 6587 | for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa); | 6345 | for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa); |
| 6588 | self.blocks.deinit(self.builder.gpa); | 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 | self.* = undefined; | 6347 | self.* = undefined; |
| 6595 | } | 6348 | } |
| 6596 | | 6349 | |
| 6597 | fn cmpTag( | 6350 | fn cmpTag( |
| 6598 | self: *WipFunction, | 6351 | self: *WipFunction, |
| 6599 | tag: Instruction.Tag, | 6352 | tag: Instruction.Tag, |
| 6600 | cond: u32, | | |
| 6601 | lhs: Value, | 6353 | lhs: Value, |
| 6602 | rhs: Value, | 6354 | rhs: Value, |
| 6603 | name: []const u8, | 6355 | name: []const u8, |
| ... | @@ -6657,113 +6409,6 @@ pub const WipFunction = struct { | ... | @@ -6657,113 +6409,6 @@ pub const WipFunction = struct { |
| 6657 | .rhs = rhs, | 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 | return instruction.toValue(); | 6412 | return instruction.toValue(); |
| 6768 | } | 6413 | } |
| 6769 | | 6414 | |
| ... | @@ -6785,16 +6430,6 @@ pub const WipFunction = struct { | ... | @@ -6785,16 +6430,6 @@ pub const WipFunction = struct { |
| 6785 | .data = self.addExtraAssumeCapacity(Instruction.Phi{ .type = ty }), | 6430 | .data = self.addExtraAssumeCapacity(Instruction.Phi{ .type = ty }), |
| 6786 | }); | 6431 | }); |
| 6787 | _ = self.extra.addManyAsSliceAssumeCapacity(incoming * 2); | 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 | return .{ .block = self.cursor.block, .instruction = instruction }; | 6433 | return .{ .block = self.cursor.block, .instruction = instruction }; |
| 6799 | } | 6434 | } |
| 6800 | | 6435 | |
| ... | @@ -6822,19 +6457,6 @@ pub const WipFunction = struct { | ... | @@ -6822,19 +6457,6 @@ pub const WipFunction = struct { |
| 6822 | .rhs = rhs, | 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 | return instruction.toValue(); | 6460 | return instruction.toValue(); |
| 6839 | } | 6461 | } |
| 6840 | | 6462 | |
| ... | @@ -6857,28 +6479,27 @@ pub const WipFunction = struct { | ... | @@ -6857,28 +6479,27 @@ pub const WipFunction = struct { |
| 6857 | ) Allocator.Error!Instruction.Index { | 6479 | ) Allocator.Error!Instruction.Index { |
| 6858 | const block_instructions = &self.cursor.block.ptr(self).instructions; | 6480 | const block_instructions = &self.cursor.block.ptr(self).instructions; |
| 6859 | try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1); | 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 | try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1); | 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 | const final_name = if (name) |n| | 6487 | const final_name = if (name) |n| |
| 6865 | if (self.builder.strip) .empty else try self.builder.string(n) | 6488 | if (self.builder.strip) .empty else try self.builder.string(n) |
| 6866 | else | 6489 | else |
| 6867 | .none; | 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 | const index: Instruction.Index = @enumFromInt(self.instructions.len); | 6492 | const index: Instruction.Index = @enumFromInt(self.instructions.len); |
| 6880 | self.instructions.appendAssumeCapacity(instruction); | 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 | block_instructions.insertAssumeCapacity(self.cursor.instruction, index); | 6503 | block_instructions.insertAssumeCapacity(self.cursor.instruction, index); |
| 6883 | self.cursor.instruction += 1; | 6504 | self.cursor.instruction += 1; |
| 6884 | return index; | 6505 | return index; |
| ... | @@ -6901,7 +6522,7 @@ pub const WipFunction = struct { | ... | @@ -6901,7 +6522,7 @@ pub const WipFunction = struct { |
| 6901 | Instruction.Alloca.Info, | 6522 | Instruction.Alloca.Info, |
| 6902 | Instruction.Call.Info, | 6523 | Instruction.Call.Info, |
| 6903 | => @bitCast(value), | 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 | return result; | 6528 | return result; |
| ... | @@ -6949,7 +6570,7 @@ pub const WipFunction = struct { | ... | @@ -6949,7 +6570,7 @@ pub const WipFunction = struct { |
| 6949 | Instruction.Alloca.Info, | 6570 | Instruction.Alloca.Info, |
| 6950 | Instruction.Call.Info, | 6571 | Instruction.Call.Info, |
| 6951 | => @bitCast(value), | 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 | return .{ | 6575 | return .{ |
| 6955 | .data = result, | 6576 | .data = result, |
| ... | @@ -6977,24 +6598,6 @@ pub const FloatCondition = enum(u4) { | ... | @@ -6977,24 +6598,6 @@ pub const FloatCondition = enum(u4) { |
| 6977 | ult = 12, | 6598 | ult = 12, |
| 6978 | ule = 13, | 6599 | ule = 13, |
| 6979 | une = 14, | 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 | pub const IntegerCondition = enum(u6) { | 6603 | pub const IntegerCondition = enum(u6) { |
| ... | @@ -7008,20 +6611,6 @@ pub const IntegerCondition = enum(u6) { | ... | @@ -7008,20 +6611,6 @@ pub const IntegerCondition = enum(u6) { |
| 7008 | sge = 39, | 6611 | sge = 39, |
| 7009 | slt = 40, | 6612 | slt = 40, |
| 7010 | sle = 41, | 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 | pub const MemoryAccessKind = enum(u1) { | 6616 | pub const MemoryAccessKind = enum(u1) { |
| ... | @@ -7058,10 +6647,10 @@ pub const AtomicOrdering = enum(u3) { | ... | @@ -7058,10 +6647,10 @@ pub const AtomicOrdering = enum(u3) { |
| 7058 | none = 0, | 6647 | none = 0, |
| 7059 | unordered = 1, | 6648 | unordered = 1, |
| 7060 | monotonic = 2, | 6649 | monotonic = 2, |
| 7061 | acquire = 4, | 6650 | acquire = 3, |
| 7062 | release = 5, | 6651 | release = 4, |
| 7063 | acq_rel = 6, | 6652 | acq_rel = 5, |
| 7064 | seq_cst = 7, | 6653 | seq_cst = 6, |
| 7065 | | 6654 | |
| 7066 | pub fn format( | 6655 | pub fn format( |
| 7067 | self: AtomicOrdering, | 6656 | self: AtomicOrdering, |
| ... | @@ -7071,18 +6660,6 @@ pub const AtomicOrdering = enum(u3) { | ... | @@ -7071,18 +6660,6 @@ pub const AtomicOrdering = enum(u3) { |
| 7071 | ) @TypeOf(writer).Error!void { | 6660 | ) @TypeOf(writer).Error!void { |
| 7072 | if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) }); | 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 | const MemoryAccessInfo = packed struct(u32) { | 6665 | const MemoryAccessInfo = packed struct(u32) { |
| ... | @@ -7095,7 +6672,8 @@ const MemoryAccessInfo = packed struct(u32) { | ... | @@ -7095,7 +6672,8 @@ const MemoryAccessInfo = packed struct(u32) { |
| 7095 | _: u13 = undefined, | 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 | nnan: bool = false, | 6677 | nnan: bool = false, |
| 7100 | ninf: bool = false, | 6678 | ninf: bool = false, |
| 7101 | nsz: bool = false, | 6679 | nsz: bool = false, |
| ... | @@ -7130,11 +6708,13 @@ pub const FastMathKind = enum { | ... | @@ -7130,11 +6708,13 @@ pub const FastMathKind = enum { |
| 7130 | pub const Constant = enum(u32) { | 6708 | pub const Constant = enum(u32) { |
| 7131 | false, | 6709 | false, |
| 7132 | true, | 6710 | true, |
| | 6711 | @"0", |
| | 6712 | @"1", |
| 7133 | none, | 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 | pub const Tag = enum(u7) { | 6719 | pub const Tag = enum(u7) { |
| 7140 | positive_integer, | 6720 | positive_integer, |
| ... | @@ -7152,7 +6732,6 @@ pub const Constant = enum(u32) { | ... | @@ -7152,7 +6732,6 @@ pub const Constant = enum(u32) { |
| 7152 | packed_structure, | 6732 | packed_structure, |
| 7153 | array, | 6733 | array, |
| 7154 | string, | 6734 | string, |
| 7155 | string_null, | | |
| 7156 | vector, | 6735 | vector, |
| 7157 | splat, | 6736 | splat, |
| 7158 | zeroinitializer, | 6737 | zeroinitializer, |
| ... | @@ -7212,6 +6791,49 @@ pub const Constant = enum(u32) { | ... | @@ -7212,6 +6791,49 @@ pub const Constant = enum(u32) { |
| 7212 | @"asm sideeffect inteldialect unwind", | 6791 | @"asm sideeffect inteldialect unwind", |
| 7213 | @"asm alignstack inteldialect unwind", | 6792 | @"asm alignstack inteldialect unwind", |
| 7214 | @"asm sideeffect alignstack inteldialect unwind", | 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 | pub const Item = struct { | 6839 | pub const Item = struct { |
| ... | @@ -7364,11 +6986,8 @@ pub const Constant = enum(u32) { | ... | @@ -7364,11 +6986,8 @@ pub const Constant = enum(u32) { |
| 7364 | .vector, | 6986 | .vector, |
| 7365 | => builder.constantExtraData(Aggregate, item.data).type, | 6987 | => builder.constantExtraData(Aggregate, item.data).type, |
| 7366 | .splat => builder.constantExtraData(Splat, item.data).type, | 6988 | .splat => builder.constantExtraData(Splat, item.data).type, |
| 7367 | .string, | 6989 | .string => builder.arrayTypeAssumeCapacity( |
| 7368 | .string_null, | 6990 | @as(String, @enumFromInt(item.data)).slice(builder).?.len, |
| 7369 | => builder.arrayTypeAssumeCapacity( | | |
| 7370 | @as(String, @enumFromInt(item.data)).slice(builder).?.len + | | |
| 7371 | @intFromBool(item.tag == .string_null), | | |
| 7372 | .i8, | 6991 | .i8, |
| 7373 | ), | 6992 | ), |
| 7374 | .blockaddress => builder.ptrTypeAssumeCapacity( | 6993 | .blockaddress => builder.ptrTypeAssumeCapacity( |
| ... | @@ -7574,7 +7193,7 @@ pub const Constant = enum(u32) { | ... | @@ -7574,7 +7193,7 @@ pub const Constant = enum(u32) { |
| 7574 | @ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]); | 7193 | @ptrCast(data.builder.constant_limbs.items[item.data..][0..Integer.limbs]); |
| 7575 | const limbs = data.builder.constant_limbs | 7194 | const limbs = data.builder.constant_limbs |
| 7576 | .items[item.data + Integer.limbs ..][0..extra.limbs_len]; | 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 | .limbs = limbs, | 7197 | .limbs = limbs, |
| 7579 | .positive = tag == .positive_integer, | 7198 | .positive = tag == .positive_integer, |
| 7580 | }; | 7199 | }; |
| ... | @@ -7616,17 +7235,31 @@ pub const Constant = enum(u32) { | ... | @@ -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 | const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent); | 7239 | const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent); |
| 7620 | const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent); | 7240 | const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent); |
| | 7241 | |
| 7621 | const repr: Float.Repr(f32) = @bitCast(item.data); | 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 | try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){ | 7250 | try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){ |
| 7623 | .mantissa = std.math.shl( | 7251 | .mantissa = std.math.shl( |
| 7624 | std.meta.FieldType(Float.Repr(f64), .mantissa), | 7252 | Mantissa64, |
| 7625 | repr.mantissa, | 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 | .exponent = switch (repr.exponent) { | 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 | else => @as(Exponent64, repr.exponent) + | 7263 | else => @as(Exponent64, repr.exponent) + |
| 7631 | (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)), | 7264 | (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)), |
| 7632 | std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64), | 7265 | std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64), |
| ... | @@ -7703,13 +7336,9 @@ pub const Constant = enum(u32) { | ... | @@ -7703,13 +7336,9 @@ pub const Constant = enum(u32) { |
| 7703 | } | 7336 | } |
| 7704 | try writer.writeByte('>'); | 7337 | try writer.writeByte('>'); |
| 7705 | }, | 7338 | }, |
| 7706 | inline .string, | 7339 | .string => try writer.print("c{\"}", .{ |
| 7707 | .string_null, | 7340 | @as(String, @enumFromInt(item.data)).fmt(data.builder), |
| 7708 | => |tag| try writer.print("c{\"" ++ switch (tag) { | 7341 | }), |
| 7709 | .string => "", | | |
| 7710 | .string_null => "@", | | |
| 7711 | else => unreachable, | | |
| 7712 | } ++ "}", .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}), | | |
| 7713 | .blockaddress => |tag| { | 7342 | .blockaddress => |tag| { |
| 7714 | const extra = data.builder.constantExtraData(BlockAddress, item.data); | 7343 | const extra = data.builder.constantExtraData(BlockAddress, item.data); |
| 7715 | const function = extra.function.ptrConst(data.builder); | 7344 | const function = extra.function.ptrConst(data.builder); |
| ... | @@ -7859,40 +7488,37 @@ pub const Constant = enum(u32) { | ... | @@ -7859,40 +7488,37 @@ pub const Constant = enum(u32) { |
| 7859 | pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) { | 7488 | pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) { |
| 7860 | return .{ .data = .{ .constant = self, .builder = builder } }; | 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 | pub const Value = enum(u32) { | 7493 | pub const Value = enum(u32) { |
| 7875 | none = std.math.maxInt(u31), | 7494 | none = std.math.maxInt(u31), |
| 7876 | false = first_constant + @intFromEnum(Constant.false), | 7495 | false = first_constant + @intFromEnum(Constant.false), |
| 7877 | true = first_constant + @intFromEnum(Constant.true), | 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 | pub fn unwrap(self: Value) union(enum) { | 7504 | pub fn unwrap(self: Value) union(enum) { |
| 7883 | instruction: Function.Instruction.Index, | 7505 | instruction: Function.Instruction.Index, |
| 7884 | constant: Constant, | 7506 | constant: Constant, |
| | 7507 | metadata: Metadata, |
| 7885 | } { | 7508 | } { |
| 7886 | return if (@intFromEnum(self) < first_constant) | 7509 | return if (@intFromEnum(self) < first_constant) |
| 7887 | .{ .instruction = @enumFromInt(@intFromEnum(self)) } | 7510 | .{ .instruction = @enumFromInt(@intFromEnum(self)) } |
| | 7511 | else if (@intFromEnum(self) < first_metadata) |
| | 7512 | .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) } |
| 7888 | else | 7513 | else |
| 7889 | .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }; | 7514 | .{ .metadata = @enumFromInt(@intFromEnum(self) - first_metadata) }; |
| 7890 | } | 7515 | } |
| 7891 | | 7516 | |
| 7892 | pub fn typeOfWip(self: Value, wip: *const WipFunction) Type { | 7517 | pub fn typeOfWip(self: Value, wip: *const WipFunction) Type { |
| 7893 | return switch (self.unwrap()) { | 7518 | return switch (self.unwrap()) { |
| 7894 | .instruction => |instruction| instruction.typeOfWip(wip), | 7519 | .instruction => |instruction| instruction.typeOfWip(wip), |
| 7895 | .constant => |constant| constant.typeOf(wip.builder), | 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,12 +7526,13 @@ pub const Value = enum(u32) { |
| 7900 | return switch (self.unwrap()) { | 7526 | return switch (self.unwrap()) { |
| 7901 | .instruction => |instruction| instruction.typeOf(function, builder), | 7527 | .instruction => |instruction| instruction.typeOf(function, builder), |
| 7902 | .constant => |constant| constant.typeOf(builder), | 7528 | .constant => |constant| constant.typeOf(builder), |
| | 7529 | .metadata => .metadata, |
| 7903 | }; | 7530 | }; |
| 7904 | } | 7531 | } |
| 7905 | | 7532 | |
| 7906 | pub fn toConst(self: Value) ?Constant { | 7533 | pub fn toConst(self: Value) ?Constant { |
| 7907 | return switch (self.unwrap()) { | 7534 | return switch (self.unwrap()) { |
| 7908 | .instruction => null, | 7535 | .instruction, .metadata => null, |
| 7909 | .constant => |constant| constant, | 7536 | .constant => |constant| constant, |
| 7910 | }; | 7537 | }; |
| 7911 | } | 7538 | } |
| ... | @@ -7931,397 +7558,854 @@ pub const Value = enum(u32) { | ... | @@ -7931,397 +7558,854 @@ pub const Value = enum(u32) { |
| 7931 | .constant = constant, | 7558 | .constant = constant, |
| 7932 | .builder = data.builder, | 7559 | .builder = data.builder, |
| 7933 | }, fmt_str, fmt_opts, writer), | 7560 | }, fmt_str, fmt_opts, writer), |
| | 7561 | .metadata => unreachable, |
| 7934 | } | 7562 | } |
| 7935 | } | 7563 | } |
| 7936 | pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) { | 7564 | pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) { |
| 7937 | return .{ .data = .{ .value = self, .function = function, .builder = builder } }; | 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 { | 7569 | pub const MetadataString = enum(u32) { |
| 7941 | return switch (self.unwrap()) { | 7570 | none = 0, |
| 7942 | .instruction => |instruction| instruction.toLlvm(wip), | 7571 | _, |
| 7943 | .constant => |constant| constant.toLlvm(wip.builder), | 7572 | |
| 7944 | }; | 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{ | 7591 | const FormatData = struct { |
| 7951 | InvalidLlvmTriple, | 7592 | metadata_string: MetadataString, |
| 7952 | } || Allocator.Error; | 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 { | 7608 | pub const Metadata = enum(u32) { |
| 7955 | var self = Builder{ | 7609 | none = 0, |
| 7956 | .gpa = options.allocator, | 7610 | _, |
| 7957 | .use_lib_llvm = options.use_lib_llvm, | | |
| 7958 | .strip = options.strip, | | |
| 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, | 7615 | pub const Tag = enum(u6) { |
| 7963 | .data_layout = .none, | 7616 | none, |
| 7964 | .target_triple = .none, | 7617 | file, |
| 7965 | .module_asm = .{}, | 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 = .{}, | 7703 | pub fn isInline(self: Metadata, builder: *const Builder) bool { |
| 7968 | .string_indices = .{}, | 7704 | return builder.metadata_items.items(.tag)[@intFromEnum(self)].isInline(); |
| 7969 | .string_bytes = .{}, | 7705 | } |
| 7970 | | 7706 | |
| 7971 | .types = .{}, | 7707 | pub fn unwrap(self: Metadata, builder: *const Builder) Metadata { |
| 7972 | .next_unnamed_type = @enumFromInt(0), | 7708 | var metadata = self; |
| 7973 | .next_unique_type_id = .{}, | 7709 | while (@intFromEnum(metadata) >= Metadata.first_forward_reference and |
| 7974 | .type_map = .{}, | 7710 | @intFromEnum(metadata) < Metadata.first_local_metadata) |
| 7975 | .type_items = .{}, | 7711 | { |
| 7976 | .type_extra = .{}, | 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 = .{}, | 7719 | pub const Item = struct { |
| 7979 | .attributes_map = .{}, | 7720 | tag: Tag, |
| 7980 | .attributes_indices = .{}, | 7721 | data: ExtraIndex, |
| 7981 | .attributes_extra = .{}, | | |
| 7982 | | 7722 | |
| 7983 | .globals = .{}, | 7723 | const ExtraIndex = u32; |
| 7984 | .next_unnamed_global = @enumFromInt(0), | 7724 | }; |
| 7985 | .next_replaced_global = .none, | | |
| 7986 | .next_unique_global_id = .{}, | | |
| 7987 | .aliases = .{}, | | |
| 7988 | .variables = .{}, | | |
| 7989 | .functions = .{}, | | |
| 7990 | | 7725 | |
| 7991 | .constant_map = .{}, | 7726 | pub const DIFlags = packed struct(u32) { |
| 7992 | .constant_items = .{}, | 7727 | Visibility: enum(u2) { Zero, Private, Protected, Public } = .Zero, |
| 7993 | .constant_extra = .{}, | 7728 | FwdDecl: bool = false, |
| 7994 | .constant_limbs = .{}, | 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 = .{ | 7787 | |
| 7997 | .context = llvm.Context.create(), | 7788 | pub const File = struct { |
| 7998 | .module = null, | 7789 | filename: MetadataString, |
| 7999 | .target = null, | 7790 | directory: MetadataString, |
| 8000 | .di_builder = null, | | |
| 8001 | .di_compile_unit = null, | | |
| 8002 | .attribute_kind_ids = null, | | |
| 8003 | .attributes = .{}, | | |
| 8004 | .types = .{}, | | |
| 8005 | .globals = .{}, | | |
| 8006 | .constants = .{}, | | |
| 8007 | .replacements = .{}, | | |
| 8008 | }; | 7791 | }; |
| 8009 | errdefer self.deinit(); | | |
| 8010 | | 7792 | |
| 8011 | try self.string_indices.append(self.gpa, 0); | 7793 | pub const CompileUnit = struct { |
| 8012 | assert(try self.string("") == .empty); | 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); | 7798 | file: Metadata, |
| 8015 | if (self.useLibLlvm()) { | 7799 | producer: MetadataString, |
| 8016 | initializeLLVMTarget(options.target.cpu.arch); | 7800 | enums: Metadata, |
| 8017 | self.llvm.module = llvm.Module.createWithName( | 7801 | globals: Metadata, |
| 8018 | (self.source_filename.slice(&self) orelse ""), | 7802 | }; |
| 8019 | self.llvm.context, | | |
| 8020 | ); | | |
| 8021 | } | | |
| 8022 | | 7803 | |
| 8023 | if (options.triple.len > 0) { | 7804 | pub const Subprogram = struct { |
| 8024 | self.target_triple = try self.string(options.triple); | 7805 | pub const Options = struct { |
| | 7806 | di_flags: DIFlags, |
| | 7807 | sp_flags: DISPFlags, |
| | 7808 | }; |
| 8025 | | 7809 | |
| 8026 | if (self.useLibLlvm()) { | 7810 | pub const DISPFlags = packed struct(u32) { |
| 8027 | var error_message: [*:0]const u8 = undefined; | 7811 | Virtuality: enum(u2) { Zero, Virtual, PureVirtual } = .Zero, |
| 8028 | var target: *llvm.Target = undefined; | 7812 | LocalToUnit: bool = false, |
| 8029 | if (llvm.Target.getFromTriple( | 7813 | Definition: bool = false, |
| 8030 | self.target_triple.slice(&self).?, | 7814 | Optimized: bool = false, |
| 8031 | &target, | 7815 | Pure: bool = false, |
| 8032 | &error_message, | 7816 | Elemental: bool = false, |
| 8033 | ).toBool()) { | 7817 | Recursive: bool = false, |
| 8034 | defer llvm.disposeMessage(error_message); | 7818 | MainSubprogram: bool = false, |
| 8035 | | 7819 | Deleted: bool = false, |
| 8036 | log.err("LLVM failed to parse '{s}': {s}", .{ | 7820 | ReservedBit10: u1 = 0, |
| 8037 | self.target_triple.slice(&self).?, | 7821 | ObjCDirect: bool = false, |
| 8038 | error_message, | 7822 | Unused: u20 = 0, |
| 8039 | }); | 7823 | |
| 8040 | return InitError.InvalidLlvmTriple; | 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; | 7848 | }; |
| 8043 | self.llvm.module.?.setTarget(self.target_triple.slice(&self).?); | 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 | { | 7884 | pub const CompositeType = struct { |
| 8048 | const static_len = @typeInfo(Type).Enum.fields.len - 1; | 7885 | name: MetadataString, |
| 8049 | try self.type_map.ensureTotalCapacity(self.gpa, static_len); | 7886 | file: Metadata, |
| 8050 | try self.type_items.ensureTotalCapacity(self.gpa, static_len); | 7887 | scope: Metadata, |
| 8051 | if (self.useLibLlvm()) try self.llvm.types.ensureTotalCapacity(self.gpa, static_len); | 7888 | line: u32, |
| 8052 | inline for (@typeInfo(Type.Simple).Enum.fields) |simple_field| { | 7889 | underlying_type: Metadata, |
| 8053 | const result = self.getOrPutTypeNoExtraAssumeCapacity( | 7890 | size_in_bits_lo: u32, |
| 8054 | .{ .tag = .simple, .data = simple_field.value }, | 7891 | size_in_bits_hi: u32, |
| 8055 | ); | 7892 | align_in_bits_lo: u32, |
| 8056 | assert(result.new and result.type == @field(Type, simple_field.name)); | 7893 | align_in_bits_hi: u32, |
| 8057 | if (self.useLibLlvm()) self.llvm.types.appendAssumeCapacity( | 7894 | fields_tuple: Metadata, |
| 8058 | @field(llvm.Context, simple_field.name ++ "Type")(self.llvm.context), | 7895 | |
| 8059 | ); | 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| | 7899 | pub fn bitAlign(self: CompositeType) u64 { |
| 8062 | assert(self.intTypeAssumeCapacity(bits) == | 7900 | return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo; |
| 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}))); | | |
| 8068 | } | 7901 | } |
| 8069 | } | 7902 | }; |
| 8070 | | 7903 | |
| 8071 | { | 7904 | pub const DerivedType = struct { |
| 8072 | if (self.useLibLlvm()) { | 7905 | name: MetadataString, |
| 8073 | self.llvm.attribute_kind_ids = try self.gpa.create([Attribute.Kind.len]c_uint); | 7906 | file: Metadata, |
| 8074 | @memset(self.llvm.attribute_kind_ids.?, 0); | 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); | 7920 | pub fn bitAlign(self: DerivedType) u64 { |
| 8077 | assert(try self.attrs(&.{}) == .none); | 7921 | return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo; |
| 8078 | assert(try self.fnAttrs(&.{}) == .none); | 7922 | } |
| 8079 | } | 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); | 7928 | pub const SubroutineType = struct { |
| 8082 | assert(try self.intConst(.i1, 1) == .true); | 7929 | types_tuple: Metadata, |
| 8083 | assert(try self.noneConst(.token) == .none); | 7930 | }; |
| 8084 | | 7931 | |
| 8085 | return self; | 7932 | pub const Enumerator = struct { |
| 8086 | } | 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 { | 7939 | pub const Subrange = struct { |
| 8089 | if (self.useLibLlvm()) { | 7940 | lower_bound: Metadata, |
| 8090 | var replacement_it = self.llvm.replacements.keyIterator(); | 7941 | count: Metadata, |
| 8091 | while (replacement_it.next()) |replacement| replacement.*.deleteGlobalValue(); | 7942 | }; |
| 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 | } | | |
| 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); | 7947 | // elements: [elements_len]u32 |
| 8106 | self.string_indices.deinit(self.gpa); | 7948 | }; |
| 8107 | self.string_bytes.deinit(self.gpa); | | |
| 8108 | | 7949 | |
| 8109 | self.types.deinit(self.gpa); | 7950 | pub const Tuple = struct { |
| 8110 | self.next_unique_type_id.deinit(self.gpa); | 7951 | elements_len: u32, |
| 8111 | self.type_map.deinit(self.gpa); | | |
| 8112 | self.type_items.deinit(self.gpa); | | |
| 8113 | self.type_extra.deinit(self.gpa); | | |
| 8114 | | 7952 | |
| 8115 | self.attributes.deinit(self.gpa); | 7953 | // elements: [elements_len]Metadata |
| 8116 | self.attributes_map.deinit(self.gpa); | 7954 | }; |
| 8117 | self.attributes_indices.deinit(self.gpa); | | |
| 8118 | self.attributes_extra.deinit(self.gpa); | | |
| 8119 | | 7955 | |
| 8120 | self.globals.deinit(self.gpa); | 7956 | pub const ModuleFlag = struct { |
| 8121 | self.next_unique_global_id.deinit(self.gpa); | 7957 | behavior: Metadata, |
| 8122 | self.aliases.deinit(self.gpa); | 7958 | name: MetadataString, |
| 8123 | self.variables.deinit(self.gpa); | 7959 | constant: Metadata, |
| 8124 | for (self.functions.items) |*function| function.deinit(self.gpa); | 7960 | }; |
| 8125 | self.functions.deinit(self.gpa); | | |
| 8126 | | 7961 | |
| 8127 | self.constant_map.deinit(self.gpa); | 7962 | pub const LocalVar = struct { |
| 8128 | self.constant_items.deinit(self.gpa); | 7963 | name: MetadataString, |
| 8129 | self.constant_extra.deinit(self.gpa); | 7964 | file: Metadata, |
| 8130 | self.constant_limbs.deinit(self.gpa); | 7965 | scope: Metadata, |
| | 7966 | line: u32, |
| | 7967 | ty: Metadata, |
| | 7968 | }; |
| 8131 | | 7969 | |
| 8132 | self.* = undefined; | 7970 | pub const Parameter = struct { |
| 8133 | } | 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 { | 8051 | const builder = data.formatter.builder; |
| 8136 | switch (arch) { | 8052 | switch (data.node) { |
| 8137 | .aarch64, .aarch64_be, .aarch64_32 => { | 8053 | .none => unreachable, |
| 8138 | llvm.LLVMInitializeAArch64Target(); | 8054 | .@"inline" => |node| { |
| 8139 | llvm.LLVMInitializeAArch64TargetInfo(); | 8055 | const needed_comma = data.formatter.need_comma; |
| 8140 | llvm.LLVMInitializeAArch64TargetMC(); | 8056 | defer data.formatter.need_comma = needed_comma; |
| 8141 | llvm.LLVMInitializeAArch64AsmPrinter(); | 8057 | data.formatter.need_comma = false; |
| 8142 | llvm.LLVMInitializeAArch64AsmParser(); | 8058 | |
| 8143 | }, | 8059 | const item = builder.metadata_items.get(@intFromEnum(node)); |
| 8144 | .amdgcn => { | 8060 | switch (item.tag) { |
| 8145 | llvm.LLVMInitializeAMDGPUTarget(); | 8061 | .expression => { |
| 8146 | llvm.LLVMInitializeAMDGPUTargetInfo(); | 8062 | var extra = builder.metadataExtraDataTrail(Expression, item.data); |
| 8147 | llvm.LLVMInitializeAMDGPUTargetMC(); | 8063 | const elements = extra.trail.next(extra.data.elements_len, u32, builder); |
| 8148 | llvm.LLVMInitializeAMDGPUAsmPrinter(); | 8064 | try writer.writeAll("!DIExpression("); |
| 8149 | llvm.LLVMInitializeAMDGPUAsmParser(); | 8065 | for (elements) |element| try format(.{ |
| 8150 | }, | 8066 | .formatter = data.formatter, |
| 8151 | .thumb, .thumbeb, .arm, .armeb => { | 8067 | .node = .{ .u64 = element }, |
| 8152 | llvm.LLVMInitializeARMTarget(); | 8068 | }, "%", fmt_opts, writer); |
| 8153 | llvm.LLVMInitializeARMTargetInfo(); | 8069 | try writer.writeByte(')'); |
| 8154 | llvm.LLVMInitializeARMTargetMC(); | 8070 | }, |
| 8155 | llvm.LLVMInitializeARMAsmPrinter(); | 8071 | .constant => try Constant.format(.{ |
| 8156 | llvm.LLVMInitializeARMAsmParser(); | 8072 | .constant = @enumFromInt(item.data), |
| 8157 | }, | 8073 | .builder = builder, |
| 8158 | .avr => { | 8074 | }, recurse_fmt_str, fmt_opts, writer), |
| 8159 | llvm.LLVMInitializeAVRTarget(); | 8075 | else => unreachable, |
| 8160 | llvm.LLVMInitializeAVRTargetInfo(); | 8076 | } |
| 8161 | llvm.LLVMInitializeAVRTargetMC(); | 8077 | }, |
| 8162 | llvm.LLVMInitializeAVRAsmPrinter(); | 8078 | .index => |node| try writer.print("!{d}", .{node}), |
| 8163 | llvm.LLVMInitializeAVRAsmParser(); | 8079 | inline .local_value, .local_metadata => |node, tag| try Value.format(.{ |
| 8164 | }, | 8080 | .value = node.value, |
| 8165 | .bpfel, .bpfeb => { | 8081 | .function = node.function, |
| 8166 | llvm.LLVMInitializeBPFTarget(); | 8082 | .builder = builder, |
| 8167 | llvm.LLVMInitializeBPFTargetInfo(); | 8083 | }, switch (tag) { |
| 8168 | llvm.LLVMInitializeBPFTargetMC(); | 8084 | .local_value => recurse_fmt_str, |
| 8169 | llvm.LLVMInitializeBPFAsmPrinter(); | 8085 | .local_metadata => "%", |
| 8170 | llvm.LLVMInitializeBPFAsmParser(); | 8086 | else => unreachable, |
| 8171 | }, | 8087 | }, fmt_opts, writer), |
| 8172 | .hexagon => { | 8088 | inline .local_inline, .local_index => |node, tag| { |
| 8173 | llvm.LLVMInitializeHexagonTarget(); | 8089 | if (comptime std.mem.eql(u8, recurse_fmt_str, "%")) |
| 8174 | llvm.LLVMInitializeHexagonTargetInfo(); | 8090 | try writer.print("{%} ", .{Type.metadata.fmt(builder)}); |
| 8175 | llvm.LLVMInitializeHexagonTargetMC(); | 8091 | try format(.{ |
| 8176 | llvm.LLVMInitializeHexagonAsmPrinter(); | 8092 | .formatter = data.formatter, |
| 8177 | llvm.LLVMInitializeHexagonAsmParser(); | 8093 | .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node), |
| 8178 | }, | 8094 | }, "%", fmt_opts, writer); |
| 8179 | .lanai => { | 8095 | }, |
| 8180 | llvm.LLVMInitializeLanaiTarget(); | 8096 | .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{ |
| 8181 | llvm.LLVMInitializeLanaiTargetInfo(); | 8097 | node.fmt(builder), |
| 8182 | llvm.LLVMInitializeLanaiTargetMC(); | 8098 | }), |
| 8183 | llvm.LLVMInitializeLanaiAsmPrinter(); | 8099 | inline .bool, |
| 8184 | llvm.LLVMInitializeLanaiAsmParser(); | 8100 | .u32, |
| 8185 | }, | 8101 | .u64, |
| 8186 | .mips, .mipsel, .mips64, .mips64el => { | 8102 | .di_flags, |
| 8187 | llvm.LLVMInitializeMipsTarget(); | 8103 | .sp_flags, |
| 8188 | llvm.LLVMInitializeMipsTargetInfo(); | 8104 | => |node| try writer.print("{}", .{node}), |
| 8189 | llvm.LLVMInitializeMipsTargetMC(); | 8105 | .raw => |node| try writer.writeAll(node), |
| 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(); | | |
| 8256 | } | 8106 | } |
| 8257 | }, | 8107 | } |
| 8258 | .xcore => { | 8108 | inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) { |
| 8259 | llvm.LLVMInitializeXCoreTarget(); | 8109 | Metadata => Allocator.Error, |
| 8260 | llvm.LLVMInitializeXCoreTargetInfo(); | 8110 | else => error{}, |
| 8261 | llvm.LLVMInitializeXCoreTargetMC(); | 8111 | }!std.fmt.Formatter(format) { |
| 8262 | llvm.LLVMInitializeXCoreAsmPrinter(); | 8112 | const Node = @TypeOf(node); |
| 8263 | // There is no LLVMInitializeXCoreAsmParser function. | 8113 | const MaybeNode = switch (@typeInfo(Node)) { |
| 8264 | }, | 8114 | .Optional => Node, |
| 8265 | .m68k => { | 8115 | .Null => ?noreturn, |
| 8266 | if (build_options.llvm_has_m68k) { | 8116 | else => ?Node, |
| 8267 | llvm.LLVMInitializeM68kTarget(); | 8117 | }; |
| 8268 | llvm.LLVMInitializeM68kTargetInfo(); | 8118 | const Some = @typeInfo(MaybeNode).Optional.child; |
| 8269 | llvm.LLVMInitializeM68kTargetMC(); | 8119 | return .{ .data = .{ |
| 8270 | llvm.LLVMInitializeM68kAsmPrinter(); | 8120 | .formatter = formatter, |
| 8271 | llvm.LLVMInitializeM68kAsmParser(); | 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 | }, | 8197 | } |
| 8274 | .csky => { | 8198 | |
| 8275 | if (build_options.llvm_has_csky) { | 8199 | inline fn specialized( |
| 8276 | llvm.LLVMInitializeCSKYTarget(); | 8200 | formatter: *Formatter, |
| 8277 | llvm.LLVMInitializeCSKYTargetInfo(); | 8201 | distinct: enum { @"!", @"distinct !" }, |
| 8278 | llvm.LLVMInitializeCSKYTargetMC(); | 8202 | node: enum { |
| 8279 | // There is no LLVMInitializeCSKYAsmPrinter function. | 8203 | DIFile, |
| 8280 | llvm.LLVMInitializeCSKYAsmParser(); | 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 | }, | 8234 | fmt_str = fmt_str ++ "("; |
| 8283 | .ve => { | 8235 | inline for (fields[2..], names) |*field, name| { |
| 8284 | llvm.LLVMInitializeVETarget(); | 8236 | fmt_str = fmt_str ++ "{[" ++ name ++ "]S}"; |
| 8285 | llvm.LLVMInitializeVETargetInfo(); | 8237 | field.* = .{ |
| 8286 | llvm.LLVMInitializeVETargetMC(); | 8238 | .name = name, |
| 8287 | llvm.LLVMInitializeVEAsmPrinter(); | 8239 | .type = std.fmt.Formatter(format), |
| 8288 | llvm.LLVMInitializeVEAsmParser(); | 8240 | .default_value = null, |
| 8289 | }, | 8241 | .is_comptime = false, |
| 8290 | .arc => { | 8242 | .alignment = 0, |
| 8291 | if (build_options.llvm_has_arc) { | 8243 | }; |
| 8292 | llvm.LLVMInitializeARCTarget(); | | |
| 8293 | llvm.LLVMInitializeARCTargetInfo(); | | |
| 8294 | llvm.LLVMInitializeARCTargetMC(); | | |
| 8295 | llvm.LLVMInitializeARCAsmPrinter(); | | |
| 8296 | // There is no LLVMInitializeARCAsmParser function. | | |
| 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. | 8264 | pub fn init(options: Options) Allocator.Error!Builder { |
| 8301 | .tce, | 8265 | var self = Builder{ |
| 8302 | .tcele, | 8266 | .gpa = options.allocator, |
| 8303 | .r600, | 8267 | .strip = options.strip, |
| 8304 | .le32, | 8268 | |
| 8305 | .le64, | 8269 | .source_filename = .none, |
| 8306 | .amdil, | 8270 | .data_layout = .none, |
| 8307 | .amdil64, | 8271 | .target_triple = .none, |
| 8308 | .hsail, | 8272 | .module_asm = .{}, |
| 8309 | .hsail64, | 8273 | |
| 8310 | .shave, | 8274 | .string_map = .{}, |
| 8311 | .spir, | 8275 | .string_indices = .{}, |
| 8312 | .spir64, | 8276 | .string_bytes = .{}, |
| 8313 | .kalimba, | 8277 | |
| 8314 | .renderscript32, | 8278 | .types = .{}, |
| 8315 | .renderscript64, | 8279 | .next_unnamed_type = @enumFromInt(0), |
| 8316 | .dxil, | 8280 | .next_unique_type_id = .{}, |
| 8317 | .loongarch32, | 8281 | .type_map = .{}, |
| 8318 | .loongarch64, | 8282 | .type_items = .{}, |
| 8319 | => {}, | 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 | 8346 | { |
| 8322 | .spirv32 => unreachable, // LLVM does not support this backend | 8347 | try self.attributes_indices.append(self.gpa, 0); |
| 8323 | .spirv64 => unreachable, // LLVM does not support this backend | 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 | pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { | 8411 | pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { |
| ... | @@ -8336,24 +8420,25 @@ pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { | ... | @@ -8336,24 +8420,25 @@ pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { |
| 8336 | pub fn finishModuleAsm(self: *Builder) Allocator.Error!void { | 8420 | pub fn finishModuleAsm(self: *Builder) Allocator.Error!void { |
| 8337 | if (self.module_asm.getLastOrNull()) |last| if (last != '\n') | 8421 | if (self.module_asm.getLastOrNull()) |last| if (last != '\n') |
| 8338 | try self.module_asm.append(self.gpa, '\n'); | 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 | pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String { | 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 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); | 8427 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 8346 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); | 8428 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8347 | | 8429 | |
| 8348 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); | 8430 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); |
| 8349 | if (!gop.found_existing) { | 8431 | if (!gop.found_existing) { |
| 8350 | self.string_bytes.appendSliceAssumeCapacity(bytes); | 8432 | self.string_bytes.appendSliceAssumeCapacity(bytes); |
| 8351 | self.string_bytes.appendAssumeCapacity(0); | | |
| 8352 | self.string_indices.appendAssumeCapacity(@intCast(self.string_bytes.items.len)); | 8433 | self.string_indices.appendAssumeCapacity(@intCast(self.string_bytes.items.len)); |
| 8353 | } | 8434 | } |
| 8354 | return String.fromIndex(gop.index); | 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 | pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String { | 8442 | pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String { |
| 8358 | return String.fromIndex( | 8443 | return String.fromIndex( |
| 8359 | self.string_map.getIndexAdapted(bytes, String.Adapter{ .builder = self }) orelse return null, | 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,16 +8447,25 @@ pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String { |
| 8362 | | 8447 | |
| 8363 | pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!String { | 8448 | pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!String { |
| 8364 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); | 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 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); | 8451 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| 8367 | return self.fmtAssumeCapacity(fmt_str, fmt_args); | 8452 | return self.fmtAssumeCapacity(fmt_str, fmt_args); |
| 8368 | } | 8453 | } |
| 8369 | | 8454 | |
| 8370 | pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String { | 8455 | pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String { |
| 8371 | const start = self.string_bytes.items.len; | 8456 | self.string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable; |
| 8372 | self.string_bytes.writer(self.gpa).print(fmt_str ++ .{0}, fmt_args) catch unreachable; | 8457 | return self.trailingStringAssumeCapacity(); |
| 8373 | const bytes: []const u8 = self.string_bytes.items[start .. self.string_bytes.items.len - 1]; | 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 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); | 8469 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); |
| 8376 | if (gop.found_existing) { | 8470 | if (gop.found_existing) { |
| 8377 | self.string_bytes.shrinkRetainingCapacity(start); | 8471 | self.string_bytes.shrinkRetainingCapacity(start); |
| ... | @@ -8435,7 +8529,7 @@ pub fn structType( | ... | @@ -8435,7 +8529,7 @@ pub fn structType( |
| 8435 | pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type { | 8529 | pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type { |
| 8436 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); | 8530 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8437 | if (name.slice(self)) |id| { | 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 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); | 8533 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); |
| 8440 | } | 8534 | } |
| 8441 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); | 8535 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | @@ -8449,98 +8543,17 @@ pub fn namedTypeSetBody( | ... | @@ -8449,98 +8543,17 @@ pub fn namedTypeSetBody( |
| 8449 | self: *Builder, | 8543 | self: *Builder, |
| 8450 | named_type: Type, | 8544 | named_type: Type, |
| 8451 | body_type: Type, | 8545 | body_type: Type, |
| 8452 | ) (if (build_options.have_llvm) Allocator.Error else error{})!void { | 8546 | ) void { |
| 8453 | const named_item = self.type_items.items[@intFromEnum(named_type)]; | 8547 | const named_item = self.type_items.items[@intFromEnum(named_type)]; |
| 8454 | self.type_extra.items[named_item.data + std.meta.fieldIndex(Type.NamedStructure, "body").?] = | 8548 | self.type_extra.items[named_item.data + std.meta.fieldIndex(Type.NamedStructure, "body").?] = |
| 8455 | @intFromEnum(body_type); | 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 | pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Index { | 8552 | pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Index { |
| 8476 | try self.attributes.ensureUnusedCapacity(self.gpa, 1); | 8553 | try self.attributes.ensureUnusedCapacity(self.gpa, 1); |
| 8477 | if (self.useLibLlvm()) try self.llvm.attributes.ensureUnusedCapacity(self.gpa, 1); | | |
| 8478 | | 8554 | |
| 8479 | const gop = self.attributes.getOrPutAssumeCapacity(attribute.toStorage()); | 8555 | const gop = self.attributes.getOrPutAssumeCapacity(attribute.toStorage()); |
| 8480 | if (!gop.found_existing) { | 8556 | if (!gop.found_existing) gop.value_ptr.* = {}; |
| 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 | } | | |
| 8544 | return @enumFromInt(gop.index); | 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,12 +8570,16 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr |
| 8557 | } | 8570 | } |
| 8558 | | 8571 | |
| 8559 | pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes { | 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 | fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last| | 8575 | fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last| |
| 8562 | last + 1 | 8576 | last + 1 |
| 8563 | else | 8577 | else |
| 8564 | 0], | 8578 | 0], |
| 8565 | ))); | 8579 | ))); |
| | 8580 | |
| | 8581 | _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes); |
| | 8582 | return function_attributes; |
| 8566 | } | 8583 | } |
| 8567 | | 8584 | |
| 8568 | pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index { | 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,7 +8603,6 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo |
| 8586 | global_gop.value_ptr.* = global; | 8603 | global_gop.value_ptr.* = global; |
| 8587 | const global_index: Global.Index = @enumFromInt(global_gop.index); | 8604 | const global_index: Global.Index = @enumFromInt(global_gop.index); |
| 8588 | global_index.updateDsoLocal(self); | 8605 | global_index.updateDsoLocal(self); |
| 8589 | global_index.updateName(self); | | |
| 8590 | return global_index; | 8606 | return global_index; |
| 8591 | } | 8607 | } |
| 8592 | | 8608 | |
| ... | @@ -8622,12 +8638,6 @@ pub fn addAliasAssumeCapacity( | ... | @@ -8622,12 +8638,6 @@ pub fn addAliasAssumeCapacity( |
| 8622 | addr_space: AddrSpace, | 8638 | addr_space: AddrSpace, |
| 8623 | aliasee: Constant, | 8639 | aliasee: Constant, |
| 8624 | ) Alias.Index { | 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 | const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len); | 8641 | const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len); |
| 8632 | self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ | 8642 | self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ |
| 8633 | .addr_space = addr_space, | 8643 | .addr_space = addr_space, |
| ... | @@ -8656,13 +8666,6 @@ pub fn addVariableAssumeCapacity( | ... | @@ -8656,13 +8666,6 @@ pub fn addVariableAssumeCapacity( |
| 8656 | name: String, | 8666 | name: String, |
| 8657 | addr_space: AddrSpace, | 8667 | addr_space: AddrSpace, |
| 8658 | ) Variable.Index { | 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 | const variable_index: Variable.Index = @enumFromInt(self.variables.items.len); | 8669 | const variable_index: Variable.Index = @enumFromInt(self.variables.items.len); |
| 8667 | self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ | 8670 | self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ |
| 8668 | .addr_space = addr_space, | 8671 | .addr_space = addr_space, |
| ... | @@ -8692,13 +8695,6 @@ pub fn addFunctionAssumeCapacity( | ... | @@ -8692,13 +8695,6 @@ pub fn addFunctionAssumeCapacity( |
| 8692 | addr_space: AddrSpace, | 8695 | addr_space: AddrSpace, |
| 8693 | ) Function.Index { | 8696 | ) Function.Index { |
| 8694 | assert(ty.isFunction(self)); | 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 | const function_index: Function.Index = @enumFromInt(self.functions.items.len); | 8698 | const function_index: Function.Index = @enumFromInt(self.functions.items.len); |
| 8703 | self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ | 8699 | self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ |
| 8704 | .addr_space = addr_space, | 8700 | .addr_space = addr_space, |
| ... | @@ -8714,7 +8710,6 @@ pub fn getIntrinsic( | ... | @@ -8714,7 +8710,6 @@ pub fn getIntrinsic( |
| 8714 | overload: []const Type, | 8710 | overload: []const Type, |
| 8715 | ) Allocator.Error!Function.Index { | 8711 | ) Allocator.Error!Function.Index { |
| 8716 | const ExpectedContents = extern union { | 8712 | const ExpectedContents = extern union { |
| 8717 | name: [expected_intrinsic_name_len]u8, | | |
| 8718 | attrs: extern struct { | 8713 | attrs: extern struct { |
| 8719 | params: [expected_args_len]Type, | 8714 | params: [expected_args_len]Type, |
| 8720 | fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes, | 8715 | fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes, |
| ... | @@ -8727,12 +8722,10 @@ pub fn getIntrinsic( | ... | @@ -8727,12 +8722,10 @@ pub fn getIntrinsic( |
| 8727 | const allocator = stack.get(); | 8722 | const allocator = stack.get(); |
| 8728 | | 8723 | |
| 8729 | const name = name: { | 8724 | const name = name: { |
| 8730 | var buffer = std.ArrayList(u8).init(allocator); | 8725 | const writer = self.string_bytes.writer(self.gpa); |
| 8731 | defer buffer.deinit(); | 8726 | try writer.print("llvm.{s}", .{@tagName(id)}); |
| 8732 | | 8727 | for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)}); |
| 8733 | try buffer.writer().print("llvm.{s}", .{@tagName(id)}); | 8728 | break :name try self.trailingString(); |
| 8734 | for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)}); | | |
| 8735 | break :name try self.string(buffer.items); | | |
| 8736 | }; | 8729 | }; |
| 8737 | if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; | 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,7 +8819,6 @@ pub fn bigIntConst(self: *Builder, ty: Type, value: std.math.big.int.Const) Allo |
| 8826 | try self.constant_map.ensureUnusedCapacity(self.gpa, 1); | 8819 | try self.constant_map.ensureUnusedCapacity(self.gpa, 1); |
| 8827 | try self.constant_items.ensureUnusedCapacity(self.gpa, 1); | 8820 | try self.constant_items.ensureUnusedCapacity(self.gpa, 1); |
| 8828 | try self.constant_limbs.ensureUnusedCapacity(self.gpa, Constant.Integer.limbs + value.limbs.len); | 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 | return self.bigIntConstAssumeCapacity(ty, value); | 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,16 +8969,6 @@ pub fn stringValue(self: *Builder, val: String) Allocator.Error!Value { |
| 8977 | return (try self.stringConst(val)).toValue(); | 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 | pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.Error!Constant { | 8972 | pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.Error!Constant { |
| 8991 | try self.ensureUnusedConstantCapacity(1, Constant.Aggregate, vals.len); | 8973 | try self.ensureUnusedConstantCapacity(1, Constant.Aggregate, vals.len); |
| 8992 | return self.vectorConstAssumeCapacity(ty, vals); | 8974 | return self.vectorConstAssumeCapacity(ty, vals); |
| ... | @@ -9244,72 +9226,20 @@ pub fn asmValue( | ... | @@ -9244,72 +9226,20 @@ pub fn asmValue( |
| 9244 | return (try self.asmConst(ty, info, assembly, constraints)).toValue(); | 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 | pub fn dump(self: *Builder) void { | 9229 | pub fn dump(self: *Builder) void { |
| 9282 | if (self.useLibLlvm()) | 9230 | self.print(std.io.getStdErr().writer()) catch {}; |
| 9283 | self.llvm.module.?.dump() | | |
| 9284 | else | | |
| 9285 | self.print(std.io.getStdErr().writer()) catch {}; | | |
| 9286 | } | 9231 | } |
| 9287 | | 9232 | |
| 9288 | pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool { | 9233 | pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool { |
| 9289 | const path_z = try self.gpa.dupeZ(u8, path); | 9234 | var file = std.fs.cwd().createFile(path, .{}) catch |err| { |
| 9290 | defer self.gpa.free(path_z); | 9235 | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); |
| 9291 | return self.printToFileZ(path_z); | 9236 | return false; |
| 9292 | } | 9237 | }; |
| 9293 | | 9238 | defer file.close(); |
| 9294 | pub fn printToFileZ(self: *Builder, path: [*:0]const u8) bool { | 9239 | self.print(file.writer()) catch |err| { |
| 9295 | if (self.useLibLlvm()) { | 9240 | log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) }); |
| 9296 | var error_message: [*:0]const u8 = undefined; | 9241 | return false; |
| 9297 | if (self.llvm.module.?.printModuleToFile(path, &error_message).toBool()) { | 9242 | }; |
| 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 | } | | |
| 9313 | return true; | 9243 | return true; |
| 9314 | } | 9244 | } |
| 9315 | | 9245 | |
| ... | @@ -9324,9 +9254,11 @@ pub fn printUnbuffered( | ... | @@ -9324,9 +9254,11 @@ pub fn printUnbuffered( |
| 9324 | writer: anytype, | 9254 | writer: anytype, |
| 9325 | ) (@TypeOf(writer).Error || Allocator.Error)!void { | 9255 | ) (@TypeOf(writer).Error || Allocator.Error)!void { |
| 9326 | var need_newline = false; | 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 | if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) { | 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 | if (self.source_filename != .none) try writer.print( | 9262 | if (self.source_filename != .none) try writer.print( |
| 9331 | \\; ModuleID = '{s}' | 9263 | \\; ModuleID = '{s}' |
| 9332 | \\source_filename = {"} | 9264 | \\source_filename = {"} |
| ... | @@ -9340,40 +9272,40 @@ pub fn printUnbuffered( | ... | @@ -9340,40 +9272,40 @@ pub fn printUnbuffered( |
| 9340 | \\target triple = {"} | 9272 | \\target triple = {"} |
| 9341 | \\ | 9273 | \\ |
| 9342 | , .{self.target_triple.fmt(self)}); | 9274 | , .{self.target_triple.fmt(self)}); |
| 9343 | need_newline = true; | | |
| 9344 | } | 9275 | } |
| 9345 | | 9276 | |
| 9346 | if (self.module_asm.items.len > 0) { | 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 | var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n'); | 9279 | var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n'); |
| 9349 | while (line_it.next()) |line| { | 9280 | while (line_it.next()) |line| { |
| 9350 | try writer.writeAll("module asm "); | 9281 | try writer.writeAll("module asm "); |
| 9351 | try printEscapedString(line, .always_quote, writer); | 9282 | try printEscapedString(line, .always_quote, writer); |
| 9352 | try writer.writeByte('\n'); | 9283 | try writer.writeByte('\n'); |
| 9353 | } | 9284 | } |
| 9354 | need_newline = true; | | |
| 9355 | } | 9285 | } |
| 9356 | | 9286 | |
| 9357 | if (self.types.count() > 0) { | 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 | for (self.types.keys(), self.types.values()) |id, ty| try writer.print( | 9289 | for (self.types.keys(), self.types.values()) |id, ty| try writer.print( |
| 9360 | \\%{} = type {} | 9290 | \\%{} = type {} |
| 9361 | \\ | 9291 | \\ |
| 9362 | , .{ id.fmt(self), ty.fmt(self) }); | 9292 | , .{ id.fmt(self), ty.fmt(self) }); |
| 9363 | need_newline = true; | | |
| 9364 | } | 9293 | } |
| 9365 | | 9294 | |
| 9366 | if (self.variables.items.len > 0) { | 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 | for (self.variables.items) |variable| { | 9297 | for (self.variables.items) |variable| { |
| 9369 | if (variable.global.getReplacement(self) != .none) continue; | 9298 | if (variable.global.getReplacement(self) != .none) continue; |
| 9370 | const global = variable.global.ptrConst(self); | 9299 | const global = variable.global.ptrConst(self); |
| | 9300 | metadata_formatter.need_comma = true; |
| | 9301 | defer metadata_formatter.need_comma = undefined; |
| 9371 | try writer.print( | 9302 | try writer.print( |
| 9372 | \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, } | 9303 | \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{} |
| 9373 | \\ | 9304 | \\ |
| 9374 | , .{ | 9305 | , .{ |
| 9375 | variable.global.fmt(self), | 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 | global.preemption, | 9309 | global.preemption, |
| 9378 | global.visibility, | 9310 | global.visibility, |
| 9379 | global.dll_storage_class, | 9311 | global.dll_storage_class, |
| ... | @@ -9385,18 +9317,20 @@ pub fn printUnbuffered( | ... | @@ -9385,18 +9317,20 @@ pub fn printUnbuffered( |
| 9385 | global.type.fmt(self), | 9317 | global.type.fmt(self), |
| 9386 | variable.init.fmt(self), | 9318 | variable.init.fmt(self), |
| 9387 | variable.alignment, | 9319 | variable.alignment, |
| | 9320 | try metadata_formatter.fmt("!dbg ", global.dbg), |
| 9388 | }); | 9321 | }); |
| 9389 | } | 9322 | } |
| 9390 | need_newline = true; | | |
| 9391 | } | 9323 | } |
| 9392 | | 9324 | |
| 9393 | if (self.aliases.items.len > 0) { | 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 | for (self.aliases.items) |alias| { | 9327 | for (self.aliases.items) |alias| { |
| 9396 | if (alias.global.getReplacement(self) != .none) continue; | 9328 | if (alias.global.getReplacement(self) != .none) continue; |
| 9397 | const global = alias.global.ptrConst(self); | 9329 | const global = alias.global.ptrConst(self); |
| | 9330 | metadata_formatter.need_comma = true; |
| | 9331 | defer metadata_formatter.need_comma = undefined; |
| 9398 | try writer.print( | 9332 | try writer.print( |
| 9399 | \\{} ={}{}{}{}{ }{} alias {%}, {%} | 9333 | \\{} ={}{}{}{}{ }{} alias {%}, {%}{} |
| 9400 | \\ | 9334 | \\ |
| 9401 | , .{ | 9335 | , .{ |
| 9402 | alias.global.fmt(self), | 9336 | alias.global.fmt(self), |
| ... | @@ -9408,9 +9342,9 @@ pub fn printUnbuffered( | ... | @@ -9408,9 +9342,9 @@ pub fn printUnbuffered( |
| 9408 | global.unnamed_addr, | 9342 | global.unnamed_addr, |
| 9409 | global.type.fmt(self), | 9343 | global.type.fmt(self), |
| 9410 | alias.aliasee.fmt(self), | 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 | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; | 9350 | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; |
| ... | @@ -9418,7 +9352,7 @@ pub fn printUnbuffered( | ... | @@ -9418,7 +9352,7 @@ pub fn printUnbuffered( |
| 9418 | | 9352 | |
| 9419 | for (0.., self.functions.items) |function_i, function| { | 9353 | for (0.., self.functions.items) |function_i, function| { |
| 9420 | if (function.global.getReplacement(self) != .none) continue; | 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 | const function_index: Function.Index = @enumFromInt(function_i); | 9356 | const function_index: Function.Index = @enumFromInt(function_i); |
| 9423 | const global = function.global.ptrConst(self); | 9357 | const global = function.global.ptrConst(self); |
| 9424 | const params_len = global.type.functionParameters(self).len; | 9358 | const params_len = global.type.functionParameters(self).len; |
| ... | @@ -9464,13 +9398,23 @@ pub fn printUnbuffered( | ... | @@ -9464,13 +9398,23 @@ pub fn printUnbuffered( |
| 9464 | if (function_attributes != .none) try writer.print(" #{d}", .{ | 9398 | if (function_attributes != .none) try writer.print(" #{d}", .{ |
| 9465 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, | 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 | if (function.instructions.len > 0) { | 9409 | if (function.instructions.len > 0) { |
| 9469 | var block_incoming_len: u32 = undefined; | 9410 | var block_incoming_len: u32 = undefined; |
| 9470 | try writer.writeAll(" {\n"); | 9411 | try writer.writeAll(" {\n"); |
| | 9412 | var dbg: Metadata = .none; |
| 9471 | for (params_len..function.instructions.len) |instruction_i| { | 9413 | for (params_len..function.instructions.len) |instruction_i| { |
| 9472 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); | 9414 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); |
| 9473 | const instruction = function.instructions.get(@intFromEnum(instruction_index)); | 9415 | const instruction = function.instructions.get(@intFromEnum(instruction_index)); |
| | 9416 | if (function.debug_locations.get(instruction_index)) |debug_location| |
| | 9417 | dbg = debug_location; |
| 9474 | switch (instruction.tag) { | 9418 | switch (instruction.tag) { |
| 9475 | .add, | 9419 | .add, |
| 9476 | .@"add nsw", | 9420 | .@"add nsw", |
| ... | @@ -9555,7 +9499,7 @@ pub fn printUnbuffered( | ... | @@ -9555,7 +9499,7 @@ pub fn printUnbuffered( |
| 9555 | .xor, | 9499 | .xor, |
| 9556 | => |tag| { | 9500 | => |tag| { |
| 9557 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); | 9501 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); |
| 9558 | try writer.print(" %{} = {s} {%}, {}\n", .{ | 9502 | try writer.print(" %{} = {s} {%}, {}", .{ |
| 9559 | instruction_index.name(&function).fmt(self), | 9503 | instruction_index.name(&function).fmt(self), |
| 9560 | @tagName(tag), | 9504 | @tagName(tag), |
| 9561 | extra.lhs.fmt(function_index, self), | 9505 | extra.lhs.fmt(function_index, self), |
| ... | @@ -9577,7 +9521,7 @@ pub fn printUnbuffered( | ... | @@ -9577,7 +9521,7 @@ pub fn printUnbuffered( |
| 9577 | .zext, | 9521 | .zext, |
| 9578 | => |tag| { | 9522 | => |tag| { |
| 9579 | const extra = function.extraData(Function.Instruction.Cast, instruction.data); | 9523 | const extra = function.extraData(Function.Instruction.Cast, instruction.data); |
| 9580 | try writer.print(" %{} = {s} {%} to {%}\n", .{ | 9524 | try writer.print(" %{} = {s} {%} to {%}", .{ |
| 9581 | instruction_index.name(&function).fmt(self), | 9525 | instruction_index.name(&function).fmt(self), |
| 9582 | @tagName(tag), | 9526 | @tagName(tag), |
| 9583 | extra.val.fmt(function_index, self), | 9527 | extra.val.fmt(function_index, self), |
| ... | @@ -9588,11 +9532,14 @@ pub fn printUnbuffered( | ... | @@ -9588,11 +9532,14 @@ pub fn printUnbuffered( |
| 9588 | .@"alloca inalloca", | 9532 | .@"alloca inalloca", |
| 9589 | => |tag| { | 9533 | => |tag| { |
| 9590 | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); | 9534 | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); |
| 9591 | try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{ | 9535 | try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{ |
| 9592 | instruction_index.name(&function).fmt(self), | 9536 | instruction_index.name(&function).fmt(self), |
| 9593 | @tagName(tag), | 9537 | @tagName(tag), |
| 9594 | extra.type.fmt(self), | 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 | extra.info.alignment, | 9543 | extra.info.alignment, |
| 9597 | extra.info.addr_space, | 9544 | extra.info.addr_space, |
| 9598 | }); | 9545 | }); |
| ... | @@ -9601,7 +9548,7 @@ pub fn printUnbuffered( | ... | @@ -9601,7 +9548,7 @@ pub fn printUnbuffered( |
| 9601 | .atomicrmw => |tag| { | 9548 | .atomicrmw => |tag| { |
| 9602 | const extra = | 9549 | const extra = |
| 9603 | function.extraData(Function.Instruction.AtomicRmw, instruction.data); | 9550 | function.extraData(Function.Instruction.AtomicRmw, instruction.data); |
| 9604 | try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{ | 9551 | try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{ |
| 9605 | instruction_index.name(&function).fmt(self), | 9552 | instruction_index.name(&function).fmt(self), |
| 9606 | @tagName(tag), | 9553 | @tagName(tag), |
| 9607 | extra.info.access_kind, | 9554 | extra.info.access_kind, |
| ... | @@ -9619,16 +9566,17 @@ pub fn printUnbuffered( | ... | @@ -9619,16 +9566,17 @@ pub fn printUnbuffered( |
| 9619 | if (@intFromEnum(instruction_index) > params_len) | 9566 | if (@intFromEnum(instruction_index) > params_len) |
| 9620 | try writer.writeByte('\n'); | 9567 | try writer.writeByte('\n'); |
| 9621 | try writer.print("{}:\n", .{name.fmt(self)}); | 9568 | try writer.print("{}:\n", .{name.fmt(self)}); |
| | 9569 | continue; |
| 9622 | }, | 9570 | }, |
| 9623 | .br => |tag| { | 9571 | .br => |tag| { |
| 9624 | const target: Function.Block.Index = @enumFromInt(instruction.data); | 9572 | const target: Function.Block.Index = @enumFromInt(instruction.data); |
| 9625 | try writer.print(" {s} {%}\n", .{ | 9573 | try writer.print(" {s} {%}", .{ |
| 9626 | @tagName(tag), target.toInst(&function).fmt(function_index, self), | 9574 | @tagName(tag), target.toInst(&function).fmt(function_index, self), |
| 9627 | }); | 9575 | }); |
| 9628 | }, | 9576 | }, |
| 9629 | .br_cond => { | 9577 | .br_cond => { |
| 9630 | const extra = function.extraData(Function.Instruction.BrCond, instruction.data); | 9578 | const extra = function.extraData(Function.Instruction.BrCond, instruction.data); |
| 9631 | try writer.print(" br {%}, {%}, {%}\n", .{ | 9579 | try writer.print(" br {%}, {%}, {%}", .{ |
| 9632 | extra.cond.fmt(function_index, self), | 9580 | extra.cond.fmt(function_index, self), |
| 9633 | extra.then.toInst(&function).fmt(function_index, self), | 9581 | extra.then.toInst(&function).fmt(function_index, self), |
| 9634 | extra.@"else".toInst(&function).fmt(function_index, self), | 9582 | extra.@"else".toInst(&function).fmt(function_index, self), |
| ... | @@ -9668,10 +9616,12 @@ pub fn printUnbuffered( | ... | @@ -9668,10 +9616,12 @@ pub fn printUnbuffered( |
| 9668 | }); | 9616 | }); |
| 9669 | for (0.., args) |arg_index, arg| { | 9617 | for (0.., args) |arg_index, arg| { |
| 9670 | if (arg_index > 0) try writer.writeAll(", "); | 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 | arg.typeOf(function_index, self).fmt(self), | 9622 | arg.typeOf(function_index, self).fmt(self), |
| 9673 | extra.data.attributes.param(arg_index, self).fmt(self), | 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 | try writer.writeByte(')'); | 9627 | try writer.writeByte(')'); |
| ... | @@ -9683,14 +9633,13 @@ pub fn printUnbuffered( | ... | @@ -9683,14 +9633,13 @@ pub fn printUnbuffered( |
| 9683 | {}, | 9633 | {}, |
| 9684 | )).index, | 9634 | )).index, |
| 9685 | }); | 9635 | }); |
| 9686 | try writer.writeByte('\n'); | | |
| 9687 | }, | 9636 | }, |
| 9688 | .cmpxchg, | 9637 | .cmpxchg, |
| 9689 | .@"cmpxchg weak", | 9638 | .@"cmpxchg weak", |
| 9690 | => |tag| { | 9639 | => |tag| { |
| 9691 | const extra = | 9640 | const extra = |
| 9692 | function.extraData(Function.Instruction.CmpXchg, instruction.data); | 9641 | function.extraData(Function.Instruction.CmpXchg, instruction.data); |
| 9693 | try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{ | 9642 | try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{ |
| 9694 | instruction_index.name(&function).fmt(self), | 9643 | instruction_index.name(&function).fmt(self), |
| 9695 | @tagName(tag), | 9644 | @tagName(tag), |
| 9696 | extra.info.access_kind, | 9645 | extra.info.access_kind, |
| ... | @@ -9706,7 +9655,7 @@ pub fn printUnbuffered( | ... | @@ -9706,7 +9655,7 @@ pub fn printUnbuffered( |
| 9706 | .extractelement => |tag| { | 9655 | .extractelement => |tag| { |
| 9707 | const extra = | 9656 | const extra = |
| 9708 | function.extraData(Function.Instruction.ExtractElement, instruction.data); | 9657 | function.extraData(Function.Instruction.ExtractElement, instruction.data); |
| 9709 | try writer.print(" %{} = {s} {%}, {%}\n", .{ | 9658 | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 9710 | instruction_index.name(&function).fmt(self), | 9659 | instruction_index.name(&function).fmt(self), |
| 9711 | @tagName(tag), | 9660 | @tagName(tag), |
| 9712 | extra.val.fmt(function_index, self), | 9661 | extra.val.fmt(function_index, self), |
| ... | @@ -9725,7 +9674,6 @@ pub fn printUnbuffered( | ... | @@ -9725,7 +9674,6 @@ pub fn printUnbuffered( |
| 9725 | extra.data.val.fmt(function_index, self), | 9674 | extra.data.val.fmt(function_index, self), |
| 9726 | }); | 9675 | }); |
| 9727 | for (indices) |index| try writer.print(", {d}", .{index}); | 9676 | for (indices) |index| try writer.print(", {d}", .{index}); |
| 9728 | try writer.writeByte('\n'); | | |
| 9729 | }, | 9677 | }, |
| 9730 | .fence => |tag| { | 9678 | .fence => |tag| { |
| 9731 | const info: MemoryAccessInfo = @bitCast(instruction.data); | 9679 | const info: MemoryAccessInfo = @bitCast(instruction.data); |
| ... | @@ -9739,7 +9687,7 @@ pub fn printUnbuffered( | ... | @@ -9739,7 +9687,7 @@ pub fn printUnbuffered( |
| 9739 | .@"fneg fast", | 9687 | .@"fneg fast", |
| 9740 | => |tag| { | 9688 | => |tag| { |
| 9741 | const val: Value = @enumFromInt(instruction.data); | 9689 | const val: Value = @enumFromInt(instruction.data); |
| 9742 | try writer.print(" %{} = {s} {%}\n", .{ | 9690 | try writer.print(" %{} = {s} {%}", .{ |
| 9743 | instruction_index.name(&function).fmt(self), | 9691 | instruction_index.name(&function).fmt(self), |
| 9744 | @tagName(tag), | 9692 | @tagName(tag), |
| 9745 | val.fmt(function_index, self), | 9693 | val.fmt(function_index, self), |
| ... | @@ -9762,12 +9710,11 @@ pub fn printUnbuffered( | ... | @@ -9762,12 +9710,11 @@ pub fn printUnbuffered( |
| 9762 | for (indices) |index| try writer.print(", {%}", .{ | 9710 | for (indices) |index| try writer.print(", {%}", .{ |
| 9763 | index.fmt(function_index, self), | 9711 | index.fmt(function_index, self), |
| 9764 | }); | 9712 | }); |
| 9765 | try writer.writeByte('\n'); | | |
| 9766 | }, | 9713 | }, |
| 9767 | .insertelement => |tag| { | 9714 | .insertelement => |tag| { |
| 9768 | const extra = | 9715 | const extra = |
| 9769 | function.extraData(Function.Instruction.InsertElement, instruction.data); | 9716 | function.extraData(Function.Instruction.InsertElement, instruction.data); |
| 9770 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | 9717 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ |
| 9771 | instruction_index.name(&function).fmt(self), | 9718 | instruction_index.name(&function).fmt(self), |
| 9772 | @tagName(tag), | 9719 | @tagName(tag), |
| 9773 | extra.val.fmt(function_index, self), | 9720 | extra.val.fmt(function_index, self), |
| ... | @@ -9786,13 +9733,12 @@ pub fn printUnbuffered( | ... | @@ -9786,13 +9733,12 @@ pub fn printUnbuffered( |
| 9786 | extra.data.elem.fmt(function_index, self), | 9733 | extra.data.elem.fmt(function_index, self), |
| 9787 | }); | 9734 | }); |
| 9788 | for (indices) |index| try writer.print(", {d}", .{index}); | 9735 | for (indices) |index| try writer.print(", {d}", .{index}); |
| 9789 | try writer.writeByte('\n'); | | |
| 9790 | }, | 9736 | }, |
| 9791 | .load, | 9737 | .load, |
| 9792 | .@"load atomic", | 9738 | .@"load atomic", |
| 9793 | => |tag| { | 9739 | => |tag| { |
| 9794 | const extra = function.extraData(Function.Instruction.Load, instruction.data); | 9740 | const extra = function.extraData(Function.Instruction.Load, instruction.data); |
| 9795 | try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{ | 9741 | try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{ |
| 9796 | instruction_index.name(&function).fmt(self), | 9742 | instruction_index.name(&function).fmt(self), |
| 9797 | @tagName(tag), | 9743 | @tagName(tag), |
| 9798 | extra.info.access_kind, | 9744 | extra.info.access_kind, |
| ... | @@ -9822,23 +9768,22 @@ pub fn printUnbuffered( | ... | @@ -9822,23 +9768,22 @@ pub fn printUnbuffered( |
| 9822 | incoming_block.toInst(&function).fmt(function_index, self), | 9768 | incoming_block.toInst(&function).fmt(function_index, self), |
| 9823 | }); | 9769 | }); |
| 9824 | } | 9770 | } |
| 9825 | try writer.writeByte('\n'); | | |
| 9826 | }, | 9771 | }, |
| 9827 | .ret => |tag| { | 9772 | .ret => |tag| { |
| 9828 | const val: Value = @enumFromInt(instruction.data); | 9773 | const val: Value = @enumFromInt(instruction.data); |
| 9829 | try writer.print(" {s} {%}\n", .{ | 9774 | try writer.print(" {s} {%}", .{ |
| 9830 | @tagName(tag), | 9775 | @tagName(tag), |
| 9831 | val.fmt(function_index, self), | 9776 | val.fmt(function_index, self), |
| 9832 | }); | 9777 | }); |
| 9833 | }, | 9778 | }, |
| 9834 | .@"ret void", | 9779 | .@"ret void", |
| 9835 | .@"unreachable", | 9780 | .@"unreachable", |
| 9836 | => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), | 9781 | => |tag| try writer.print(" {s}", .{@tagName(tag)}), |
| 9837 | .select, | 9782 | .select, |
| 9838 | .@"select fast", | 9783 | .@"select fast", |
| 9839 | => |tag| { | 9784 | => |tag| { |
| 9840 | const extra = function.extraData(Function.Instruction.Select, instruction.data); | 9785 | const extra = function.extraData(Function.Instruction.Select, instruction.data); |
| 9841 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | 9786 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ |
| 9842 | instruction_index.name(&function).fmt(self), | 9787 | instruction_index.name(&function).fmt(self), |
| 9843 | @tagName(tag), | 9788 | @tagName(tag), |
| 9844 | extra.cond.fmt(function_index, self), | 9789 | extra.cond.fmt(function_index, self), |
| ... | @@ -9849,7 +9794,7 @@ pub fn printUnbuffered( | ... | @@ -9849,7 +9794,7 @@ pub fn printUnbuffered( |
| 9849 | .shufflevector => |tag| { | 9794 | .shufflevector => |tag| { |
| 9850 | const extra = | 9795 | const extra = |
| 9851 | function.extraData(Function.Instruction.ShuffleVector, instruction.data); | 9796 | function.extraData(Function.Instruction.ShuffleVector, instruction.data); |
| 9852 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | 9797 | try writer.print(" %{} = {s} {%}, {%}, {%}", .{ |
| 9853 | instruction_index.name(&function).fmt(self), | 9798 | instruction_index.name(&function).fmt(self), |
| 9854 | @tagName(tag), | 9799 | @tagName(tag), |
| 9855 | extra.lhs.fmt(function_index, self), | 9800 | extra.lhs.fmt(function_index, self), |
| ... | @@ -9861,7 +9806,7 @@ pub fn printUnbuffered( | ... | @@ -9861,7 +9806,7 @@ pub fn printUnbuffered( |
| 9861 | .@"store atomic", | 9806 | .@"store atomic", |
| 9862 | => |tag| { | 9807 | => |tag| { |
| 9863 | const extra = function.extraData(Function.Instruction.Store, instruction.data); | 9808 | const extra = function.extraData(Function.Instruction.Store, instruction.data); |
| 9864 | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{ | 9809 | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{ |
| 9865 | @tagName(tag), | 9810 | @tagName(tag), |
| 9866 | extra.info.access_kind, | 9811 | extra.info.access_kind, |
| 9867 | extra.val.fmt(function_index, self), | 9812 | extra.val.fmt(function_index, self), |
| ... | @@ -9889,11 +9834,11 @@ pub fn printUnbuffered( | ... | @@ -9889,11 +9834,11 @@ pub fn printUnbuffered( |
| 9889 | case_block.toInst(&function).fmt(function_index, self), | 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 | .va_arg => |tag| { | 9839 | .va_arg => |tag| { |
| 9895 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); | 9840 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); |
| 9896 | try writer.print(" %{} = {s} {%}, {%}\n", .{ | 9841 | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 9897 | instruction_index.name(&function).fmt(self), | 9842 | instruction_index.name(&function).fmt(self), |
| 9898 | @tagName(tag), | 9843 | @tagName(tag), |
| 9899 | extra.list.fmt(function_index, self), | 9844 | extra.list.fmt(function_index, self), |
| ... | @@ -9901,11 +9846,13 @@ pub fn printUnbuffered( | ... | @@ -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 | try writer.writeByte('}'); | 9853 | try writer.writeByte('}'); |
| 9906 | } | 9854 | } |
| 9907 | try writer.writeByte('\n'); | 9855 | try writer.writeByte('\n'); |
| 9908 | need_newline = true; | | |
| 9909 | } | 9856 | } |
| 9910 | | 9857 | |
| 9911 | if (attribute_groups.count() > 0) { | 9858 | if (attribute_groups.count() > 0) { |
| ... | @@ -9915,12 +9862,375 @@ pub fn printUnbuffered( | ... | @@ -9915,12 +9862,375 @@ pub fn printUnbuffered( |
| 9915 | \\attributes #{d} = {{{#"} }} | 9862 | \\attributes #{d} = {{{#"} }} |
| 9916 | \\ | 9863 | \\ |
| 9917 | , .{ attribute_group_index, attribute_group.fmt(self) }); | 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 { | 9867 | if (self.metadata_named.count() > 0) { |
| 9923 | return build_options.have_llvm and self.use_lib_llvm; | 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 | const NoExtra = struct {}; | 10236 | const NoExtra = struct {}; |
| ... | @@ -9954,10 +10264,9 @@ fn printEscapedString( | ... | @@ -9954,10 +10264,9 @@ fn printEscapedString( |
| 9954 | } | 10264 | } |
| 9955 | | 10265 | |
| 9956 | fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void { | 10266 | fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void { |
| 9957 | if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1); | | |
| 9958 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); | 10267 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 9959 | if (name.slice(self)) |id| { | 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 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); | 10270 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); |
| 9962 | } | 10271 | } |
| 9963 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); | 10272 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | @@ -9970,7 +10279,7 @@ fn fnTypeAssumeCapacity( | ... | @@ -9970,7 +10279,7 @@ fn fnTypeAssumeCapacity( |
| 9970 | ret: Type, | 10279 | ret: Type, |
| 9971 | params: []const Type, | 10280 | params: []const Type, |
| 9972 | comptime kind: Type.Function.Kind, | 10281 | comptime kind: Type.Function.Kind, |
| 9973 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Type { | 10282 | ) Type { |
| 9974 | const tag: Type.Tag = switch (kind) { | 10283 | const tag: Type.Tag = switch (kind) { |
| 9975 | .normal => .function, | 10284 | .normal => .function, |
| 9976 | .vararg => .vararg_function, | 10285 | .vararg => .vararg_function, |
| ... | @@ -10007,20 +10316,6 @@ fn fnTypeAssumeCapacity( | ... | @@ -10007,20 +10316,6 @@ fn fnTypeAssumeCapacity( |
| 10007 | }), | 10316 | }), |
| 10008 | }); | 10317 | }); |
| 10009 | self.type_extra.appendSliceAssumeCapacity(@ptrCast(params)); | 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 | return @enumFromInt(gop.index); | 10320 | return @enumFromInt(gop.index); |
| 10026 | } | 10321 | } |
| ... | @@ -10028,8 +10323,6 @@ fn fnTypeAssumeCapacity( | ... | @@ -10028,8 +10323,6 @@ fn fnTypeAssumeCapacity( |
| 10028 | fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type { | 10323 | fn intTypeAssumeCapacity(self: *Builder, bits: u24) Type { |
| 10029 | assert(bits > 0); | 10324 | assert(bits > 0); |
| 10030 | const result = self.getOrPutTypeNoExtraAssumeCapacity(.{ .tag = .integer, .data = bits }); | 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 | return result.type; | 10326 | return result.type; |
| 10034 | } | 10327 | } |
| 10035 | | 10328 | |
| ... | @@ -10037,8 +10330,6 @@ fn ptrTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type { | ... | @@ -10037,8 +10330,6 @@ fn ptrTypeAssumeCapacity(self: *Builder, addr_space: AddrSpace) Type { |
| 10037 | const result = self.getOrPutTypeNoExtraAssumeCapacity( | 10330 | const result = self.getOrPutTypeNoExtraAssumeCapacity( |
| 10038 | .{ .tag = .pointer, .data = @intFromEnum(addr_space) }, | 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 | return result.type; | 10333 | return result.type; |
| 10043 | } | 10334 | } |
| 10044 | | 10335 | |
| ... | @@ -10076,10 +10367,6 @@ fn vectorTypeAssumeCapacity( | ... | @@ -10076,10 +10367,6 @@ fn vectorTypeAssumeCapacity( |
| 10076 | .tag = tag, | 10367 | .tag = tag, |
| 10077 | .data = self.addTypeExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 10371 | return @enumFromInt(gop.index); |
| 10085 | } | 10372 | } |
| ... | @@ -10109,9 +10396,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type { | ... | @@ -10109,9 +10396,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type { |
| 10109 | .tag = .small_array, | 10396 | .tag = .small_array, |
| 10110 | .data = self.addTypeExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 10400 | return @enumFromInt(gop.index); |
| 10117 | } else { | 10401 | } else { |
| ... | @@ -10142,9 +10426,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type { | ... | @@ -10142,9 +10426,6 @@ fn arrayTypeAssumeCapacity(self: *Builder, len: u64, child: Type) Type { |
| 10142 | .tag = .array, | 10426 | .tag = .array, |
| 10143 | .data = self.addTypeExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 10430 | return @enumFromInt(gop.index); |
| 10150 | } | 10431 | } |
| ... | @@ -10154,7 +10435,7 @@ fn structTypeAssumeCapacity( | ... | @@ -10154,7 +10435,7 @@ fn structTypeAssumeCapacity( |
| 10154 | self: *Builder, | 10435 | self: *Builder, |
| 10155 | comptime kind: Type.Structure.Kind, | 10436 | comptime kind: Type.Structure.Kind, |
| 10156 | fields: []const Type, | 10437 | fields: []const Type, |
| 10157 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Type { | 10438 | ) Type { |
| 10158 | const tag: Type.Tag = switch (kind) { | 10439 | const tag: Type.Tag = switch (kind) { |
| 10159 | .normal => .structure, | 10440 | .normal => .structure, |
| 10160 | .@"packed" => .packed_structure, | 10441 | .@"packed" => .packed_structure, |
| ... | @@ -10186,25 +10467,6 @@ fn structTypeAssumeCapacity( | ... | @@ -10186,25 +10467,6 @@ fn structTypeAssumeCapacity( |
| 10186 | }), | 10467 | }), |
| 10187 | }); | 10468 | }); |
| 10188 | self.type_extra.appendSliceAssumeCapacity(@ptrCast(fields)); | 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 | return @enumFromInt(gop.index); | 10471 | return @enumFromInt(gop.index); |
| 10210 | } | 10472 | } |
| ... | @@ -10246,9 +10508,6 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type { | ... | @@ -10246,9 +10508,6 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type { |
| 10246 | }); | 10508 | }); |
| 10247 | const result: Type = @enumFromInt(gop.index); | 10509 | const result: Type = @enumFromInt(gop.index); |
| 10248 | type_gop.value_ptr.* = result; | 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 | return result; | 10511 | return result; |
| 10253 | } | 10512 | } |
| 10254 | | 10513 | |
| ... | @@ -10271,7 +10530,6 @@ fn ensureUnusedTypeCapacity( | ... | @@ -10271,7 +10530,6 @@ fn ensureUnusedTypeCapacity( |
| 10271 | self.gpa, | 10530 | self.gpa, |
| 10272 | count * (@typeInfo(Extra).Struct.fields.len + trail_len), | 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 | fn getOrPutTypeNoExtraAssumeCapacity(self: *Builder, item: Type.Item) struct { new: bool, type: Type } { | 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,7 +10563,7 @@ fn addTypeExtraAssumeCapacity(self: *Builder, extra: anytype) Type.Item.ExtraInd |
| 10305 | self.type_extra.appendAssumeCapacity(switch (field.type) { | 10563 | self.type_extra.appendAssumeCapacity(switch (field.type) { |
| 10306 | u32 => value, | 10564 | u32 => value, |
| 10307 | String, Type => @intFromEnum(value), | 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 | return result; | 10569 | return result; |
| ... | @@ -10388,10 +10646,7 @@ fn bigIntConstAssumeCapacity( | ... | @@ -10388,10 +10646,7 @@ fn bigIntConstAssumeCapacity( |
| 10388 | assert(type_item.tag == .integer); | 10646 | assert(type_item.tag == .integer); |
| 10389 | const bits = type_item.data; | 10647 | const bits = type_item.data; |
| 10390 | | 10648 | |
| 10391 | const ExpectedContents = extern struct { | 10649 | const ExpectedContents = [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb; |
| 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 | }; | | |
| 10395 | var stack align(@alignOf(ExpectedContents)) = | 10650 | var stack align(@alignOf(ExpectedContents)) = |
| 10396 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); | 10651 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| 10397 | const allocator = stack.get(); | 10652 | const allocator = stack.get(); |
| ... | @@ -10448,44 +10703,6 @@ fn bigIntConstAssumeCapacity( | ... | @@ -10448,44 +10703,6 @@ fn bigIntConstAssumeCapacity( |
| 10448 | @ptrCast(self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs)); | 10703 | @ptrCast(self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs)); |
| 10449 | extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) }; | 10704 | extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) }; |
| 10450 | self.constant_limbs.appendSliceAssumeCapacity(canonical_value.limbs); | 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 | return @enumFromInt(gop.index); | 10707 | return @enumFromInt(gop.index); |
| 10491 | } | 10708 | } |
| ... | @@ -10494,13 +10711,6 @@ fn halfConstAssumeCapacity(self: *Builder, val: f16) Constant { | ... | @@ -10494,13 +10711,6 @@ fn halfConstAssumeCapacity(self: *Builder, val: f16) Constant { |
| 10494 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 10711 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10495 | .{ .tag = .half, .data = @as(u16, @bitCast(val)) }, | 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 | return result.constant; | 10714 | return result.constant; |
| 10505 | } | 10715 | } |
| 10506 | | 10716 | |
| ... | @@ -10509,16 +10719,6 @@ fn bfloatConstAssumeCapacity(self: *Builder, val: f32) Constant { | ... | @@ -10509,16 +10719,6 @@ fn bfloatConstAssumeCapacity(self: *Builder, val: f32) Constant { |
| 10509 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 10719 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10510 | .{ .tag = .bfloat, .data = @bitCast(val) }, | 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 | return result.constant; | 10722 | return result.constant; |
| 10523 | } | 10723 | } |
| 10524 | | 10724 | |
| ... | @@ -10526,13 +10726,6 @@ fn floatConstAssumeCapacity(self: *Builder, val: f32) Constant { | ... | @@ -10526,13 +10726,6 @@ fn floatConstAssumeCapacity(self: *Builder, val: f32) Constant { |
| 10526 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 10726 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10527 | .{ .tag = .float, .data = @bitCast(val) }, | 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 | return result.constant; | 10729 | return result.constant; |
| 10537 | } | 10730 | } |
| 10538 | | 10731 | |
| ... | @@ -10563,13 +10756,6 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant { | ... | @@ -10563,13 +10756,6 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant { |
| 10563 | .hi = @intCast(@as(u64, @bitCast(val)) >> 32), | 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 | return @enumFromInt(gop.index); | 10760 | return @enumFromInt(gop.index); |
| 10575 | } | 10761 | } |
| ... | @@ -10604,17 +10790,6 @@ fn fp128ConstAssumeCapacity(self: *Builder, val: f128) Constant { | ... | @@ -10604,17 +10790,6 @@ fn fp128ConstAssumeCapacity(self: *Builder, val: f128) Constant { |
| 10604 | .hi_hi = @intCast(@as(u128, @bitCast(val)) >> 96), | 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 | return @enumFromInt(gop.index); | 10794 | return @enumFromInt(gop.index); |
| 10620 | } | 10795 | } |
| ... | @@ -10648,17 +10823,6 @@ fn x86_fp80ConstAssumeCapacity(self: *Builder, val: f80) Constant { | ... | @@ -10648,17 +10823,6 @@ fn x86_fp80ConstAssumeCapacity(self: *Builder, val: f80) Constant { |
| 10648 | .hi = @intCast(@as(u80, @bitCast(val)) >> 64), | 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 | return @enumFromInt(gop.index); | 10827 | return @enumFromInt(gop.index); |
| 10664 | } | 10828 | } |
| ... | @@ -10693,14 +10857,6 @@ fn ppc_fp128ConstAssumeCapacity(self: *Builder, val: [2]f64) Constant { | ... | @@ -10693,14 +10857,6 @@ fn ppc_fp128ConstAssumeCapacity(self: *Builder, val: [2]f64) Constant { |
| 10693 | .hi_hi = @intCast(@as(u64, @bitCast(val[1])) >> 32), | 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 | return @enumFromInt(gop.index); | 10861 | return @enumFromInt(gop.index); |
| 10706 | } | 10862 | } |
| ... | @@ -10710,8 +10866,6 @@ fn nullConstAssumeCapacity(self: *Builder, ty: Type) Constant { | ... | @@ -10710,8 +10866,6 @@ fn nullConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10710 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 10866 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10711 | .{ .tag = .null, .data = @intFromEnum(ty) }, | 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 | return result.constant; | 10869 | return result.constant; |
| 10716 | } | 10870 | } |
| 10717 | | 10871 | |
| ... | @@ -10720,16 +10874,10 @@ fn noneConstAssumeCapacity(self: *Builder, ty: Type) Constant { | ... | @@ -10720,16 +10874,10 @@ fn noneConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10720 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 10874 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10721 | .{ .tag = .none, .data = @intFromEnum(ty) }, | 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 | return result.constant; | 10877 | return result.constant; |
| 10726 | } | 10878 | } |
| 10727 | | 10879 | |
| 10728 | fn structConstAssumeCapacity( | 10880 | fn structConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant { |
| 10729 | self: *Builder, | | |
| 10730 | ty: Type, | | |
| 10731 | vals: []const Constant, | | |
| 10732 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { | | |
| 10733 | const type_item = self.type_items.items[@intFromEnum(ty)]; | 10881 | const type_item = self.type_items.items[@intFromEnum(ty)]; |
| 10734 | var extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) { | 10882 | var extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) { |
| 10735 | .structure, .packed_structure => type_item.data, | 10883 | .structure, .packed_structure => type_item.data, |
| ... | @@ -10756,28 +10904,10 @@ fn structConstAssumeCapacity( | ... | @@ -10756,28 +10904,10 @@ fn structConstAssumeCapacity( |
| 10756 | else => unreachable, | 10904 | else => unreachable, |
| 10757 | }; | 10905 | }; |
| 10758 | const result = self.getOrPutConstantAggregateAssumeCapacity(tag, ty, vals); | 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 | return result.constant; | 10907 | return result.constant; |
| 10774 | } | 10908 | } |
| 10775 | | 10909 | |
| 10776 | fn arrayConstAssumeCapacity( | 10910 | fn arrayConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant { |
| 10777 | self: *Builder, | | |
| 10778 | ty: Type, | | |
| 10779 | vals: []const Constant, | | |
| 10780 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { | | |
| 10781 | const type_item = self.type_items.items[@intFromEnum(ty)]; | 10911 | const type_item = self.type_items.items[@intFromEnum(ty)]; |
| 10782 | const type_extra: struct { len: u64, child: Type } = switch (type_item.tag) { | 10912 | const type_extra: struct { len: u64, child: Type } = switch (type_item.tag) { |
| 10783 | inline .small_array, .array => |kind| extra: { | 10913 | inline .small_array, .array => |kind| extra: { |
| ... | @@ -10798,20 +10928,6 @@ fn arrayConstAssumeCapacity( | ... | @@ -10798,20 +10928,6 @@ fn arrayConstAssumeCapacity( |
| 10798 | } else return self.zeroInitConstAssumeCapacity(ty); | 10928 | } else return self.zeroInitConstAssumeCapacity(ty); |
| 10799 | | 10929 | |
| 10800 | const result = self.getOrPutConstantAggregateAssumeCapacity(.array, ty, vals); | 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 | return result.constant; | 10931 | return result.constant; |
| 10816 | } | 10932 | } |
| 10817 | | 10933 | |
| ... | @@ -10822,30 +10938,10 @@ fn stringConstAssumeCapacity(self: *Builder, val: String) Constant { | ... | @@ -10822,30 +10938,10 @@ fn stringConstAssumeCapacity(self: *Builder, val: String) Constant { |
| 10822 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 10938 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10823 | .{ .tag = .string, .data = @intFromEnum(val) }, | 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 | return result.constant; | 10941 | return result.constant; |
| 10842 | } | 10942 | } |
| 10843 | | 10943 | |
| 10844 | fn vectorConstAssumeCapacity( | 10944 | fn vectorConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant { |
| 10845 | self: *Builder, | | |
| 10846 | ty: Type, | | |
| 10847 | vals: []const Constant, | | |
| 10848 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { | | |
| 10849 | assert(ty.isVector(self)); | 10945 | assert(ty.isVector(self)); |
| 10850 | assert(ty.vectorLen(self) == vals.len); | 10946 | assert(ty.vectorLen(self) == vals.len); |
| 10851 | for (vals) |val| assert(ty.childType(self) == val.typeOf(self)); | 10947 | for (vals) |val| assert(ty.childType(self) == val.typeOf(self)); |
| ... | @@ -10858,28 +10954,10 @@ fn vectorConstAssumeCapacity( | ... | @@ -10858,28 +10954,10 @@ fn vectorConstAssumeCapacity( |
| 10858 | } else return self.zeroInitConstAssumeCapacity(ty); | 10954 | } else return self.zeroInitConstAssumeCapacity(ty); |
| 10859 | | 10955 | |
| 10860 | const result = self.getOrPutConstantAggregateAssumeCapacity(.vector, ty, vals); | 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 | return result.constant; | 10957 | return result.constant; |
| 10876 | } | 10958 | } |
| 10877 | | 10959 | |
| 10878 | fn splatConstAssumeCapacity( | 10960 | fn splatConstAssumeCapacity(self: *Builder, ty: Type, val: Constant) Constant { |
| 10879 | self: *Builder, | | |
| 10880 | ty: Type, | | |
| 10881 | val: Constant, | | |
| 10882 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { | | |
| 10883 | assert(ty.scalarType(self) == val.typeOf(self)); | 10961 | assert(ty.scalarType(self) == val.typeOf(self)); |
| 10884 | | 10962 | |
| 10885 | if (!ty.isVector(self)) return val; | 10963 | if (!ty.isVector(self)) return val; |
| ... | @@ -10909,20 +10987,6 @@ fn splatConstAssumeCapacity( | ... | @@ -10909,20 +10987,6 @@ fn splatConstAssumeCapacity( |
| 10909 | .tag = .splat, | 10987 | .tag = .splat, |
| 10910 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 10991 | return @enumFromInt(gop.index); |
| 10928 | } | 10992 | } |
| ... | @@ -10964,8 +11028,6 @@ fn zeroInitConstAssumeCapacity(self: *Builder, ty: Type) Constant { | ... | @@ -10964,8 +11028,6 @@ fn zeroInitConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10964 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 11028 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10965 | .{ .tag = .zeroinitializer, .data = @intFromEnum(ty) }, | 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 | return result.constant; | 11031 | return result.constant; |
| 10970 | } | 11032 | } |
| 10971 | | 11033 | |
| ... | @@ -10981,8 +11043,6 @@ fn undefConstAssumeCapacity(self: *Builder, ty: Type) Constant { | ... | @@ -10981,8 +11043,6 @@ fn undefConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10981 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 11043 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10982 | .{ .tag = .undef, .data = @intFromEnum(ty) }, | 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 | return result.constant; | 11046 | return result.constant; |
| 10987 | } | 11047 | } |
| 10988 | | 11048 | |
| ... | @@ -10998,8 +11058,6 @@ fn poisonConstAssumeCapacity(self: *Builder, ty: Type) Constant { | ... | @@ -10998,8 +11058,6 @@ fn poisonConstAssumeCapacity(self: *Builder, ty: Type) Constant { |
| 10998 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 11058 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 10999 | .{ .tag = .poison, .data = @intFromEnum(ty) }, | 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 | return result.constant; | 11061 | return result.constant; |
| 11004 | } | 11062 | } |
| 11005 | | 11063 | |
| ... | @@ -11032,9 +11090,6 @@ fn blockAddrConstAssumeCapacity( | ... | @@ -11032,9 +11090,6 @@ fn blockAddrConstAssumeCapacity( |
| 11032 | .tag = .blockaddress, | 11090 | .tag = .blockaddress, |
| 11033 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 11094 | return @enumFromInt(gop.index); |
| 11040 | } | 11095 | } |
| ... | @@ -11043,7 +11098,6 @@ fn dsoLocalEquivalentConstAssumeCapacity(self: *Builder, function: Function.Inde | ... | @@ -11043,7 +11098,6 @@ fn dsoLocalEquivalentConstAssumeCapacity(self: *Builder, function: Function.Inde |
| 11043 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 11098 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 11044 | .{ .tag = .dso_local_equivalent, .data = @intFromEnum(function) }, | 11099 | .{ .tag = .dso_local_equivalent, .data = @intFromEnum(function) }, |
| 11045 | ); | 11100 | ); |
| 11046 | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(undefined); | | |
| 11047 | return result.constant; | 11101 | return result.constant; |
| 11048 | } | 11102 | } |
| 11049 | | 11103 | |
| ... | @@ -11051,7 +11105,6 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant { | ... | @@ -11051,7 +11105,6 @@ fn noCfiConstAssumeCapacity(self: *Builder, function: Function.Index) Constant { |
| 11051 | const result = self.getOrPutConstantNoExtraAssumeCapacity( | 11105 | const result = self.getOrPutConstantNoExtraAssumeCapacity( |
| 11052 | .{ .tag = .no_cfi, .data = @intFromEnum(function) }, | 11106 | .{ .tag = .no_cfi, .data = @intFromEnum(function) }, |
| 11053 | ); | 11107 | ); |
| 11054 | if (self.useLibLlvm() and result.new) self.llvm.constants.appendAssumeCapacity(undefined); | | |
| 11055 | return result.constant; | 11108 | return result.constant; |
| 11056 | } | 11109 | } |
| 11057 | | 11110 | |
| ... | @@ -11141,22 +11194,6 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: | ... | @@ -11141,22 +11194,6 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: |
| 11141 | .tag = tag, | 11194 | .tag = tag, |
| 11142 | .data = self.addConstantExtraAssumeCapacity(data.cast), | 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 | return @enumFromInt(gop.index); | 11198 | return @enumFromInt(gop.index); |
| 11162 | } | 11199 | } |
| ... | @@ -11168,7 +11205,7 @@ fn gepConstAssumeCapacity( | ... | @@ -11168,7 +11205,7 @@ fn gepConstAssumeCapacity( |
| 11168 | base: Constant, | 11205 | base: Constant, |
| 11169 | inrange: ?u16, | 11206 | inrange: ?u16, |
| 11170 | indices: []const Constant, | 11207 | indices: []const Constant, |
| 11171 | ) (if (build_options.have_llvm) Allocator.Error else error{})!Constant { | 11208 | ) Constant { |
| 11172 | const tag: Constant.Tag = switch (kind) { | 11209 | const tag: Constant.Tag = switch (kind) { |
| 11173 | .normal => .getelementptr, | 11210 | .normal => .getelementptr, |
| 11174 | .inbounds => .@"getelementptr inbounds", | 11211 | .inbounds => .@"getelementptr inbounds", |
| ... | @@ -11249,21 +11286,6 @@ fn gepConstAssumeCapacity( | ... | @@ -11249,21 +11286,6 @@ fn gepConstAssumeCapacity( |
| 11249 | }), | 11286 | }), |
| 11250 | }); | 11287 | }); |
| 11251 | self.constant_extra.appendSliceAssumeCapacity(@ptrCast(indices)); | 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 | return @enumFromInt(gop.index); | 11290 | return @enumFromInt(gop.index); |
| 11269 | } | 11291 | } |
| ... | @@ -11298,9 +11320,6 @@ fn icmpConstAssumeCapacity( | ... | @@ -11298,9 +11320,6 @@ fn icmpConstAssumeCapacity( |
| 11298 | .tag = .icmp, | 11320 | .tag = .icmp, |
| 11299 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 11324 | return @enumFromInt(gop.index); |
| 11306 | } | 11325 | } |
| ... | @@ -11335,9 +11354,6 @@ fn fcmpConstAssumeCapacity( | ... | @@ -11335,9 +11354,6 @@ fn fcmpConstAssumeCapacity( |
| 11335 | .tag = .fcmp, | 11354 | .tag = .fcmp, |
| 11336 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 11358 | return @enumFromInt(gop.index); |
| 11343 | } | 11359 | } |
| ... | @@ -11371,9 +11387,6 @@ fn extractElementConstAssumeCapacity( | ... | @@ -11371,9 +11387,6 @@ fn extractElementConstAssumeCapacity( |
| 11371 | .tag = .extractelement, | 11387 | .tag = .extractelement, |
| 11372 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 11391 | return @enumFromInt(gop.index); |
| 11379 | } | 11392 | } |
| ... | @@ -11408,9 +11421,6 @@ fn insertElementConstAssumeCapacity( | ... | @@ -11408,9 +11421,6 @@ fn insertElementConstAssumeCapacity( |
| 11408 | .tag = .insertelement, | 11421 | .tag = .insertelement, |
| 11409 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 11425 | return @enumFromInt(gop.index); |
| 11416 | } | 11426 | } |
| ... | @@ -11449,9 +11459,6 @@ fn shuffleVectorConstAssumeCapacity( | ... | @@ -11449,9 +11459,6 @@ fn shuffleVectorConstAssumeCapacity( |
| 11449 | .tag = .shufflevector, | 11459 | .tag = .shufflevector, |
| 11450 | .data = self.addConstantExtraAssumeCapacity(data), | 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 | return @enumFromInt(gop.index); | 11463 | return @enumFromInt(gop.index); |
| 11457 | } | 11464 | } |
| ... | @@ -11506,18 +11513,6 @@ fn binConstAssumeCapacity( | ... | @@ -11506,18 +11513,6 @@ fn binConstAssumeCapacity( |
| 11506 | .tag = tag, | 11513 | .tag = tag, |
| 11507 | .data = self.addConstantExtraAssumeCapacity(data.extra), | 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 | return @enumFromInt(gop.index); | 11517 | return @enumFromInt(gop.index); |
| 11523 | } | 11518 | } |
| ... | @@ -11560,21 +11555,6 @@ fn asmConstAssumeCapacity( | ... | @@ -11560,21 +11555,6 @@ fn asmConstAssumeCapacity( |
| 11560 | .tag = data.tag, | 11555 | .tag = data.tag, |
| 11561 | .data = self.addConstantExtraAssumeCapacity(data.extra), | 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 | return @enumFromInt(gop.index); | 11559 | return @enumFromInt(gop.index); |
| 11580 | } | 11560 | } |
| ... | @@ -11591,7 +11571,6 @@ fn ensureUnusedConstantCapacity( | ... | @@ -11591,7 +11571,6 @@ fn ensureUnusedConstantCapacity( |
| 11591 | self.gpa, | 11571 | self.gpa, |
| 11592 | count * (@typeInfo(Extra).Struct.fields.len + trail_len), | 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 | fn getOrPutConstantNoExtraAssumeCapacity( | 11576 | fn getOrPutConstantNoExtraAssumeCapacity( |
| ... | @@ -11722,15 +11701,3260 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite | ... | @@ -11722,15 +11701,3260 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite |
| 11722 | return self.constantExtraDataTrail(T, index).data; | 11701 | return self.constantExtraDataTrail(T, index).data; |
| 11723 | } | 11702 | } |
| 11724 | | 11703 | |
| 11725 | const assert = std.debug.assert; | 11704 | fn ensureUnusedMetadataCapacity( |
| 11726 | const build_options = @import("build_options"); | 11705 | self: *Builder, |
| 11727 | const builtin = @import("builtin"); | 11706 | count: usize, |
| 11728 | const llvm = if (build_options.have_llvm) | 11707 | comptime Extra: type, |
| 11729 | @import("bindings.zig") | 11708 | trail_len: usize, |
| 11730 | else | 11709 | ) Allocator.Error!void { |
| 11731 | @compileError("LLVM unavailable"); | 11710 | try self.metadata_map.ensureUnusedCapacity(self.gpa, count); |
| 11732 | const log = std.log.scoped(.llvm); | 11711 | try self.metadata_items.ensureUnusedCapacity(self.gpa, count); |
| 11733 | const std = @import("std"); | 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; | 11718 | fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.ExtraIndex { |
| 11736 | const Builder = @This(); | 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"); |