authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-13 05:02:27-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-19 23:38:40-04:00
log3f46e747a8adc61d0274c1cafa8abe8d02e6b10b
treedb4642853517d69e23ae755597cf3791087fc667
parent8fde3a8f04e393b05879aff7afb9b09aadb4f2e1

llvm: convert basic block creation


3 files changed, 516 insertions(+), 309 deletions(-)

src/codegen/llvm.zig+221-228
......@@ -602,6 +602,7 @@ pub const Object = struct {
602602 var builder = try Builder.init(.{
603603 .allocator = gpa,
604604 .use_lib_llvm = options.use_lib_llvm,
605 .strip = options.strip,
605606 .name = options.root_name,
606607 .target = options.target,
607608 .triple = llvm_target_triple,
......@@ -682,7 +683,7 @@ pub const Object = struct {
682683
683684 target_machine = llvm.TargetMachine.create(
684685 builder.llvm.target.?,
685 builder.target_triple.toSlice(&builder).?.ptr,
686 builder.target_triple.toSlice(&builder).?,
686687 if (options.target.cpu.model.llvm_name) |s| s.ptr else null,
687688 options.llvm_cpu_features,
688689 opt_level,
......@@ -749,7 +750,6 @@ pub const Object = struct {
749750 self.named_enum_map.deinit(gpa);
750751 self.type_map.deinit(gpa);
751752 self.extern_collisions.deinit(gpa);
752 self.builder.deinit();
753753 self.* = undefined;
754754 }
755755
......@@ -850,22 +850,19 @@ pub const Object = struct {
850850 error_name_table_ptr_global.toLlvm(&o.builder).setInitializer(error_name_table_ptr);
851851 }
852852
853 fn genCmpLtErrorsLenFunction(object: *Object) !void {
853 fn genCmpLtErrorsLenFunction(o: *Object) !void {
854854 // If there is no such function in the module, it means the source code does not need it.
855 const llvm_fn = object.llvm_module.getNamedFunction(lt_errors_fn_name) orelse return;
856 const mod = object.module;
855 const name = o.builder.stringIfExists(lt_errors_fn_name) orelse return;
856 const llvm_fn = o.builder.getGlobal(name) orelse return;
857 const mod = o.module;
857858 const errors_len = mod.global_error_set.count();
858859
859 // Delete previous implementation. We replace it with every flush() because the
860 // total number of errors may have changed.
861 while (llvm_fn.getFirstBasicBlock()) |bb| {
862 bb.deleteBasicBlock();
863 }
860 var wip = Builder.WipFunction.init(&o.builder, llvm_fn.ptrConst(&o.builder).kind.function);
861 defer wip.deinit();
864862
865 const builder = object.context.createBuilder();
866
867 const entry_block = object.context.appendBasicBlock(llvm_fn, "Entry");
868 builder.positionBuilderAtEnd(entry_block);
863 const builder = wip.llvm.builder;
864 const entry_block = try wip.block("Entry");
865 builder.positionBuilderAtEnd(entry_block.toLlvm(&wip));
869866 builder.clearCurrentDebugLocation();
870867
871868 // Example source of the following LLVM IR:
......@@ -873,10 +870,12 @@ pub const Object = struct {
873870 // return index < total_errors_len;
874871 // }
875872
876 const lhs = llvm_fn.getParam(0);
877 const rhs = try object.builder.intConst(Builder.Type.err_int, errors_len);
878 const is_lt = builder.buildICmp(.ULT, lhs, rhs.toLlvm(&object.builder), "");
873 const lhs = llvm_fn.toLlvm(&o.builder).getParam(0);
874 const rhs = try o.builder.intConst(Builder.Type.err_int, errors_len);
875 const is_lt = builder.buildICmp(.ULT, lhs, rhs.toLlvm(&o.builder), "");
879876 _ = builder.buildRet(is_lt);
877
878 try wip.finish();
880879 }
881880
882881 fn genModuleLevelAssembly(object: *Object) !void {
......@@ -1158,11 +1157,14 @@ pub const Object = struct {
11581157 bb.deleteBasicBlock();
11591158 }
11601159
1161 const builder = o.context.createBuilder();
1160 var deinit_wip = true;
1161 var wip = Builder.WipFunction.init(&o.builder, function);
1162 defer if (deinit_wip) wip.deinit();
11621163
1163 function.ptr(&o.builder).body = {};
1164 const entry_block = o.context.appendBasicBlock(llvm_func, "Entry");
1165 builder.positionBuilderAtEnd(entry_block);
1164 const builder = wip.llvm.builder;
1165 const entry_block = try wip.block("Entry");
1166 wip.cursor = .{ .block = entry_block };
1167 builder.positionBuilderAtEnd(entry_block.toLlvm(&wip));
11661168
11671169 // This gets the LLVM values from the function and stores them in `dg.args`.
11681170 const fn_info = mod.typeToFunc(decl.ty).?;
......@@ -1260,8 +1262,7 @@ pub const Object = struct {
12601262 llvm_arg_i += 1;
12611263
12621264 const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder);
1263 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
1264 const int_llvm_ty = (try o.builder.intType(@intCast(abi_size * 8))).toLlvm(&o.builder);
1265 const int_llvm_ty = (try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8))).toLlvm(&o.builder);
12651266 const alignment = @max(
12661267 param_ty.abiAlignment(mod),
12671268 o.target_data.abiAlignmentOfType(int_llvm_ty),
......@@ -1317,11 +1318,10 @@ pub const Object = struct {
13171318 const param_alignment = param_ty.abiAlignment(mod);
13181319 const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, param_alignment, target);
13191320 const llvm_ty = (try o.builder.structType(.normal, field_types)).toLlvm(&o.builder);
1320 for (0..field_types.len) |field_i_usize| {
1321 const field_i = @as(c_uint, @intCast(field_i_usize));
1321 for (0..field_types.len) |field_i| {
13221322 const param = llvm_func.getParam(llvm_arg_i);
13231323 llvm_arg_i += 1;
1324 const field_ptr = builder.buildStructGEP(llvm_ty, arg_ptr, field_i, "");
1324 const field_ptr = builder.buildStructGEP(llvm_ty, arg_ptr, @intCast(field_i), "");
13251325 const store_inst = builder.buildStore(param, field_ptr);
13261326 store_inst.setAlignment(target.ptrBitWidth() / 8);
13271327 }
......@@ -1422,6 +1422,7 @@ pub const Object = struct {
14221422 .liveness = liveness,
14231423 .context = o.context,
14241424 .dg = &dg,
1425 .wip = wip,
14251426 .builder = builder,
14261427 .ret_ptr = ret_ptr,
14271428 .args = args.items,
......@@ -1438,6 +1439,7 @@ pub const Object = struct {
14381439 .err_ret_trace = err_ret_trace,
14391440 };
14401441 defer fg.deinit();
1442 deinit_wip = false;
14411443
14421444 fg.genBody(air.getMainBody()) catch |err| switch (err) {
14431445 error.CodegenFail => {
......@@ -1449,6 +1451,8 @@ pub const Object = struct {
14491451 else => |e| return e,
14501452 };
14511453
1454 try fg.wip.finish();
1455
14521456 try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
14531457 }
14541458
......@@ -1517,11 +1521,11 @@ pub const Object = struct {
15171521 if (self.di_map.get(decl)) |di_node| {
15181522 const decl_name_slice = decl_name.toSlice(&self.builder).?;
15191523 if (try decl.isFunction(mod)) {
1520 const di_func = @as(*llvm.DISubprogram, @ptrCast(di_node));
1524 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
15211525 const linkage_name = llvm.MDString.get(self.context, decl_name_slice.ptr, decl_name_slice.len);
15221526 di_func.replaceLinkageName(linkage_name);
15231527 } else {
1524 const di_global = @as(*llvm.DIGlobalVariable, @ptrCast(di_node));
1528 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
15251529 const linkage_name = llvm.MDString.get(self.context, decl_name_slice.ptr, decl_name_slice.len);
15261530 di_global.replaceLinkageName(linkage_name);
15271531 }
......@@ -1554,11 +1558,11 @@ pub const Object = struct {
15541558 if (self.di_map.get(decl)) |di_node| {
15551559 const exp_name_slice = exp_name.toSlice(&self.builder).?;
15561560 if (try decl.isFunction(mod)) {
1557 const di_func = @as(*llvm.DISubprogram, @ptrCast(di_node));
1561 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
15581562 const linkage_name = llvm.MDString.get(self.context, exp_name_slice.ptr, exp_name_slice.len);
15591563 di_func.replaceLinkageName(linkage_name);
15601564 } else {
1561 const di_global = @as(*llvm.DIGlobalVariable, @ptrCast(di_node));
1565 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
15621566 const linkage_name = llvm.MDString.get(self.context, exp_name_slice.ptr, exp_name_slice.len);
15631567 di_global.replaceLinkageName(linkage_name);
15641568 }
......@@ -1661,7 +1665,7 @@ pub const Object = struct {
16611665 const gop = try o.di_map.getOrPut(gpa, file);
16621666 errdefer assert(o.di_map.remove(file));
16631667 if (gop.found_existing) {
1664 return @as(*llvm.DIFile, @ptrCast(gop.value_ptr.*));
1668 return @ptrCast(gop.value_ptr.*);
16651669 }
16661670 const dir_path_z = d: {
16671671 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
......@@ -1809,7 +1813,7 @@ pub const Object = struct {
18091813 ty.abiSize(mod) * 8,
18101814 ty.abiAlignment(mod) * 8,
18111815 enumerators.ptr,
1812 @as(c_int, @intCast(enumerators.len)),
1816 @intCast(enumerators.len),
18131817 try o.lowerDebugType(int_ty, .full),
18141818 "",
18151819 );
......@@ -1984,7 +1988,7 @@ pub const Object = struct {
19841988 ty.abiSize(mod) * 8,
19851989 ty.abiAlignment(mod) * 8,
19861990 try o.lowerDebugType(ty.childType(mod), .full),
1987 @as(i64, @intCast(ty.arrayLen(mod))),
1991 @intCast(ty.arrayLen(mod)),
19881992 );
19891993 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
19901994 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty));
......@@ -2289,7 +2293,7 @@ pub const Object = struct {
22892293 0, // flags
22902294 null, // derived from
22912295 di_fields.items.ptr,
2292 @as(c_int, @intCast(di_fields.items.len)),
2296 @intCast(di_fields.items.len),
22932297 0, // run time lang
22942298 null, // vtable holder
22952299 "", // unique id
......@@ -2376,7 +2380,7 @@ pub const Object = struct {
23762380 0, // flags
23772381 null, // derived from
23782382 di_fields.items.ptr,
2379 @as(c_int, @intCast(di_fields.items.len)),
2383 @intCast(di_fields.items.len),
23802384 0, // run time lang
23812385 null, // vtable holder
23822386 "", // unique id
......@@ -2488,7 +2492,7 @@ pub const Object = struct {
24882492 ty.abiAlignment(mod) * 8, // align in bits
24892493 0, // flags
24902494 di_fields.items.ptr,
2491 @as(c_int, @intCast(di_fields.items.len)),
2495 @intCast(di_fields.items.len),
24922496 0, // run time lang
24932497 "", // unique id
24942498 );
......@@ -2601,7 +2605,7 @@ pub const Object = struct {
26012605
26022606 const fn_di_ty = dib.createSubroutineType(
26032607 param_di_types.items.ptr,
2604 @as(c_int, @intCast(param_di_types.items.len)),
2608 @intCast(param_di_types.items.len),
26052609 0,
26062610 );
26072611 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
......@@ -4248,9 +4252,9 @@ pub const Object = struct {
42484252 ) void {
42494253 const llvm_attr = o.context.createStringAttribute(
42504254 name.ptr,
4251 @as(c_uint, @intCast(name.len)),
4255 @intCast(name.len),
42524256 value.ptr,
4253 @as(c_uint, @intCast(value.len)),
4257 @intCast(value.len),
42544258 );
42554259 val.addAttributeAtIndex(index, llvm_attr);
42564260 }
......@@ -4364,11 +4368,7 @@ pub const Object = struct {
43644368 }
43654369
43664370 const entry_block = llvm_func.getFirstBasicBlock().?;
4367 if (entry_block.getFirstInstruction()) |first_inst| {
4368 builder.positionBuilder(entry_block, first_inst);
4369 } else {
4370 builder.positionBuilderAtEnd(entry_block);
4371 }
4371 builder.positionBuilder(entry_block, entry_block.getFirstInstruction());
43724372 builder.clearCurrentDebugLocation();
43734373
43744374 break :blk builder.buildAllocaInAddressSpace(llvm_ty, @intFromEnum(address_space), "");
......@@ -4502,6 +4502,7 @@ pub const FuncGen = struct {
45024502 dg: *DeclGen,
45034503 air: Air,
45044504 liveness: Liveness,
4505 wip: Builder.WipFunction,
45054506 context: *llvm.Context,
45064507 builder: *llvm.Builder,
45074508 di_scope: ?*llvm.DIScope,
......@@ -4542,7 +4543,7 @@ pub const FuncGen = struct {
45424543
45434544 /// This data structure is used to implement breaking to blocks.
45444545 blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
4545 parent_bb: *llvm.BasicBlock,
4546 parent_bb: Builder.Function.Block.Index,
45464547 breaks: *BreakList,
45474548 }),
45484549
......@@ -4555,7 +4556,7 @@ pub const FuncGen = struct {
45554556 });
45564557
45574558 fn deinit(self: *FuncGen) void {
4558 self.builder.dispose();
4559 self.wip.deinit();
45594560 self.dbg_inlined.deinit(self.gpa);
45604561 self.dbg_block_stack.deinit(self.gpa);
45614562 self.func_inst_table.deinit(self.gpa);
......@@ -4898,7 +4899,7 @@ pub const FuncGen = struct {
48984899 fn airCall(self: *FuncGen, inst: Air.Inst.Index, attr: llvm.CallAttr) !?*llvm.Value {
48994900 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
49004901 const extra = self.air.extraData(Air.Call, pl_op.payload);
4901 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
4902 const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);
49024903 const o = self.dg.object;
49034904 const mod = o.module;
49044905 const ip = &mod.intern_pool;
......@@ -4987,8 +4988,7 @@ pub const FuncGen = struct {
49874988 const arg = args[it.zig_index - 1];
49884989 const param_ty = self.typeOf(arg);
49894990 const llvm_arg = try self.resolveInst(arg);
4990 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
4991 const int_llvm_ty = (try o.builder.intType(@intCast(abi_size * 8))).toLlvm(&o.builder);
4991 const int_llvm_ty = (try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8))).toLlvm(&o.builder);
49924992
49934993 if (isByRef(param_ty, mod)) {
49944994 const alignment = param_ty.abiAlignment(mod);
......@@ -5034,9 +5034,8 @@ pub const FuncGen = struct {
50345034
50355035 const llvm_ty = (try o.builder.structType(.normal, llvm_types)).toLlvm(&o.builder);
50365036 try llvm_args.ensureUnusedCapacity(it.types_len);
5037 for (llvm_types, 0..) |field_ty, i_usize| {
5038 const i = @as(c_uint, @intCast(i_usize));
5039 const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, i, "");
5037 for (llvm_types, 0..) |field_ty, i| {
5038 const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, @intCast(i), "");
50405039 const load_inst = self.builder.buildLoad(field_ty.toLlvm(&o.builder), field_ptr, "");
50415040 load_inst.setAlignment(target.ptrBitWidth() / 8);
50425041 llvm_args.appendAssumeCapacity(load_inst);
......@@ -5091,7 +5090,7 @@ pub const FuncGen = struct {
50915090 (try o.lowerType(zig_fn_ty)).toLlvm(&o.builder),
50925091 llvm_fn,
50935092 llvm_args.items.ptr,
5094 @as(c_uint, @intCast(llvm_args.items.len)),
5093 @intCast(llvm_args.items.len),
50955094 toLlvmCallConv(fn_info.cc, target),
50965095 attr,
50975096 "",
......@@ -5256,7 +5255,7 @@ pub const FuncGen = struct {
52565255 const operand = try self.resolveInst(un_op);
52575256 const ptr_ty = try mod.singleMutPtrType(ret_ty);
52585257 try self.store(ret_ptr, ptr_ty, operand, .NotAtomic);
5259 _ = self.builder.buildRetVoid();
5258 try self.wip.retVoid();
52605259 return null;
52615260 }
52625261 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
......@@ -5268,7 +5267,7 @@ pub const FuncGen = struct {
52685267 const int = try o.builder.intConst(Builder.Type.err_int, 0);
52695268 _ = self.builder.buildRet(int.toLlvm(&o.builder));
52705269 } else {
5271 _ = self.builder.buildRetVoid();
5270 try self.wip.retVoid();
52725271 }
52735272 return null;
52745273 }
......@@ -5316,12 +5315,12 @@ pub const FuncGen = struct {
53165315 const int = try o.builder.intConst(Builder.Type.err_int, 0);
53175316 _ = self.builder.buildRet(int.toLlvm(&o.builder));
53185317 } else {
5319 _ = self.builder.buildRetVoid();
5318 try self.wip.retVoid();
53205319 }
53215320 return null;
53225321 }
53235322 if (self.ret_ptr != null) {
5324 _ = self.builder.buildRetVoid();
5323 try self.wip.retVoid();
53255324 return null;
53265325 }
53275326 const ptr = try self.resolveInst(un_op);
......@@ -5476,33 +5475,33 @@ pub const FuncGen = struct {
54765475 const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2.toLlvm(&o.builder), "");
54775476 const lhs_shifted = self.builder.buildShl(lhs_non_null_i2, (try o.builder.intConst(llvm_i2, 1)).toLlvm(&o.builder), "");
54785477 const lhs_rhs_ored = self.builder.buildOr(lhs_shifted, rhs_non_null_i2, "");
5479 const both_null_block = self.context.appendBasicBlock(self.llvm_func, "BothNull");
5480 const mixed_block = self.context.appendBasicBlock(self.llvm_func, "Mixed");
5481 const both_pl_block = self.context.appendBasicBlock(self.llvm_func, "BothNonNull");
5482 const end_block = self.context.appendBasicBlock(self.llvm_func, "End");
5483 const llvm_switch = self.builder.buildSwitch(lhs_rhs_ored, mixed_block, 2);
5478 const both_null_block = try self.wip.block("BothNull");
5479 const mixed_block = try self.wip.block("Mixed");
5480 const both_pl_block = try self.wip.block("BothNonNull");
5481 const end_block = try self.wip.block("End");
5482 const llvm_switch = self.builder.buildSwitch(lhs_rhs_ored, mixed_block.toLlvm(&self.wip), 2);
54845483 const llvm_i2_00 = try o.builder.intConst(llvm_i2, 0b00);
54855484 const llvm_i2_11 = try o.builder.intConst(llvm_i2, 0b11);
5486 llvm_switch.addCase(llvm_i2_00.toLlvm(&o.builder), both_null_block);
5487 llvm_switch.addCase(llvm_i2_11.toLlvm(&o.builder), both_pl_block);
5485 llvm_switch.addCase(llvm_i2_00.toLlvm(&o.builder), both_null_block.toLlvm(&self.wip));
5486 llvm_switch.addCase(llvm_i2_11.toLlvm(&o.builder), both_pl_block.toLlvm(&self.wip));
54885487
5489 self.builder.positionBuilderAtEnd(both_null_block);
5490 _ = self.builder.buildBr(end_block);
5488 self.builder.positionBuilderAtEnd(both_null_block.toLlvm(&self.wip));
5489 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
54915490
5492 self.builder.positionBuilderAtEnd(mixed_block);
5493 _ = self.builder.buildBr(end_block);
5491 self.builder.positionBuilderAtEnd(mixed_block.toLlvm(&self.wip));
5492 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
54945493
5495 self.builder.positionBuilderAtEnd(both_pl_block);
5494 self.builder.positionBuilderAtEnd(both_pl_block.toLlvm(&self.wip));
54965495 const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true);
54975496 const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty, true);
54985497 const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op);
5499 _ = self.builder.buildBr(end_block);
5498 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
55005499 const both_pl_block_end = self.builder.getInsertBlock();
55015500
5502 self.builder.positionBuilderAtEnd(end_block);
5501 self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip));
55035502 const incoming_blocks: [3]*llvm.BasicBlock = .{
5504 both_null_block,
5505 mixed_block,
5503 both_null_block.toLlvm(&self.wip),
5504 mixed_block.toLlvm(&self.wip),
55065505 both_pl_block_end,
55075506 };
55085507 const llvm_i1_0 = Builder.Constant.false.toLlvm(&o.builder);
......@@ -5552,7 +5551,6 @@ pub const FuncGen = struct {
55525551 const extra = self.air.extraData(Air.Block, ty_pl.payload);
55535552 const body = self.air.extra[extra.end..][0..extra.data.body_len];
55545553 const inst_ty = self.typeOfIndex(inst);
5555 const parent_bb = self.context.createBasicBlock("Block");
55565554
55575555 if (inst_ty.isNoReturn(mod)) {
55585556 try self.genBody(body);
......@@ -5562,6 +5560,7 @@ pub const FuncGen = struct {
55625560 var breaks: BreakList = .{};
55635561 defer breaks.deinit(self.gpa);
55645562
5563 const parent_bb = try self.wip.block("Block");
55655564 try self.blocks.putNoClobber(self.gpa, inst, .{
55665565 .parent_bb = parent_bb,
55675566 .breaks = &breaks,
......@@ -5570,8 +5569,7 @@ pub const FuncGen = struct {
55705569
55715570 try self.genBody(body);
55725571
5573 self.llvm_func.appendExistingBasicBlock(parent_bb);
5574 self.builder.positionBuilderAtEnd(parent_bb);
5572 self.builder.positionBuilderAtEnd(parent_bb.toLlvm(&self.wip));
55755573
55765574 // Create a phi node only if the block returns a value.
55775575 const is_body = inst_ty.zigTypeTag(mod) == .Fn;
......@@ -5585,7 +5583,7 @@ pub const FuncGen = struct {
55855583 // of function pointers, however the phi makes it a runtime value and therefore
55865584 // the LLVM type has to be wrapped in a pointer.
55875585 if (is_body or isByRef(inst_ty, mod)) {
5588 break :ty self.context.pointerType(0);
5586 break :ty Builder.Type.ptr.toLlvm(&o.builder);
55895587 }
55905588 break :ty raw_llvm_ty;
55915589 };
......@@ -5594,7 +5592,7 @@ pub const FuncGen = struct {
55945592 phi_node.addIncoming(
55955593 breaks.items(.val).ptr,
55965594 breaks.items(.bb).ptr,
5597 @as(c_uint, @intCast(breaks.len)),
5595 @intCast(breaks.len),
55985596 );
55995597 return phi_node;
56005598 }
......@@ -5617,7 +5615,7 @@ pub const FuncGen = struct {
56175615 .val = val,
56185616 });
56195617 }
5620 _ = self.builder.buildBr(block.parent_bb);
5618 _ = self.builder.buildBr(block.parent_bb.toLlvm(&self.wip));
56215619 return null;
56225620 }
56235621
......@@ -5628,14 +5626,14 @@ pub const FuncGen = struct {
56285626 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
56295627 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
56305628
5631 const then_block = self.context.appendBasicBlock(self.llvm_func, "Then");
5632 const else_block = self.context.appendBasicBlock(self.llvm_func, "Else");
5633 _ = self.builder.buildCondBr(cond, then_block, else_block);
5629 const then_block = try self.wip.block("Then");
5630 const else_block = try self.wip.block("Else");
5631 _ = self.builder.buildCondBr(cond, then_block.toLlvm(&self.wip), else_block.toLlvm(&self.wip));
56345632
5635 self.builder.positionBuilderAtEnd(then_block);
5633 self.builder.positionBuilderAtEnd(then_block.toLlvm(&self.wip));
56365634 try self.genBody(then_body);
56375635
5638 self.builder.positionBuilderAtEnd(else_block);
5636 self.builder.positionBuilderAtEnd(else_block.toLlvm(&self.wip));
56395637 try self.genBody(else_body);
56405638
56415639 // No need to reset the insert cursor since this instruction is noreturn.
......@@ -5707,14 +5705,14 @@ pub const FuncGen = struct {
57075705 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
57085706 };
57095707
5710 const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet");
5711 const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont");
5712 _ = fg.builder.buildCondBr(is_err, return_block, continue_block);
5708 const return_block = try fg.wip.block("TryRet");
5709 const continue_block = try fg.wip.block("TryCont");
5710 _ = fg.builder.buildCondBr(is_err, return_block.toLlvm(&fg.wip), continue_block.toLlvm(&fg.wip));
57135711
5714 fg.builder.positionBuilderAtEnd(return_block);
5712 fg.builder.positionBuilderAtEnd(return_block.toLlvm(&fg.wip));
57155713 try fg.genBody(body);
57165714
5717 fg.builder.positionBuilderAtEnd(continue_block);
5715 fg.builder.positionBuilderAtEnd(continue_block.toLlvm(&fg.wip));
57185716 }
57195717 if (is_unused) {
57205718 return null;
......@@ -5745,24 +5743,24 @@ pub const FuncGen = struct {
57455743 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
57465744 const cond = try self.resolveInst(pl_op.operand);
57475745 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
5748 const else_block = self.context.appendBasicBlock(self.llvm_func, "Else");
5746 const else_block = try self.wip.block("Else");
57495747 const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder);
57505748 const cond_int = if (cond.typeOf().getTypeKind() == .Pointer)
57515749 self.builder.buildPtrToInt(cond, llvm_usize, "")
57525750 else
57535751 cond;
5754 const llvm_switch = self.builder.buildSwitch(cond_int, else_block, switch_br.data.cases_len);
5752 const llvm_switch = self.builder.buildSwitch(cond_int, else_block.toLlvm(&self.wip), switch_br.data.cases_len);
57555753
57565754 var extra_index: usize = switch_br.end;
57575755 var case_i: u32 = 0;
57585756
57595757 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
57605758 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);
5761 const items = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[case.end..][0..case.data.items_len]));
5759 const items: []const Air.Inst.Ref = @ptrCast(self.air.extra[case.end..][0..case.data.items_len]);
57625760 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];
57635761 extra_index = case.end + case.data.items_len + case_body.len;
57645762
5765 const case_block = self.context.appendBasicBlock(self.llvm_func, "Case");
5763 const case_block = try self.wip.block("Case");
57665764
57675765 for (items) |item| {
57685766 const llvm_item = try self.resolveInst(item);
......@@ -5770,14 +5768,14 @@ pub const FuncGen = struct {
57705768 llvm_item.constPtrToInt(llvm_usize)
57715769 else
57725770 llvm_item;
5773 llvm_switch.addCase(llvm_int_item, case_block);
5771 llvm_switch.addCase(llvm_int_item, case_block.toLlvm(&self.wip));
57745772 }
57755773
5776 self.builder.positionBuilderAtEnd(case_block);
5774 self.builder.positionBuilderAtEnd(case_block.toLlvm(&self.wip));
57775775 try self.genBody(case_body);
57785776 }
57795777
5780 self.builder.positionBuilderAtEnd(else_block);
5778 self.builder.positionBuilderAtEnd(else_block.toLlvm(&self.wip));
57815779 const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len];
57825780 if (else_body.len != 0) {
57835781 try self.genBody(else_body);
......@@ -5795,10 +5793,10 @@ pub const FuncGen = struct {
57955793 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
57965794 const loop = self.air.extraData(Air.Block, ty_pl.payload);
57975795 const body = self.air.extra[loop.end..][0..loop.data.body_len];
5798 const loop_block = self.context.appendBasicBlock(self.llvm_func, "Loop");
5799 _ = self.builder.buildBr(loop_block);
5796 const loop_block = try self.wip.block("Loop");
5797 _ = self.builder.buildBr(loop_block.toLlvm(&self.wip));
58005798
5801 self.builder.positionBuilderAtEnd(loop_block);
5799 self.builder.positionBuilderAtEnd(loop_block.toLlvm(&self.wip));
58025800 try self.genBody(body);
58035801
58045802 // TODO instead of this logic, change AIR to have the property that
......@@ -5808,7 +5806,7 @@ pub const FuncGen = struct {
58085806 // be while(true) instead of for(body), which will eliminate 1 branch on
58095807 // a hot path.
58105808 if (body.len == 0 or !self.typeOfIndex(body[body.len - 1]).isNoReturn(mod)) {
5811 _ = self.builder.buildBr(loop_block);
5809 _ = self.builder.buildBr(loop_block.toLlvm(&self.wip));
58125810 }
58135811 return null;
58145812 }
......@@ -5858,8 +5856,7 @@ pub const FuncGen = struct {
58585856 }
58595857 }
58605858
5861 const operand_bits = @as(u16, @intCast(operand_scalar_ty.bitSize(mod)));
5862 const rt_int_bits = compilerRtIntBits(operand_bits);
5859 const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(mod)));
58635860 const rt_int_ty = try o.builder.intType(rt_int_bits);
58645861 var extended = e: {
58655862 if (operand_scalar_ty.isSignedInt(mod)) {
......@@ -6193,13 +6190,11 @@ pub const FuncGen = struct {
61936190 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
61946191 const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder);
61956192 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
6196 const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod)));
6197 const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder);
6193 const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder);
61986194 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
61996195 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
62006196 } else if (field_ty.isPtrAtRuntime(mod)) {
6201 const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod)));
6202 const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder);
6197 const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder);
62036198 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
62046199 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
62056200 }
......@@ -6215,13 +6210,11 @@ pub const FuncGen = struct {
62156210 const containing_int = struct_llvm_val;
62166211 const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder);
62176212 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
6218 const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod)));
6219 const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder);
6213 const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder);
62206214 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");
62216215 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
62226216 } else if (field_ty.isPtrAtRuntime(mod)) {
6223 const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod)));
6224 const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder);
6217 const same_size_int = (try o.builder.intType(@intCast(field_ty.bitSize(mod)))).toLlvm(&o.builder);
62256218 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");
62266219 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
62276220 }
......@@ -6310,8 +6303,8 @@ pub const FuncGen = struct {
63106303 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) ?*llvm.Value {
63116304 const di_scope = self.di_scope orelse return null;
63126305 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
6313 self.prev_dbg_line = @as(c_uint, @intCast(self.base_line + dbg_stmt.line + 1));
6314 self.prev_dbg_column = @as(c_uint, @intCast(dbg_stmt.column + 1));
6306 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
6307 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);
63156308 const inlined_at = if (self.dbg_inlined.items.len > 0)
63166309 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
63176310 else
......@@ -6491,12 +6484,12 @@ pub const FuncGen = struct {
64916484 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
64926485 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
64936486 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
6494 const clobbers_len = @as(u31, @truncate(extra.data.flags));
6487 const clobbers_len: u31 = @truncate(extra.data.flags);
64956488 var extra_i: usize = extra.end;
64966489
6497 const outputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]));
6490 const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]);
64986491 extra_i += outputs.len;
6499 const inputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]));
6492 const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]);
65006493 extra_i += inputs.len;
65016494
65026495 var llvm_constraints: std.ArrayListUnmanaged(u8) = .{};
......@@ -6779,7 +6772,7 @@ pub const FuncGen = struct {
67796772 const llvm_fn_ty = llvm.functionType(
67806773 ret_llvm_ty.toLlvm(&o.builder),
67816774 llvm_param_types.ptr,
6782 @as(c_uint, @intCast(param_count)),
6775 @intCast(param_count),
67836776 .False,
67846777 );
67856778 const asm_fn = llvm.getInlineAsm(
......@@ -6797,7 +6790,7 @@ pub const FuncGen = struct {
67976790 llvm_fn_ty,
67986791 asm_fn,
67996792 llvm_param_values.ptr,
6800 @as(c_uint, @intCast(param_count)),
6793 @intCast(param_count),
68016794 .C,
68026795 .Auto,
68036796 "",
......@@ -6814,7 +6807,7 @@ pub const FuncGen = struct {
68146807 if (llvm_ret_indirect[i]) continue;
68156808
68166809 const output_value = if (return_count > 1) b: {
6817 break :b self.builder.buildExtractValue(call, @as(c_uint, @intCast(llvm_ret_i)), "");
6810 break :b self.builder.buildExtractValue(call, @intCast(llvm_ret_i), "");
68186811 } else call;
68196812
68206813 if (output != .none) {
......@@ -7364,14 +7357,14 @@ pub const FuncGen = struct {
73647357 false => fg.builder.buildOrReduce(overflow_bit),
73657358 };
73667359
7367 const fail_block = fg.context.appendBasicBlock(fg.llvm_func, "OverflowFail");
7368 const ok_block = fg.context.appendBasicBlock(fg.llvm_func, "OverflowOk");
7369 _ = fg.builder.buildCondBr(scalar_overflow_bit, fail_block, ok_block);
7360 const fail_block = try fg.wip.block("OverflowFail");
7361 const ok_block = try fg.wip.block("OverflowOk");
7362 _ = fg.builder.buildCondBr(scalar_overflow_bit, fail_block.toLlvm(&fg.wip), ok_block.toLlvm(&fg.wip));
73707363
7371 fg.builder.positionBuilderAtEnd(fail_block);
7364 fg.builder.positionBuilderAtEnd(fail_block.toLlvm(&fg.wip));
73727365 try fg.buildSimplePanic(.integer_overflow);
73737366
7374 fg.builder.positionBuilderAtEnd(ok_block);
7367 fg.builder.positionBuilderAtEnd(ok_block.toLlvm(&fg.wip));
73757368 return fg.builder.buildExtractValue(result_struct, 0, "");
73767369 }
73777370
......@@ -7729,8 +7722,7 @@ pub const FuncGen = struct {
77297722 vector_len: usize,
77307723 ) !*llvm.Value {
77317724 const o = self.dg.object;
7732 const args_len = @as(c_uint, @intCast(args_vectors.len));
7733 assert(args_len <= 3);
7725 assert(args_vectors.len <= 3);
77347726
77357727 var i: usize = 0;
77367728 var result = result_vector;
......@@ -7741,7 +7733,7 @@ pub const FuncGen = struct {
77417733 for (args_vectors, 0..) |arg_vector, k| {
77427734 args[k] = self.builder.buildExtractElement(arg_vector, index_i32, "");
77437735 }
7744 const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args_len, .C, .Auto, "");
7736 const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, @intCast(args_vectors.len), .C, .Auto, "");
77457737 result = self.builder.buildInsertElement(result, result_elem, index_i32, "");
77467738 }
77477739 return result;
......@@ -8744,8 +8736,8 @@ pub const FuncGen = struct {
87448736 return null;
87458737 const ordering = toLlvmAtomicOrdering(atomic_load.order);
87468738 const abi_ty = try o.getAtomicAbiType(elem_ty, false);
8747 const ptr_alignment = @as(u32, @intCast(ptr_info.flags.alignment.toByteUnitsOptional() orelse
8748 ptr_info.child.toType().abiAlignment(mod)));
8739 const ptr_alignment: u32 = @intCast(ptr_info.flags.alignment.toByteUnitsOptional() orelse
8740 ptr_info.child.toType().abiAlignment(mod));
87498741 const ptr_volatile = llvm.Bool.fromBool(ptr_info.flags.is_volatile);
87508742 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
87518743
......@@ -8887,9 +8879,9 @@ pub const FuncGen = struct {
88878879 // end:
88888880 // ...
88898881 const entry_block = self.builder.getInsertBlock();
8890 const loop_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetLoop");
8891 const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody");
8892 const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd");
8882 const loop_block = try self.wip.block("InlineMemsetLoop");
8883 const body_block = try self.wip.block("InlineMemsetBody");
8884 const end_block = try self.wip.block("InlineMemsetEnd");
88938885
88948886 const usize_ty = try o.lowerType(Type.usize);
88958887 const len = switch (ptr_ty.ptrSize(mod)) {
......@@ -8900,14 +8892,14 @@ pub const FuncGen = struct {
89008892 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
89018893 const len_gep = [_]*llvm.Value{len};
89028894 const end_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, dest_ptr, &len_gep, len_gep.len, "");
8903 _ = self.builder.buildBr(loop_block);
8895 _ = self.builder.buildBr(loop_block.toLlvm(&self.wip));
89048896
8905 self.builder.positionBuilderAtEnd(loop_block);
8906 const it_ptr = self.builder.buildPhi(self.context.pointerType(0), "");
8897 self.builder.positionBuilderAtEnd(loop_block.toLlvm(&self.wip));
8898 const it_ptr = self.builder.buildPhi(Builder.Type.ptr.toLlvm(&o.builder), "");
89078899 const end = self.builder.buildICmp(.NE, it_ptr, end_ptr, "");
8908 _ = self.builder.buildCondBr(end, body_block, end_block);
8900 _ = self.builder.buildCondBr(end, body_block.toLlvm(&self.wip), end_block.toLlvm(&self.wip));
89098901
8910 self.builder.positionBuilderAtEnd(body_block);
8902 self.builder.positionBuilderAtEnd(body_block.toLlvm(&self.wip));
89118903 const elem_abi_alignment = elem_ty.abiAlignment(mod);
89128904 const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align);
89138905 if (isByRef(elem_ty, mod)) {
......@@ -8928,12 +8920,12 @@ pub const FuncGen = struct {
89288920 (try o.builder.intConst(usize_ty, 1)).toLlvm(&o.builder),
89298921 };
89308922 const next_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, it_ptr, &one_gep, one_gep.len, "");
8931 _ = self.builder.buildBr(loop_block);
8923 _ = self.builder.buildBr(loop_block.toLlvm(&self.wip));
89328924
8933 self.builder.positionBuilderAtEnd(end_block);
8925 self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip));
89348926
89358927 const incoming_values: [2]*llvm.Value = .{ next_ptr, dest_ptr };
8936 const incoming_blocks: [2]*llvm.BasicBlock = .{ body_block, entry_block };
8928 const incoming_blocks: [2]*llvm.BasicBlock = .{ body_block.toLlvm(&self.wip), entry_block };
89378929 it_ptr.addIncoming(&incoming_values, &incoming_blocks, 2);
89388930
89398931 return null;
......@@ -8950,13 +8942,13 @@ pub const FuncGen = struct {
89508942 const o = self.dg.object;
89518943 const llvm_usize_ty = try o.lowerType(Type.usize);
89528944 const cond = try self.cmp(len, (try o.builder.intConst(llvm_usize_ty, 0)).toLlvm(&o.builder), Type.usize, .neq);
8953 const memset_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapSkip");
8954 const end_block = self.context.appendBasicBlock(self.llvm_func, "MemsetTrapEnd");
8955 _ = self.builder.buildCondBr(cond, memset_block, end_block);
8956 self.builder.positionBuilderAtEnd(memset_block);
8945 const memset_block = try self.wip.block("MemsetTrapSkip");
8946 const end_block = try self.wip.block("MemsetTrapEnd");
8947 _ = self.builder.buildCondBr(cond, memset_block.toLlvm(&self.wip), end_block.toLlvm(&self.wip));
8948 self.builder.positionBuilderAtEnd(memset_block.toLlvm(&self.wip));
89578949 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
8958 _ = self.builder.buildBr(end_block);
8959 self.builder.positionBuilderAtEnd(end_block);
8950 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
8951 self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip));
89608952 }
89618953
89628954 fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
......@@ -8983,10 +8975,10 @@ pub const FuncGen = struct {
89838975 {
89848976 const llvm_usize_ty = try o.lowerType(Type.usize);
89858977 const cond = try self.cmp(len, (try o.builder.intConst(llvm_usize_ty, 0)).toLlvm(&o.builder), Type.usize, .neq);
8986 const memcpy_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapSkip");
8987 const end_block = self.context.appendBasicBlock(self.llvm_func, "MemcpyTrapEnd");
8988 _ = self.builder.buildCondBr(cond, memcpy_block, end_block);
8989 self.builder.positionBuilderAtEnd(memcpy_block);
8978 const memcpy_block = try self.wip.block("MemcpyTrapSkip");
8979 const end_block = try self.wip.block("MemcpyTrapEnd");
8980 _ = self.builder.buildCondBr(cond, memcpy_block.toLlvm(&self.wip), end_block.toLlvm(&self.wip));
8981 self.builder.positionBuilderAtEnd(memcpy_block.toLlvm(&self.wip));
89908982 _ = self.builder.buildMemCpy(
89918983 dest_ptr,
89928984 dest_ptr_ty.ptrAlignment(mod),
......@@ -8995,8 +8987,8 @@ pub const FuncGen = struct {
89958987 len,
89968988 is_volatile,
89978989 );
8998 _ = self.builder.buildBr(end_block);
8999 self.builder.positionBuilderAtEnd(end_block);
8990 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
8991 self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip));
90008992 return null;
90018993 }
90028994
......@@ -9179,31 +9171,31 @@ pub const FuncGen = struct {
91799171 const error_set_ty = self.air.getRefType(ty_op.ty);
91809172
91819173 const names = error_set_ty.errorSetNames(mod);
9182 const valid_block = self.context.appendBasicBlock(self.llvm_func, "Valid");
9183 const invalid_block = self.context.appendBasicBlock(self.llvm_func, "Invalid");
9184 const end_block = self.context.appendBasicBlock(self.llvm_func, "End");
9185 const switch_instr = self.builder.buildSwitch(operand, invalid_block, @as(c_uint, @intCast(names.len)));
9174 const valid_block = try self.wip.block("Valid");
9175 const invalid_block = try self.wip.block("Invalid");
9176 const end_block = try self.wip.block("End");
9177 const switch_instr = self.builder.buildSwitch(operand, invalid_block.toLlvm(&self.wip), @intCast(names.len));
91869178
91879179 for (names) |name| {
9188 const err_int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?));
9180 const err_int = mod.global_error_set.getIndex(name).?;
91899181 const this_tag_int_value =
91909182 try o.lowerValue((try mod.intValue(Type.err_int, err_int)).toIntern());
9191 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), valid_block);
9183 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), valid_block.toLlvm(&self.wip));
91929184 }
9193 self.builder.positionBuilderAtEnd(valid_block);
9194 _ = self.builder.buildBr(end_block);
9185 self.builder.positionBuilderAtEnd(valid_block.toLlvm(&self.wip));
9186 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
91959187
9196 self.builder.positionBuilderAtEnd(invalid_block);
9197 _ = self.builder.buildBr(end_block);
9188 self.builder.positionBuilderAtEnd(invalid_block.toLlvm(&self.wip));
9189 _ = self.builder.buildBr(end_block.toLlvm(&self.wip));
91989190
9199 self.builder.positionBuilderAtEnd(end_block);
9191 self.builder.positionBuilderAtEnd(end_block.toLlvm(&self.wip));
92009192
92019193 const incoming_values: [2]*llvm.Value = .{
92029194 Builder.Constant.true.toLlvm(&o.builder),
92039195 Builder.Constant.false.toLlvm(&o.builder),
92049196 };
92059197 const incoming_blocks: [2]*llvm.BasicBlock = .{
9206 valid_block, invalid_block,
9198 valid_block.toLlvm(&self.wip), invalid_block.toLlvm(&self.wip),
92079199 };
92089200 const phi_node = self.builder.buildPhi(Builder.Type.i1.toLlvm(&o.builder), "");
92099201 phi_node.addIncoming(&incoming_values, &incoming_blocks, 2);
......@@ -9250,8 +9242,11 @@ pub const FuncGen = struct {
92509242 };
92519243 var function = Builder.Function{
92529244 .global = @enumFromInt(o.builder.globals.count()),
9253 .body = {},
92549245 };
9246 try o.builder.llvm.globals.append(self.gpa, fn_val);
9247 _ = try o.builder.addGlobal(llvm_fn_name, global);
9248 try o.builder.functions.append(self.gpa, function);
9249 gop.value_ptr.* = global.kind.function;
92559250
92569251 const prev_block = self.builder.getInsertBlock();
92579252 const prev_debug_location = self.builder.getCurrentDebugLocation2();
......@@ -9262,31 +9257,30 @@ pub const FuncGen = struct {
92629257 }
92639258 }
92649259
9265 const entry_block = self.context.appendBasicBlock(fn_val, "Entry");
9266 self.builder.positionBuilderAtEnd(entry_block);
9260 var wip = Builder.WipFunction.init(&o.builder, global.kind.function);
9261 defer wip.deinit();
9262
9263 const entry_block = try wip.block("Entry");
9264 self.builder.positionBuilderAtEnd(entry_block.toLlvm(&wip));
92679265 self.builder.clearCurrentDebugLocation();
92689266
9269 const named_block = self.context.appendBasicBlock(fn_val, "Named");
9270 const unnamed_block = self.context.appendBasicBlock(fn_val, "Unnamed");
9267 const named_block = try wip.block("Named");
9268 const unnamed_block = try wip.block("Unnamed");
92719269 const tag_int_value = fn_val.getParam(0);
9272 const switch_instr = self.builder.buildSwitch(tag_int_value, unnamed_block, @as(c_uint, @intCast(enum_type.names.len)));
9270 const switch_instr = self.builder.buildSwitch(tag_int_value, unnamed_block.toLlvm(&wip), @intCast(enum_type.names.len));
92739271
9274 for (enum_type.names, 0..) |_, field_index_usize| {
9275 const field_index = @as(u32, @intCast(field_index_usize));
9272 for (0..enum_type.names.len) |field_index| {
92769273 const this_tag_int_value =
9277 try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, field_index)).toIntern());
9278 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), named_block);
9274 try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern());
9275 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), named_block.toLlvm(&wip));
92799276 }
9280 self.builder.positionBuilderAtEnd(named_block);
9277 self.builder.positionBuilderAtEnd(named_block.toLlvm(&wip));
92819278 _ = self.builder.buildRet(Builder.Constant.true.toLlvm(&o.builder));
92829279
9283 self.builder.positionBuilderAtEnd(unnamed_block);
9280 self.builder.positionBuilderAtEnd(unnamed_block.toLlvm(&wip));
92849281 _ = self.builder.buildRet(Builder.Constant.false.toLlvm(&o.builder));
92859282
9286 try o.builder.llvm.globals.append(self.gpa, fn_val);
9287 _ = try o.builder.addGlobal(llvm_fn_name, global);
9288 try o.builder.functions.append(self.gpa, function);
9289 gop.value_ptr.* = global.kind.function;
9283 try wip.finish();
92909284 return fn_val;
92919285 }
92929286
......@@ -9331,8 +9325,10 @@ pub const FuncGen = struct {
93319325 };
93329326 var function = Builder.Function{
93339327 .global = @enumFromInt(o.builder.globals.count()),
9334 .body = {},
93359328 };
9329 try o.builder.llvm.globals.append(self.gpa, fn_val);
9330 gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global);
9331 try o.builder.functions.append(self.gpa, function);
93369332
93379333 const prev_block = self.builder.getInsertBlock();
93389334 const prev_debug_location = self.builder.getCurrentDebugLocation2();
......@@ -9343,16 +9339,18 @@ pub const FuncGen = struct {
93439339 }
93449340 }
93459341
9346 const entry_block = self.context.appendBasicBlock(fn_val, "Entry");
9347 self.builder.positionBuilderAtEnd(entry_block);
9342 var wip = Builder.WipFunction.init(&o.builder, global.kind.function);
9343 defer wip.deinit();
9344
9345 const entry_block = try wip.block("Entry");
9346 self.builder.positionBuilderAtEnd(entry_block.toLlvm(&wip));
93489347 self.builder.clearCurrentDebugLocation();
93499348
9350 const bad_value_block = self.context.appendBasicBlock(fn_val, "BadValue");
9349 const bad_value_block = try wip.block("BadValue");
93519350 const tag_int_value = fn_val.getParam(0);
9352 const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @as(c_uint, @intCast(enum_type.names.len)));
9351 const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block.toLlvm(&wip), @intCast(enum_type.names.len));
93539352
9354 for (enum_type.names, 0..) |name_ip, field_index_usize| {
9355 const field_index = @as(u32, @intCast(field_index_usize));
9353 for (enum_type.names, 0..) |name_ip, field_index| {
93569354 const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip));
93579355 const str_init = try o.builder.stringNullConst(name);
93589356 const str_ty = str_init.typeOf(&o.builder);
......@@ -9384,35 +9382,32 @@ pub const FuncGen = struct {
93849382 try o.builder.intConst(usize_ty, name.toSlice(&o.builder).?.len),
93859383 });
93869384
9387 const return_block = self.context.appendBasicBlock(fn_val, "Name");
9385 const return_block = try wip.block("Name");
93889386 const this_tag_int_value =
9389 try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, field_index)).toIntern());
9390 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), return_block);
9387 try o.lowerValue((try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern());
9388 switch_instr.addCase(this_tag_int_value.toLlvm(&o.builder), return_block.toLlvm(&wip));
93919389
9392 self.builder.positionBuilderAtEnd(return_block);
9390 self.builder.positionBuilderAtEnd(return_block.toLlvm(&wip));
93939391 _ = self.builder.buildRet(slice_val.toLlvm(&o.builder));
93949392 }
93959393
9396 self.builder.positionBuilderAtEnd(bad_value_block);
9394 self.builder.positionBuilderAtEnd(bad_value_block.toLlvm(&wip));
93979395 _ = self.builder.buildUnreachable();
93989396
9399 try o.builder.llvm.globals.append(self.gpa, fn_val);
9400 gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global);
9401 try o.builder.functions.append(self.gpa, function);
9397 try wip.finish();
94029398 return fn_val;
94039399 }
94049400
94059401 fn getCmpLtErrorsLenFunction(self: *FuncGen) !*llvm.Value {
94069402 const o = self.dg.object;
94079403
9408 if (o.llvm_module.getNamedFunction(lt_errors_fn_name)) |llvm_fn| {
9409 return llvm_fn;
9410 }
9404 const name = try o.builder.string(lt_errors_fn_name);
9405 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.toLlvm(&o.builder);
94119406
94129407 // Function signature: fn (anyerror) bool
94139408
94149409 const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal);
9415 const llvm_fn = o.llvm_module.addFunction(lt_errors_fn_name, fn_type.toLlvm(&o.builder));
9410 const llvm_fn = o.llvm_module.addFunction(name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder));
94169411
94179412 llvm_fn.setLinkage(.Internal);
94189413 llvm_fn.setFunctionCallConv(.Fast);
......@@ -9425,13 +9420,12 @@ pub const FuncGen = struct {
94259420 };
94269421 var function = Builder.Function{
94279422 .global = @enumFromInt(o.builder.globals.count()),
9428 .body = {},
94299423 };
94309424
94319425 try o.builder.llvm.globals.append(self.gpa, llvm_fn);
9432 _ = try o.builder.addGlobal(try o.builder.string(lt_errors_fn_name), global);
9426 const global_index = try o.builder.addGlobal(name, global);
94339427 try o.builder.functions.append(self.gpa, function);
9434 return llvm_fn;
9428 return global_index.toLlvm(&o.builder);
94359429 }
94369430
94379431 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
......@@ -9494,7 +9488,7 @@ pub const FuncGen = struct {
94949488 val.* = try o.builder.undefConst(.i32);
94959489 } else {
94969490 const int = elem.toSignedInt(mod);
9497 const unsigned = if (int >= 0) @as(u32, @intCast(int)) else @as(u32, @intCast(~int + a_len));
9491 const unsigned: u32 = @intCast(if (int >= 0) int else ~int + a_len);
94989492 val.* = try o.builder.intConst(.i32, unsigned);
94999493 }
95009494 }
......@@ -9537,21 +9531,21 @@ pub const FuncGen = struct {
95379531 _ = self.builder.buildStore(accum_init, accum_ptr);
95389532
95399533 // Setup the loop
9540 const loop = self.context.appendBasicBlock(self.llvm_func, "ReduceLoop");
9541 const loop_exit = self.context.appendBasicBlock(self.llvm_func, "AfterReduce");
9542 _ = self.builder.buildBr(loop);
9534 const loop = try self.wip.block("ReduceLoop");
9535 const loop_exit = try self.wip.block("AfterReduce");
9536 _ = self.builder.buildBr(loop.toLlvm(&self.wip));
95439537 {
9544 self.builder.positionBuilderAtEnd(loop);
9538 self.builder.positionBuilderAtEnd(loop.toLlvm(&self.wip));
95459539
95469540 // while (i < vec.len)
95479541 const i = self.builder.buildLoad(usize_ty.toLlvm(&o.builder), i_ptr, "");
95489542 const cond = self.builder.buildICmp(.ULT, i, llvm_vector_len.toLlvm(&o.builder), "");
9549 const loop_then = self.context.appendBasicBlock(self.llvm_func, "ReduceLoopThen");
9543 const loop_then = try self.wip.block("ReduceLoopThen");
95509544
9551 _ = self.builder.buildCondBr(cond, loop_then, loop_exit);
9545 _ = self.builder.buildCondBr(cond, loop_then.toLlvm(&self.wip), loop_exit.toLlvm(&self.wip));
95529546
95539547 {
9554 self.builder.positionBuilderAtEnd(loop_then);
9548 self.builder.positionBuilderAtEnd(loop_then.toLlvm(&self.wip));
95559549
95569550 // accum = f(accum, vec[i]);
95579551 const accum = self.builder.buildLoad(llvm_result_ty, accum_ptr, "");
......@@ -9563,11 +9557,11 @@ pub const FuncGen = struct {
95639557 // i += 1
95649558 const new_i = self.builder.buildAdd(i, (try o.builder.intConst(usize_ty, 1)).toLlvm(&o.builder), "");
95659559 _ = self.builder.buildStore(new_i, i_ptr);
9566 _ = self.builder.buildBr(loop);
9560 _ = self.builder.buildBr(loop.toLlvm(&self.wip));
95679561 }
95689562 }
95699563
9570 self.builder.positionBuilderAtEnd(loop_exit);
9564 self.builder.positionBuilderAtEnd(loop_exit.toLlvm(&self.wip));
95719565 return self.builder.buildLoad(llvm_result_ty, accum_ptr, "");
95729566 }
95739567
......@@ -9656,8 +9650,8 @@ pub const FuncGen = struct {
96569650 const mod = o.module;
96579651 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
96589652 const result_ty = self.typeOfIndex(inst);
9659 const len = @as(usize, @intCast(result_ty.arrayLen(mod)));
9660 const elements = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[ty_pl.payload..][0..len]));
9653 const len: usize = @intCast(result_ty.arrayLen(mod));
9654 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);
96619655 const llvm_result_ty = (try o.lowerType(result_ty)).toLlvm(&o.builder);
96629656
96639657 switch (result_ty.zigTypeTag(mod)) {
......@@ -9685,8 +9679,8 @@ pub const FuncGen = struct {
96859679 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
96869680
96879681 const non_int_val = try self.resolveInst(elem);
9688 const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod)));
9689 const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder);
9682 const ty_bit_size: u16 = @intCast(field.ty.bitSize(mod));
9683 const small_int_ty = (try o.builder.intType(ty_bit_size)).toLlvm(&o.builder);
96909684 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
96919685 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
96929686 else
......@@ -9798,8 +9792,7 @@ pub const FuncGen = struct {
97989792 const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder);
97999793 const field = union_obj.fields.values()[extra.field_index];
98009794 const non_int_val = try self.resolveInst(extra.init);
9801 const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod)));
9802 const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder);
9795 const small_int_ty = (try o.builder.intType(@intCast(field.ty.bitSize(mod)))).toLlvm(&o.builder);
98039796 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
98049797 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
98059798 else
......@@ -10273,8 +10266,8 @@ pub const FuncGen = struct {
1027310266 const elem_ty = info.child.toType();
1027410267 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
1027510268
10276 const ptr_alignment = @as(u32, @intCast(info.flags.alignment.toByteUnitsOptional() orelse
10277 elem_ty.abiAlignment(mod)));
10269 const ptr_alignment: u32 = @intCast(info.flags.alignment.toByteUnitsOptional() orelse
10270 elem_ty.abiAlignment(mod));
1027810271 const ptr_volatile = llvm.Bool.fromBool(info.flags.is_volatile);
1027910272
1028010273 assert(info.flags.vector_index != .runtime);
......@@ -10306,7 +10299,7 @@ pub const FuncGen = struct {
1030610299 containing_int.setAlignment(ptr_alignment);
1030710300 containing_int.setVolatile(ptr_volatile);
1030810301
10309 const elem_bits = @as(c_uint, @intCast(ptr_ty.childType(mod).bitSize(mod)));
10302 const elem_bits = ptr_ty.childType(mod).bitSize(mod);
1031010303 const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset);
1031110304 const shifted_value = self.builder.buildLShr(containing_int, shift_amt.toLlvm(&o.builder), "");
1031210305 const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder);
......@@ -10379,7 +10372,7 @@ pub const FuncGen = struct {
1037910372 assert(ordering == .NotAtomic);
1038010373 containing_int.setAlignment(ptr_alignment);
1038110374 containing_int.setVolatile(ptr_volatile);
10382 const elem_bits = @as(c_uint, @intCast(ptr_ty.childType(mod).bitSize(mod)));
10375 const elem_bits = ptr_ty.childType(mod).bitSize(mod);
1038310376 const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset);
1038410377 // Convert to equally-sized integer type in order to perform the bit
1038510378 // operations on the value to store
......@@ -10451,11 +10444,11 @@ pub const FuncGen = struct {
1045110444 if (!target_util.hasValgrindSupport(target)) return default_value;
1045210445
1045310446 const llvm_usize = try o.lowerType(Type.usize);
10454 const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod)));
10447 const usize_alignment = Type.usize.abiSize(mod);
1045510448
1045610449 const array_llvm_ty = (try o.builder.arrayType(6, llvm_usize)).toLlvm(&o.builder);
1045710450 const array_ptr = fg.valgrind_client_request_array orelse a: {
10458 const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_alignment);
10451 const array_ptr = try fg.buildAlloca(array_llvm_ty, @intCast(usize_alignment));
1045910452 fg.valgrind_client_request_array = array_ptr;
1046010453 break :a array_ptr;
1046110454 };
......@@ -10467,7 +10460,7 @@ pub const FuncGen = struct {
1046710460 };
1046810461 const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, "");
1046910462 const store_inst = fg.builder.buildStore(elem, elem_ptr);
10470 store_inst.setAlignment(usize_alignment);
10463 store_inst.setAlignment(@intCast(usize_alignment));
1047110464 }
1047210465
1047310466 const arch_specific: struct {
......@@ -11642,23 +11635,23 @@ const AnnotatedDITypePtr = enum(usize) {
1164211635 fn initFwd(di_type: *llvm.DIType) AnnotatedDITypePtr {
1164311636 const addr = @intFromPtr(di_type);
1164411637 assert(@as(u1, @truncate(addr)) == 0);
11645 return @as(AnnotatedDITypePtr, @enumFromInt(addr | 1));
11638 return @enumFromInt(addr | 1);
1164611639 }
1164711640
1164811641 fn initFull(di_type: *llvm.DIType) AnnotatedDITypePtr {
1164911642 const addr = @intFromPtr(di_type);
11650 return @as(AnnotatedDITypePtr, @enumFromInt(addr));
11643 return @enumFromInt(addr);
1165111644 }
1165211645
1165311646 fn init(di_type: *llvm.DIType, resolve: Object.DebugResolveStatus) AnnotatedDITypePtr {
1165411647 const addr = @intFromPtr(di_type);
1165511648 const bit = @intFromBool(resolve == .fwd);
11656 return @as(AnnotatedDITypePtr, @enumFromInt(addr | bit));
11649 return @enumFromInt(addr | bit);
1165711650 }
1165811651
1165911652 fn toDIType(self: AnnotatedDITypePtr) *llvm.DIType {
1166011653 const fixed_addr = @intFromEnum(self) & ~@as(usize, 1);
11661 return @as(*llvm.DIType, @ptrFromInt(fixed_addr));
11654 return @ptrFromInt(fixed_addr);
1166211655 }
1166311656
1166411657 fn isFwdOnly(self: AnnotatedDITypePtr) bool {
src/codegen/llvm/Builder.zig+294-80
......@@ -1,5 +1,6 @@
11gpa: Allocator,
22use_lib_llvm: bool,
3strip: bool,
34
45llvm: if (build_options.have_llvm) struct {
56 context: *llvm.Context,
......@@ -12,33 +13,33 @@ llvm: if (build_options.have_llvm) struct {
1213 constants: std.ArrayListUnmanaged(*llvm.Value) = .{},
1314} else void,
1415
15source_filename: String = .none,
16data_layout: String = .none,
17target_triple: String = .none,
18
19string_map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
20string_bytes: std.ArrayListUnmanaged(u8) = .{},
21string_indices: std.ArrayListUnmanaged(u32) = .{},
22
23types: std.AutoArrayHashMapUnmanaged(String, Type) = .{},
24next_unnamed_type: String = @enumFromInt(0),
25next_unique_type_id: std.AutoHashMapUnmanaged(String, u32) = .{},
26type_map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
27type_items: std.ArrayListUnmanaged(Type.Item) = .{},
28type_extra: std.ArrayListUnmanaged(u32) = .{},
29
30globals: std.AutoArrayHashMapUnmanaged(String, Global) = .{},
31next_unnamed_global: String = @enumFromInt(0),
32next_replaced_global: String = .none,
33next_unique_global_id: std.AutoHashMapUnmanaged(String, u32) = .{},
34aliases: std.ArrayListUnmanaged(Alias) = .{},
35variables: std.ArrayListUnmanaged(Variable) = .{},
36functions: std.ArrayListUnmanaged(Function) = .{},
37
38constant_map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
39constant_items: std.MultiArrayList(Constant.Item) = .{},
40constant_extra: std.ArrayListUnmanaged(u32) = .{},
41constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb) = .{},
16source_filename: String,
17data_layout: String,
18target_triple: String,
19
20string_map: std.AutoArrayHashMapUnmanaged(void, void),
21string_bytes: std.ArrayListUnmanaged(u8),
22string_indices: std.ArrayListUnmanaged(u32),
23
24types: std.AutoArrayHashMapUnmanaged(String, Type),
25next_unnamed_type: String,
26next_unique_type_id: std.AutoHashMapUnmanaged(String, u32),
27type_map: std.AutoArrayHashMapUnmanaged(void, void),
28type_items: std.ArrayListUnmanaged(Type.Item),
29type_extra: std.ArrayListUnmanaged(u32),
30
31globals: std.AutoArrayHashMapUnmanaged(String, Global),
32next_unnamed_global: String,
33next_replaced_global: String,
34next_unique_global_id: std.AutoHashMapUnmanaged(String, u32),
35aliases: std.ArrayListUnmanaged(Alias),
36variables: std.ArrayListUnmanaged(Variable),
37functions: std.ArrayListUnmanaged(Function),
38
39constant_map: std.AutoArrayHashMapUnmanaged(void, void),
40constant_items: std.MultiArrayList(Constant.Item),
41constant_extra: std.ArrayListUnmanaged(u32),
42constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
4243
4344pub const expected_fields_len = 32;
4445pub const expected_gep_indices_len = 8;
......@@ -46,6 +47,7 @@ pub const expected_gep_indices_len = 8;
4647pub const Options = struct {
4748 allocator: Allocator,
4849 use_lib_llvm: bool = false,
50 strip: bool = true,
4951 name: []const u8 = &.{},
5052 target: std.Target = builtin.target,
5153 triple: []const u8 = &.{},
......@@ -986,9 +988,11 @@ pub const Variable = struct {
986988
987989pub const Function = struct {
988990 global: Global.Index,
989 body: ?void = null,
990 instructions: std.ArrayListUnmanaged(Instruction) = .{},
991 blocks: std.ArrayListUnmanaged(Block) = .{},
991 blocks: []const Block = &.{},
992 instructions: std.MultiArrayList(Instruction) = .{},
993 names: ?[*]const String = null,
994 metadata: ?[*]const Metadata = null,
995 extra: []const u32 = &.{},
992996
993997 pub const Index = enum(u32) {
994998 none = std.math.maxInt(u32),
......@@ -1007,28 +1011,236 @@ pub const Function = struct {
10071011 }
10081012 };
10091013
1014 pub const Block = struct {
1015 instruction: Instruction.Index,
1016
1017 pub const Index = WipFunction.Block.Index;
1018 };
1019
10101020 pub const Instruction = struct {
10111021 tag: Tag,
1022 data: u32,
10121023
10131024 pub const Tag = enum {
10141025 arg,
10151026 block,
1027 @"ret void",
1028 ret,
10161029 };
10171030
1018 pub const Index = enum(u32) { _ };
1031 pub const Index = enum(u32) {
1032 _,
1033
1034 pub fn name(self: Instruction.Index, function: *const Function) String {
1035 return if (function.names) |names|
1036 names[@intFromEnum(self)]
1037 else
1038 @enumFromInt(@intFromEnum(self));
1039 }
1040 };
10191041 };
10201042
1043 pub fn deinit(self: *Function, gpa: Allocator) void {
1044 gpa.free(self.extra);
1045 if (self.metadata) |metadata| gpa.free(metadata[0..self.instructions.len]);
1046 if (self.names) |names| gpa.free(names[0..self.instructions.len]);
1047 self.instructions.deinit(gpa);
1048 self.* = undefined;
1049 }
1050};
1051
1052pub const WipFunction = struct {
1053 builder: *Builder,
1054 function: Function.Index,
1055 llvm: if (build_options.have_llvm) struct {
1056 builder: *llvm.Builder,
1057 blocks: std.ArrayListUnmanaged(*llvm.BasicBlock),
1058 instructions: std.ArrayListUnmanaged(*llvm.Value),
1059 } else void,
1060 cursor: Cursor,
1061 blocks: std.ArrayListUnmanaged(Block),
1062 instructions: std.MultiArrayList(Instruction),
1063 names: std.ArrayListUnmanaged(String),
1064 metadata: std.ArrayListUnmanaged(Metadata),
1065 extra: std.ArrayListUnmanaged(u32),
1066
1067 pub const Cursor = struct { block: Block.Index, instruction: u32 = 0 };
1068
10211069 pub const Block = struct {
1022 body: std.ArrayListUnmanaged(Instruction.Index) = .{},
1070 name: String,
1071 incoming: u32,
1072 instructions: std.ArrayListUnmanaged(Instruction.Index),
10231073
1024 pub const Index = enum(u32) { _ };
1074 const Index = enum(u32) {
1075 _,
1076
1077 pub fn toLlvm(self: Index, wip: *const WipFunction) *llvm.BasicBlock {
1078 assert(wip.builder.useLibLlvm());
1079 return wip.llvm.blocks.items[@intFromEnum(self)];
1080 }
1081 };
10251082 };
10261083
1027 pub fn deinit(self: *Function, gpa: Allocator) void {
1028 self.instructions.deinit(gpa);
1029 self.blocks.deinit(gpa);
1084 pub const Instruction = Function.Instruction;
1085
1086 pub fn init(builder: *Builder, function: Function.Index) WipFunction {
1087 if (builder.useLibLlvm()) {
1088 const llvm_function = function.toLlvm(builder);
1089 while (llvm_function.getFirstBasicBlock()) |bb| bb.deleteBasicBlock();
1090 }
1091 return .{
1092 .builder = builder,
1093 .function = function,
1094 .llvm = if (builder.useLibLlvm()) .{
1095 .builder = builder.llvm.context.createBuilder(),
1096 .blocks = .{},
1097 .instructions = .{},
1098 } else undefined,
1099 .cursor = undefined,
1100 .blocks = .{},
1101 .instructions = .{},
1102 .names = .{},
1103 .metadata = .{},
1104 .extra = .{},
1105 };
1106 }
1107
1108 pub fn block(self: *WipFunction, name: []const u8) Allocator.Error!Block.Index {
1109 try self.blocks.ensureUnusedCapacity(self.builder.gpa, 1);
1110 if (self.builder.useLibLlvm()) try self.llvm.blocks.ensureUnusedCapacity(self.builder.gpa, 1);
1111
1112 const index: Block.Index = @enumFromInt(self.blocks.items.len);
1113 const final_name = if (self.builder.strip) .empty else try self.builder.string(name);
1114 self.blocks.appendAssumeCapacity(.{ .name = final_name, .incoming = 0, .instructions = .{} });
1115 if (self.builder.useLibLlvm()) self.llvm.blocks.appendAssumeCapacity(
1116 self.builder.llvm.context.appendBasicBlock(
1117 self.function.toLlvm(self.builder),
1118 final_name.toSlice(self.builder).?,
1119 ),
1120 );
1121 return index;
1122 }
1123
1124 pub fn retVoid(self: *WipFunction) Allocator.Error!void {
1125 _ = try self.addInst(.{ .tag = .@"ret void", .data = undefined }, .none);
1126 if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity(
1127 self.llvm.builder.buildRetVoid(),
1128 );
1129 }
1130
1131 pub fn finish(self: *WipFunction) Allocator.Error!void {
1132 const gpa = self.builder.gpa;
1133 const function = self.function.ptr(self.builder);
1134 const final_instructions_len = self.blocks.items.len + self.instructions.len;
1135
1136 const blocks = try gpa.alloc(Function.Block, self.blocks.items.len);
1137 errdefer gpa.free(blocks);
1138
1139 const instructions = try gpa.alloc(Instruction.Index, self.instructions.len);
1140 defer gpa.free(instructions);
1141
1142 const names = if (self.builder.strip) null else try gpa.alloc(String, final_instructions_len);
1143 errdefer if (names) |new_names| gpa.free(new_names);
1144
1145 const metadata =
1146 if (self.builder.strip) null else try gpa.alloc(Metadata, final_instructions_len);
1147 errdefer if (metadata) |new_metadata| gpa.free(new_metadata);
1148
1149 gpa.free(function.blocks);
1150 function.blocks = &.{};
1151 if (function.names) |old_names| gpa.free(old_names[0..function.instructions.len]);
1152 function.names = null;
1153 if (function.metadata) |old_metadata| gpa.free(old_metadata[0..function.instructions.len]);
1154 function.metadata = null;
1155
1156 function.instructions.shrinkRetainingCapacity(0);
1157 try function.instructions.setCapacity(gpa, final_instructions_len);
1158 errdefer function.instructions.shrinkRetainingCapacity(0);
1159
1160 {
1161 var final_instruction: Instruction.Index = @enumFromInt(0);
1162 for (blocks, self.blocks.items) |*final_block, current_block| {
1163 final_block.instruction = final_instruction;
1164 final_instruction = @enumFromInt(@intFromEnum(final_instruction) + 1);
1165 for (current_block.instructions.items) |instruction| {
1166 instructions[@intFromEnum(instruction)] = final_instruction;
1167 final_instruction = @enumFromInt(@intFromEnum(final_instruction) + 1);
1168 }
1169 }
1170 }
1171
1172 var next_name: String = @enumFromInt(0);
1173 for (self.blocks.items) |current_block| {
1174 const block_instruction: Instruction.Index = @enumFromInt(function.instructions.len);
1175 function.instructions.appendAssumeCapacity(.{
1176 .tag = .block,
1177 .data = current_block.incoming,
1178 });
1179 if (names) |new_names|
1180 new_names[@intFromEnum(block_instruction)] = switch (current_block.name) {
1181 .empty => name: {
1182 const name = next_name;
1183 next_name = @enumFromInt(@intFromEnum(name) + 1);
1184 break :name name;
1185 },
1186 else => |name| name,
1187 };
1188 for (current_block.instructions.items) |instruction_index| {
1189 var instruction = self.instructions.get(@intFromEnum(instruction_index));
1190 switch (instruction.tag) {
1191 .block => unreachable,
1192 .@"ret void" => {},
1193 else => unreachable,
1194 }
1195 function.instructions.appendAssumeCapacity(instruction);
1196 }
1197 }
1198
1199 function.extra = try self.extra.toOwnedSlice(gpa);
1200 function.blocks = blocks;
1201 function.names = if (names) |new_names| new_names.ptr else null;
1202 function.metadata = if (metadata) |new_metadata| new_metadata.ptr else null;
1203 }
1204
1205 pub fn deinit(self: *WipFunction) void {
1206 self.extra.deinit(self.builder.gpa);
1207 self.instructions.deinit(self.builder.gpa);
1208 for (self.blocks.items) |*b| b.instructions.deinit(self.builder.gpa);
1209 self.blocks.deinit(self.builder.gpa);
1210 if (self.builder.useLibLlvm()) self.llvm.builder.dispose();
10301211 self.* = undefined;
10311212 }
1213
1214 fn addInst(
1215 self: *WipFunction,
1216 instruction: Instruction,
1217 name: String,
1218 ) Allocator.Error!Instruction.Index {
1219 const block_instructions = &self.blocks.items[@intFromEnum(self.cursor.block)].instructions;
1220 try self.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
1221 try self.names.ensureUnusedCapacity(self.builder.gpa, 1);
1222 try block_instructions.ensureUnusedCapacity(self.builder.gpa, 1);
1223 if (self.builder.useLibLlvm()) {
1224 try self.llvm.instructions.ensureUnusedCapacity(self.builder.gpa, 1);
1225
1226 if (false) self.llvm.builder.positionBuilder(
1227 self.cursor.block.toLlvm(self),
1228 if (self.cursor.instruction < block_instructions.items.len)
1229 self.llvm.instructions.items[
1230 @intFromEnum(block_instructions.items[self.cursor.instruction])
1231 ]
1232 else
1233 null,
1234 );
1235 }
1236
1237 const index: Instruction.Index = @enumFromInt(self.instructions.len);
1238 self.instructions.appendAssumeCapacity(instruction);
1239 self.names.appendAssumeCapacity(name);
1240 block_instructions.insertAssumeCapacity(self.cursor.instruction, index);
1241 self.cursor.instruction += 1;
1242 return index;
1243 }
10321244};
10331245
10341246pub const FloatCondition = enum(u4) {
......@@ -1696,6 +1908,8 @@ pub const Value = enum(u32) {
16961908 }
16971909};
16981910
1911pub const Metadata = enum(u32) { _ };
1912
16991913pub const InitError = error{
17001914 InvalidLlvmTriple,
17011915} || Allocator.Error;
......@@ -1704,7 +1918,37 @@ pub fn init(options: Options) InitError!Builder {
17041918 var self = Builder{
17051919 .gpa = options.allocator,
17061920 .use_lib_llvm = options.use_lib_llvm,
1921 .strip = options.strip,
1922
17071923 .llvm = undefined,
1924
1925 .source_filename = .none,
1926 .data_layout = .none,
1927 .target_triple = .none,
1928
1929 .string_map = .{},
1930 .string_bytes = .{},
1931 .string_indices = .{},
1932
1933 .types = .{},
1934 .next_unnamed_type = @enumFromInt(0),
1935 .next_unique_type_id = .{},
1936 .type_map = .{},
1937 .type_items = .{},
1938 .type_extra = .{},
1939
1940 .globals = .{},
1941 .next_unnamed_global = @enumFromInt(0),
1942 .next_replaced_global = .none,
1943 .next_unique_global_id = .{},
1944 .aliases = .{},
1945 .variables = .{},
1946 .functions = .{},
1947
1948 .constant_map = .{},
1949 .constant_items = .{},
1950 .constant_extra = .{},
1951 .constant_limbs = .{},
17081952 };
17091953 if (self.useLibLlvm()) self.llvm = .{ .context = llvm.Context.create() };
17101954 errdefer self.deinit();
......@@ -1726,7 +1970,7 @@ pub fn init(options: Options) InitError!Builder {
17261970 var error_message: [*:0]const u8 = undefined;
17271971 var target: *llvm.Target = undefined;
17281972 if (llvm.Target.getFromTriple(
1729 self.target_triple.toSlice(&self).?.ptr,
1973 self.target_triple.toSlice(&self).?,
17301974 &target,
17311975 &error_message,
17321976 ).toBool()) {
......@@ -1739,7 +1983,7 @@ pub fn init(options: Options) InitError!Builder {
17391983 return InitError.InvalidLlvmTriple;
17401984 }
17411985 self.llvm.target = target;
1742 self.llvm.module.?.setTarget(self.target_triple.toSlice(&self).?.ptr);
1986 self.llvm.module.?.setTarget(self.target_triple.toSlice(&self).?);
17431987 }
17441988 }
17451989
......@@ -2448,7 +2692,7 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator
24482692 try writer.print(
24492693 \\{s}{}{}{}{} {} {}(
24502694 , .{
2451 if (function.body) |_| "define" else "declare",
2695 if (function.instructions.len > 0) "define" else "declare",
24522696 global.linkage,
24532697 global.preemption,
24542698 global.visibility,
......@@ -2469,48 +2713,18 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator
24692713 else => unreachable,
24702714 }
24712715 try writer.print("){}{}", .{ global.unnamed_addr, global.alignment });
2472 if (function.body) |_| {
2473 try writer.writeAll(" {\n ret ");
2474 void: {
2475 try writer.print("{%}", .{switch (extra.data.ret) {
2476 .void => |tag| {
2477 try writer.writeAll(@tagName(tag));
2478 break :void;
2479 },
2480 inline .half,
2481 .bfloat,
2482 .float,
2483 .double,
2484 .fp128,
2485 .x86_fp80,
2486 => |tag| try @field(Builder, @tagName(tag) ++ "Const")(self, 0.0),
2487 .ppc_fp128 => try self.ppc_fp128Const(.{ 0.0, 0.0 }),
2488 .x86_amx,
2489 .x86_mmx,
2490 .label,
2491 .metadata,
2492 => unreachable,
2493 .token => Constant.none,
2494 else => switch (extra.data.ret.tag(self)) {
2495 .simple,
2496 .function,
2497 .vararg_function,
2498 => unreachable,
2499 .integer => try self.intConst(extra.data.ret, 0),
2500 .pointer => try self.nullConst(extra.data.ret),
2501 .target,
2502 .vector,
2503 .scalable_vector,
2504 .small_array,
2505 .array,
2506 .structure,
2507 .packed_structure,
2508 .named_structure,
2509 => try self.zeroInitConst(extra.data.ret),
2510 },
2511 }.fmt(self)});
2716 if (function.instructions.len > 0) {
2717 try writer.writeAll(" {\n");
2718 for (0..function.instructions.len) |index| {
2719 const instruction_index: Function.Instruction.Index = @enumFromInt(index);
2720 const instruction = function.instructions.get(index);
2721 switch (instruction.tag) {
2722 .block => try writer.print("{}:\n", .{instruction_index.name(&function).fmt(self)}),
2723 .@"ret void" => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
2724 else => unreachable,
2725 }
25122726 }
2513 try writer.writeAll("\n}");
2727 try writer.writeByte('}');
25142728 }
25152729 try writer.writeAll("\n\n");
25162730 }
src/codegen/llvm/bindings.zig+1-1
......@@ -621,7 +621,7 @@ pub const Builder = opaque {
621621 extern fn LLVMPositionBuilder(
622622 Builder: *Builder,
623623 Block: *BasicBlock,
624 Instr: *Value,
624 Instr: ?*Value,
625625 ) void;
626626
627627 pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd;