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