| ... | @@ -276,10 +276,71 @@ pub const Object = struct { | ... | @@ -276,10 +276,71 @@ pub const Object = struct { |
| 276 | } | 276 | } |
| 277 | } | 277 | } |
| 278 | | 278 | |
| 279 | pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void { | 279 | pub fn updateFunc( |
| 280 | const tracy = trace(@src()); | 280 | self: *Object, |
| 281 | defer tracy.end(); | 281 | module: *Module, |
| | 282 | func: *Module.Fn, |
| | 283 | air: Air, |
| | 284 | liveness: Liveness, |
| | 285 | ) !void { |
| | 286 | var dg: DeclGen = .{ |
| | 287 | .object = self, |
| | 288 | .module = module, |
| | 289 | .decl = func.owner_decl, |
| | 290 | .err_msg = null, |
| | 291 | .gpa = module.gpa, |
| | 292 | }; |
| | 293 | |
| | 294 | const llvm_func = try dg.resolveLLVMFunction(func.owner_decl); |
| | 295 | |
| | 296 | // This gets the LLVM values from the function and stores them in `dg.args`. |
| | 297 | const fn_param_len = func.owner_decl.ty.fnParamLen(); |
| | 298 | var args = try dg.gpa.alloc(*const llvm.Value, fn_param_len); |
| 282 | | 299 | |
| | 300 | for (args) |*arg, i| { |
| | 301 | arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i)); |
| | 302 | } |
| | 303 | |
| | 304 | // We remove all the basic blocks of a function to support incremental |
| | 305 | // compilation! |
| | 306 | // TODO: remove all basic blocks if functions can have more than one |
| | 307 | if (llvm_func.getFirstBasicBlock()) |bb| { |
| | 308 | bb.deleteBasicBlock(); |
| | 309 | } |
| | 310 | |
| | 311 | const builder = dg.context().createBuilder(); |
| | 312 | |
| | 313 | const entry_block = dg.context().appendBasicBlock(llvm_func, "Entry"); |
| | 314 | builder.positionBuilderAtEnd(entry_block); |
| | 315 | |
| | 316 | var fg: FuncGen = .{ |
| | 317 | .gpa = dg.gpa, |
| | 318 | .air = air, |
| | 319 | .liveness = liveness, |
| | 320 | .dg = &dg, |
| | 321 | .builder = builder, |
| | 322 | .args = args, |
| | 323 | .arg_index = 0, |
| | 324 | .func_inst_table = .{}, |
| | 325 | .entry_block = entry_block, |
| | 326 | .latest_alloca_inst = null, |
| | 327 | .llvm_func = llvm_func, |
| | 328 | .blocks = .{}, |
| | 329 | }; |
| | 330 | defer fg.deinit(); |
| | 331 | |
| | 332 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| | 333 | error.CodegenFail => { |
| | 334 | func.owner_decl.analysis = .codegen_failure; |
| | 335 | try module.failed_decls.put(module.gpa, func.owner_decl, dg.err_msg.?); |
| | 336 | dg.err_msg = null; |
| | 337 | return; |
| | 338 | }, |
| | 339 | else => |e| return e, |
| | 340 | }; |
| | 341 | } |
| | 342 | |
| | 343 | pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void { |
| 283 | var dg: DeclGen = .{ | 344 | var dg: DeclGen = .{ |
| 284 | .object = self, | 345 | .object = self, |
| 285 | .module = module, | 346 | .module = module, |
| ... | @@ -330,45 +391,8 @@ pub const DeclGen = struct { | ... | @@ -330,45 +391,8 @@ pub const DeclGen = struct { |
| 330 | log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val }); | 391 | log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val }); |
| 331 | | 392 | |
| 332 | if (decl.val.castTag(.function)) |func_payload| { | 393 | if (decl.val.castTag(.function)) |func_payload| { |
| 333 | const func = func_payload.data; | 394 | _ = func_payload; |
| 334 | | 395 | @panic("TODO llvm backend genDecl function pointer"); |
| 335 | const llvm_func = try self.resolveLLVMFunction(func.owner_decl); | | |
| 336 | | | |
| 337 | // This gets the LLVM values from the function and stores them in `self.args`. | | |
| 338 | const fn_param_len = func.owner_decl.ty.fnParamLen(); | | |
| 339 | var args = try self.gpa.alloc(*const llvm.Value, fn_param_len); | | |
| 340 | | | |
| 341 | for (args) |*arg, i| { | | |
| 342 | arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i)); | | |
| 343 | } | | |
| 344 | | | |
| 345 | // We remove all the basic blocks of a function to support incremental | | |
| 346 | // compilation! | | |
| 347 | // TODO: remove all basic blocks if functions can have more than one | | |
| 348 | if (llvm_func.getFirstBasicBlock()) |bb| { | | |
| 349 | bb.deleteBasicBlock(); | | |
| 350 | } | | |
| 351 | | | |
| 352 | const builder = self.context().createBuilder(); | | |
| 353 | | | |
| 354 | const entry_block = self.context().appendBasicBlock(llvm_func, "Entry"); | | |
| 355 | builder.positionBuilderAtEnd(entry_block); | | |
| 356 | | | |
| 357 | var fg: FuncGen = .{ | | |
| 358 | .gpa = self.gpa, | | |
| 359 | .dg = self, | | |
| 360 | .builder = builder, | | |
| 361 | .args = args, | | |
| 362 | .arg_index = 0, | | |
| 363 | .func_inst_table = .{}, | | |
| 364 | .entry_block = entry_block, | | |
| 365 | .latest_alloca_inst = null, | | |
| 366 | .llvm_func = llvm_func, | | |
| 367 | .blocks = .{}, | | |
| 368 | }; | | |
| 369 | defer fg.deinit(); | | |
| 370 | | | |
| 371 | try fg.genBody(func.body); | | |
| 372 | } else if (decl.val.castTag(.extern_fn)) |extern_fn| { | 396 | } else if (decl.val.castTag(.extern_fn)) |extern_fn| { |
| 373 | _ = try self.resolveLLVMFunction(extern_fn.data); | 397 | _ = try self.resolveLLVMFunction(extern_fn.data); |
| 374 | } else { | 398 | } else { |
| ... | @@ -596,6 +620,8 @@ pub const DeclGen = struct { | ... | @@ -596,6 +620,8 @@ pub const DeclGen = struct { |
| 596 | pub const FuncGen = struct { | 620 | pub const FuncGen = struct { |
| 597 | gpa: *Allocator, | 621 | gpa: *Allocator, |
| 598 | dg: *DeclGen, | 622 | dg: *DeclGen, |
| | 623 | air: Air, |
| | 624 | liveness: Liveness, |
| 599 | | 625 | |
| 600 | builder: *const llvm.Builder, | 626 | builder: *const llvm.Builder, |
| 601 | | 627 | |
| ... | @@ -649,14 +675,15 @@ pub const FuncGen = struct { | ... | @@ -649,14 +675,15 @@ pub const FuncGen = struct { |
| 649 | if (self.air.value(inst)) |val| { | 675 | if (self.air.value(inst)) |val| { |
| 650 | return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val }, self); | 676 | return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val }, self); |
| 651 | } | 677 | } |
| 652 | if (self.func_inst_table.get(inst)) |value| return value; | 678 | const inst_index = Air.refToIndex(inst).?; |
| | 679 | if (self.func_inst_table.get(inst_index)) |value| return value; |
| 653 | | 680 | |
| 654 | return self.todo("implement global llvm values (or the value is not in the func_inst_table table)", .{}); | 681 | return self.todo("implement global llvm values (or the value is not in the func_inst_table table)", .{}); |
| 655 | } | 682 | } |
| 656 | | 683 | |
| 657 | fn genBody(self: *FuncGen, body: ir.Body) error{ OutOfMemory, CodegenFail }!void { | 684 | fn genBody(self: *FuncGen, body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void { |
| 658 | const air_tags = self.air.instructions.items(.tag); | 685 | const air_tags = self.air.instructions.items(.tag); |
| 659 | for (body.instructions) |inst| { | 686 | for (body) |inst| { |
| 660 | const opt_value = switch (air_tags[inst]) { | 687 | const opt_value = switch (air_tags[inst]) { |
| 661 | .add => try self.airAdd(inst), | 688 | .add => try self.airAdd(inst), |
| 662 | .sub => try self.airSub(inst), | 689 | .sub => try self.airSub(inst), |
| ... | @@ -828,8 +855,8 @@ pub const FuncGen = struct { | ... | @@ -828,8 +855,8 @@ pub const FuncGen = struct { |
| 828 | | 855 | |
| 829 | // If the break doesn't break a value, then we don't have to add | 856 | // If the break doesn't break a value, then we don't have to add |
| 830 | // the values to the lists. | 857 | // the values to the lists. |
| 831 | if (self.air.typeOf(branch.result).hasCodeGenBits()) { | 858 | if (self.air.typeOf(branch.operand).hasCodeGenBits()) { |
| 832 | const val = try self.resolveInst(branch.result); | 859 | const val = try self.resolveInst(branch.operand); |
| 833 | | 860 | |
| 834 | // For the phi node, we need the basic blocks and the values of the | 861 | // For the phi node, we need the basic blocks and the values of the |
| 835 | // break instructions. | 862 | // break instructions. |