| ... | ... | @@ -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 { |
| 280 | | const tracy = trace(@src()); |
| 281 | | defer tracy.end(); |
| 279 | pub fn updateFunc( |
| 280 | self: *Object, |
| 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 | 344 | var dg: DeclGen = .{ |
| 284 | 345 | .object = self, |
| 285 | 346 | .module = module, |
| ... | ... | @@ -330,45 +391,8 @@ pub const DeclGen = struct { |
| 330 | 391 | log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val }); |
| 331 | 392 | |
| 332 | 393 | if (decl.val.castTag(.function)) |func_payload| { |
| 333 | | const func = func_payload.data; |
| 334 | | |
| 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); |
| 394 | _ = func_payload; |
| 395 | @panic("TODO llvm backend genDecl function pointer"); |
| 372 | 396 | } else if (decl.val.castTag(.extern_fn)) |extern_fn| { |
| 373 | 397 | _ = try self.resolveLLVMFunction(extern_fn.data); |
| 374 | 398 | } else { |
| ... | ... | @@ -596,6 +620,8 @@ pub const DeclGen = struct { |
| 596 | 620 | pub const FuncGen = struct { |
| 597 | 621 | gpa: *Allocator, |
| 598 | 622 | dg: *DeclGen, |
| 623 | air: Air, |
| 624 | liveness: Liveness, |
| 599 | 625 | |
| 600 | 626 | builder: *const llvm.Builder, |
| 601 | 627 | |
| ... | ... | @@ -649,14 +675,15 @@ pub const FuncGen = struct { |
| 649 | 675 | if (self.air.value(inst)) |val| { |
| 650 | 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 | 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 | 685 | const air_tags = self.air.instructions.items(.tag); |
| 659 | | for (body.instructions) |inst| { |
| 686 | for (body) |inst| { |
| 660 | 687 | const opt_value = switch (air_tags[inst]) { |
| 661 | 688 | .add => try self.airAdd(inst), |
| 662 | 689 | .sub => try self.airSub(inst), |
| ... | ... | @@ -828,8 +855,8 @@ pub const FuncGen = struct { |
| 828 | 855 | |
| 829 | 856 | // If the break doesn't break a value, then we don't have to add |
| 830 | 857 | // the values to the lists. |
| 831 | | if (self.air.typeOf(branch.result).hasCodeGenBits()) { |
| 832 | | const val = try self.resolveInst(branch.result); |
| 858 | if (self.air.typeOf(branch.operand).hasCodeGenBits()) { |
| 859 | const val = try self.resolveInst(branch.operand); |
| 833 | 860 | |
| 834 | 861 | // For the phi node, we need the basic blocks and the values of the |
| 835 | 862 | // break instructions. |