aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-13 12:02:55 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-13 12:02:55 -0700
commit2a701a92c403dda47a61848a38998b474442d805 (patch)
tree52f69e339df727aae1a29a6009d3a4c0860e181c /src/codegen/llvm.zig
parentfc302f00a9de5de0490f4a66720e75946763c695 (diff)
downloadzig-2a701a92c403dda47a61848a38998b474442d805.tar.gz
zig-2a701a92c403dda47a61848a38998b474442d805.zip
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`.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig30
1 files changed, 8 insertions, 22 deletions
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 {