| ... | ... | @@ -1121,7 +1121,7 @@ pub const Attribute = union(Kind) { |
| 1121 | 1121 | => |kind| { |
| 1122 | 1122 | const field = comptime blk: { |
| 1123 | 1123 | @setEvalBranchQuota(10_000); |
| 1124 | | inline for (@typeInfo(Attribute).Union.fields) |field| { |
| 1124 | for (@typeInfo(Attribute).Union.fields) |field| { |
| 1125 | 1125 | if (std.mem.eql(u8, field.name, @tagName(kind))) break :blk field; |
| 1126 | 1126 | } |
| 1127 | 1127 | unreachable; |
| ... | ... | @@ -12042,6 +12042,1476 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite |
| 12042 | 12042 | return self.constantExtraDataTrail(T, index).data; |
| 12043 | 12043 | } |
| 12044 | 12044 | |
| 12045 | pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]const u32 { |
| 12046 | const BitcodeWriter = bitcode_writer.BitcodeWriter(&.{ Type, FunctionAttributes }); |
| 12047 | var bitcode = BitcodeWriter.init(allocator, &.{ |
| 12048 | std.math.log2_int_ceil(usize, self.type_items.items.len - 1), |
| 12049 | std.math.log2_int_ceil(usize, self.function_attributes_set.count() - 1), |
| 12050 | }); |
| 12051 | errdefer bitcode.deinit(); |
| 12052 | |
| 12053 | // Write LLVM IR magic |
| 12054 | try bitcode.writeBits(IR.MAGIC, 32); |
| 12055 | |
| 12056 | var record = std.ArrayListUnmanaged(u64){}; |
| 12057 | defer record.deinit(self.gpa); |
| 12058 | |
| 12059 | // IDENTIFICATION_BLOCK |
| 12060 | { |
| 12061 | const Identification = IR.Identification; |
| 12062 | var identification_block = try bitcode.enterTopBlock(Identification); |
| 12063 | |
| 12064 | const producer = try std.fmt.allocPrint(self.gpa, "zig {d}.{d}.{d}", .{ |
| 12065 | build_options.semver.major, |
| 12066 | build_options.semver.minor, |
| 12067 | build_options.semver.patch, |
| 12068 | }); |
| 12069 | defer self.gpa.free(producer); |
| 12070 | |
| 12071 | try identification_block.writeAbbrev(Identification.Version{ .string = producer }); |
| 12072 | try identification_block.writeAbbrev(Identification.Epoch{ .epoch = 0 }); |
| 12073 | |
| 12074 | try identification_block.end(); |
| 12075 | } |
| 12076 | |
| 12077 | // MODULE_BLOCK |
| 12078 | { |
| 12079 | const Module = IR.Module; |
| 12080 | var module_block = try bitcode.enterTopBlock(Module); |
| 12081 | |
| 12082 | try module_block.writeAbbrev(Module.Version{}); |
| 12083 | |
| 12084 | if (self.target_triple.slice(self)) |triple| { |
| 12085 | try module_block.writeAbbrev(Module.String{ |
| 12086 | .code = 2, |
| 12087 | .string = triple, |
| 12088 | }); |
| 12089 | } |
| 12090 | |
| 12091 | if (self.data_layout.slice(self)) |data_layout| { |
| 12092 | try module_block.writeAbbrev(Module.String{ |
| 12093 | .code = 3, |
| 12094 | .string = data_layout, |
| 12095 | }); |
| 12096 | } |
| 12097 | |
| 12098 | if (self.source_filename.slice(self)) |source_filename| { |
| 12099 | try module_block.writeAbbrev(Module.String{ |
| 12100 | .code = 16, |
| 12101 | .string = source_filename, |
| 12102 | }); |
| 12103 | } |
| 12104 | |
| 12105 | if (self.module_asm.items.len != 0) { |
| 12106 | try module_block.writeAbbrev(Module.String{ |
| 12107 | .code = 4, |
| 12108 | .string = self.module_asm.items, |
| 12109 | }); |
| 12110 | } |
| 12111 | |
| 12112 | // TYPE_BLOCK |
| 12113 | { |
| 12114 | var type_block = try module_block.enterSubBlock(IR.Type); |
| 12115 | |
| 12116 | try type_block.writeAbbrev(IR.Type.NumEntry{ .num = @intCast(self.type_items.items.len) }); |
| 12117 | |
| 12118 | for (self.type_items.items, 0..) |item, i| { |
| 12119 | const ty: Type = @enumFromInt(i); |
| 12120 | |
| 12121 | switch (item.tag) { |
| 12122 | .simple => try type_block.writeAbbrev(IR.Type.Simple{ .code = @truncate(item.data) }), |
| 12123 | .integer => try type_block.writeAbbrev(IR.Type.Integer{ .width = item.data }), |
| 12124 | .structure, |
| 12125 | .packed_structure, |
| 12126 | => |kind| { |
| 12127 | const is_packed = switch (kind) { |
| 12128 | .structure => false, |
| 12129 | .packed_structure => true, |
| 12130 | else => unreachable, |
| 12131 | }; |
| 12132 | var extra = self.typeExtraDataTrail(Type.Structure, item.data); |
| 12133 | try type_block.writeAbbrev(IR.Type.StructAnon{ |
| 12134 | .is_packed = is_packed, |
| 12135 | .types = extra.trail.next(extra.data.fields_len, Type, self), |
| 12136 | }); |
| 12137 | }, |
| 12138 | .named_structure => { |
| 12139 | const extra = self.typeExtraData(Type.NamedStructure, item.data); |
| 12140 | try type_block.writeAbbrev(IR.Type.StructName{ |
| 12141 | .string = extra.id.slice(self).?, |
| 12142 | }); |
| 12143 | |
| 12144 | const real_struct = self.type_items.items[@intFromEnum(extra.body)]; |
| 12145 | const is_packed: bool = switch (real_struct.tag) { |
| 12146 | .structure => false, |
| 12147 | .packed_structure => true, |
| 12148 | else => unreachable, |
| 12149 | }; |
| 12150 | |
| 12151 | var real_extra = self.typeExtraDataTrail(Type.Structure, real_struct.data); |
| 12152 | try type_block.writeAbbrev(IR.Type.StructNamed{ |
| 12153 | .is_packed = is_packed, |
| 12154 | .types = real_extra.trail.next(real_extra.data.fields_len, Type, self), |
| 12155 | }); |
| 12156 | }, |
| 12157 | .array, |
| 12158 | .small_array, |
| 12159 | => try type_block.writeAbbrev(IR.Type.Array{ |
| 12160 | .len = ty.aggregateLen(self), |
| 12161 | .child = ty.childType(self), |
| 12162 | }), |
| 12163 | .vector, |
| 12164 | .scalable_vector, |
| 12165 | => try type_block.writeAbbrev(IR.Type.Vector{ |
| 12166 | .len = ty.aggregateLen(self), |
| 12167 | .child = ty.childType(self), |
| 12168 | }), |
| 12169 | .pointer => try type_block.writeAbbrev(IR.Type.Pointer{ |
| 12170 | .addr_space = ty.pointerAddrSpace(self), |
| 12171 | }), |
| 12172 | .target => { |
| 12173 | var extra = self.typeExtraDataTrail(Type.Target, item.data); |
| 12174 | try type_block.writeAbbrev(IR.Type.StructName{ |
| 12175 | .string = extra.data.name.slice(self).?, |
| 12176 | }); |
| 12177 | |
| 12178 | const types = extra.trail.next(extra.data.types_len, Type, self); |
| 12179 | const ints = extra.trail.next(extra.data.ints_len, u32, self); |
| 12180 | |
| 12181 | try type_block.writeAbbrev(IR.Type.Target{ |
| 12182 | .num_types = extra.data.types_len, |
| 12183 | .types = types, |
| 12184 | .ints = ints, |
| 12185 | }); |
| 12186 | }, |
| 12187 | .function, .vararg_function => |kind| { |
| 12188 | const is_vararg = switch (kind) { |
| 12189 | .function => false, |
| 12190 | .vararg_function => true, |
| 12191 | else => unreachable, |
| 12192 | }; |
| 12193 | var extra = self.typeExtraDataTrail(Type.Function, item.data); |
| 12194 | try type_block.writeAbbrev(IR.Type.Function{ |
| 12195 | .is_vararg = is_vararg, |
| 12196 | .return_type = extra.data.ret, |
| 12197 | .param_types = extra.trail.next(extra.data.params_len, Type, self), |
| 12198 | }); |
| 12199 | }, |
| 12200 | } |
| 12201 | } |
| 12202 | |
| 12203 | try type_block.end(); |
| 12204 | } |
| 12205 | |
| 12206 | var attributes_set: std.AutoArrayHashMapUnmanaged(struct { |
| 12207 | attributes: Attributes, |
| 12208 | index: u32, |
| 12209 | }, void) = .{}; |
| 12210 | defer attributes_set.deinit(self.gpa); |
| 12211 | |
| 12212 | // PARAMATTR_GROUP_BLOCK |
| 12213 | { |
| 12214 | const ParamattrGroup = IR.ParamattrGroup; |
| 12215 | |
| 12216 | var paramattr_group_block = try module_block.enterSubBlock(ParamattrGroup); |
| 12217 | |
| 12218 | for (self.function_attributes_set.keys()) |func_attributes| { |
| 12219 | for (func_attributes.slice(self), 0..) |attributes, i| { |
| 12220 | const attributes_slice = attributes.slice(self); |
| 12221 | if (attributes_slice.len == 0) continue; |
| 12222 | |
| 12223 | const attr_gop = try attributes_set.getOrPut(self.gpa, .{ |
| 12224 | .attributes = attributes, |
| 12225 | .index = @intCast(i), |
| 12226 | }); |
| 12227 | |
| 12228 | if (attr_gop.found_existing) continue; |
| 12229 | |
| 12230 | record.clearRetainingCapacity(); |
| 12231 | try record.ensureUnusedCapacity(self.gpa, 2); |
| 12232 | |
| 12233 | record.appendAssumeCapacity(attr_gop.index); |
| 12234 | record.appendAssumeCapacity(switch (i) { |
| 12235 | 0 => 0xffffffff, |
| 12236 | else => i - 1, |
| 12237 | }); |
| 12238 | |
| 12239 | for (attributes_slice) |attr_index| { |
| 12240 | const kind = attr_index.getKind(self); |
| 12241 | switch (attr_index.toAttribute(self)) { |
| 12242 | .zeroext, |
| 12243 | .signext, |
| 12244 | .inreg, |
| 12245 | .@"noalias", |
| 12246 | .nocapture, |
| 12247 | .nofree, |
| 12248 | .nest, |
| 12249 | .returned, |
| 12250 | .nonnull, |
| 12251 | .swiftself, |
| 12252 | .swiftasync, |
| 12253 | .swifterror, |
| 12254 | .immarg, |
| 12255 | .noundef, |
| 12256 | .allocalign, |
| 12257 | .allocptr, |
| 12258 | .readnone, |
| 12259 | .readonly, |
| 12260 | .writeonly, |
| 12261 | .alwaysinline, |
| 12262 | .builtin, |
| 12263 | .cold, |
| 12264 | .convergent, |
| 12265 | .disable_sanitizer_information, |
| 12266 | .fn_ret_thunk_extern, |
| 12267 | .hot, |
| 12268 | .inlinehint, |
| 12269 | .jumptable, |
| 12270 | .minsize, |
| 12271 | .naked, |
| 12272 | .nobuiltin, |
| 12273 | .nocallback, |
| 12274 | .noduplicate, |
| 12275 | .noimplicitfloat, |
| 12276 | .@"noinline", |
| 12277 | .nomerge, |
| 12278 | .nonlazybind, |
| 12279 | .noprofile, |
| 12280 | .skipprofile, |
| 12281 | .noredzone, |
| 12282 | .noreturn, |
| 12283 | .norecurse, |
| 12284 | .willreturn, |
| 12285 | .nosync, |
| 12286 | .nounwind, |
| 12287 | .nosanitize_bounds, |
| 12288 | .nosanitize_coverage, |
| 12289 | .null_pointer_is_valid, |
| 12290 | .optforfuzzing, |
| 12291 | .optnone, |
| 12292 | .optsize, |
| 12293 | .returns_twice, |
| 12294 | .safestack, |
| 12295 | .sanitize_address, |
| 12296 | .sanitize_memory, |
| 12297 | .sanitize_thread, |
| 12298 | .sanitize_hwaddress, |
| 12299 | .sanitize_memtag, |
| 12300 | .speculative_load_hardening, |
| 12301 | .speculatable, |
| 12302 | .ssp, |
| 12303 | .sspstrong, |
| 12304 | .sspreq, |
| 12305 | .strictfp, |
| 12306 | .nocf_check, |
| 12307 | .shadowcallstack, |
| 12308 | .mustprogress, |
| 12309 | .no_sanitize_address, |
| 12310 | .no_sanitize_hwaddress, |
| 12311 | .sanitize_address_dyninit, |
| 12312 | => { |
| 12313 | try record.ensureUnusedCapacity(self.gpa, 2); |
| 12314 | record.appendAssumeCapacity(0); |
| 12315 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12316 | }, |
| 12317 | .byval, |
| 12318 | .byref, |
| 12319 | .preallocated, |
| 12320 | .inalloca, |
| 12321 | .sret, |
| 12322 | .elementtype, |
| 12323 | => |ty| { |
| 12324 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12325 | record.appendAssumeCapacity(6); |
| 12326 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12327 | record.appendAssumeCapacity(@intFromEnum(ty)); |
| 12328 | }, |
| 12329 | .@"align", |
| 12330 | .alignstack, |
| 12331 | => |alignment| { |
| 12332 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12333 | record.appendAssumeCapacity(1); |
| 12334 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12335 | record.appendAssumeCapacity(alignment.toByteUnits() orelse 0); |
| 12336 | }, |
| 12337 | .dereferenceable, |
| 12338 | .dereferenceable_or_null, |
| 12339 | => |size| { |
| 12340 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12341 | record.appendAssumeCapacity(1); |
| 12342 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12343 | record.appendAssumeCapacity(size); |
| 12344 | }, |
| 12345 | .nofpclass => |fpclass| { |
| 12346 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12347 | record.appendAssumeCapacity(1); |
| 12348 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12349 | record.appendAssumeCapacity(@as(u32, @bitCast(fpclass))); |
| 12350 | }, |
| 12351 | .allockind => |allockind| { |
| 12352 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12353 | record.appendAssumeCapacity(1); |
| 12354 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12355 | record.appendAssumeCapacity(@as(u32, @bitCast(allockind))); |
| 12356 | }, |
| 12357 | |
| 12358 | .allocsize => |allocsize| { |
| 12359 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12360 | record.appendAssumeCapacity(1); |
| 12361 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12362 | record.appendAssumeCapacity(@bitCast(allocsize.toLlvm())); |
| 12363 | }, |
| 12364 | .memory => |memory| { |
| 12365 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12366 | record.appendAssumeCapacity(1); |
| 12367 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12368 | record.appendAssumeCapacity(@as(u32, @bitCast(memory))); |
| 12369 | }, |
| 12370 | .uwtable => |uwtable| if (uwtable != .none) { |
| 12371 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12372 | record.appendAssumeCapacity(1); |
| 12373 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12374 | record.appendAssumeCapacity(@intFromEnum(uwtable)); |
| 12375 | }, |
| 12376 | .vscale_range => |vscale_range| { |
| 12377 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 12378 | record.appendAssumeCapacity(1); |
| 12379 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 12380 | record.appendAssumeCapacity(@bitCast(vscale_range.toLlvm())); |
| 12381 | }, |
| 12382 | .string => |string_attr| { |
| 12383 | const string_attr_kind_slice = string_attr.kind.slice(self).?; |
| 12384 | const string_attr_value_slice = if (string_attr.value != .none) |
| 12385 | string_attr.value.slice(self).? |
| 12386 | else |
| 12387 | null; |
| 12388 | |
| 12389 | try record.ensureUnusedCapacity( |
| 12390 | self.gpa, |
| 12391 | 2 + string_attr_kind_slice.len + if (string_attr_value_slice) |slice| slice.len + 1 else 0, |
| 12392 | ); |
| 12393 | record.appendAssumeCapacity(if (string_attr.value == .none) 3 else 4); |
| 12394 | for (string_attr.kind.slice(self).?) |c| { |
| 12395 | record.appendAssumeCapacity(c); |
| 12396 | } |
| 12397 | record.appendAssumeCapacity(0); |
| 12398 | if (string_attr_value_slice) |slice| { |
| 12399 | for (slice) |c| { |
| 12400 | record.appendAssumeCapacity(c); |
| 12401 | } |
| 12402 | record.appendAssumeCapacity(0); |
| 12403 | } |
| 12404 | }, |
| 12405 | .none => unreachable, |
| 12406 | } |
| 12407 | } |
| 12408 | |
| 12409 | try paramattr_group_block.writeUnabbrev(3, record.items); |
| 12410 | } |
| 12411 | } |
| 12412 | |
| 12413 | try paramattr_group_block.end(); |
| 12414 | } |
| 12415 | |
| 12416 | // PARAMATTR_BLOCK |
| 12417 | { |
| 12418 | const Paramattr = IR.Paramattr; |
| 12419 | var paramattr_block = try module_block.enterSubBlock(Paramattr); |
| 12420 | |
| 12421 | for (self.function_attributes_set.keys()) |func_attributes| { |
| 12422 | const func_attributes_slice = func_attributes.slice(self); |
| 12423 | record.clearRetainingCapacity(); |
| 12424 | try record.ensureUnusedCapacity(self.gpa, func_attributes_slice.len); |
| 12425 | for (func_attributes_slice, 0..) |attributes, i| { |
| 12426 | const attributes_slice = attributes.slice(self); |
| 12427 | if (attributes_slice.len == 0) continue; |
| 12428 | |
| 12429 | const group_index = attributes_set.getIndex(.{ |
| 12430 | .attributes = attributes, |
| 12431 | .index = @intCast(i), |
| 12432 | }) orelse unreachable; |
| 12433 | record.appendAssumeCapacity(@intCast(group_index)); |
| 12434 | } |
| 12435 | |
| 12436 | try paramattr_block.writeAbbrev(Paramattr.Entry{ .group_indices = record.items }); |
| 12437 | } |
| 12438 | |
| 12439 | try paramattr_block.end(); |
| 12440 | } |
| 12441 | |
| 12442 | var globals = std.AutoArrayHashMapUnmanaged(Global.Index, void){}; |
| 12443 | defer globals.deinit(self.gpa); |
| 12444 | try globals.ensureUnusedCapacity( |
| 12445 | self.gpa, |
| 12446 | self.variables.items.len + |
| 12447 | self.functions.items.len + |
| 12448 | self.aliases.items.len, |
| 12449 | ); |
| 12450 | |
| 12451 | for (self.variables.items) |variable| { |
| 12452 | if (variable.global.getReplacement(self) != .none) continue; |
| 12453 | |
| 12454 | globals.putAssumeCapacity(variable.global, {}); |
| 12455 | } |
| 12456 | |
| 12457 | for (self.functions.items) |function| { |
| 12458 | if (function.global.getReplacement(self) != .none) continue; |
| 12459 | |
| 12460 | globals.putAssumeCapacity(function.global, {}); |
| 12461 | } |
| 12462 | |
| 12463 | for (self.aliases.items) |alias| { |
| 12464 | if (alias.global.getReplacement(self) != .none) continue; |
| 12465 | |
| 12466 | globals.putAssumeCapacity(alias.global, {}); |
| 12467 | } |
| 12468 | |
| 12469 | const ConstantAdapter = struct { |
| 12470 | const ConstantAdapter = @This(); |
| 12471 | builder: *const Builder, |
| 12472 | globals: *const std.AutoArrayHashMapUnmanaged(Global.Index, void), |
| 12473 | |
| 12474 | pub fn get(adapter: @This(), param: anytype, comptime field_name: []const u8) @TypeOf(param) { |
| 12475 | _ = field_name; |
| 12476 | return switch (@TypeOf(param)) { |
| 12477 | Constant => @enumFromInt(adapter.getConstantIndex(param)), |
| 12478 | else => param, |
| 12479 | }; |
| 12480 | } |
| 12481 | |
| 12482 | pub fn getConstantIndex(adapter: ConstantAdapter, constant: Constant) u32 { |
| 12483 | return switch (constant.unwrap()) { |
| 12484 | .constant => |c| c + adapter.numGlobals(), |
| 12485 | .global => |global| @intCast(adapter.globals.getIndex(global.unwrap(adapter.builder)).?), |
| 12486 | }; |
| 12487 | } |
| 12488 | |
| 12489 | pub fn numConstants(adapter: ConstantAdapter) u32 { |
| 12490 | return @intCast(adapter.globals.count() + adapter.builder.constant_items.len); |
| 12491 | } |
| 12492 | |
| 12493 | pub fn numGlobals(adapter: ConstantAdapter) u32 { |
| 12494 | return @intCast(adapter.globals.count()); |
| 12495 | } |
| 12496 | }; |
| 12497 | |
| 12498 | const constant_adapter = ConstantAdapter{ |
| 12499 | .builder = self, |
| 12500 | .globals = &globals, |
| 12501 | }; |
| 12502 | |
| 12503 | // Globals |
| 12504 | { |
| 12505 | var section_map: std.AutoArrayHashMapUnmanaged(String, void) = .{}; |
| 12506 | defer section_map.deinit(self.gpa); |
| 12507 | try section_map.ensureUnusedCapacity(self.gpa, globals.count()); |
| 12508 | |
| 12509 | for (self.variables.items) |variable| { |
| 12510 | if (variable.global.getReplacement(self) != .none) continue; |
| 12511 | |
| 12512 | const section = blk: { |
| 12513 | if (variable.section == .none) break :blk 0; |
| 12514 | const gop = section_map.getOrPutAssumeCapacity(variable.section); |
| 12515 | if (!gop.found_existing) { |
| 12516 | try module_block.writeAbbrev(Module.String{ |
| 12517 | .code = 5, |
| 12518 | .string = variable.section.slice(self) orelse unreachable, |
| 12519 | }); |
| 12520 | } |
| 12521 | break :blk gop.index + 1; |
| 12522 | }; |
| 12523 | |
| 12524 | const initid = if (variable.init == .no_init) |
| 12525 | 0 |
| 12526 | else |
| 12527 | (constant_adapter.getConstantIndex(variable.init) + 1); |
| 12528 | |
| 12529 | const strtab = variable.global.strtab(self); |
| 12530 | |
| 12531 | const global = variable.global.ptrConst(self); |
| 12532 | try module_block.writeAbbrev(Module.Variable{ |
| 12533 | .strtab_offset = strtab.offset, |
| 12534 | .strtab_size = strtab.size, |
| 12535 | .type_index = global.type, |
| 12536 | .is_const = .{ |
| 12537 | .is_const = switch (variable.mutability) { |
| 12538 | .global => false, |
| 12539 | .constant => true, |
| 12540 | }, |
| 12541 | .addr_space = global.addr_space, |
| 12542 | }, |
| 12543 | .initid = initid, |
| 12544 | .linkage = global.linkage, |
| 12545 | .alignment = variable.alignment.toLlvm(), |
| 12546 | .section = section, |
| 12547 | .visibility = global.visibility, |
| 12548 | .thread_local = variable.thread_local, |
| 12549 | .unnamed_addr = global.unnamed_addr, |
| 12550 | .externally_initialized = global.externally_initialized, |
| 12551 | .dllstorageclass = global.dll_storage_class, |
| 12552 | .preemption = global.preemption, |
| 12553 | }); |
| 12554 | } |
| 12555 | |
| 12556 | for (self.functions.items) |func| { |
| 12557 | if (func.global.getReplacement(self) != .none) continue; |
| 12558 | |
| 12559 | const section = blk: { |
| 12560 | if (func.section == .none) break :blk 0; |
| 12561 | const gop = section_map.getOrPutAssumeCapacity(func.section); |
| 12562 | if (!gop.found_existing) { |
| 12563 | try module_block.writeAbbrev(Module.String{ |
| 12564 | .code = 5, |
| 12565 | .string = func.section.slice(self) orelse unreachable, |
| 12566 | }); |
| 12567 | } |
| 12568 | break :blk gop.index + 1; |
| 12569 | }; |
| 12570 | |
| 12571 | const paramattr_index = if (self.function_attributes_set.getIndex(func.attributes)) |index| |
| 12572 | index + 1 |
| 12573 | else |
| 12574 | 0; |
| 12575 | |
| 12576 | const strtab = func.global.strtab(self); |
| 12577 | |
| 12578 | const global = func.global.ptrConst(self); |
| 12579 | try module_block.writeAbbrev(Module.Function{ |
| 12580 | .strtab_offset = strtab.offset, |
| 12581 | .strtab_size = strtab.size, |
| 12582 | .type_index = global.type, |
| 12583 | .call_conv = func.call_conv, |
| 12584 | .is_proto = func.instructions.len == 0, |
| 12585 | .linkage = global.linkage, |
| 12586 | .paramattr = paramattr_index, |
| 12587 | .alignment = func.alignment.toLlvm(), |
| 12588 | .section = section, |
| 12589 | .visibility = global.visibility, |
| 12590 | .unnamed_addr = global.unnamed_addr, |
| 12591 | .dllstorageclass = global.dll_storage_class, |
| 12592 | .preemption = global.preemption, |
| 12593 | .addr_space = global.addr_space, |
| 12594 | }); |
| 12595 | } |
| 12596 | |
| 12597 | for (self.aliases.items) |alias| { |
| 12598 | if (alias.global.getReplacement(self) != .none) continue; |
| 12599 | |
| 12600 | const strtab = alias.global.strtab(self); |
| 12601 | |
| 12602 | const global = alias.global.ptrConst(self); |
| 12603 | try module_block.writeAbbrev(Module.Alias{ |
| 12604 | .strtab_offset = strtab.offset, |
| 12605 | .strtab_size = strtab.size, |
| 12606 | .type_index = global.type, |
| 12607 | .addr_space = global.addr_space, |
| 12608 | .aliasee = constant_adapter.getConstantIndex(alias.aliasee), |
| 12609 | .linkage = global.linkage, |
| 12610 | .visibility = global.visibility, |
| 12611 | .thread_local = alias.thread_local, |
| 12612 | .unnamed_addr = global.unnamed_addr, |
| 12613 | .dllstorageclass = global.dll_storage_class, |
| 12614 | .preemption = global.preemption, |
| 12615 | }); |
| 12616 | } |
| 12617 | } |
| 12618 | |
| 12619 | // CONSTANTS_BLOCK |
| 12620 | { |
| 12621 | const Constants = IR.Constants; |
| 12622 | var constants_block = try module_block.enterSubBlock(Constants); |
| 12623 | |
| 12624 | var current_type: Type = .none; |
| 12625 | const tags = self.constant_items.items(.tag); |
| 12626 | const datas = self.constant_items.items(.data); |
| 12627 | for (0..self.constant_items.len) |index| { |
| 12628 | record.clearRetainingCapacity(); |
| 12629 | const constant: Constant = @enumFromInt(index); |
| 12630 | const constant_type = constant.typeOf(self); |
| 12631 | if (constant_type != current_type) { |
| 12632 | try constants_block.writeAbbrev(Constants.SetType{ .type_id = constant_type }); |
| 12633 | current_type = constant_type; |
| 12634 | } |
| 12635 | const data = datas[index]; |
| 12636 | switch (tags[index]) { |
| 12637 | .null, |
| 12638 | .zeroinitializer, |
| 12639 | .none, |
| 12640 | => try constants_block.writeAbbrev(Constants.Null{}), |
| 12641 | .undef => try constants_block.writeAbbrev(Constants.Undef{}), |
| 12642 | .poison => try constants_block.writeAbbrev(Constants.Poison{}), |
| 12643 | .positive_integer, |
| 12644 | .negative_integer, |
| 12645 | => |tag| { |
| 12646 | const extra: *align(@alignOf(std.math.big.Limb)) Constant.Integer = |
| 12647 | @ptrCast(self.constant_limbs.items[data..][0..Constant.Integer.limbs]); |
| 12648 | const limbs = self.constant_limbs |
| 12649 | .items[data + Constant.Integer.limbs ..][0..extra.limbs_len]; |
| 12650 | const bigint = std.math.big.int.Const{ |
| 12651 | .limbs = limbs, |
| 12652 | .positive = tag == .positive_integer, |
| 12653 | }; |
| 12654 | |
| 12655 | const bit_count = extra.type.scalarBits(self); |
| 12656 | if (bit_count <= 64) { |
| 12657 | const val = bigint.to(i64) catch unreachable; |
| 12658 | const emit_val = if (tag == .positive_integer) |
| 12659 | @shlWithOverflow(val, 1)[0] |
| 12660 | else |
| 12661 | (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1); |
| 12662 | try constants_block.writeAbbrev(Constants.Integer{ .value = @bitCast(emit_val) }); |
| 12663 | } else { |
| 12664 | const word_count = std.mem.alignForward(u24, bit_count, 64) / 64; |
| 12665 | try record.ensureUnusedCapacity(self.gpa, word_count); |
| 12666 | const buffer: [*]u8 = @ptrCast(record.items.ptr); |
| 12667 | bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little); |
| 12668 | |
| 12669 | const signed_buffer: [*]i64 = @ptrCast(record.items.ptr); |
| 12670 | for (signed_buffer[0..word_count], 0..) |val, i| { |
| 12671 | signed_buffer[i] = if (val >= 0) |
| 12672 | @shlWithOverflow(val, 1)[0] |
| 12673 | else |
| 12674 | (@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1); |
| 12675 | } |
| 12676 | |
| 12677 | try constants_block.writeUnabbrev(5, record.items.ptr[0..word_count]); |
| 12678 | } |
| 12679 | }, |
| 12680 | .half, |
| 12681 | .bfloat, |
| 12682 | => try constants_block.writeAbbrev(Constants.Half{ .value = @truncate(data) }), |
| 12683 | .float => try constants_block.writeAbbrev(Constants.Float{ .value = data }), |
| 12684 | .double => { |
| 12685 | const extra = self.constantExtraData(Constant.Double, data); |
| 12686 | try constants_block.writeAbbrev(Constants.Double{ |
| 12687 | .value = (@as(u64, extra.hi) << 32) | extra.lo, |
| 12688 | }); |
| 12689 | }, |
| 12690 | .x86_fp80 => { |
| 12691 | const extra = self.constantExtraData(Constant.Fp80, data); |
| 12692 | try constants_block.writeAbbrev(Constants.Fp80{ |
| 12693 | .lo = @as(u64, extra.lo_hi) << 32 | @as(u64, extra.lo_lo), |
| 12694 | .hi = @intCast(extra.hi), |
| 12695 | }); |
| 12696 | }, |
| 12697 | .fp128, |
| 12698 | .ppc_fp128, |
| 12699 | => { |
| 12700 | const extra = self.constantExtraData(Constant.Fp128, data); |
| 12701 | try constants_block.writeAbbrev(Constants.Fp128{ |
| 12702 | .lo = @as(u64, extra.lo_hi) << 32 | @as(u64, extra.lo_lo), |
| 12703 | .hi = @as(u64, extra.hi_hi) << 32 | @as(u64, extra.hi_lo), |
| 12704 | }); |
| 12705 | }, |
| 12706 | .array, |
| 12707 | .vector, |
| 12708 | .structure, |
| 12709 | .packed_structure, |
| 12710 | => { |
| 12711 | var extra = self.constantExtraDataTrail(Constant.Aggregate, data); |
| 12712 | const len: u32 = @intCast(extra.data.type.aggregateLen(self)); |
| 12713 | const values = extra.trail.next(len, Constant, self); |
| 12714 | |
| 12715 | try constants_block.writeAbbrevAdapted( |
| 12716 | Constants.Aggregate{ .values = values }, |
| 12717 | constant_adapter, |
| 12718 | ); |
| 12719 | }, |
| 12720 | .splat => { |
| 12721 | const ConstantsWriter = @TypeOf(constants_block); |
| 12722 | const extra = self.constantExtraData(Constant.Splat, data); |
| 12723 | const vector_len = extra.type.vectorLen(self); |
| 12724 | const c = constant_adapter.getConstantIndex(extra.value); |
| 12725 | |
| 12726 | try bitcode.writeBits( |
| 12727 | ConstantsWriter.abbrevId(Constants.Aggregate), |
| 12728 | ConstantsWriter.abbrev_len, |
| 12729 | ); |
| 12730 | try bitcode.writeVBR(vector_len, 6); |
| 12731 | for (0..vector_len) |_| { |
| 12732 | try bitcode.writeBits(c, Constants.Aggregate.ops[1].array_fixed); |
| 12733 | } |
| 12734 | }, |
| 12735 | .string, |
| 12736 | .string_null, |
| 12737 | => { |
| 12738 | const str: String = @enumFromInt(data); |
| 12739 | if (str == .none) { |
| 12740 | try constants_block.writeAbbrev(Constants.Null{}); |
| 12741 | } else { |
| 12742 | const slice = str.slice(self) orelse unreachable; |
| 12743 | switch (tags[index]) { |
| 12744 | .string => try constants_block.writeAbbrev(Constants.String{ .string = slice }), |
| 12745 | .string_null => try constants_block.writeAbbrev(Constants.CString{ .string = slice }), |
| 12746 | else => unreachable, |
| 12747 | } |
| 12748 | } |
| 12749 | }, |
| 12750 | .bitcast, |
| 12751 | .inttoptr, |
| 12752 | .ptrtoint, |
| 12753 | .fptosi, |
| 12754 | .fptoui, |
| 12755 | .sitofp, |
| 12756 | .uitofp, |
| 12757 | .addrspacecast, |
| 12758 | .fptrunc, |
| 12759 | .trunc, |
| 12760 | .fpext, |
| 12761 | .sext, |
| 12762 | .zext, |
| 12763 | => |tag| { |
| 12764 | const extra = self.constantExtraData(Constant.Cast, data); |
| 12765 | try constants_block.writeAbbrevAdapted(Constants.Cast{ |
| 12766 | .type_index = extra.type, |
| 12767 | .val = extra.val, |
| 12768 | .opcode = tag.toCastOpcode(), |
| 12769 | }, constant_adapter); |
| 12770 | }, |
| 12771 | .add, |
| 12772 | .@"add nsw", |
| 12773 | .@"add nuw", |
| 12774 | .sub, |
| 12775 | .@"sub nsw", |
| 12776 | .@"sub nuw", |
| 12777 | .mul, |
| 12778 | .@"mul nsw", |
| 12779 | .@"mul nuw", |
| 12780 | .shl, |
| 12781 | .lshr, |
| 12782 | .ashr, |
| 12783 | .@"and", |
| 12784 | .@"or", |
| 12785 | .xor, |
| 12786 | => |tag| { |
| 12787 | const extra = self.constantExtraData(Constant.Binary, data); |
| 12788 | try constants_block.writeAbbrevAdapted(Constants.Binary{ |
| 12789 | .opcode = tag.toBinaryOpcode(), |
| 12790 | .lhs = extra.lhs, |
| 12791 | .rhs = extra.rhs, |
| 12792 | }, constant_adapter); |
| 12793 | }, |
| 12794 | .icmp, |
| 12795 | .fcmp, |
| 12796 | => { |
| 12797 | const extra = self.constantExtraData(Constant.Compare, data); |
| 12798 | try constants_block.writeAbbrevAdapted(Constants.Cmp{ |
| 12799 | .ty = extra.lhs.typeOf(self), |
| 12800 | .lhs = extra.lhs, |
| 12801 | .rhs = extra.rhs, |
| 12802 | .pred = extra.cond, |
| 12803 | }, constant_adapter); |
| 12804 | }, |
| 12805 | .extractelement => { |
| 12806 | const extra = self.constantExtraData(Constant.ExtractElement, data); |
| 12807 | try constants_block.writeAbbrevAdapted(Constants.ExtractElement{ |
| 12808 | .val_type = extra.val.typeOf(self), |
| 12809 | .val = extra.val, |
| 12810 | .index_type = extra.index.typeOf(self), |
| 12811 | .index = extra.index, |
| 12812 | }, constant_adapter); |
| 12813 | }, |
| 12814 | .insertelement => { |
| 12815 | const extra = self.constantExtraData(Constant.InsertElement, data); |
| 12816 | try constants_block.writeAbbrevAdapted(Constants.InsertElement{ |
| 12817 | .val = extra.val, |
| 12818 | .elem = extra.elem, |
| 12819 | .index_type = extra.index.typeOf(self), |
| 12820 | .index = extra.index, |
| 12821 | }, constant_adapter); |
| 12822 | }, |
| 12823 | .shufflevector => { |
| 12824 | const extra = self.constantExtraData(Constant.ShuffleVector, data); |
| 12825 | const ty = constant.typeOf(self); |
| 12826 | const lhs_type = extra.lhs.typeOf(self); |
| 12827 | // Check if instruction is widening, truncating or not |
| 12828 | if (ty == lhs_type) { |
| 12829 | try constants_block.writeAbbrevAdapted(Constants.ShuffleVector{ |
| 12830 | .lhs = extra.lhs, |
| 12831 | .rhs = extra.rhs, |
| 12832 | .mask = extra.mask, |
| 12833 | }, constant_adapter); |
| 12834 | } else { |
| 12835 | try constants_block.writeAbbrevAdapted(Constants.ShuffleVectorEx{ |
| 12836 | .ty = ty, |
| 12837 | .lhs = extra.lhs, |
| 12838 | .rhs = extra.rhs, |
| 12839 | .mask = extra.mask, |
| 12840 | }, constant_adapter); |
| 12841 | } |
| 12842 | }, |
| 12843 | .getelementptr, |
| 12844 | .@"getelementptr inbounds", |
| 12845 | => |tag| { |
| 12846 | var extra = self.constantExtraDataTrail(Constant.GetElementPtr, data); |
| 12847 | const indices = extra.trail.next(extra.data.info.indices_len, Constant, self); |
| 12848 | try record.ensureUnusedCapacity(self.gpa, 1 + 2 + 2 * indices.len); |
| 12849 | |
| 12850 | record.appendAssumeCapacity(@intFromEnum(extra.data.type)); |
| 12851 | |
| 12852 | record.appendAssumeCapacity(@intFromEnum(extra.data.base.typeOf(self))); |
| 12853 | record.appendAssumeCapacity(constant_adapter.getConstantIndex(extra.data.base)); |
| 12854 | |
| 12855 | for (indices) |i| { |
| 12856 | record.appendAssumeCapacity(@intFromEnum(i.typeOf(self))); |
| 12857 | record.appendAssumeCapacity(constant_adapter.getConstantIndex(i)); |
| 12858 | } |
| 12859 | |
| 12860 | try constants_block.writeUnabbrev(switch (tag) { |
| 12861 | .getelementptr => 12, |
| 12862 | .@"getelementptr inbounds" => 20, |
| 12863 | else => unreachable, |
| 12864 | }, record.items); |
| 12865 | }, |
| 12866 | .@"asm", |
| 12867 | .@"asm sideeffect", |
| 12868 | .@"asm alignstack", |
| 12869 | .@"asm sideeffect alignstack", |
| 12870 | .@"asm inteldialect", |
| 12871 | .@"asm sideeffect inteldialect", |
| 12872 | .@"asm alignstack inteldialect", |
| 12873 | .@"asm sideeffect alignstack inteldialect", |
| 12874 | .@"asm unwind", |
| 12875 | .@"asm sideeffect unwind", |
| 12876 | .@"asm alignstack unwind", |
| 12877 | .@"asm sideeffect alignstack unwind", |
| 12878 | .@"asm inteldialect unwind", |
| 12879 | .@"asm sideeffect inteldialect unwind", |
| 12880 | .@"asm alignstack inteldialect unwind", |
| 12881 | .@"asm sideeffect alignstack inteldialect unwind", |
| 12882 | => |tag| { |
| 12883 | const extra = self.constantExtraData(Constant.Assembly, data); |
| 12884 | |
| 12885 | const assembly_slice = extra.assembly.slice(self) orelse unreachable; |
| 12886 | const constraints_slice = extra.constraints.slice(self) orelse unreachable; |
| 12887 | |
| 12888 | try record.ensureUnusedCapacity(self.gpa, 4 + assembly_slice.len + constraints_slice.len); |
| 12889 | |
| 12890 | record.appendAssumeCapacity(@intFromEnum(extra.type)); |
| 12891 | record.appendAssumeCapacity(switch (tag) { |
| 12892 | .@"asm" => 0, |
| 12893 | .@"asm sideeffect" => 0b0001, |
| 12894 | .@"asm sideeffect alignstack" => 0b0011, |
| 12895 | .@"asm sideeffect inteldialect" => 0b0101, |
| 12896 | .@"asm sideeffect alignstack inteldialect" => 0b0111, |
| 12897 | .@"asm sideeffect unwind" => 0b1001, |
| 12898 | .@"asm sideeffect alignstack unwind" => 0b1011, |
| 12899 | .@"asm sideeffect inteldialect unwind" => 0b1101, |
| 12900 | .@"asm sideeffect alignstack inteldialect unwind" => 0b1111, |
| 12901 | .@"asm alignstack" => 0b0010, |
| 12902 | .@"asm inteldialect" => 0b0100, |
| 12903 | .@"asm alignstack inteldialect" => 0b0110, |
| 12904 | .@"asm unwind" => 0b1000, |
| 12905 | .@"asm alignstack unwind" => 0b1010, |
| 12906 | .@"asm inteldialect unwind" => 0b1100, |
| 12907 | .@"asm alignstack inteldialect unwind" => 0b1110, |
| 12908 | else => unreachable, |
| 12909 | }); |
| 12910 | |
| 12911 | record.appendAssumeCapacity(assembly_slice.len); |
| 12912 | for (assembly_slice) |c| record.appendAssumeCapacity(c); |
| 12913 | |
| 12914 | record.appendAssumeCapacity(constraints_slice.len); |
| 12915 | for (constraints_slice) |c| record.appendAssumeCapacity(c); |
| 12916 | |
| 12917 | try constants_block.writeUnabbrev(30, record.items); |
| 12918 | }, |
| 12919 | .blockaddress => { |
| 12920 | const extra = self.constantExtraData(Constant.BlockAddress, data); |
| 12921 | try constants_block.writeAbbrev(Constants.BlockAddress{ |
| 12922 | .type_id = extra.function.typeOf(self), |
| 12923 | .function = constant_adapter.getConstantIndex(extra.function.toConst(self)), |
| 12924 | .block = @intFromEnum(extra.block), |
| 12925 | }); |
| 12926 | }, |
| 12927 | .dso_local_equivalent, |
| 12928 | .no_cfi, |
| 12929 | => |tag| { |
| 12930 | const function: Function.Index = @enumFromInt(data); |
| 12931 | try constants_block.writeAbbrev(Constants.DsoLocalEquivalentOrNoCfi{ |
| 12932 | .code = switch (tag) { |
| 12933 | .dso_local_equivalent => 27, |
| 12934 | .no_cfi => 29, |
| 12935 | else => unreachable, |
| 12936 | }, |
| 12937 | .type_id = function.typeOf(self), |
| 12938 | .function = constant_adapter.getConstantIndex(function.toConst(self)), |
| 12939 | }); |
| 12940 | }, |
| 12941 | } |
| 12942 | } |
| 12943 | |
| 12944 | try constants_block.end(); |
| 12945 | } |
| 12946 | |
| 12947 | // FUNCTION_BLOCKS |
| 12948 | { |
| 12949 | const FunctionAdapter = struct { |
| 12950 | constant_adapter: ConstantAdapter, |
| 12951 | func: *const Function, |
| 12952 | instruction_index: u32 = 0, |
| 12953 | |
| 12954 | pub fn init( |
| 12955 | const_adapter: ConstantAdapter, |
| 12956 | func: *const Function, |
| 12957 | ) @This() { |
| 12958 | return .{ |
| 12959 | .constant_adapter = const_adapter, |
| 12960 | .func = func, |
| 12961 | .instruction_index = 0, |
| 12962 | }; |
| 12963 | } |
| 12964 | |
| 12965 | pub fn get(adapter: @This(), value: anytype, comptime field_name: []const u8) @TypeOf(value) { |
| 12966 | _ = field_name; |
| 12967 | const Ty = @TypeOf(value); |
| 12968 | return switch (Ty) { |
| 12969 | Value => @enumFromInt(adapter.getOffsetValueIndex(value)), |
| 12970 | Constant => @enumFromInt(adapter.getOffsetConstantIndex(value)), |
| 12971 | FunctionAttributes => @enumFromInt(if (value == .none) 0 else (adapter.constant_adapter.builder.function_attributes_set.getIndex(value) orelse unreachable) + 1), |
| 12972 | else => value, |
| 12973 | }; |
| 12974 | } |
| 12975 | |
| 12976 | pub fn getValueIndex(adapter: @This(), value: Value) u32 { |
| 12977 | return @intCast(switch (value.unwrap()) { |
| 12978 | .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(), |
| 12979 | .constant => |constant| adapter.constant_adapter.getConstantIndex(constant), |
| 12980 | }); |
| 12981 | } |
| 12982 | |
| 12983 | pub fn getOffsetValueIndex(adapter: @This(), value: Value) u32 { |
| 12984 | return adapter.offset() - adapter.getValueIndex(value); |
| 12985 | } |
| 12986 | |
| 12987 | pub fn getOffsetValueSignedIndex(adapter: @This(), value: Value) i32 { |
| 12988 | const signed_offset: i32 = @intCast(adapter.offset()); |
| 12989 | const signed_value: i32 = @intCast(adapter.getValueIndex(value)); |
| 12990 | return signed_offset - signed_value; |
| 12991 | } |
| 12992 | |
| 12993 | pub fn getOffsetConstantIndex(adapter: @This(), constant: Constant) u32 { |
| 12994 | return adapter.offset() - adapter.constant_adapter.getConstantIndex(constant); |
| 12995 | } |
| 12996 | |
| 12997 | pub fn offset(adapter: @This()) u32 { |
| 12998 | return @as( |
| 12999 | Function.Instruction.Index, |
| 13000 | @enumFromInt(adapter.instruction_index), |
| 13001 | ).valueIndex(adapter.func) + adapter.firstInstr(); |
| 13002 | } |
| 13003 | |
| 13004 | fn firstInstr(adapter: @This()) u32 { |
| 13005 | return adapter.constant_adapter.numConstants(); |
| 13006 | } |
| 13007 | |
| 13008 | pub fn next(adapter: *@This()) void { |
| 13009 | adapter.instruction_index += 1; |
| 13010 | } |
| 13011 | }; |
| 13012 | |
| 13013 | for (self.functions.items, 0..) |func, func_index| { |
| 13014 | const FunctionBlock = IR.FunctionBlock; |
| 13015 | if (func.global.getReplacement(self) != .none) continue; |
| 13016 | |
| 13017 | if (func.instructions.len == 0) continue; |
| 13018 | |
| 13019 | var function_block = try module_block.enterSubBlock(FunctionBlock); |
| 13020 | |
| 13021 | try function_block.writeAbbrev(FunctionBlock.DeclareBlocks{ .num_blocks = func.blocks.len }); |
| 13022 | |
| 13023 | var adapter = FunctionAdapter.init(constant_adapter, &func); |
| 13024 | |
| 13025 | const tags = func.instructions.items(.tag); |
| 13026 | const datas = func.instructions.items(.data); |
| 13027 | |
| 13028 | var block_incoming_len: u32 = undefined; |
| 13029 | for (0..func.instructions.len) |instr_index| { |
| 13030 | const tag = tags[instr_index]; |
| 13031 | |
| 13032 | record.clearRetainingCapacity(); |
| 13033 | |
| 13034 | switch (tag) { |
| 13035 | .block => block_incoming_len = datas[instr_index], |
| 13036 | .arg => {}, |
| 13037 | .@"unreachable" => try function_block.writeAbbrev(FunctionBlock.Unreachable{}), |
| 13038 | .call, |
| 13039 | .@"musttail call", |
| 13040 | .@"notail call", |
| 13041 | .@"tail call", |
| 13042 | => |kind| { |
| 13043 | var extra = func.extraDataTrail(Function.Instruction.Call, datas[instr_index]); |
| 13044 | |
| 13045 | const call_conv = extra.data.info.call_conv; |
| 13046 | const args = extra.trail.next(extra.data.args_len, Value, &func); |
| 13047 | try function_block.writeAbbrevAdapted(FunctionBlock.Call{ |
| 13048 | .attributes = extra.data.attributes, |
| 13049 | .call_type = switch (kind) { |
| 13050 | .call => .{ .call_conv = call_conv }, |
| 13051 | .@"tail call" => .{ .tail = true, .call_conv = call_conv }, |
| 13052 | .@"musttail call" => .{ .must_tail = true, .call_conv = call_conv }, |
| 13053 | .@"notail call" => .{ .no_tail = true, .call_conv = call_conv }, |
| 13054 | else => unreachable, |
| 13055 | }, |
| 13056 | .type_id = extra.data.ty, |
| 13057 | .callee = extra.data.callee, |
| 13058 | .args = args, |
| 13059 | }, adapter); |
| 13060 | }, |
| 13061 | .@"call fast", |
| 13062 | .@"musttail call fast", |
| 13063 | .@"notail call fast", |
| 13064 | .@"tail call fast", |
| 13065 | => |kind| { |
| 13066 | var extra = func.extraDataTrail(Function.Instruction.Call, datas[instr_index]); |
| 13067 | |
| 13068 | const call_conv = extra.data.info.call_conv; |
| 13069 | const args = extra.trail.next(extra.data.args_len, Value, &func); |
| 13070 | try function_block.writeAbbrevAdapted(FunctionBlock.CallFast{ |
| 13071 | .attributes = extra.data.attributes, |
| 13072 | .call_type = switch (kind) { |
| 13073 | .call => .{ .call_conv = call_conv }, |
| 13074 | .@"tail call" => .{ .tail = true, .call_conv = call_conv }, |
| 13075 | .@"musttail call" => .{ .must_tail = true, .call_conv = call_conv }, |
| 13076 | .@"notail call" => .{ .no_tail = true, .call_conv = call_conv }, |
| 13077 | else => unreachable, |
| 13078 | }, |
| 13079 | .fast_math = .{}, |
| 13080 | .type_id = extra.data.ty, |
| 13081 | .callee = extra.data.callee, |
| 13082 | .args = args, |
| 13083 | }, adapter); |
| 13084 | }, |
| 13085 | .add, |
| 13086 | .@"add nsw", |
| 13087 | .@"add nuw", |
| 13088 | .@"add nuw nsw", |
| 13089 | .@"and", |
| 13090 | .fadd, |
| 13091 | .fdiv, |
| 13092 | .fmul, |
| 13093 | .mul, |
| 13094 | .@"mul nsw", |
| 13095 | .@"mul nuw", |
| 13096 | .@"mul nuw nsw", |
| 13097 | .frem, |
| 13098 | .fsub, |
| 13099 | .sdiv, |
| 13100 | .@"sdiv exact", |
| 13101 | .sub, |
| 13102 | .@"sub nsw", |
| 13103 | .@"sub nuw", |
| 13104 | .@"sub nuw nsw", |
| 13105 | .udiv, |
| 13106 | .@"udiv exact", |
| 13107 | .xor, |
| 13108 | .shl, |
| 13109 | .@"shl nsw", |
| 13110 | .@"shl nuw", |
| 13111 | .@"shl nuw nsw", |
| 13112 | .lshr, |
| 13113 | .@"lshr exact", |
| 13114 | .@"or", |
| 13115 | .urem, |
| 13116 | .srem, |
| 13117 | .ashr, |
| 13118 | .@"ashr exact", |
| 13119 | => { |
| 13120 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 13121 | try function_block.writeAbbrev(FunctionBlock.Binary{ |
| 13122 | .opcode = tag.toBinaryOpcode(), |
| 13123 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13124 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13125 | }); |
| 13126 | }, |
| 13127 | .@"fadd fast", |
| 13128 | .@"fdiv fast", |
| 13129 | .@"fmul fast", |
| 13130 | .@"frem fast", |
| 13131 | .@"fsub fast", |
| 13132 | => { |
| 13133 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 13134 | try function_block.writeAbbrev(FunctionBlock.BinaryFast{ |
| 13135 | .opcode = tag.toBinaryOpcode(), |
| 13136 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13137 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13138 | .fast_math = .{}, |
| 13139 | }); |
| 13140 | }, |
| 13141 | .alloca, |
| 13142 | .@"alloca inalloca", |
| 13143 | => |kind| { |
| 13144 | const extra = func.extraData(Function.Instruction.Alloca, datas[instr_index]); |
| 13145 | const alignment = extra.info.alignment.toLlvm(); |
| 13146 | try function_block.writeAbbrev(FunctionBlock.Alloca{ |
| 13147 | .inst_type = extra.type, |
| 13148 | .len_type = if (extra.len == .none) .i1 else extra.len.typeOf(@enumFromInt(func_index), self), |
| 13149 | .len_value = adapter.getValueIndex(if (extra.len == .none) Constant.true.toValue() else extra.len), |
| 13150 | .flags = .{ |
| 13151 | .align_lower = @truncate(alignment), |
| 13152 | .inalloca = kind == .@"alloca inalloca", |
| 13153 | .explicit_type = true, |
| 13154 | .swift_error = false, |
| 13155 | .align_upper = @truncate(alignment << 5), |
| 13156 | }, |
| 13157 | }); |
| 13158 | }, |
| 13159 | .bitcast, |
| 13160 | .inttoptr, |
| 13161 | .ptrtoint, |
| 13162 | .fptosi, |
| 13163 | .fptoui, |
| 13164 | .sitofp, |
| 13165 | .uitofp, |
| 13166 | .addrspacecast, |
| 13167 | .fptrunc, |
| 13168 | .trunc, |
| 13169 | .fpext, |
| 13170 | .sext, |
| 13171 | .zext, |
| 13172 | => { |
| 13173 | const extra = func.extraData(Function.Instruction.Cast, datas[instr_index]); |
| 13174 | try function_block.writeAbbrev(FunctionBlock.Cast{ |
| 13175 | .val = adapter.getOffsetValueIndex(extra.val), |
| 13176 | .type_index = extra.type, |
| 13177 | .opcode = tag.toCastOpcode(), |
| 13178 | }); |
| 13179 | }, |
| 13180 | .@"fcmp false", |
| 13181 | .@"fcmp oeq", |
| 13182 | .@"fcmp oge", |
| 13183 | .@"fcmp ogt", |
| 13184 | .@"fcmp ole", |
| 13185 | .@"fcmp olt", |
| 13186 | .@"fcmp one", |
| 13187 | .@"fcmp ord", |
| 13188 | .@"fcmp true", |
| 13189 | .@"fcmp ueq", |
| 13190 | .@"fcmp uge", |
| 13191 | .@"fcmp ugt", |
| 13192 | .@"fcmp ule", |
| 13193 | .@"fcmp ult", |
| 13194 | .@"fcmp une", |
| 13195 | .@"fcmp uno", |
| 13196 | .@"icmp eq", |
| 13197 | .@"icmp ne", |
| 13198 | .@"icmp sge", |
| 13199 | .@"icmp sgt", |
| 13200 | .@"icmp sle", |
| 13201 | .@"icmp slt", |
| 13202 | .@"icmp uge", |
| 13203 | .@"icmp ugt", |
| 13204 | .@"icmp ule", |
| 13205 | .@"icmp ult", |
| 13206 | => { |
| 13207 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 13208 | try function_block.writeAbbrev(FunctionBlock.Cmp{ |
| 13209 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13210 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13211 | .pred = tag.toCmpPredicate(), |
| 13212 | }); |
| 13213 | }, |
| 13214 | .@"fcmp fast false", |
| 13215 | .@"fcmp fast oeq", |
| 13216 | .@"fcmp fast oge", |
| 13217 | .@"fcmp fast ogt", |
| 13218 | .@"fcmp fast ole", |
| 13219 | .@"fcmp fast olt", |
| 13220 | .@"fcmp fast one", |
| 13221 | .@"fcmp fast ord", |
| 13222 | .@"fcmp fast true", |
| 13223 | .@"fcmp fast ueq", |
| 13224 | .@"fcmp fast uge", |
| 13225 | .@"fcmp fast ugt", |
| 13226 | .@"fcmp fast ule", |
| 13227 | .@"fcmp fast ult", |
| 13228 | .@"fcmp fast une", |
| 13229 | .@"fcmp fast uno", |
| 13230 | => { |
| 13231 | const extra = func.extraData(Function.Instruction.Binary, datas[instr_index]); |
| 13232 | try function_block.writeAbbrev(FunctionBlock.CmpFast{ |
| 13233 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13234 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13235 | .pred = tag.toCmpPredicate(), |
| 13236 | .fast_math = .{}, |
| 13237 | }); |
| 13238 | }, |
| 13239 | .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{ |
| 13240 | .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])), |
| 13241 | }), |
| 13242 | .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{ |
| 13243 | .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])), |
| 13244 | .fast_math = .{}, |
| 13245 | }), |
| 13246 | .extractvalue => { |
| 13247 | var extra = func.extraDataTrail(Function.Instruction.ExtractValue, datas[instr_index]); |
| 13248 | const indices = extra.trail.next(extra.data.indices_len, u32, &func); |
| 13249 | try function_block.writeAbbrev(FunctionBlock.ExtractValue{ |
| 13250 | .val = adapter.getOffsetValueIndex(extra.data.val), |
| 13251 | .indices = indices, |
| 13252 | }); |
| 13253 | }, |
| 13254 | .insertvalue => { |
| 13255 | var extra = func.extraDataTrail(Function.Instruction.InsertValue, datas[instr_index]); |
| 13256 | const indices = extra.trail.next(extra.data.indices_len, u32, &func); |
| 13257 | try function_block.writeAbbrev(FunctionBlock.InsertValue{ |
| 13258 | .val = adapter.getOffsetValueIndex(extra.data.val), |
| 13259 | .elem = adapter.getOffsetValueIndex(extra.data.elem), |
| 13260 | .indices = indices, |
| 13261 | }); |
| 13262 | }, |
| 13263 | .extractelement => { |
| 13264 | const extra = func.extraData(Function.Instruction.ExtractElement, datas[instr_index]); |
| 13265 | try function_block.writeAbbrev(FunctionBlock.ExtractElement{ |
| 13266 | .val = adapter.getOffsetValueIndex(extra.val), |
| 13267 | .index = adapter.getOffsetValueIndex(extra.index), |
| 13268 | }); |
| 13269 | }, |
| 13270 | .insertelement => { |
| 13271 | const extra = func.extraData(Function.Instruction.InsertElement, datas[instr_index]); |
| 13272 | try function_block.writeAbbrev(FunctionBlock.InsertElement{ |
| 13273 | .val = adapter.getOffsetValueIndex(extra.val), |
| 13274 | .elem = adapter.getOffsetValueIndex(extra.elem), |
| 13275 | .index = adapter.getOffsetValueIndex(extra.index), |
| 13276 | }); |
| 13277 | }, |
| 13278 | .select => { |
| 13279 | const extra = func.extraData(Function.Instruction.Select, datas[instr_index]); |
| 13280 | try function_block.writeAbbrev(FunctionBlock.Select{ |
| 13281 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13282 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13283 | .cond = adapter.getOffsetValueIndex(extra.cond), |
| 13284 | }); |
| 13285 | }, |
| 13286 | .@"select fast" => { |
| 13287 | const extra = func.extraData(Function.Instruction.Select, datas[instr_index]); |
| 13288 | try function_block.writeAbbrev(FunctionBlock.SelectFast{ |
| 13289 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13290 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13291 | .cond = adapter.getOffsetValueIndex(extra.cond), |
| 13292 | .fast_math = .{}, |
| 13293 | }); |
| 13294 | }, |
| 13295 | .shufflevector => { |
| 13296 | const extra = func.extraData(Function.Instruction.ShuffleVector, datas[instr_index]); |
| 13297 | try function_block.writeAbbrev(FunctionBlock.ShuffleVector{ |
| 13298 | .lhs = adapter.getOffsetValueIndex(extra.lhs), |
| 13299 | .rhs = adapter.getOffsetValueIndex(extra.rhs), |
| 13300 | .mask = adapter.getOffsetValueIndex(extra.mask), |
| 13301 | }); |
| 13302 | }, |
| 13303 | .getelementptr, |
| 13304 | .@"getelementptr inbounds", |
| 13305 | => { |
| 13306 | var extra = func.extraDataTrail(Function.Instruction.GetElementPtr, datas[instr_index]); |
| 13307 | const indices = extra.trail.next(extra.data.indices_len, Value, &func); |
| 13308 | try function_block.writeAbbrevAdapted( |
| 13309 | FunctionBlock.GetElementPtr{ |
| 13310 | .is_inbounds = tag == .@"getelementptr inbounds", |
| 13311 | .type_index = extra.data.type, |
| 13312 | .base = extra.data.base, |
| 13313 | .indices = indices, |
| 13314 | }, |
| 13315 | adapter, |
| 13316 | ); |
| 13317 | }, |
| 13318 | .load => { |
| 13319 | const extra = func.extraData(Function.Instruction.Load, datas[instr_index]); |
| 13320 | try function_block.writeAbbrev(FunctionBlock.Load{ |
| 13321 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 13322 | .ty = extra.type, |
| 13323 | .alignment = extra.info.alignment.toLlvm(), |
| 13324 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 13325 | }); |
| 13326 | }, |
| 13327 | .@"load atomic" => { |
| 13328 | const extra = func.extraData(Function.Instruction.Load, datas[instr_index]); |
| 13329 | try function_block.writeAbbrev(FunctionBlock.LoadAtomic{ |
| 13330 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 13331 | .ty = extra.type, |
| 13332 | .alignment = extra.info.alignment.toLlvm(), |
| 13333 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 13334 | .success_ordering = extra.info.success_ordering, |
| 13335 | .sync_scope = extra.info.sync_scope, |
| 13336 | }); |
| 13337 | }, |
| 13338 | .store => { |
| 13339 | const extra = func.extraData(Function.Instruction.Store, datas[instr_index]); |
| 13340 | try function_block.writeAbbrev(FunctionBlock.Store{ |
| 13341 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 13342 | .val = adapter.getOffsetValueIndex(extra.val), |
| 13343 | .alignment = extra.info.alignment.toLlvm(), |
| 13344 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 13345 | }); |
| 13346 | }, |
| 13347 | .@"store atomic" => { |
| 13348 | const extra = func.extraData(Function.Instruction.Store, datas[instr_index]); |
| 13349 | try function_block.writeAbbrev(FunctionBlock.StoreAtomic{ |
| 13350 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 13351 | .val = adapter.getOffsetValueIndex(extra.val), |
| 13352 | .alignment = extra.info.alignment.toLlvm(), |
| 13353 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 13354 | .success_ordering = extra.info.success_ordering, |
| 13355 | .sync_scope = extra.info.sync_scope, |
| 13356 | }); |
| 13357 | }, |
| 13358 | .br => { |
| 13359 | try function_block.writeAbbrev(FunctionBlock.BrUnconditional{ |
| 13360 | .block = datas[instr_index], |
| 13361 | }); |
| 13362 | }, |
| 13363 | .br_cond => { |
| 13364 | const extra = func.extraData(Function.Instruction.BrCond, datas[instr_index]); |
| 13365 | try function_block.writeAbbrev(FunctionBlock.BrConditional{ |
| 13366 | .then_block = @intFromEnum(extra.then), |
| 13367 | .else_block = @intFromEnum(extra.@"else"), |
| 13368 | .condition = adapter.getOffsetValueIndex(extra.cond), |
| 13369 | }); |
| 13370 | }, |
| 13371 | .@"switch" => { |
| 13372 | var extra = func.extraDataTrail(Function.Instruction.Switch, datas[instr_index]); |
| 13373 | |
| 13374 | try record.ensureUnusedCapacity(self.gpa, 3 + extra.data.cases_len * 2); |
| 13375 | |
| 13376 | // Conditional type |
| 13377 | record.appendAssumeCapacity(@intFromEnum(extra.data.val.typeOf(@enumFromInt(func_index), self))); |
| 13378 | |
| 13379 | // Conditional |
| 13380 | record.appendAssumeCapacity(adapter.getOffsetValueIndex(extra.data.val)); |
| 13381 | |
| 13382 | // Default block |
| 13383 | record.appendAssumeCapacity(@intFromEnum(extra.data.default)); |
| 13384 | |
| 13385 | const vals = extra.trail.next(extra.data.cases_len, Constant, &func); |
| 13386 | const blocks = extra.trail.next(extra.data.cases_len, Function.Block.Index, &func); |
| 13387 | for (vals, blocks) |val, block| { |
| 13388 | record.appendAssumeCapacity(adapter.constant_adapter.getConstantIndex(val)); |
| 13389 | record.appendAssumeCapacity(@intFromEnum(block)); |
| 13390 | } |
| 13391 | |
| 13392 | try function_block.writeUnabbrev(12, record.items); |
| 13393 | }, |
| 13394 | .va_arg => { |
| 13395 | const extra = func.extraData(Function.Instruction.VaArg, datas[instr_index]); |
| 13396 | try function_block.writeAbbrev(FunctionBlock.VaArg{ |
| 13397 | .list_type = extra.list.typeOf(@enumFromInt(func_index), self), |
| 13398 | .list = adapter.getOffsetValueIndex(extra.list), |
| 13399 | .type = extra.type, |
| 13400 | }); |
| 13401 | }, |
| 13402 | .phi, |
| 13403 | .@"phi fast", |
| 13404 | => |kind| { |
| 13405 | var extra = func.extraDataTrail(Function.Instruction.Phi, datas[instr_index]); |
| 13406 | const vals = extra.trail.next(block_incoming_len, Value, &func); |
| 13407 | const blocks = extra.trail.next(block_incoming_len, Function.Block.Index, &func); |
| 13408 | |
| 13409 | try record.ensureUnusedCapacity( |
| 13410 | self.gpa, |
| 13411 | 1 + block_incoming_len * 2 + @intFromBool(kind == .@"phi fast"), |
| 13412 | ); |
| 13413 | |
| 13414 | record.appendAssumeCapacity(@intFromEnum(extra.data.type)); |
| 13415 | |
| 13416 | for (vals, blocks) |val, block| { |
| 13417 | const offset_value = adapter.getOffsetValueSignedIndex(val); |
| 13418 | const abs_value: u32 = @intCast(@abs(offset_value)); |
| 13419 | const signed_vbr = if (offset_value > 0) abs_value << 1 else ((abs_value << 1) | 1); |
| 13420 | record.appendAssumeCapacity(signed_vbr); |
| 13421 | record.appendAssumeCapacity(@intFromEnum(block)); |
| 13422 | } |
| 13423 | |
| 13424 | if (kind == .@"phi fast") record.appendAssumeCapacity(@as(u8, @bitCast(FastMath{}))); |
| 13425 | |
| 13426 | try function_block.writeUnabbrev(16, record.items); |
| 13427 | }, |
| 13428 | .ret => try function_block.writeAbbrev(FunctionBlock.Ret{ |
| 13429 | .val = adapter.getOffsetValueIndex(@enumFromInt(datas[instr_index])), |
| 13430 | }), |
| 13431 | .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}), |
| 13432 | .atomicrmw => { |
| 13433 | const extra = func.extraData(Function.Instruction.AtomicRmw, datas[instr_index]); |
| 13434 | try function_block.writeAbbrev(FunctionBlock.AtomicRmw{ |
| 13435 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 13436 | .val = adapter.getOffsetValueIndex(extra.val), |
| 13437 | .operation = extra.info.atomic_rmw_operation, |
| 13438 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 13439 | .success_ordering = extra.info.success_ordering, |
| 13440 | .sync_scope = extra.info.sync_scope, |
| 13441 | .alignment = extra.info.alignment.toLlvm(), |
| 13442 | }); |
| 13443 | }, |
| 13444 | .cmpxchg, |
| 13445 | .@"cmpxchg weak", |
| 13446 | => |kind| { |
| 13447 | const extra = func.extraData(Function.Instruction.CmpXchg, datas[instr_index]); |
| 13448 | |
| 13449 | try function_block.writeAbbrev(FunctionBlock.CmpXchg{ |
| 13450 | .ptr = adapter.getOffsetValueIndex(extra.ptr), |
| 13451 | .cmp = adapter.getOffsetValueIndex(extra.cmp), |
| 13452 | .new = adapter.getOffsetValueIndex(extra.new), |
| 13453 | .is_volatile = extra.info.access_kind == .@"volatile", |
| 13454 | .success_ordering = extra.info.success_ordering, |
| 13455 | .sync_scope = extra.info.sync_scope, |
| 13456 | .failure_ordering = extra.info.failure_ordering, |
| 13457 | .is_weak = kind == .@"cmpxchg weak", |
| 13458 | .alignment = extra.info.alignment.toLlvm(), |
| 13459 | }); |
| 13460 | }, |
| 13461 | .fence => { |
| 13462 | const info: MemoryAccessInfo = @bitCast(datas[instr_index]); |
| 13463 | try function_block.writeAbbrev(FunctionBlock.Fence{ |
| 13464 | .ordering = info.success_ordering, |
| 13465 | .sync_scope = info.sync_scope, |
| 13466 | }); |
| 13467 | }, |
| 13468 | } |
| 13469 | |
| 13470 | adapter.next(); |
| 13471 | } |
| 13472 | |
| 13473 | // VALUE_SYMTAB |
| 13474 | if (!self.strip) { |
| 13475 | const ValueSymbolTable = IR.FunctionValueSymbolTable; |
| 13476 | |
| 13477 | var value_symtab_block = try function_block.enterSubBlock(ValueSymbolTable); |
| 13478 | |
| 13479 | for (func.blocks, 0..) |block, block_index| { |
| 13480 | const name = block.instruction.name(&func); |
| 13481 | |
| 13482 | if (name == .none or name == .empty) continue; |
| 13483 | |
| 13484 | try value_symtab_block.writeAbbrev(ValueSymbolTable.BlockEntry{ |
| 13485 | .value_id = @intCast(block_index), |
| 13486 | .string = name.slice(self).?, |
| 13487 | }); |
| 13488 | } |
| 13489 | |
| 13490 | // TODO: Emit non block entries if the builder ever starts assigning names to non blocks |
| 13491 | |
| 13492 | try value_symtab_block.end(); |
| 13493 | } |
| 13494 | |
| 13495 | try function_block.end(); |
| 13496 | } |
| 13497 | } |
| 13498 | |
| 13499 | try module_block.end(); |
| 13500 | } |
| 13501 | |
| 13502 | // STRTAB_BLOCK |
| 13503 | { |
| 13504 | const Strtab = IR.Strtab; |
| 13505 | var strtab_block = try bitcode.enterTopBlock(Strtab); |
| 13506 | |
| 13507 | try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.string_bytes.items }); |
| 13508 | |
| 13509 | try strtab_block.end(); |
| 13510 | } |
| 13511 | |
| 13512 | return bitcode.toSlice(); |
| 13513 | } |
| 13514 | |
| 12045 | 13515 | const assert = std.debug.assert; |
| 12046 | 13516 | const build_options = @import("build_options"); |
| 12047 | 13517 | const builtin = @import("builtin"); |
| ... | ... | @@ -12052,5 +13522,8 @@ else |
| 12052 | 13522 | const log = std.log.scoped(.llvm); |
| 12053 | 13523 | const std = @import("std"); |
| 12054 | 13524 | |
| 13525 | const bitcode_writer = @import("bitcode_writer.zig"); |
| 13526 | const IR = @import("IR.zig"); |
| 13527 | |
| 12055 | 13528 | const Allocator = std.mem.Allocator; |
| 12056 | 13529 | const Builder = @This(); |