authorgravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2020-12-24 16:52:14+01:00
committergravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2020-12-28 21:20:49+01:00
logec3aedffb173845b3fe6f7559e06e1bc3cfde6f7
tree8826f40cd08a1cbe945e82bc3f2495a0ed42ad7d
parent4a32d4f288737a0d67484c1f05817ec468ec41f1

stage2: add initial implementation of func arguments in LLVM backend

The following works: ``` export fn _start() noreturn { assert(true); exit(); } fn assert(cond: bool) void {} fn exit() noreturn { unreachable; } ```

2 files changed, 47 insertions(+), 2 deletions(-)

src/llvm_backend.zig+38-2
......@@ -301,6 +301,7 @@ pub const LLVMIRModule = struct {
301301 .call => try self.genCall(inst.castTag(.call).?),
302302 .unreach => self.genUnreach(inst.castTag(.unreach).?),
303303 .retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
304 .arg => self.genArg(inst.castTag(.arg).?),
304305 .dbg_stmt => {
305306 // TODO: implement debug info
306307 },
......@@ -319,11 +320,23 @@ pub const LLVMIRModule = struct {
319320 const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;
320321 const llvm_fn = try self.resolveLLVMFunction(func);
321322
322 // TODO: handle more arguments, inst.args
323 const num_args = inst.args.len;
324
325 const llvm_param_vals = try self.gpa.alloc(*const llvm.ValueRef, num_args);
326 defer self.gpa.free(llvm_param_vals);
327
328 for (inst.args) |arg, i| {
329 llvm_param_vals[i] = try self.resolveInst(arg);
330 }
323331
324332 // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs
325333 // Do we need that?
326 const call = self.builder.buildCall(llvm_fn, null, 0, "");
334 const call = self.builder.buildCall(
335 llvm_fn,
336 if (num_args == 0) null else llvm_param_vals.ptr,
337 @intCast(c_uint, num_args),
338 "",
339 );
327340
328341 if (zig_fn_type.fnReturnType().zigTypeTag() == .NoReturn) {
329342 _ = self.builder.buildUnreachable();
......@@ -340,6 +353,10 @@ pub const LLVMIRModule = struct {
340353 _ = self.builder.buildUnreachable();
341354 }
342355
356 fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) void {
357 // TODO: implement this
358 }
359
343360 fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !void {
344361 // TODO: Store this function somewhere such that we dont have to add it again
345362 const fn_type = llvm.TypeRef.functionType(llvm.voidType(), null, 0, false);
......@@ -348,6 +365,25 @@ pub const LLVMIRModule = struct {
348365 _ = self.builder.buildCall(func, null, 0, "");
349366 }
350367
368 fn resolveInst(self: *LLVMIRModule, inst: *ir.Inst) !*const llvm.ValueRef {
369 if (inst.castTag(.constant)) |const_inst| {
370 return self.genTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val });
371 }
372 return self.fail(inst.src, "TODO implement resolveInst", .{});
373 }
374
375 fn genTypedValue(self: *LLVMIRModule, src: usize, typed_value: TypedValue) !*const llvm.ValueRef {
376 const llvm_type = self.getLLVMType(typed_value.ty);
377
378 if (typed_value.val.isUndef())
379 return llvm_type.getUndef();
380
381 switch (typed_value.ty.zigTypeTag()) {
382 .Bool => return if (typed_value.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(),
383 else => return self.fail(src, "TODO implement const of type '{}'", .{typed_value.ty}),
384 }
385 }
386
351387 /// If the llvm function does not exist, create it
352388 fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Fn) !*const llvm.ValueRef {
353389 // TODO: do we want to store this in our own datastructure?
src/llvm_bindings.zig+9
......@@ -36,6 +36,15 @@ pub const ValueRef = opaque {
3636pub const TypeRef = opaque {
3737 pub const functionType = LLVMFunctionType;
3838 extern fn LLVMFunctionType(ReturnType: *const TypeRef, ParamTypes: ?[*]*const TypeRef, ParamCount: c_uint, IsVarArg: LLVMBool) *const TypeRef;
39
40 pub const constNull = LLVMConstNull;
41 extern fn LLVMConstNull(Ty: *const TypeRef) *const ValueRef;
42
43 pub const constAllOnes = LLVMConstAllOnes;
44 extern fn LLVMConstAllOnes(Ty: *const TypeRef) *const ValueRef;
45
46 pub const getUndef = LLVMGetUndef;
47 extern fn LLVMGetUndef(Ty: *const TypeRef) *const ValueRef;
3948};
4049
4150pub const ModuleRef = opaque {