mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
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;
}
```
This commit is contained in:
parent
47a4d43e41
commit
da545d6a31
@ -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 {
|
||||
|
||||
@ -79,6 +79,9 @@ pub const VerifierFailureAction = extern enum {
|
||||
pub const voidType = LLVMVoidType;
|
||||
extern fn LLVMVoidType() *const TypeRef;
|
||||
|
||||
pub const getParam = LLVMGetParam;
|
||||
extern fn LLVMGetParam(Fn: *const ValueRef, Index: c_uint) *const ValueRef;
|
||||
|
||||
pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
|
||||
extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
|
||||
|
||||
@ -117,6 +120,9 @@ pub const BuilderRef = opaque {
|
||||
pub const buildRetVoid = LLVMBuildRetVoid;
|
||||
extern fn LLVMBuildRetVoid(*const BuilderRef) *const ValueRef;
|
||||
|
||||
pub const buildRet = LLVMBuildRet;
|
||||
extern fn LLVMBuildRet(*const BuilderRef, V: *const ValueRef) *const ValueRef;
|
||||
|
||||
pub const buildUnreachable = LLVMBuildUnreachable;
|
||||
extern fn LLVMBuildUnreachable(*const BuilderRef) *const ValueRef;
|
||||
|
||||
@ -128,6 +134,9 @@ pub const BuilderRef = opaque {
|
||||
|
||||
pub const buildLoad = LLVMBuildLoad;
|
||||
extern fn LLVMBuildLoad(*const BuilderRef, PointerVal: *const ValueRef, Name: [*:0]const u8) *const ValueRef;
|
||||
|
||||
pub const buildNot = LLVMBuildNot;
|
||||
extern fn LLVMBuildNot(*const BuilderRef, V: *const ValueRef, Name: [*:0]const u8) *const ValueRef;
|
||||
};
|
||||
|
||||
pub const BasicBlockRef = opaque {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user