| ... | ... | @@ -301,6 +301,7 @@ pub const LLVMIRModule = struct { |
| 301 | 301 | .call => try self.genCall(inst.castTag(.call).?), |
| 302 | 302 | .unreach => self.genUnreach(inst.castTag(.unreach).?), |
| 303 | 303 | .retvoid => self.genRetVoid(inst.castTag(.retvoid).?), |
| 304 | .arg => self.genArg(inst.castTag(.arg).?), |
| 304 | 305 | .dbg_stmt => { |
| 305 | 306 | // TODO: implement debug info |
| 306 | 307 | }, |
| ... | ... | @@ -319,11 +320,23 @@ pub const LLVMIRModule = struct { |
| 319 | 320 | const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty; |
| 320 | 321 | const llvm_fn = try self.resolveLLVMFunction(func); |
| 321 | 322 | |
| 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 | } |
| 323 | 331 | |
| 324 | 332 | // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs |
| 325 | 333 | // 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 | ); |
| 327 | 340 | |
| 328 | 341 | if (zig_fn_type.fnReturnType().zigTypeTag() == .NoReturn) { |
| 329 | 342 | _ = self.builder.buildUnreachable(); |
| ... | ... | @@ -340,6 +353,10 @@ pub const LLVMIRModule = struct { |
| 340 | 353 | _ = self.builder.buildUnreachable(); |
| 341 | 354 | } |
| 342 | 355 | |
| 356 | fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) void { |
| 357 | // TODO: implement this |
| 358 | } |
| 359 | |
| 343 | 360 | fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !void { |
| 344 | 361 | // TODO: Store this function somewhere such that we dont have to add it again |
| 345 | 362 | const fn_type = llvm.TypeRef.functionType(llvm.voidType(), null, 0, false); |
| ... | ... | @@ -348,6 +365,25 @@ pub const LLVMIRModule = struct { |
| 348 | 365 | _ = self.builder.buildCall(func, null, 0, ""); |
| 349 | 366 | } |
| 350 | 367 | |
| 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 | |
| 351 | 387 | /// If the llvm function does not exist, create it |
| 352 | 388 | fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Fn) !*const llvm.ValueRef { |
| 353 | 389 | // TODO: do we want to store this in our own datastructure? |