From 2a701a92c403dda47a61848a38998b474442d805 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Oct 2021 12:02:55 -0700 Subject: 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`. --- src/codegen/llvm.zig | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5f461b1276..2e072fbdd6 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -448,8 +448,6 @@ pub const Object = struct { .args = args.toOwnedSlice(), .arg_index = 0, .func_inst_table = .{}, - .entry_block = entry_block, - .latest_alloca_inst = null, .llvm_func = llvm_func, .blocks = .{}, .single_threaded = module.comp.bin_file.options.single_threaded, @@ -1285,11 +1283,6 @@ pub const FuncGen = struct { args: []*const llvm.Value, arg_index: usize, - entry_block: *const llvm.BasicBlock, - /// This fields stores the last alloca instruction, such that we can append - /// more alloca instructions to the top of the function. - latest_alloca_inst: ?*const llvm.Value, - llvm_func: *const llvm.Value, /// This data structure is used to implement breaking to blocks. @@ -2658,26 +2651,19 @@ pub const FuncGen = struct { /// Use this instead of builder.buildAlloca, because this function makes sure to /// put the alloca instruction at the top of the function! - fn buildAlloca(self: *FuncGen, t: *const llvm.Type) *const llvm.Value { + fn buildAlloca(self: *FuncGen, llvm_ty: *const llvm.Type) *const llvm.Value { const prev_block = self.builder.getInsertBlock(); - defer self.builder.positionBuilderAtEnd(prev_block); - if (self.latest_alloca_inst) |latest_alloc| { - // builder.positionBuilder adds it before the instruction, - // but we want to put it after the last alloca instruction. - self.builder.positionBuilder(self.entry_block, latest_alloc.getNextInstruction().?); + const entry_block = self.llvm_func.getFirstBasicBlock().?; + if (entry_block.getFirstInstruction()) |first_inst| { + self.builder.positionBuilder(entry_block, first_inst); } else { - // There might have been other instructions emitted before the - // first alloca has been generated. However the alloca should still - // be first in the function. - if (self.entry_block.getFirstInstruction()) |first_inst| { - self.builder.positionBuilder(self.entry_block, first_inst); - } + self.builder.positionBuilderAtEnd(entry_block); } - const val = self.builder.buildAlloca(t, ""); - self.latest_alloca_inst = val; - return val; + const alloca = self.builder.buildAlloca(llvm_ty, ""); + self.builder.positionBuilderAtEnd(prev_block); + return alloca; } fn airStore(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { -- cgit v1.2.3