diff options
| author | Timon Kruiper <timonkruiper@gmail.com> | 2020-12-29 20:39:58 +0100 |
|---|---|---|
| committer | Timon Kruiper <timonkruiper@gmail.com> | 2021-01-03 17:23:30 +0100 |
| commit | da545d6a3195c1cafca498d8a695082982f74676 (patch) | |
| tree | c85dc18ef61eee7982c98ddd80c81223a25f69db /src/llvm_backend.zig | |
| parent | 47a4d43e41b07b939b840fbf8230b89e27694093 (diff) | |
| download | zig-da545d6a3195c1cafca498d8a695082982f74676.tar.gz zig-da545d6a3195c1cafca498d8a695082982f74676.zip | |
stage2: implement argument passing and returning in LLVM backend
Furthermore add the Not instruction.
The following now works:
```
export fn _start() noreturn {
var x: bool = true;
var other: bool = foo(x);
exit();
}
fn foo(cond: bool) bool {
return !cond;
}
fn exit() noreturn {
unreachable;
}
```
Diffstat (limited to 'src/llvm_backend.zig')
| -rw-r--r-- | src/llvm_backend.zig | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/llvm_backend.zig b/src/llvm_backend.zig index d56233a503..dbfe182eed 100644 --- a/src/llvm_backend.zig +++ b/src/llvm_backend.zig @@ -150,6 +150,10 @@ pub const LLVMIRModule = struct { /// referred to in other instructions. This table is cleared before every function is generated. func_inst_table: std.AutoHashMapUnmanaged(*Inst, *const llvm.ValueRef) = .{}, + /// These fields are used to refer to the LLVM value of the function paramaters in an Arg instruction. + args: []*const llvm.ValueRef = &[_]*const llvm.ValueRef{}, + arg_index: usize = 0, + pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule { const self = try allocator.create(LLVMIRModule); errdefer allocator.destroy(self); @@ -289,6 +293,17 @@ pub const LLVMIRModule = struct { const llvm_func = try self.resolveLLVMFunction(func, src); + // This gets the LLVM values from the function and stores them in `self.args`. + const fn_param_len = func.owner_decl.typed_value.most_recent.typed_value.ty.fnParamLen(); + var args = try self.gpa.alloc(*const llvm.ValueRef, fn_param_len); + defer self.gpa.free(args); + + for (args) |*arg, i| { + arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i)); + } + self.args = args; + self.arg_index = 0; + // Make sure no other LLVM values from other functions can be referenced self.func_inst_table.clearRetainingCapacity(); @@ -313,6 +328,8 @@ pub const LLVMIRModule = struct { .alloc => try self.genAlloc(inst.castTag(.alloc).?), .store => try self.genStore(inst.castTag(.store).?), .load => try self.genLoad(inst.castTag(.load).?), + .ret => try self.genRet(inst.castTag(.ret).?), + .not => try self.genNot(inst.castTag(.not).?), .dbg_stmt => blk: { // TODO: implement debug info break :blk null; @@ -370,14 +387,27 @@ pub const LLVMIRModule = struct { return null; } + fn genRet(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.ValueRef { + _ = self.builder.buildRet(try self.resolveInst(inst.operand)); + return null; + } + + fn genNot(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.ValueRef { + return self.builder.buildNot(try self.resolveInst(inst.operand), ""); + } + fn genUnreach(self: *LLVMIRModule, inst: *Inst.NoOp) ?*const llvm.ValueRef { _ = self.builder.buildUnreachable(); return null; } fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) !?*const llvm.ValueRef { - // TODO: implement this - return null; + const arg_val = self.args[self.arg_index]; + self.arg_index += 1; + + const ptr_val = self.builder.buildAlloca(try self.getLLVMType(inst.base.ty, inst.base.src), ""); + _ = self.builder.buildStore(arg_val, ptr_val); + return self.builder.buildLoad(ptr_val, ""); } fn genAlloc(self: *LLVMIRModule, inst: *Inst.NoOp) !?*const llvm.ValueRef { |
