aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/llvm_backend.zig40
-rw-r--r--src/llvm_bindings.zig9
2 files changed, 47 insertions, 2 deletions
diff --git a/src/llvm_backend.zig b/src/llvm_backend.zig
index 5dce808eed..77aa4d3bd5 100644
--- a/src/llvm_backend.zig
+++ b/src/llvm_backend.zig
@@ -301,6 +301,7 @@ pub const LLVMIRModule = struct {
.call => try self.genCall(inst.castTag(.call).?),
.unreach => self.genUnreach(inst.castTag(.unreach).?),
.retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
+ .arg => self.genArg(inst.castTag(.arg).?),
.dbg_stmt => {
// TODO: implement debug info
},
@@ -319,11 +320,23 @@ pub const LLVMIRModule = struct {
const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;
const llvm_fn = try self.resolveLLVMFunction(func);
- // TODO: handle more arguments, inst.args
+ const num_args = inst.args.len;
+
+ const llvm_param_vals = try self.gpa.alloc(*const llvm.ValueRef, num_args);
+ defer self.gpa.free(llvm_param_vals);
+
+ for (inst.args) |arg, i| {
+ llvm_param_vals[i] = try self.resolveInst(arg);
+ }
// TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs
// Do we need that?
- const call = self.builder.buildCall(llvm_fn, null, 0, "");
+ const call = self.builder.buildCall(
+ llvm_fn,
+ if (num_args == 0) null else llvm_param_vals.ptr,
+ @intCast(c_uint, num_args),
+ "",
+ );
if (zig_fn_type.fnReturnType().zigTypeTag() == .NoReturn) {
_ = self.builder.buildUnreachable();
@@ -340,6 +353,10 @@ pub const LLVMIRModule = struct {
_ = self.builder.buildUnreachable();
}
+ fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) void {
+ // TODO: implement this
+ }
+
fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !void {
// TODO: Store this function somewhere such that we dont have to add it again
const fn_type = llvm.TypeRef.functionType(llvm.voidType(), null, 0, false);
@@ -348,6 +365,25 @@ pub const LLVMIRModule = struct {
_ = self.builder.buildCall(func, null, 0, "");
}
+ fn resolveInst(self: *LLVMIRModule, inst: *ir.Inst) !*const llvm.ValueRef {
+ if (inst.castTag(.constant)) |const_inst| {
+ return self.genTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val });
+ }
+ return self.fail(inst.src, "TODO implement resolveInst", .{});
+ }
+
+ fn genTypedValue(self: *LLVMIRModule, src: usize, typed_value: TypedValue) !*const llvm.ValueRef {
+ const llvm_type = self.getLLVMType(typed_value.ty);
+
+ if (typed_value.val.isUndef())
+ return llvm_type.getUndef();
+
+ switch (typed_value.ty.zigTypeTag()) {
+ .Bool => return if (typed_value.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(),
+ else => return self.fail(src, "TODO implement const of type '{}'", .{typed_value.ty}),
+ }
+ }
+
/// If the llvm function does not exist, create it
fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Fn) !*const llvm.ValueRef {
// TODO: do we want to store this in our own datastructure?
diff --git a/src/llvm_bindings.zig b/src/llvm_bindings.zig
index e36d71b312..388acc4ba2 100644
--- a/src/llvm_bindings.zig
+++ b/src/llvm_bindings.zig
@@ -36,6 +36,15 @@ pub const ValueRef = opaque {
pub const TypeRef = opaque {
pub const functionType = LLVMFunctionType;
extern fn LLVMFunctionType(ReturnType: *const TypeRef, ParamTypes: ?[*]*const TypeRef, ParamCount: c_uint, IsVarArg: LLVMBool) *const TypeRef;
+
+ pub const constNull = LLVMConstNull;
+ extern fn LLVMConstNull(Ty: *const TypeRef) *const ValueRef;
+
+ pub const constAllOnes = LLVMConstAllOnes;
+ extern fn LLVMConstAllOnes(Ty: *const TypeRef) *const ValueRef;
+
+ pub const getUndef = LLVMGetUndef;
+ extern fn LLVMGetUndef(Ty: *const TypeRef) *const ValueRef;
};
pub const ModuleRef = opaque {