| ... | @@ -148,6 +148,9 @@ pub const LLVMIRModule = struct { | ... | @@ -148,6 +148,9 @@ pub const LLVMIRModule = struct { |
| 148 | gpa: *Allocator, | 148 | gpa: *Allocator, |
| 149 | err_msg: ?*Compilation.ErrorMsg = null, | 149 | err_msg: ?*Compilation.ErrorMsg = null, |
| 150 | | 150 | |
| | 151 | // TODO: The fields below should really move into a different struct, |
| | 152 | // because they are only valid when generating a function |
| | 153 | |
| 151 | /// This stores the LLVM values used in a function, such that they can be | 154 | /// This stores the LLVM values used in a function, such that they can be |
| 152 | /// referred to in other instructions. This table is cleared before every function is generated. | 155 | /// referred to in other instructions. This table is cleared before every function is generated. |
| 153 | func_inst_table: std.AutoHashMapUnmanaged(*Inst, *const llvm.Value) = .{}, | 156 | func_inst_table: std.AutoHashMapUnmanaged(*Inst, *const llvm.Value) = .{}, |
| ... | @@ -156,6 +159,11 @@ pub const LLVMIRModule = struct { | ... | @@ -156,6 +159,11 @@ pub const LLVMIRModule = struct { |
| 156 | args: []*const llvm.Value = &[_]*const llvm.Value{}, | 159 | args: []*const llvm.Value = &[_]*const llvm.Value{}, |
| 157 | arg_index: usize = 0, | 160 | arg_index: usize = 0, |
| 158 | | 161 | |
| | 162 | entry_block: *const llvm.BasicBlock = undefined, |
| | 163 | /// This fields stores the last alloca instruction, such that we can append more alloca instructions |
| | 164 | /// to the top of the function. |
| | 165 | latest_alloca_inst: ?*const llvm.Value = null, |
| | 166 | |
| 159 | pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule { | 167 | pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule { |
| 160 | const self = try allocator.create(LLVMIRModule); | 168 | const self = try allocator.create(LLVMIRModule); |
| 161 | errdefer allocator.destroy(self); | 169 | errdefer allocator.destroy(self); |
| ... | @@ -332,8 +340,9 @@ pub const LLVMIRModule = struct { | ... | @@ -332,8 +340,9 @@ pub const LLVMIRModule = struct { |
| 332 | bb.deleteBasicBlock(); | 340 | bb.deleteBasicBlock(); |
| 333 | } | 341 | } |
| 334 | | 342 | |
| 335 | const entry_block = llvm_func.appendBasicBlock("Entry"); | 343 | self.entry_block = llvm_func.appendBasicBlock("Entry"); |
| 336 | self.builder.positionBuilderAtEnd(entry_block); | 344 | self.builder.positionBuilderAtEnd(self.entry_block); |
| | 345 | self.latest_alloca_inst = null; |
| 337 | | 346 | |
| 338 | const instructions = func.body.instructions; | 347 | const instructions = func.body.instructions; |
| 339 | for (instructions) |inst| { | 348 | for (instructions) |inst| { |
| ... | @@ -476,7 +485,7 @@ pub const LLVMIRModule = struct { | ... | @@ -476,7 +485,7 @@ pub const LLVMIRModule = struct { |
| 476 | const arg_val = self.args[self.arg_index]; | 485 | const arg_val = self.args[self.arg_index]; |
| 477 | self.arg_index += 1; | 486 | self.arg_index += 1; |
| 478 | | 487 | |
| 479 | const ptr_val = self.builder.buildAlloca(try self.getLLVMType(inst.base.ty, inst.base.src), ""); | 488 | const ptr_val = self.buildAlloca(try self.getLLVMType(inst.base.ty, inst.base.src)); |
| 480 | _ = self.builder.buildStore(arg_val, ptr_val); | 489 | _ = self.builder.buildStore(arg_val, ptr_val); |
| 481 | return self.builder.buildLoad(ptr_val, ""); | 490 | return self.builder.buildLoad(ptr_val, ""); |
| 482 | } | 491 | } |
| ... | @@ -488,7 +497,29 @@ pub const LLVMIRModule = struct { | ... | @@ -488,7 +497,29 @@ pub const LLVMIRModule = struct { |
| 488 | | 497 | |
| 489 | // TODO: figure out a way to get the name of the var decl. | 498 | // TODO: figure out a way to get the name of the var decl. |
| 490 | // TODO: set alignment and volatile | 499 | // TODO: set alignment and volatile |
| 491 | return self.builder.buildAlloca(try self.getLLVMType(pointee_type, inst.base.src), ""); | 500 | return self.buildAlloca(try self.getLLVMType(pointee_type, inst.base.src)); |
| | 501 | } |
| | 502 | |
| | 503 | /// Use this instead of builder.buildAlloca, because this function makes sure to |
| | 504 | /// put the alloca instruction at the top of the function! |
| | 505 | fn buildAlloca(self: *LLVMIRModule, t: *const llvm.Type) *const llvm.Value { |
| | 506 | if (self.latest_alloca_inst) |latest_alloc| { |
| | 507 | // builder.positionBuilder adds it before the instruction, |
| | 508 | // but we want to put it after the last alloca instruction. |
| | 509 | self.builder.positionBuilder(self.entry_block, latest_alloc.getNextInstruction().?); |
| | 510 | } else { |
| | 511 | // There might have been other instructions emitted before the |
| | 512 | // first alloca has been generated. However the alloca should still |
| | 513 | // be first in the function. |
| | 514 | if (self.entry_block.getFirstInstruction()) |first_inst| { |
| | 515 | self.builder.positionBuilder(self.entry_block, first_inst); |
| | 516 | } |
| | 517 | } |
| | 518 | defer self.builder.positionBuilderAtEnd(self.entry_block); |
| | 519 | |
| | 520 | const val = self.builder.buildAlloca(t, ""); |
| | 521 | self.latest_alloca_inst = val; |
| | 522 | return val; |
| 492 | } | 523 | } |
| 493 | | 524 | |
| 494 | fn genStore(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value { | 525 | fn genStore(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value { |