authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-13 12:02:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-13 12:02:55-07:00
log2a701a92c403dda47a61848a38998b474442d805
tree52f69e339df727aae1a29a6009d3a4c0860e181c
parentfc302f00a9de5de0490f4a66720e75946763c695

stage2: LLVM backend: fix crash adding alloca

The logic for `buildAlloca` had a null deref when the latest alloca was the last instruction in the entry block. Now the logic is simplified to always insert alloca instructions first before all other instructions. There is no longer a need to track `entry_block` or `latest_alloca_inst`; these fields are deleted frem `FuncGen`.

1 files changed, 8 insertions(+), 22 deletions(-)

src/codegen/llvm.zig+8-22
...@@ -448,8 +448,6 @@ pub const Object = struct {...@@ -448,8 +448,6 @@ pub const Object = struct {
448 .args = args.toOwnedSlice(),448 .args = args.toOwnedSlice(),
449 .arg_index = 0,449 .arg_index = 0,
450 .func_inst_table = .{},450 .func_inst_table = .{},
451 .entry_block = entry_block,
452 .latest_alloca_inst = null,
453 .llvm_func = llvm_func,451 .llvm_func = llvm_func,
454 .blocks = .{},452 .blocks = .{},
455 .single_threaded = module.comp.bin_file.options.single_threaded,453 .single_threaded = module.comp.bin_file.options.single_threaded,
...@@ -1285,11 +1283,6 @@ pub const FuncGen = struct {...@@ -1285,11 +1283,6 @@ pub const FuncGen = struct {
1285 args: []*const llvm.Value,1283 args: []*const llvm.Value,
1286 arg_index: usize,1284 arg_index: usize,
12871285
1288 entry_block: *const llvm.BasicBlock,
1289 /// This fields stores the last alloca instruction, such that we can append
1290 /// more alloca instructions to the top of the function.
1291 latest_alloca_inst: ?*const llvm.Value,
1292
1293 llvm_func: *const llvm.Value,1286 llvm_func: *const llvm.Value,
12941287
1295 /// This data structure is used to implement breaking to blocks.1288 /// This data structure is used to implement breaking to blocks.
...@@ -2658,26 +2651,19 @@ pub const FuncGen = struct {...@@ -2658,26 +2651,19 @@ pub const FuncGen = struct {
26582651
2659 /// Use this instead of builder.buildAlloca, because this function makes sure to2652 /// Use this instead of builder.buildAlloca, because this function makes sure to
2660 /// put the alloca instruction at the top of the function!2653 /// put the alloca instruction at the top of the function!
2661 fn buildAlloca(self: *FuncGen, t: *const llvm.Type) *const llvm.Value {2654 fn buildAlloca(self: *FuncGen, llvm_ty: *const llvm.Type) *const llvm.Value {
2662 const prev_block = self.builder.getInsertBlock();2655 const prev_block = self.builder.getInsertBlock();
2663 defer self.builder.positionBuilderAtEnd(prev_block);
26642656
2665 if (self.latest_alloca_inst) |latest_alloc| {2657 const entry_block = self.llvm_func.getFirstBasicBlock().?;
2666 // builder.positionBuilder adds it before the instruction,2658 if (entry_block.getFirstInstruction()) |first_inst| {
2667 // but we want to put it after the last alloca instruction.2659 self.builder.positionBuilder(entry_block, first_inst);
2668 self.builder.positionBuilder(self.entry_block, latest_alloc.getNextInstruction().?);
2669 } else {2660 } else {
2670 // There might have been other instructions emitted before the2661 self.builder.positionBuilderAtEnd(entry_block);
2671 // first alloca has been generated. However the alloca should still
2672 // be first in the function.
2673 if (self.entry_block.getFirstInstruction()) |first_inst| {
2674 self.builder.positionBuilder(self.entry_block, first_inst);
2675 }
2676 }2662 }
26772663
2678 const val = self.builder.buildAlloca(t, "");2664 const alloca = self.builder.buildAlloca(llvm_ty, "");
2679 self.latest_alloca_inst = val;2665 self.builder.positionBuilderAtEnd(prev_block);
2680 return val;2666 return alloca;
2681 }2667 }
26822668
2683 fn airStore(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {2669 fn airStore(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {