authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-13 11:38:46-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-06-13 02:22:05-07:00
log206e66858c69cd667aad3779837493968bfcd228
treecd63bedc020c731688345746f2b089b103c4b3b9
parentc10d1c6a75f818eda092ef7912fd3c2b996632f0
signaturelock-open Commit is signed but in an unrecognized format.

riscv: rename `Self` to `Func`

Very similar reasoning to the Wasm backend. I believe that "Self" is not the most descriptive possible name here and "Func" better explains it. The generation is happening for a Function, and accessing "Func" is like accessing the context of that current function.

1 files changed, 1868 insertions(+), 1877 deletions(-)

src/arch/riscv64/CodeGen.zig+1868-1877
...@@ -281,9 +281,9 @@ const MCValue = union(enum) {...@@ -281,9 +281,9 @@ const MCValue = union(enum) {
281const Branch = struct {281const Branch = struct {
282 inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .{},282 inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .{},
283283
284 fn deinit(self: *Branch, gpa: Allocator) void {284 fn deinit(func: *Branch, gpa: Allocator) void {
285 self.inst_table.deinit(gpa);285 func.inst_table.deinit(gpa);
286 self.* = undefined;286 func.* = undefined;
287 }287 }
288};288};
289289
...@@ -317,33 +317,33 @@ const InstTracking = struct {...@@ -317,33 +317,33 @@ const InstTracking = struct {
317 }, .short = result };317 }, .short = result };
318 }318 }
319319
320 fn getReg(self: InstTracking) ?Register {320 fn getReg(func: InstTracking) ?Register {
321 return self.short.getReg();321 return func.short.getReg();
322 }322 }
323323
324 fn getRegs(self: *const InstTracking) []const Register {324 fn getRegs(func: *const InstTracking) []const Register {
325 return self.short.getRegs();325 return func.short.getRegs();
326 }326 }
327327
328 fn spill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {328 fn spill(func: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
329 if (std.meta.eql(self.long, self.short)) return; // Already spilled329 if (std.meta.eql(func.long, func.short)) return; // Already spilled
330 // Allocate or reuse frame index330 // Allocate or reuse frame index
331 switch (self.long) {331 switch (func.long) {
332 .none => self.long = try function.allocRegOrMem(inst, false),332 .none => func.long = try function.allocRegOrMem(inst, false),
333 .load_frame => {},333 .load_frame => {},
334 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },334 .reserved_frame => |index| func.long = .{ .load_frame = .{ .index = index } },
335 else => unreachable,335 else => unreachable,
336 }336 }
337 tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });337 tracking_log.debug("spill %{d} from {} to {}", .{ inst, func.short, func.long });
338 try function.genCopy(function.typeOfIndex(inst), self.long, self.short);338 try function.genCopy(function.typeOfIndex(inst), func.long, func.short);
339 }339 }
340340
341 fn reuseFrame(self: *InstTracking) void {341 fn reuseFrame(func: *InstTracking) void {
342 switch (self.long) {342 switch (func.long) {
343 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },343 .reserved_frame => |index| func.long = .{ .load_frame = .{ .index = index } },
344 else => {},344 else => {},
345 }345 }
346 self.short = switch (self.long) {346 func.short = switch (func.long) {
347 .none,347 .none,
348 .unreach,348 .unreach,
349 .undef,349 .undef,
...@@ -353,7 +353,7 @@ const InstTracking = struct {...@@ -353,7 +353,7 @@ const InstTracking = struct {
353 .lea_frame,353 .lea_frame,
354 .load_symbol,354 .load_symbol,
355 .lea_symbol,355 .lea_symbol,
356 => self.long,356 => func.long,
357 .dead,357 .dead,
358 .register,358 .register,
359 .register_pair,359 .register_pair,
...@@ -365,14 +365,14 @@ const InstTracking = struct {...@@ -365,14 +365,14 @@ const InstTracking = struct {
365 };365 };
366 }366 }
367367
368 fn trackSpill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {368 fn trackSpill(func: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
369 try function.freeValue(self.short);369 try function.freeValue(func.short);
370 self.reuseFrame();370 func.reuseFrame();
371 tracking_log.debug("%{d} => {} (spilled)", .{ inst, self.* });371 tracking_log.debug("%{d} => {} (spilled)", .{ inst, func.* });
372 }372 }
373373
374 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {374 fn verifyMaterialize(func: InstTracking, target: InstTracking) void {
375 switch (self.long) {375 switch (func.long) {
376 .none,376 .none,
377 .unreach,377 .unreach,
378 .undef,378 .undef,
...@@ -381,7 +381,7 @@ const InstTracking = struct {...@@ -381,7 +381,7 @@ const InstTracking = struct {
381 .lea_frame,381 .lea_frame,
382 .load_symbol,382 .load_symbol,
383 .lea_symbol,383 .lea_symbol,
384 => assert(std.meta.eql(self.long, target.long)),384 => assert(std.meta.eql(func.long, target.long)),
385 .load_frame,385 .load_frame,
386 .reserved_frame,386 .reserved_frame,
387 => switch (target.long) {387 => switch (target.long) {
...@@ -402,73 +402,73 @@ const InstTracking = struct {...@@ -402,73 +402,73 @@ const InstTracking = struct {
402 }402 }
403403
404 fn materialize(404 fn materialize(
405 self: *InstTracking,405 func: *InstTracking,
406 function: *Self,406 function: *Func,
407 inst: Air.Inst.Index,407 inst: Air.Inst.Index,
408 target: InstTracking,408 target: InstTracking,
409 ) !void {409 ) !void {
410 self.verifyMaterialize(target);410 func.verifyMaterialize(target);
411 try self.materializeUnsafe(function, inst, target);411 try func.materializeUnsafe(function, inst, target);
412 }412 }
413413
414 fn materializeUnsafe(414 fn materializeUnsafe(
415 self: InstTracking,415 func: InstTracking,
416 function: *Self,416 function: *Func,
417 inst: Air.Inst.Index,417 inst: Air.Inst.Index,
418 target: InstTracking,418 target: InstTracking,
419 ) !void {419 ) !void {
420 const ty = function.typeOfIndex(inst);420 const ty = function.typeOfIndex(inst);
421 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)421 if ((func.long == .none or func.long == .reserved_frame) and target.long == .load_frame)
422 try function.genCopy(ty, target.long, self.short);422 try function.genCopy(ty, target.long, func.short);
423 try function.genCopy(ty, target.short, self.short);423 try function.genCopy(ty, target.short, func.short);
424 }424 }
425425
426 fn trackMaterialize(self: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {426 fn trackMaterialize(func: *InstTracking, inst: Air.Inst.Index, target: InstTracking) void {
427 self.verifyMaterialize(target);427 func.verifyMaterialize(target);
428 // Don't clobber reserved frame indices428 // Don't clobber reserved frame indices
429 self.long = if (target.long == .none) switch (self.long) {429 func.long = if (target.long == .none) switch (func.long) {
430 .load_frame => |addr| .{ .reserved_frame = addr.index },430 .load_frame => |addr| .{ .reserved_frame = addr.index },
431 .reserved_frame => self.long,431 .reserved_frame => func.long,
432 else => target.long,432 else => target.long,
433 } else target.long;433 } else target.long;
434 self.short = target.short;434 func.short = target.short;
435 tracking_log.debug("%{d} => {} (materialize)", .{ inst, self.* });435 tracking_log.debug("%{d} => {} (materialize)", .{ inst, func.* });
436 }436 }
437437
438 fn resurrect(self: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {438 fn resurrect(func: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
439 switch (self.short) {439 switch (func.short) {
440 .dead => |die_generation| if (die_generation >= scope_generation) {440 .dead => |die_generation| if (die_generation >= scope_generation) {
441 self.reuseFrame();441 func.reuseFrame();
442 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, self.* });442 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, func.* });
443 },443 },
444 else => {},444 else => {},
445 }445 }
446 }446 }
447447
448 fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {448 fn die(func: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
449 if (self.short == .dead) return;449 if (func.short == .dead) return;
450 try function.freeValue(self.short);450 try function.freeValue(func.short);
451 self.short = .{ .dead = function.scope_generation };451 func.short = .{ .dead = function.scope_generation };
452 tracking_log.debug("%{d} => {} (death)", .{ inst, self.* });452 tracking_log.debug("%{d} => {} (death)", .{ inst, func.* });
453 }453 }
454454
455 fn reuse(455 fn reuse(
456 self: *InstTracking,456 func: *InstTracking,
457 function: *Self,457 function: *Func,
458 new_inst: ?Air.Inst.Index,458 new_inst: ?Air.Inst.Index,
459 old_inst: Air.Inst.Index,459 old_inst: Air.Inst.Index,
460 ) void {460 ) void {
461 self.short = .{ .dead = function.scope_generation };461 func.short = .{ .dead = function.scope_generation };
462 if (new_inst) |inst|462 if (new_inst) |inst|
463 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, self.*, old_inst })463 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, func.*, old_inst })
464 else464 else
465 tracking_log.debug("tmp => {} (reuse %{d})", .{ self.*, old_inst });465 tracking_log.debug("tmp => {} (reuse %{d})", .{ func.*, old_inst });
466 }466 }
467467
468 fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void {468 fn liveOut(func: *InstTracking, function: *Func, inst: Air.Inst.Index) void {
469 for (self.getRegs()) |reg| {469 for (func.getRegs()) |reg| {
470 if (function.register_manager.isRegFree(reg)) {470 if (function.register_manager.isRegFree(reg)) {
471 tracking_log.debug("%{d} => {} (live-out)", .{ inst, self.* });471 tracking_log.debug("%{d} => {} (live-out)", .{ inst, func.* });
472 continue;472 continue;
473 }473 }
474474
...@@ -495,18 +495,18 @@ const InstTracking = struct {...@@ -495,18 +495,18 @@ const InstTracking = struct {
495 // Perform side-effects of freeValue manually.495 // Perform side-effects of freeValue manually.
496 function.register_manager.freeReg(reg);496 function.register_manager.freeReg(reg);
497497
498 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, self.*, tracked_inst });498 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, func.*, tracked_inst });
499 }499 }
500 }500 }
501501
502 pub fn format(502 pub fn format(
503 self: InstTracking,503 func: InstTracking,
504 comptime _: []const u8,504 comptime _: []const u8,
505 _: std.fmt.FormatOptions,505 _: std.fmt.FormatOptions,
506 writer: anytype,506 writer: anytype,
507 ) @TypeOf(writer).Error!void {507 ) @TypeOf(writer).Error!void {
508 if (!std.meta.eql(self.long, self.short)) try writer.print("|{}| ", .{self.long});508 if (!std.meta.eql(func.long, func.short)) try writer.print("|{}| ", .{func.long});
509 try writer.print("{}", .{self.short});509 try writer.print("{}", .{func.short});
510 }510 }
511};511};
512512
...@@ -546,19 +546,13 @@ const FrameAlloc = struct {...@@ -546,19 +546,13 @@ const FrameAlloc = struct {
546 }546 }
547};547};
548548
549const StackAllocation = struct {
550 inst: ?Air.Inst.Index,
551 /// TODO: make the size inferred from the bits of the inst
552 size: u32,
553};
554
555const BlockData = struct {549const BlockData = struct {
556 relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},550 relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},
557 state: State,551 state: State,
558552
559 fn deinit(self: *BlockData, gpa: Allocator) void {553 fn deinit(bd: *BlockData, gpa: Allocator) void {
560 self.relocs.deinit(gpa);554 bd.relocs.deinit(gpa);
561 self.* = undefined;555 bd.* = undefined;
562 }556 }
563};557};
564558
...@@ -570,31 +564,31 @@ const State = struct {...@@ -570,31 +564,31 @@ const State = struct {
570 scope_generation: u32,564 scope_generation: u32,
571};565};
572566
573fn initRetroactiveState(self: *Self) State {567fn initRetroactiveState(func: *Func) State {
574 var state: State = undefined;568 var state: State = undefined;
575 state.inst_tracking_len = @intCast(self.inst_tracking.count());569 state.inst_tracking_len = @intCast(func.inst_tracking.count());
576 state.scope_generation = self.scope_generation;570 state.scope_generation = func.scope_generation;
577 return state;571 return state;
578}572}
579573
580fn saveRetroactiveState(self: *Self, state: *State) !void {574fn saveRetroactiveState(func: *Func, state: *State) !void {
581 const free_registers = self.register_manager.free_registers;575 const free_registers = func.register_manager.free_registers;
582 var it = free_registers.iterator(.{ .kind = .unset });576 var it = free_registers.iterator(.{ .kind = .unset });
583 while (it.next()) |index| {577 while (it.next()) |index| {
584 const tracked_inst = self.register_manager.registers[index];578 const tracked_inst = func.register_manager.registers[index];
585 state.registers[index] = tracked_inst;579 state.registers[index] = tracked_inst;
586 state.reg_tracking[index] = self.inst_tracking.get(tracked_inst).?;580 state.reg_tracking[index] = func.inst_tracking.get(tracked_inst).?;
587 }581 }
588 state.free_registers = free_registers;582 state.free_registers = free_registers;
589}583}
590584
591fn saveState(self: *Self) !State {585fn saveState(func: *Func) !State {
592 var state = self.initRetroactiveState();586 var state = func.initRetroactiveState();
593 try self.saveRetroactiveState(&state);587 try func.saveRetroactiveState(&state);
594 return state;588 return state;
595}589}
596590
597fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, comptime opts: struct {591fn restoreState(func: *Func, state: State, deaths: []const Air.Inst.Index, comptime opts: struct {
598 emit_instructions: bool,592 emit_instructions: bool,
599 update_tracking: bool,593 update_tracking: bool,
600 resurrect: bool,594 resurrect: bool,
...@@ -602,81 +596,81 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt...@@ -602,81 +596,81 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
602}) !void {596}) !void {
603 if (opts.close_scope) {597 if (opts.close_scope) {
604 for (598 for (
605 self.inst_tracking.keys()[state.inst_tracking_len..],599 func.inst_tracking.keys()[state.inst_tracking_len..],
606 self.inst_tracking.values()[state.inst_tracking_len..],600 func.inst_tracking.values()[state.inst_tracking_len..],
607 ) |inst, *tracking| try tracking.die(self, inst);601 ) |inst, *tracking| try tracking.die(func, inst);
608 self.inst_tracking.shrinkRetainingCapacity(state.inst_tracking_len);602 func.inst_tracking.shrinkRetainingCapacity(state.inst_tracking_len);
609 }603 }
610604
611 if (opts.resurrect) for (605 if (opts.resurrect) for (
612 self.inst_tracking.keys()[0..state.inst_tracking_len],606 func.inst_tracking.keys()[0..state.inst_tracking_len],
613 self.inst_tracking.values()[0..state.inst_tracking_len],607 func.inst_tracking.values()[0..state.inst_tracking_len],
614 ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);608 ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);
615 for (deaths) |death| try self.processDeath(death);609 for (deaths) |death| try func.processDeath(death);
616610
617 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock;611 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock;
618 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =612 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
619 if (opts.update_tracking)613 if (opts.update_tracking)
620 {} else std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);614 {} else std.heap.stackFallback(@sizeOf(ExpectedContents), func.gpa);
621615
622 var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity(616 var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity(
623 stack.get(),617 stack.get(),
624 @typeInfo(ExpectedContents).Array.len,618 @typeInfo(ExpectedContents).Array.len,
625 );619 );
626 defer if (!opts.update_tracking) {620 defer if (!opts.update_tracking) {
627 for (reg_locks.items) |lock| self.register_manager.unlockReg(lock);621 for (reg_locks.items) |lock| func.register_manager.unlockReg(lock);
628 reg_locks.deinit();622 reg_locks.deinit();
629 };623 };
630624
631 for (0..state.registers.len) |index| {625 for (0..state.registers.len) |index| {
632 const current_maybe_inst = if (self.register_manager.free_registers.isSet(index))626 const current_maybe_inst = if (func.register_manager.free_registers.isSet(index))
633 null627 null
634 else628 else
635 self.register_manager.registers[index];629 func.register_manager.registers[index];
636 const target_maybe_inst = if (state.free_registers.isSet(index))630 const target_maybe_inst = if (state.free_registers.isSet(index))
637 null631 null
638 else632 else
639 state.registers[index];633 state.registers[index];
640 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|634 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|
641 assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);635 assert(func.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);
642 if (opts.emit_instructions) {636 if (opts.emit_instructions) {
643 if (current_maybe_inst) |current_inst| {637 if (current_maybe_inst) |current_inst| {
644 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);638 try func.inst_tracking.getPtr(current_inst).?.spill(func, current_inst);
645 }639 }
646 if (target_maybe_inst) |target_inst| {640 if (target_maybe_inst) |target_inst| {
647 const target_tracking = self.inst_tracking.getPtr(target_inst).?;641 const target_tracking = func.inst_tracking.getPtr(target_inst).?;
648 try target_tracking.materialize(self, target_inst, state.reg_tracking[index]);642 try target_tracking.materialize(func, target_inst, state.reg_tracking[index]);
649 }643 }
650 }644 }
651 if (opts.update_tracking) {645 if (opts.update_tracking) {
652 if (current_maybe_inst) |current_inst| {646 if (current_maybe_inst) |current_inst| {
653 try self.inst_tracking.getPtr(current_inst).?.trackSpill(self, current_inst);647 try func.inst_tracking.getPtr(current_inst).?.trackSpill(func, current_inst);
654 }648 }
655 blk: {649 blk: {
656 const inst = target_maybe_inst orelse break :blk;650 const inst = target_maybe_inst orelse break :blk;
657 const reg = RegisterManager.regAtTrackedIndex(@intCast(index));651 const reg = RegisterManager.regAtTrackedIndex(@intCast(index));
658 self.register_manager.freeReg(reg);652 func.register_manager.freeReg(reg);
659 self.register_manager.getRegAssumeFree(reg, inst);653 func.register_manager.getRegAssumeFree(reg, inst);
660 }654 }
661 if (target_maybe_inst) |target_inst| {655 if (target_maybe_inst) |target_inst| {
662 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(656 func.inst_tracking.getPtr(target_inst).?.trackMaterialize(
663 target_inst,657 target_inst,
664 state.reg_tracking[index],658 state.reg_tracking[index],
665 );659 );
666 }660 }
667 } else if (target_maybe_inst) |_|661 } else if (target_maybe_inst) |_|
668 try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(@intCast(index)));662 try reg_locks.append(func.register_manager.lockRegIndexAssumeUnused(@intCast(index)));
669 }663 }
670664
671 if (opts.update_tracking and std.debug.runtime_safety) {665 if (opts.update_tracking and std.debug.runtime_safety) {
672 assert(self.register_manager.free_registers.eql(state.free_registers));666 assert(func.register_manager.free_registers.eql(state.free_registers));
673 var used_reg_it = state.free_registers.iterator(.{ .kind = .unset });667 var used_reg_it = state.free_registers.iterator(.{ .kind = .unset });
674 while (used_reg_it.next()) |index|668 while (used_reg_it.next()) |index|
675 assert(self.register_manager.registers[index] == state.registers[index]);669 assert(func.register_manager.registers[index] == state.registers[index]);
676 }670 }
677}671}
678672
679const Self = @This();673const Func = @This();
680674
681const CallView = enum(u1) {675const CallView = enum(u1) {
682 callee,676 callee,
...@@ -712,7 +706,7 @@ pub fn generate(...@@ -712,7 +706,7 @@ pub fn generate(
712 }706 }
713 try branch_stack.append(.{});707 try branch_stack.append(.{});
714708
715 var function = Self{709 var function = Func{
716 .gpa = gpa,710 .gpa = gpa,
717 .air = air,711 .air = air,
718 .mod = mod,712 .mod = mod,
...@@ -852,51 +846,51 @@ pub fn generate(...@@ -852,51 +846,51 @@ pub fn generate(
852 }846 }
853}847}
854848
855fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {849fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
856 const gpa = self.gpa;850 const gpa = func.gpa;
857851
858 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);852 try func.mir_instructions.ensureUnusedCapacity(gpa, 1);
859853
860 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);854 const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len);
861 self.mir_instructions.appendAssumeCapacity(inst);855 func.mir_instructions.appendAssumeCapacity(inst);
862 return result_index;856 return result_index;
863}857}
864858
865fn addNop(self: *Self) error{OutOfMemory}!Mir.Inst.Index {859fn addNop(func: *Func) error{OutOfMemory}!Mir.Inst.Index {
866 return self.addInst(.{860 return func.addInst(.{
867 .tag = .nop,861 .tag = .nop,
868 .ops = .none,862 .ops = .none,
869 .data = undefined,863 .data = undefined,
870 });864 });
871}865}
872866
873fn addPseudoNone(self: *Self, ops: Mir.Inst.Ops) !void {867fn addPseudoNone(func: *Func, ops: Mir.Inst.Ops) !void {
874 _ = try self.addInst(.{868 _ = try func.addInst(.{
875 .tag = .pseudo,869 .tag = .pseudo,
876 .ops = ops,870 .ops = ops,
877 .data = undefined,871 .data = undefined,
878 });872 });
879}873}
880874
881fn addPseudo(self: *Self, ops: Mir.Inst.Ops) !Mir.Inst.Index {875fn addPseudo(func: *Func, ops: Mir.Inst.Ops) !Mir.Inst.Index {
882 return self.addInst(.{876 return func.addInst(.{
883 .tag = .pseudo,877 .tag = .pseudo,
884 .ops = ops,878 .ops = ops,
885 .data = undefined,879 .data = undefined,
886 });880 });
887}881}
888882
889pub fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 {883pub fn addExtra(func: *Func, extra: anytype) Allocator.Error!u32 {
890 const fields = std.meta.fields(@TypeOf(extra));884 const fields = std.meta.fields(@TypeOf(extra));
891 try self.mir_extra.ensureUnusedCapacity(self.gpa, fields.len);885 try func.mir_extra.ensureUnusedCapacity(func.gpa, fields.len);
892 return self.addExtraAssumeCapacity(extra);886 return func.addExtraAssumeCapacity(extra);
893}887}
894888
895pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {889pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 {
896 const fields = std.meta.fields(@TypeOf(extra));890 const fields = std.meta.fields(@TypeOf(extra));
897 const result: u32 = @intCast(self.mir_extra.items.len);891 const result: u32 = @intCast(func.mir_extra.items.len);
898 inline for (fields) |field| {892 inline for (fields) |field| {
899 self.mir_extra.appendAssumeCapacity(switch (field.type) {893 func.mir_extra.appendAssumeCapacity(switch (field.type) {
900 u32 => @field(extra, field.name),894 u32 => @field(extra, field.name),
901 i32 => @bitCast(@field(extra, field.name)),895 i32 => @bitCast(@field(extra, field.name)),
902 else => @compileError("bad field type"),896 else => @compileError("bad field type"),
...@@ -910,13 +904,13 @@ const required_features = [_]Target.riscv.Feature{...@@ -910,13 +904,13 @@ const required_features = [_]Target.riscv.Feature{
910 .m,904 .m,
911};905};
912906
913fn gen(self: *Self) !void {907fn gen(func: *Func) !void {
914 const mod = self.bin_file.comp.module.?;908 const mod = func.bin_file.comp.module.?;
915 const fn_info = mod.typeToFunc(self.fn_type).?;909 const fn_info = mod.typeToFunc(func.fn_type).?;
916910
917 inline for (required_features) |feature| {911 inline for (required_features) |feature| {
918 if (!self.hasFeature(feature)) {912 if (!func.hasFeature(feature)) {
919 return self.fail(913 return func.fail(
920 "target missing required feature {s}",914 "target missing required feature {s}",
921 .{@tagName(feature)},915 .{@tagName(feature)},
922 );916 );
...@@ -924,52 +918,52 @@ fn gen(self: *Self) !void {...@@ -924,52 +918,52 @@ fn gen(self: *Self) !void {
924 }918 }
925919
926 if (fn_info.cc != .Naked) {920 if (fn_info.cc != .Naked) {
927 try self.addPseudoNone(.pseudo_dbg_prologue_end);921 try func.addPseudoNone(.pseudo_dbg_prologue_end);
928922
929 const backpatch_stack_alloc = try self.addPseudo(.pseudo_dead);923 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);
930 const backpatch_ra_spill = try self.addPseudo(.pseudo_dead);924 const backpatch_ra_spill = try func.addPseudo(.pseudo_dead);
931 const backpatch_fp_spill = try self.addPseudo(.pseudo_dead);925 const backpatch_fp_spill = try func.addPseudo(.pseudo_dead);
932 const backpatch_fp_add = try self.addPseudo(.pseudo_dead);926 const backpatch_fp_add = try func.addPseudo(.pseudo_dead);
933 const backpatch_spill_callee_preserved_regs = try self.addPseudo(.pseudo_dead);927 const backpatch_spill_callee_preserved_regs = try func.addPseudo(.pseudo_dead);
934928
935 switch (self.ret_mcv.long) {929 switch (func.ret_mcv.long) {
936 .none, .unreach => {},930 .none, .unreach => {},
937 .indirect => {931 .indirect => {
938 // The address where to store the return value for the caller is in a932 // The address where to store the return value for the caller is in a
939 // register which the callee is free to clobber. Therefore, we purposely933 // register which the callee is free to clobber. Therefore, we purposely
940 // spill it to stack immediately.934 // spill it to stack immediately.
941 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod));935 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod));
942 try self.genSetMem(936 try func.genSetMem(
943 .{ .frame = frame_index },937 .{ .frame = frame_index },
944 0,938 0,
945 Type.usize,939 Type.usize,
946 self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off),940 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
947 );941 );
948 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };942 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
949 tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index });943 tracking_log.debug("spill {} to {}", .{ func.ret_mcv.long, frame_index });
950 },944 },
951 else => unreachable,945 else => unreachable,
952 }946 }
953947
954 try self.genBody(self.air.getMainBody());948 try func.genBody(func.air.getMainBody());
955949
956 for (self.exitlude_jump_relocs.items) |jmp_reloc| {950 for (func.exitlude_jump_relocs.items) |jmp_reloc| {
957 self.mir_instructions.items(.data)[jmp_reloc].inst =951 func.mir_instructions.items(.data)[jmp_reloc].inst =
958 @intCast(self.mir_instructions.len);952 @intCast(func.mir_instructions.len);
959 }953 }
960954
961 try self.addPseudoNone(.pseudo_dbg_epilogue_begin);955 try func.addPseudoNone(.pseudo_dbg_epilogue_begin);
962956
963 const backpatch_restore_callee_preserved_regs = try self.addPseudo(.pseudo_dead);957 const backpatch_restore_callee_preserved_regs = try func.addPseudo(.pseudo_dead);
964 const backpatch_ra_restore = try self.addPseudo(.pseudo_dead);958 const backpatch_ra_restore = try func.addPseudo(.pseudo_dead);
965 const backpatch_fp_restore = try self.addPseudo(.pseudo_dead);959 const backpatch_fp_restore = try func.addPseudo(.pseudo_dead);
966 const backpatch_stack_alloc_restore = try self.addPseudo(.pseudo_dead);960 const backpatch_stack_alloc_restore = try func.addPseudo(.pseudo_dead);
967 try self.addPseudoNone(.pseudo_ret);961 try func.addPseudoNone(.pseudo_ret);
968962
969 const frame_layout = try self.computeFrameLayout();963 const frame_layout = try func.computeFrameLayout();
970 const need_save_reg = frame_layout.save_reg_list.count() > 0;964 const need_save_reg = frame_layout.save_reg_list.count() > 0;
971965
972 self.mir_instructions.set(backpatch_stack_alloc, .{966 func.mir_instructions.set(backpatch_stack_alloc, .{
973 .tag = .addi,967 .tag = .addi,
974 .ops = .rri,968 .ops = .rri,
975 .data = .{ .i_type = .{969 .data = .{ .i_type = .{
...@@ -978,7 +972,7 @@ fn gen(self: *Self) !void {...@@ -978,7 +972,7 @@ fn gen(self: *Self) !void {
978 .imm12 = Immediate.s(-@as(i32, @intCast(frame_layout.stack_adjust))),972 .imm12 = Immediate.s(-@as(i32, @intCast(frame_layout.stack_adjust))),
979 } },973 } },
980 });974 });
981 self.mir_instructions.set(backpatch_ra_spill, .{975 func.mir_instructions.set(backpatch_ra_spill, .{
982 .tag = .pseudo,976 .tag = .pseudo,
983 .ops = .pseudo_store_rm,977 .ops = .pseudo_store_rm,
984 .data = .{ .rm = .{978 .data = .{ .rm = .{
...@@ -989,7 +983,7 @@ fn gen(self: *Self) !void {...@@ -989,7 +983,7 @@ fn gen(self: *Self) !void {
989 },983 },
990 } },984 } },
991 });985 });
992 self.mir_instructions.set(backpatch_ra_restore, .{986 func.mir_instructions.set(backpatch_ra_restore, .{
993 .tag = .pseudo,987 .tag = .pseudo,
994 .ops = .pseudo_load_rm,988 .ops = .pseudo_load_rm,
995 .data = .{ .rm = .{989 .data = .{ .rm = .{
...@@ -1000,7 +994,7 @@ fn gen(self: *Self) !void {...@@ -1000,7 +994,7 @@ fn gen(self: *Self) !void {
1000 },994 },
1001 } },995 } },
1002 });996 });
1003 self.mir_instructions.set(backpatch_fp_spill, .{997 func.mir_instructions.set(backpatch_fp_spill, .{
1004 .tag = .pseudo,998 .tag = .pseudo,
1005 .ops = .pseudo_store_rm,999 .ops = .pseudo_store_rm,
1006 .data = .{ .rm = .{1000 .data = .{ .rm = .{
...@@ -1011,7 +1005,7 @@ fn gen(self: *Self) !void {...@@ -1011,7 +1005,7 @@ fn gen(self: *Self) !void {
1011 },1005 },
1012 } },1006 } },
1013 });1007 });
1014 self.mir_instructions.set(backpatch_fp_restore, .{1008 func.mir_instructions.set(backpatch_fp_restore, .{
1015 .tag = .pseudo,1009 .tag = .pseudo,
1016 .ops = .pseudo_load_rm,1010 .ops = .pseudo_load_rm,
1017 .data = .{ .rm = .{1011 .data = .{ .rm = .{
...@@ -1022,7 +1016,7 @@ fn gen(self: *Self) !void {...@@ -1022,7 +1016,7 @@ fn gen(self: *Self) !void {
1022 },1016 },
1023 } },1017 } },
1024 });1018 });
1025 self.mir_instructions.set(backpatch_fp_add, .{1019 func.mir_instructions.set(backpatch_fp_add, .{
1026 .tag = .addi,1020 .tag = .addi,
1027 .ops = .rri,1021 .ops = .rri,
1028 .data = .{ .i_type = .{1022 .data = .{ .i_type = .{
...@@ -1031,7 +1025,7 @@ fn gen(self: *Self) !void {...@@ -1031,7 +1025,7 @@ fn gen(self: *Self) !void {
1031 .imm12 = Immediate.s(@intCast(frame_layout.stack_adjust)),1025 .imm12 = Immediate.s(@intCast(frame_layout.stack_adjust)),
1032 } },1026 } },
1033 });1027 });
1034 self.mir_instructions.set(backpatch_stack_alloc_restore, .{1028 func.mir_instructions.set(backpatch_stack_alloc_restore, .{
1035 .tag = .addi,1029 .tag = .addi,
1036 .ops = .rri,1030 .ops = .rri,
1037 .data = .{ .i_type = .{1031 .data = .{ .i_type = .{
...@@ -1042,72 +1036,72 @@ fn gen(self: *Self) !void {...@@ -1042,72 +1036,72 @@ fn gen(self: *Self) !void {
1042 });1036 });
10431037
1044 if (need_save_reg) {1038 if (need_save_reg) {
1045 self.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{1039 func.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{
1046 .tag = .pseudo,1040 .tag = .pseudo,
1047 .ops = .pseudo_spill_regs,1041 .ops = .pseudo_spill_regs,
1048 .data = .{ .reg_list = frame_layout.save_reg_list },1042 .data = .{ .reg_list = frame_layout.save_reg_list },
1049 });1043 });
10501044
1051 self.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{1045 func.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{
1052 .tag = .pseudo,1046 .tag = .pseudo,
1053 .ops = .pseudo_restore_regs,1047 .ops = .pseudo_restore_regs,
1054 .data = .{ .reg_list = frame_layout.save_reg_list },1048 .data = .{ .reg_list = frame_layout.save_reg_list },
1055 });1049 });
1056 }1050 }
1057 } else {1051 } else {
1058 try self.addPseudoNone(.pseudo_dbg_prologue_end);1052 try func.addPseudoNone(.pseudo_dbg_prologue_end);
1059 try self.genBody(self.air.getMainBody());1053 try func.genBody(func.air.getMainBody());
1060 try self.addPseudoNone(.pseudo_dbg_epilogue_begin);1054 try func.addPseudoNone(.pseudo_dbg_epilogue_begin);
1061 }1055 }
10621056
1063 // Drop them off at the rbrace.1057 // Drop them off at the rbrace.
1064 _ = try self.addInst(.{1058 _ = try func.addInst(.{
1065 .tag = .pseudo,1059 .tag = .pseudo,
1066 .ops = .pseudo_dbg_line_column,1060 .ops = .pseudo_dbg_line_column,
1067 .data = .{ .pseudo_dbg_line_column = .{1061 .data = .{ .pseudo_dbg_line_column = .{
1068 .line = self.end_di_line,1062 .line = func.end_di_line,
1069 .column = self.end_di_column,1063 .column = func.end_di_column,
1070 } },1064 } },
1071 });1065 });
1072}1066}
10731067
1074fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {1068fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1075 const zcu = self.bin_file.comp.module.?;1069 const zcu = func.bin_file.comp.module.?;
1076 const ip = &zcu.intern_pool;1070 const ip = &zcu.intern_pool;
1077 const air_tags = self.air.instructions.items(.tag);1071 const air_tags = func.air.instructions.items(.tag);
10781072
1079 for (body) |inst| {1073 for (body) |inst| {
1080 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) continue;1074 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;
10811075
1082 const old_air_bookkeeping = self.air_bookkeeping;1076 const old_air_bookkeeping = func.air_bookkeeping;
1083 try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);1077 try func.inst_tracking.ensureUnusedCapacity(func.gpa, 1);
1084 switch (air_tags[@intFromEnum(inst)]) {1078 switch (air_tags[@intFromEnum(inst)]) {
1085 // zig fmt: off1079 // zig fmt: off
1086 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),1080 .ptr_add => try func.airPtrArithmetic(inst, .ptr_add),
1087 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),1081 .ptr_sub => try func.airPtrArithmetic(inst, .ptr_sub),
10881082
1089 .add => try self.airBinOp(inst, .add),1083 .add => try func.airBinOp(inst, .add),
1090 .sub => try self.airBinOp(inst, .sub),1084 .sub => try func.airBinOp(inst, .sub),
10911085
1092 .add_safe,1086 .add_safe,
1093 .sub_safe,1087 .sub_safe,
1094 .mul_safe,1088 .mul_safe,
1095 => return self.fail("TODO implement safety_checked_instructions", .{}),1089 => return func.fail("TODO implement safety_checked_instructions", .{}),
10961090
1097 .add_wrap => try self.airAddWrap(inst),1091 .add_wrap => try func.airAddWrap(inst),
1098 .add_sat => try self.airAddSat(inst),1092 .add_sat => try func.airAddSat(inst),
1099 .sub_wrap => try self.airSubWrap(inst),1093 .sub_wrap => try func.airSubWrap(inst),
1100 .sub_sat => try self.airSubSat(inst),1094 .sub_sat => try func.airSubSat(inst),
1101 .mul => try self.airMul(inst),1095 .mul => try func.airMul(inst),
1102 .mul_wrap => try self.airMulWrap(inst),1096 .mul_wrap => try func.airMulWrap(inst),
1103 .mul_sat => try self.airMulSat(inst),1097 .mul_sat => try func.airMulSat(inst),
1104 .rem => try self.airRem(inst),1098 .rem => try func.airRem(inst),
1105 .mod => try self.airMod(inst),1099 .mod => try func.airMod(inst),
1106 .shl, .shl_exact => try self.airShl(inst),1100 .shl, .shl_exact => try func.airShl(inst),
1107 .shl_sat => try self.airShlSat(inst),1101 .shl_sat => try func.airShlSat(inst),
1108 .min => try self.airMinMax(inst, .min),1102 .min => try func.airMinMax(inst, .min),
1109 .max => try self.airMinMax(inst, .max),1103 .max => try func.airMinMax(inst, .max),
1110 .slice => try self.airSlice(inst),1104 .slice => try func.airSlice(inst),
11111105
1112 .sqrt,1106 .sqrt,
1113 .sin,1107 .sin,
...@@ -1123,157 +1117,157 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1123,157 +1117,157 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1123 .round,1117 .round,
1124 .trunc_float,1118 .trunc_float,
1125 .neg,1119 .neg,
1126 => try self.airUnaryMath(inst),1120 => try func.airUnaryMath(inst),
11271121
1128 .add_with_overflow => try self.airAddWithOverflow(inst),1122 .add_with_overflow => try func.airAddWithOverflow(inst),
1129 .sub_with_overflow => try self.airSubWithOverflow(inst),1123 .sub_with_overflow => try func.airSubWithOverflow(inst),
1130 .mul_with_overflow => try self.airMulWithOverflow(inst),1124 .mul_with_overflow => try func.airMulWithOverflow(inst),
1131 .shl_with_overflow => try self.airShlWithOverflow(inst),1125 .shl_with_overflow => try func.airShlWithOverflow(inst),
11321126
1133 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),1127 .div_float, .div_trunc, .div_floor, .div_exact => try func.airDiv(inst),
11341128
1135 .cmp_lt => try self.airCmp(inst),1129 .cmp_lt => try func.airCmp(inst),
1136 .cmp_lte => try self.airCmp(inst),1130 .cmp_lte => try func.airCmp(inst),
1137 .cmp_eq => try self.airCmp(inst),1131 .cmp_eq => try func.airCmp(inst),
1138 .cmp_gte => try self.airCmp(inst),1132 .cmp_gte => try func.airCmp(inst),
1139 .cmp_gt => try self.airCmp(inst),1133 .cmp_gt => try func.airCmp(inst),
1140 .cmp_neq => try self.airCmp(inst),1134 .cmp_neq => try func.airCmp(inst),
11411135
1142 .cmp_vector => try self.airCmpVector(inst),1136 .cmp_vector => try func.airCmpVector(inst),
1143 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),1137 .cmp_lt_errors_len => try func.airCmpLtErrorsLen(inst),
11441138
1145 .bool_and => try self.airBoolOp(inst),1139 .bool_and => try func.airBoolOp(inst),
1146 .bool_or => try self.airBoolOp(inst),1140 .bool_or => try func.airBoolOp(inst),
1147 .bit_and => try self.airBitAnd(inst),1141 .bit_and => try func.airBitAnd(inst),
1148 .bit_or => try self.airBitOr(inst),1142 .bit_or => try func.airBitOr(inst),
1149 .xor => try self.airXor(inst),1143 .xor => try func.airXor(inst),
1150 .shr, .shr_exact => try self.airShr(inst),1144 .shr, .shr_exact => try func.airShr(inst),
11511145
1152 .alloc => try self.airAlloc(inst),1146 .alloc => try func.airAlloc(inst),
1153 .ret_ptr => try self.airRetPtr(inst),1147 .ret_ptr => try func.airRetPtr(inst),
1154 .arg => try self.airArg(inst),1148 .arg => try func.airArg(inst),
1155 .assembly => try self.airAsm(inst),1149 .assembly => try func.airAsm(inst),
1156 .bitcast => try self.airBitCast(inst),1150 .bitcast => try func.airBitCast(inst),
1157 .block => try self.airBlock(inst),1151 .block => try func.airBlock(inst),
1158 .br => try self.airBr(inst),1152 .br => try func.airBr(inst),
1159 .trap => try self.airTrap(),1153 .trap => try func.airTrap(),
1160 .breakpoint => try self.airBreakpoint(),1154 .breakpoint => try func.airBreakpoint(),
1161 .ret_addr => try self.airRetAddr(inst),1155 .ret_addr => try func.airRetAddr(inst),
1162 .frame_addr => try self.airFrameAddress(inst),1156 .frame_addr => try func.airFrameAddress(inst),
1163 .fence => try self.airFence(),1157 .fence => try func.airFence(),
1164 .cond_br => try self.airCondBr(inst),1158 .cond_br => try func.airCondBr(inst),
1165 .dbg_stmt => try self.airDbgStmt(inst),1159 .dbg_stmt => try func.airDbgStmt(inst),
1166 .fptrunc => try self.airFptrunc(inst),1160 .fptrunc => try func.airFptrunc(inst),
1167 .fpext => try self.airFpext(inst),1161 .fpext => try func.airFpext(inst),
1168 .intcast => try self.airIntCast(inst),1162 .intcast => try func.airIntCast(inst),
1169 .trunc => try self.airTrunc(inst),1163 .trunc => try func.airTrunc(inst),
1170 .int_from_bool => try self.airIntFromBool(inst),1164 .int_from_bool => try func.airIntFromBool(inst),
1171 .is_non_null => try self.airIsNonNull(inst),1165 .is_non_null => try func.airIsNonNull(inst),
1172 .is_non_null_ptr => try self.airIsNonNullPtr(inst),1166 .is_non_null_ptr => try func.airIsNonNullPtr(inst),
1173 .is_null => try self.airIsNull(inst),1167 .is_null => try func.airIsNull(inst),
1174 .is_null_ptr => try self.airIsNullPtr(inst),1168 .is_null_ptr => try func.airIsNullPtr(inst),
1175 .is_non_err => try self.airIsNonErr(inst),1169 .is_non_err => try func.airIsNonErr(inst),
1176 .is_non_err_ptr => try self.airIsNonErrPtr(inst),1170 .is_non_err_ptr => try func.airIsNonErrPtr(inst),
1177 .is_err => try self.airIsErr(inst),1171 .is_err => try func.airIsErr(inst),
1178 .is_err_ptr => try self.airIsErrPtr(inst),1172 .is_err_ptr => try func.airIsErrPtr(inst),
1179 .load => try self.airLoad(inst),1173 .load => try func.airLoad(inst),
1180 .loop => try self.airLoop(inst),1174 .loop => try func.airLoop(inst),
1181 .not => try self.airNot(inst),1175 .not => try func.airNot(inst),
1182 .int_from_ptr => try self.airIntFromPtr(inst),1176 .int_from_ptr => try func.airIntFromPtr(inst),
1183 .ret => try self.airRet(inst, false),1177 .ret => try func.airRet(inst, false),
1184 .ret_safe => try self.airRet(inst, true),1178 .ret_safe => try func.airRet(inst, true),
1185 .ret_load => try self.airRetLoad(inst),1179 .ret_load => try func.airRetLoad(inst),
1186 .store => try self.airStore(inst, false),1180 .store => try func.airStore(inst, false),
1187 .store_safe => try self.airStore(inst, true),1181 .store_safe => try func.airStore(inst, true),
1188 .struct_field_ptr=> try self.airStructFieldPtr(inst),1182 .struct_field_ptr=> try func.airStructFieldPtr(inst),
1189 .struct_field_val=> try self.airStructFieldVal(inst),1183 .struct_field_val=> try func.airStructFieldVal(inst),
1190 .array_to_slice => try self.airArrayToSlice(inst),1184 .array_to_slice => try func.airArrayToSlice(inst),
1191 .float_from_int => try self.airFloatFromInt(inst),1185 .float_from_int => try func.airFloatFromInt(inst),
1192 .int_from_float => try self.airIntFromFloat(inst),1186 .int_from_float => try func.airIntFromFloat(inst),
1193 .cmpxchg_strong => try self.airCmpxchg(inst),1187 .cmpxchg_strong => try func.airCmpxchg(inst),
1194 .cmpxchg_weak => try self.airCmpxchg(inst),1188 .cmpxchg_weak => try func.airCmpxchg(inst),
1195 .atomic_rmw => try self.airAtomicRmw(inst),1189 .atomic_rmw => try func.airAtomicRmw(inst),
1196 .atomic_load => try self.airAtomicLoad(inst),1190 .atomic_load => try func.airAtomicLoad(inst),
1197 .memcpy => try self.airMemcpy(inst),1191 .memcpy => try func.airMemcpy(inst),
1198 .memset => try self.airMemset(inst, false),1192 .memset => try func.airMemset(inst, false),
1199 .memset_safe => try self.airMemset(inst, true),1193 .memset_safe => try func.airMemset(inst, true),
1200 .set_union_tag => try self.airSetUnionTag(inst),1194 .set_union_tag => try func.airSetUnionTag(inst),
1201 .get_union_tag => try self.airGetUnionTag(inst),1195 .get_union_tag => try func.airGetUnionTag(inst),
1202 .clz => try self.airClz(inst),1196 .clz => try func.airClz(inst),
1203 .ctz => try self.airCtz(inst),1197 .ctz => try func.airCtz(inst),
1204 .popcount => try self.airPopcount(inst),1198 .popcount => try func.airPopcount(inst),
1205 .abs => try self.airAbs(inst),1199 .abs => try func.airAbs(inst),
1206 .byte_swap => try self.airByteSwap(inst),1200 .byte_swap => try func.airByteSwap(inst),
1207 .bit_reverse => try self.airBitReverse(inst),1201 .bit_reverse => try func.airBitReverse(inst),
1208 .tag_name => try self.airTagName(inst),1202 .tag_name => try func.airTagName(inst),
1209 .error_name => try self.airErrorName(inst),1203 .error_name => try func.airErrorName(inst),
1210 .splat => try self.airSplat(inst),1204 .splat => try func.airSplat(inst),
1211 .select => try self.airSelect(inst),1205 .select => try func.airSelect(inst),
1212 .shuffle => try self.airShuffle(inst),1206 .shuffle => try func.airShuffle(inst),
1213 .reduce => try self.airReduce(inst),1207 .reduce => try func.airReduce(inst),
1214 .aggregate_init => try self.airAggregateInit(inst),1208 .aggregate_init => try func.airAggregateInit(inst),
1215 .union_init => try self.airUnionInit(inst),1209 .union_init => try func.airUnionInit(inst),
1216 .prefetch => try self.airPrefetch(inst),1210 .prefetch => try func.airPrefetch(inst),
1217 .mul_add => try self.airMulAdd(inst),1211 .mul_add => try func.airMulAdd(inst),
1218 .addrspace_cast => return self.fail("TODO: addrspace_cast", .{}),1212 .addrspace_cast => return func.fail("TODO: addrspace_cast", .{}),
12191213
1220 .@"try" => try self.airTry(inst),1214 .@"try" => try func.airTry(inst),
1221 .try_ptr => return self.fail("TODO: try_ptr", .{}),1215 .try_ptr => return func.fail("TODO: try_ptr", .{}),
12221216
1223 .dbg_var_ptr,1217 .dbg_var_ptr,
1224 .dbg_var_val,1218 .dbg_var_val,
1225 => try self.airDbgVar(inst),1219 => try func.airDbgVar(inst),
12261220
1227 .dbg_inline_block => try self.airDbgInlineBlock(inst),1221 .dbg_inline_block => try func.airDbgInlineBlock(inst),
12281222
1229 .call => try self.airCall(inst, .auto),1223 .call => try func.airCall(inst, .auto),
1230 .call_always_tail => try self.airCall(inst, .always_tail),1224 .call_always_tail => try func.airCall(inst, .always_tail),
1231 .call_never_tail => try self.airCall(inst, .never_tail),1225 .call_never_tail => try func.airCall(inst, .never_tail),
1232 .call_never_inline => try self.airCall(inst, .never_inline),1226 .call_never_inline => try func.airCall(inst, .never_inline),
12331227
1234 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),1228 .atomic_store_unordered => try func.airAtomicStore(inst, .unordered),
1235 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),1229 .atomic_store_monotonic => try func.airAtomicStore(inst, .monotonic),
1236 .atomic_store_release => try self.airAtomicStore(inst, .release),1230 .atomic_store_release => try func.airAtomicStore(inst, .release),
1237 .atomic_store_seq_cst => try self.airAtomicStore(inst, .seq_cst),1231 .atomic_store_seq_cst => try func.airAtomicStore(inst, .seq_cst),
12381232
1239 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),1233 .struct_field_ptr_index_0 => try func.airStructFieldPtrIndex(inst, 0),
1240 .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),1234 .struct_field_ptr_index_1 => try func.airStructFieldPtrIndex(inst, 1),
1241 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),1235 .struct_field_ptr_index_2 => try func.airStructFieldPtrIndex(inst, 2),
1242 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),1236 .struct_field_ptr_index_3 => try func.airStructFieldPtrIndex(inst, 3),
12431237
1244 .field_parent_ptr => try self.airFieldParentPtr(inst),1238 .field_parent_ptr => try func.airFieldParentPtr(inst),
12451239
1246 .switch_br => try self.airSwitchBr(inst),1240 .switch_br => try func.airSwitchBr(inst),
1247 .slice_ptr => try self.airSlicePtr(inst),1241 .slice_ptr => try func.airSlicePtr(inst),
1248 .slice_len => try self.airSliceLen(inst),1242 .slice_len => try func.airSliceLen(inst),
12491243
1250 .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst),1244 .ptr_slice_len_ptr => try func.airPtrSliceLenPtr(inst),
1251 .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst),1245 .ptr_slice_ptr_ptr => try func.airPtrSlicePtrPtr(inst),
12521246
1253 .array_elem_val => try self.airArrayElemVal(inst),1247 .array_elem_val => try func.airArrayElemVal(inst),
1254 .slice_elem_val => try self.airSliceElemVal(inst),1248 .slice_elem_val => try func.airSliceElemVal(inst),
1255 .slice_elem_ptr => try self.airSliceElemPtr(inst),1249 .slice_elem_ptr => try func.airSliceElemPtr(inst),
1256 .ptr_elem_val => try self.airPtrElemVal(inst),1250 .ptr_elem_val => try func.airPtrElemVal(inst),
1257 .ptr_elem_ptr => try self.airPtrElemPtr(inst),1251 .ptr_elem_ptr => try func.airPtrElemPtr(inst),
12581252
1259 .inferred_alloc, .inferred_alloc_comptime => unreachable,1253 .inferred_alloc, .inferred_alloc_comptime => unreachable,
1260 .unreach => self.finishAirBookkeeping(),1254 .unreach => func.finishAirBookkeeping(),
12611255
1262 .optional_payload => try self.airOptionalPayload(inst),1256 .optional_payload => try func.airOptionalPayload(inst),
1263 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),1257 .optional_payload_ptr => try func.airOptionalPayloadPtr(inst),
1264 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),1258 .optional_payload_ptr_set => try func.airOptionalPayloadPtrSet(inst),
1265 .unwrap_errunion_err => try self.airUnwrapErrErr(inst),1259 .unwrap_errunion_err => try func.airUnwrapErrErr(inst),
1266 .unwrap_errunion_payload => try self.airUnwrapErrPayload(inst),1260 .unwrap_errunion_payload => try func.airUnwrapErrPayload(inst),
1267 .unwrap_errunion_err_ptr => try self.airUnwrapErrErrPtr(inst),1261 .unwrap_errunion_err_ptr => try func.airUnwrapErrErrPtr(inst),
1268 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrPayloadPtr(inst),1262 .unwrap_errunion_payload_ptr=> try func.airUnwrapErrPayloadPtr(inst),
1269 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),1263 .errunion_payload_ptr_set => try func.airErrUnionPayloadPtrSet(inst),
1270 .err_return_trace => try self.airErrReturnTrace(inst),1264 .err_return_trace => try func.airErrReturnTrace(inst),
1271 .set_err_return_trace => try self.airSetErrReturnTrace(inst),1265 .set_err_return_trace => try func.airSetErrReturnTrace(inst),
1272 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),1266 .save_err_return_trace_index=> try func.airSaveErrReturnTraceIndex(inst),
12731267
1274 .wrap_optional => try self.airWrapOptional(inst),1268 .wrap_optional => try func.airWrapOptional(inst),
1275 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),1269 .wrap_errunion_payload => try func.airWrapErrUnionPayload(inst),
1276 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),1270 .wrap_errunion_err => try func.airWrapErrUnionErr(inst),
12771271
1278 .add_optimized,1272 .add_optimized,
1279 .sub_optimized,1273 .sub_optimized,
...@@ -1294,16 +1288,16 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1294,16 +1288,16 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1294 .cmp_vector_optimized,1288 .cmp_vector_optimized,
1295 .reduce_optimized,1289 .reduce_optimized,
1296 .int_from_float_optimized,1290 .int_from_float_optimized,
1297 => return self.fail("TODO implement optimized float mode", .{}),1291 => return func.fail("TODO implement optimized float mode", .{}),
12981292
1299 .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),1293 .is_named_enum_value => return func.fail("TODO implement is_named_enum_value", .{}),
1300 .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),1294 .error_set_has_value => return func.fail("TODO implement error_set_has_value", .{}),
1301 .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),1295 .vector_store_elem => return func.fail("TODO implement vector_store_elem", .{}),
13021296
1303 .c_va_arg => return self.fail("TODO implement c_va_arg", .{}),1297 .c_va_arg => return func.fail("TODO implement c_va_arg", .{}),
1304 .c_va_copy => return self.fail("TODO implement c_va_copy", .{}),1298 .c_va_copy => return func.fail("TODO implement c_va_copy", .{}),
1305 .c_va_end => return self.fail("TODO implement c_va_end", .{}),1299 .c_va_end => return func.fail("TODO implement c_va_end", .{}),
1306 .c_va_start => return self.fail("TODO implement c_va_start", .{}),1300 .c_va_start => return func.fail("TODO implement c_va_start", .{}),
13071301
1308 .wasm_memory_size => unreachable,1302 .wasm_memory_size => unreachable,
1309 .wasm_memory_grow => unreachable,1303 .wasm_memory_grow => unreachable,
...@@ -1314,19 +1308,19 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1314,19 +1308,19 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1314 // zig fmt: on1308 // zig fmt: on
1315 }1309 }
13161310
1317 assert(!self.register_manager.lockedRegsExist());1311 assert(!func.register_manager.lockedRegsExist());
13181312
1319 if (std.debug.runtime_safety) {1313 if (std.debug.runtime_safety) {
1320 if (self.air_bookkeeping < old_air_bookkeeping + 1) {1314 if (func.air_bookkeeping < old_air_bookkeeping + 1) {
1321 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });1315 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, air_tags[@intFromEnum(inst)] });
1322 }1316 }
13231317
1324 { // check consistency of tracked registers1318 { // check consistency of tracked registers
1325 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });1319 var it = func.register_manager.free_registers.iterator(.{ .kind = .unset });
1326 while (it.next()) |index| {1320 while (it.next()) |index| {
1327 const tracked_inst = self.register_manager.registers[index];1321 const tracked_inst = func.register_manager.registers[index];
1328 tracking_log.debug("tracked inst: {}", .{tracked_inst});1322 tracking_log.debug("tracked inst: {}", .{tracked_inst});
1329 const tracking = self.getResolvedInstValue(tracked_inst);1323 const tracking = func.getResolvedInstValue(tracked_inst);
1330 for (tracking.getRegs()) |reg| {1324 for (tracking.getRegs()) |reg| {
1331 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;1325 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
1332 } else return std.debug.panic(1326 } else return std.debug.panic(
...@@ -1338,72 +1332,72 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1338,72 +1332,72 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1338 }1332 }
1339}1333}
13401334
1341fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) !void {1335fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {
1342 for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst);1336 for (value.getRegs()) |reg| try func.register_manager.getReg(reg, inst);
1343}1337}
13441338
1345fn getValueIfFree(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {1339fn getValueIfFree(func: *Func, value: MCValue, inst: ?Air.Inst.Index) void {
1346 for (value.getRegs()) |reg| if (self.register_manager.isRegFree(reg))1340 for (value.getRegs()) |reg| if (func.register_manager.isRegFree(reg))
1347 self.register_manager.getRegAssumeFree(reg, inst);1341 func.register_manager.getRegAssumeFree(reg, inst);
1348}1342}
13491343
1350fn freeValue(self: *Self, value: MCValue) !void {1344fn freeValue(func: *Func, value: MCValue) !void {
1351 switch (value) {1345 switch (value) {
1352 .register => |reg| self.register_manager.freeReg(reg),1346 .register => |reg| func.register_manager.freeReg(reg),
1353 .register_pair => |regs| for (regs) |reg| self.register_manager.freeReg(reg),1347 .register_pair => |regs| for (regs) |reg| func.register_manager.freeReg(reg),
1354 .register_offset => |reg_off| self.register_manager.freeReg(reg_off.reg),1348 .register_offset => |reg_off| func.register_manager.freeReg(reg_off.reg),
1355 else => {}, // TODO process stack allocation death1349 else => {}, // TODO process stack allocation death
1356 }1350 }
1357}1351}
13581352
1359fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) !void {1353fn feed(func: *Func, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) !void {
1360 if (bt.feed()) if (operand.toIndex()) |inst| {1354 if (bt.feed()) if (operand.toIndex()) |inst| {
1361 log.debug("feed inst: %{}", .{inst});1355 log.debug("feed inst: %{}", .{inst});
1362 try self.processDeath(inst);1356 try func.processDeath(inst);
1363 };1357 };
1364}1358}
13651359
1366/// Asserts there is already capacity to insert into top branch inst_table.1360/// Asserts there is already capacity to insert into top branch inst_table.
1367fn processDeath(self: *Self, inst: Air.Inst.Index) !void {1361fn processDeath(func: *Func, inst: Air.Inst.Index) !void {
1368 try self.inst_tracking.getPtr(inst).?.die(self, inst);1362 try func.inst_tracking.getPtr(inst).?.die(func, inst);
1369}1363}
13701364
1371/// Called when there are no operands, and the instruction is always unreferenced.1365/// Called when there are no operands, and the instruction is always unreferenced.
1372fn finishAirBookkeeping(self: *Self) void {1366fn finishAirBookkeeping(func: *Func) void {
1373 if (std.debug.runtime_safety) {1367 if (std.debug.runtime_safety) {
1374 self.air_bookkeeping += 1;1368 func.air_bookkeeping += 1;
1375 }1369 }
1376}1370}
13771371
1378fn finishAirResult(self: *Self, inst: Air.Inst.Index, result: MCValue) void {1372fn finishAirResult(func: *Func, inst: Air.Inst.Index, result: MCValue) void {
1379 if (self.liveness.isUnused(inst)) switch (result) {1373 if (func.liveness.isUnused(inst)) switch (result) {
1380 .none, .dead, .unreach => {},1374 .none, .dead, .unreach => {},
1381 else => unreachable, // Why didn't the result die?1375 else => unreachable, // Why didn't the result die?
1382 } else {1376 } else {
1383 tracking_log.debug("%{d} => {} (birth)", .{ inst, result });1377 tracking_log.debug("%{d} => {} (birth)", .{ inst, result });
1384 self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));1378 func.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));
1385 // In some cases, an operand may be reused as the result.1379 // In some cases, an operand may be reused as the result.
1386 // If that operand died and was a register, it was freed by1380 // If that operand died and was a register, it was freed by
1387 // processDeath, so we have to "re-allocate" the register.1381 // processDeath, so we have to "re-allocate" the register.
1388 self.getValueIfFree(result, inst);1382 func.getValueIfFree(result, inst);
1389 }1383 }
1390 self.finishAirBookkeeping();1384 func.finishAirBookkeeping();
1391}1385}
13921386
1393fn finishAir(1387fn finishAir(
1394 self: *Self,1388 func: *Func,
1395 inst: Air.Inst.Index,1389 inst: Air.Inst.Index,
1396 result: MCValue,1390 result: MCValue,
1397 operands: [Liveness.bpi - 1]Air.Inst.Ref,1391 operands: [Liveness.bpi - 1]Air.Inst.Ref,
1398) !void {1392) !void {
1399 var tomb_bits = self.liveness.getTombBits(inst);1393 var tomb_bits = func.liveness.getTombBits(inst);
1400 for (operands) |op| {1394 for (operands) |op| {
1401 const dies = @as(u1, @truncate(tomb_bits)) != 0;1395 const dies = @as(u1, @truncate(tomb_bits)) != 0;
1402 tomb_bits >>= 1;1396 tomb_bits >>= 1;
1403 if (!dies) continue;1397 if (!dies) continue;
1404 try self.processDeath(op.toIndexAllowNone() orelse continue);1398 try func.processDeath(op.toIndexAllowNone() orelse continue);
1405 }1399 }
1406 self.finishAirResult(inst, result);1400 func.finishAirResult(inst, result);
1407}1401}
14081402
1409const FrameLayout = struct {1403const FrameLayout = struct {
...@@ -1412,7 +1406,7 @@ const FrameLayout = struct {...@@ -1412,7 +1406,7 @@ const FrameLayout = struct {
1412};1406};
14131407
1414fn setFrameLoc(1408fn setFrameLoc(
1415 self: *Self,1409 func: *Func,
1416 frame_index: FrameIndex,1410 frame_index: FrameIndex,
1417 base: Register,1411 base: Register,
1418 offset: *i32,1412 offset: *i32,
...@@ -1420,24 +1414,24 @@ fn setFrameLoc(...@@ -1420,24 +1414,24 @@ fn setFrameLoc(
1420) void {1414) void {
1421 const frame_i = @intFromEnum(frame_index);1415 const frame_i = @intFromEnum(frame_index);
1422 if (aligned) {1416 if (aligned) {
1423 const alignment: InternPool.Alignment = self.frame_allocs.items(.abi_align)[frame_i];1417 const alignment: InternPool.Alignment = func.frame_allocs.items(.abi_align)[frame_i];
1424 offset.* = if (math.sign(offset.*) < 0)1418 offset.* = if (math.sign(offset.*) < 0)
1425 -1 * @as(i32, @intCast(alignment.backward(@intCast(@abs(offset.*)))))1419 -1 * @as(i32, @intCast(alignment.backward(@intCast(@abs(offset.*)))))
1426 else1420 else
1427 @intCast(alignment.forward(@intCast(@abs(offset.*))));1421 @intCast(alignment.forward(@intCast(@abs(offset.*))));
1428 }1422 }
1429 self.frame_locs.set(frame_i, .{ .base = base, .disp = offset.* });1423 func.frame_locs.set(frame_i, .{ .base = base, .disp = offset.* });
1430 offset.* += self.frame_allocs.items(.abi_size)[frame_i];1424 offset.* += func.frame_allocs.items(.abi_size)[frame_i];
1431}1425}
14321426
1433fn computeFrameLayout(self: *Self) !FrameLayout {1427fn computeFrameLayout(func: *Func) !FrameLayout {
1434 const frame_allocs_len = self.frame_allocs.len;1428 const frame_allocs_len = func.frame_allocs.len;
1435 try self.frame_locs.resize(self.gpa, frame_allocs_len);1429 try func.frame_locs.resize(func.gpa, frame_allocs_len);
1436 const stack_frame_order = try self.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count);1430 const stack_frame_order = try func.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count);
1437 defer self.gpa.free(stack_frame_order);1431 defer func.gpa.free(stack_frame_order);
14381432
1439 const frame_size = self.frame_allocs.items(.abi_size);1433 const frame_size = func.frame_allocs.items(.abi_size);
1440 const frame_align = self.frame_allocs.items(.abi_align);1434 const frame_align = func.frame_allocs.items(.abi_align);
14411435
1442 for (stack_frame_order, FrameIndex.named_count..) |*frame_order, frame_index|1436 for (stack_frame_order, FrameIndex.named_count..) |*frame_order, frame_index|
1443 frame_order.* = @enumFromInt(frame_index);1437 frame_order.* = @enumFromInt(frame_index);
...@@ -1455,7 +1449,7 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1455,7 +1449,7 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
14551449
1456 var save_reg_list = Mir.RegisterList{};1450 var save_reg_list = Mir.RegisterList{};
1457 for (abi.Registers.all_preserved) |reg| {1451 for (abi.Registers.all_preserved) |reg| {
1458 if (self.register_manager.isRegAllocated(reg)) {1452 if (func.register_manager.isRegAllocated(reg)) {
1459 save_reg_list.push(&abi.Registers.all_preserved, reg);1453 save_reg_list.push(&abi.Registers.all_preserved, reg);
1460 }1454 }
1461 }1455 }
...@@ -1489,11 +1483,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1489,11 +1483,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
14891483
1490 // store the ra at total_size - 8, so it's the very first thing in the stack1484 // store the ra at total_size - 8, so it's the very first thing in the stack
1491 // relative to the fp1485 // relative to the fp
1492 self.frame_locs.set(1486 func.frame_locs.set(
1493 @intFromEnum(FrameIndex.ret_addr),1487 @intFromEnum(FrameIndex.ret_addr),
1494 .{ .base = .sp, .disp = acc_frame_size - 8 },1488 .{ .base = .sp, .disp = acc_frame_size - 8 },
1495 );1489 );
1496 self.frame_locs.set(1490 func.frame_locs.set(
1497 @intFromEnum(FrameIndex.base_ptr),1491 @intFromEnum(FrameIndex.base_ptr),
1498 .{ .base = .sp, .disp = acc_frame_size - 16 },1492 .{ .base = .sp, .disp = acc_frame_size - 16 },
1499 );1493 );
...@@ -1502,11 +1496,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1502,11 +1496,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
1502 // not need to know the size of the first allocation. Stack offsets point at the "bottom"1496 // not need to know the size of the first allocation. Stack offsets point at the "bottom"
1503 // of variables.1497 // of variables.
1504 var s0_offset: i32 = -acc_frame_size;1498 var s0_offset: i32 = -acc_frame_size;
1505 self.setFrameLoc(.stack_frame, .s0, &s0_offset, true);1499 func.setFrameLoc(.stack_frame, .s0, &s0_offset, true);
1506 for (stack_frame_order) |frame_index| self.setFrameLoc(frame_index, .s0, &s0_offset, true);1500 for (stack_frame_order) |frame_index| func.setFrameLoc(frame_index, .s0, &s0_offset, true);
1507 self.setFrameLoc(.args_frame, .s0, &s0_offset, true);1501 func.setFrameLoc(.args_frame, .s0, &s0_offset, true);
1508 self.setFrameLoc(.call_frame, .s0, &s0_offset, true);1502 func.setFrameLoc(.call_frame, .s0, &s0_offset, true);
1509 self.setFrameLoc(.spill_frame, .s0, &s0_offset, true);1503 func.setFrameLoc(.spill_frame, .s0, &s0_offset, true);
15101504
1511 return .{1505 return .{
1512 .stack_adjust = @intCast(acc_frame_size),1506 .stack_adjust = @intCast(acc_frame_size),
...@@ -1514,21 +1508,21 @@ fn computeFrameLayout(self: *Self) !FrameLayout {...@@ -1514,21 +1508,21 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
1514 };1508 };
1515}1509}
15161510
1517fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {1511fn ensureProcessDeathCapacity(func: *Func, additional_count: usize) !void {
1518 const table = &self.branch_stack.items[self.branch_stack.items.len - 1].inst_table;1512 const table = &func.branch_stack.items[func.branch_stack.items.len - 1].inst_table;
1519 try table.ensureUnusedCapacity(self.gpa, additional_count);1513 try table.ensureUnusedCapacity(func.gpa, additional_count);
1520}1514}
15211515
1522fn memSize(self: *Self, ty: Type) Memory.Size {1516fn memSize(func: *Func, ty: Type) Memory.Size {
1523 const mod = self.bin_file.comp.module.?;1517 const mod = func.bin_file.comp.module.?;
1524 return switch (ty.zigTypeTag(mod)) {1518 return switch (ty.zigTypeTag(mod)) {
1525 .Float => Memory.Size.fromBitSize(ty.floatBits(self.target.*)),1519 .Float => Memory.Size.fromBitSize(ty.floatBits(func.target.*)),
1526 else => Memory.Size.fromByteSize(ty.abiSize(mod)),1520 else => Memory.Size.fromByteSize(ty.abiSize(mod)),
1527 };1521 };
1528}1522}
15291523
1530fn splitType(self: *Self, ty: Type) ![2]Type {1524fn splitType(func: *Func, ty: Type) ![2]Type {
1531 const zcu = self.bin_file.comp.module.?;1525 const zcu = func.bin_file.comp.module.?;
1532 const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none);1526 const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none);
1533 var parts: [2]Type = undefined;1527 var parts: [2]Type = undefined;
1534 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {1528 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
...@@ -1545,63 +1539,63 @@ fn splitType(self: *Self, ty: Type) ![2]Type {...@@ -1545,63 +1539,63 @@ fn splitType(self: *Self, ty: Type) ![2]Type {
1545 },1539 },
1546 else => unreachable,1540 else => unreachable,
1547 },1541 },
1548 else => return self.fail("TODO: splitType class {}", .{class}),1542 else => return func.fail("TODO: splitType class {}", .{class}),
1549 };1543 };
1550 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;1544 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;
1551 return self.fail("TODO implement splitType for {}", .{ty.fmt(zcu)});1545 return func.fail("TODO implement splitType for {}", .{ty.fmt(zcu)});
1552}1546}
15531547
1554fn symbolIndex(self: *Self) !u32 {1548fn symbolIndex(func: *Func) !u32 {
1555 const zcu = self.bin_file.comp.module.?;1549 const zcu = func.bin_file.comp.module.?;
1556 const decl_index = zcu.funcOwnerDeclIndex(self.func_index);1550 const decl_index = zcu.funcOwnerDeclIndex(func.func_index);
1557 return switch (self.bin_file.tag) {1551 return switch (func.bin_file.tag) {
1558 .elf => blk: {1552 .elf => blk: {
1559 const elf_file = self.bin_file.cast(link.File.Elf).?;1553 const elf_file = func.bin_file.cast(link.File.Elf).?;
1560 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);1554 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
1561 break :blk atom_index;1555 break :blk atom_index;
1562 },1556 },
1563 else => return self.fail("TODO symbolIndex {s}", .{@tagName(self.bin_file.tag)}),1557 else => return func.fail("TODO symbolIndex {s}", .{@tagName(func.bin_file.tag)}),
1564 };1558 };
1565}1559}
15661560
1567fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex {1561fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
1568 const frame_allocs_slice = self.frame_allocs.slice();1562 const frame_allocs_slice = func.frame_allocs.slice();
1569 const frame_size = frame_allocs_slice.items(.abi_size);1563 const frame_size = frame_allocs_slice.items(.abi_size);
1570 const frame_align = frame_allocs_slice.items(.abi_align);1564 const frame_align = frame_allocs_slice.items(.abi_align);
15711565
1572 const stack_frame_align = &frame_align[@intFromEnum(FrameIndex.stack_frame)];1566 const stack_frame_align = &frame_align[@intFromEnum(FrameIndex.stack_frame)];
1573 stack_frame_align.* = stack_frame_align.max(alloc.abi_align);1567 stack_frame_align.* = stack_frame_align.max(alloc.abi_align);
15741568
1575 for (self.free_frame_indices.keys(), 0..) |frame_index, free_i| {1569 for (func.free_frame_indices.keys(), 0..) |frame_index, free_i| {
1576 const abi_size = frame_size[@intFromEnum(frame_index)];1570 const abi_size = frame_size[@intFromEnum(frame_index)];
1577 if (abi_size != alloc.abi_size) continue;1571 if (abi_size != alloc.abi_size) continue;
1578 const abi_align = &frame_align[@intFromEnum(frame_index)];1572 const abi_align = &frame_align[@intFromEnum(frame_index)];
1579 abi_align.* = abi_align.max(alloc.abi_align);1573 abi_align.* = abi_align.max(alloc.abi_align);
15801574
1581 _ = self.free_frame_indices.swapRemoveAt(free_i);1575 _ = func.free_frame_indices.swapRemoveAt(free_i);
1582 return frame_index;1576 return frame_index;
1583 }1577 }
1584 const frame_index: FrameIndex = @enumFromInt(self.frame_allocs.len);1578 const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len);
1585 try self.frame_allocs.append(self.gpa, alloc);1579 try func.frame_allocs.append(func.gpa, alloc);
1586 log.debug("allocated frame {}", .{frame_index});1580 log.debug("allocated frame {}", .{frame_index});
1587 return frame_index;1581 return frame_index;
1588}1582}
15891583
1590/// Use a pointer instruction as the basis for allocating stack memory.1584/// Use a pointer instruction as the basis for allocating stack memory.
1591fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {1585fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {
1592 const zcu = self.bin_file.comp.module.?;1586 const zcu = func.bin_file.comp.module.?;
1593 const ptr_ty = self.typeOfIndex(inst);1587 const ptr_ty = func.typeOfIndex(inst);
1594 const val_ty = ptr_ty.childType(zcu);1588 const val_ty = ptr_ty.childType(zcu);
1595 return self.allocFrameIndex(FrameAlloc.init(.{1589 return func.allocFrameIndex(FrameAlloc.init(.{
1596 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {1590 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
1597 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(zcu)});1591 return func.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(zcu)});
1598 },1592 },
1599 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),1593 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
1600 }));1594 }));
1601}1595}
16021596
1603fn typeRegClass(self: *Self, ty: Type) abi.RegisterClass {1597fn typeRegClass(func: *Func, ty: Type) abi.RegisterClass {
1604 const zcu = self.bin_file.comp.module.?;1598 const zcu = func.bin_file.comp.module.?;
1605 return switch (ty.zigTypeTag(zcu)) {1599 return switch (ty.zigTypeTag(zcu)) {
1606 .Float => .float,1600 .Float => .float,
1607 .Vector => @panic("TODO: typeRegClass for Vectors"),1601 .Vector => @panic("TODO: typeRegClass for Vectors"),
...@@ -1609,8 +1603,8 @@ fn typeRegClass(self: *Self, ty: Type) abi.RegisterClass {...@@ -1609,8 +1603,8 @@ fn typeRegClass(self: *Self, ty: Type) abi.RegisterClass {
1609 };1603 };
1610}1604}
16111605
1612fn regGeneralClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {1606fn regGeneralClassForType(func: *Func, ty: Type) RegisterManager.RegisterBitSet {
1613 const zcu = self.bin_file.comp.module.?;1607 const zcu = func.bin_file.comp.module.?;
1614 return switch (ty.zigTypeTag(zcu)) {1608 return switch (ty.zigTypeTag(zcu)) {
1615 .Float => abi.Registers.Float.general_purpose,1609 .Float => abi.Registers.Float.general_purpose,
1616 .Vector => @panic("TODO: regGeneralClassForType for Vectors"),1610 .Vector => @panic("TODO: regGeneralClassForType for Vectors"),
...@@ -1618,8 +1612,8 @@ fn regGeneralClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet...@@ -1618,8 +1612,8 @@ fn regGeneralClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet
1618 };1612 };
1619}1613}
16201614
1621fn regTempClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {1615fn regTempClassForType(func: *Func, ty: Type) RegisterManager.RegisterBitSet {
1622 const zcu = self.bin_file.comp.module.?;1616 const zcu = func.bin_file.comp.module.?;
1623 return switch (ty.zigTypeTag(zcu)) {1617 return switch (ty.zigTypeTag(zcu)) {
1624 .Float => abi.Registers.Float.temporary,1618 .Float => abi.Registers.Float.temporary,
1625 .Vector => @panic("TODO: regTempClassForType for Vectors"),1619 .Vector => @panic("TODO: regTempClassForType for Vectors"),
...@@ -1627,12 +1621,12 @@ fn regTempClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {...@@ -1627,12 +1621,12 @@ fn regTempClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {
1627 };1621 };
1628}1622}
16291623
1630fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {1624fn allocRegOrMem(func: *Func, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
1631 const zcu = self.bin_file.comp.module.?;1625 const zcu = func.bin_file.comp.module.?;
1632 const elem_ty = self.typeOfIndex(inst);1626 const elem_ty = func.typeOfIndex(inst);
16331627
1634 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {1628 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
1635 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(zcu)});1629 return func.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(zcu)});
1636 };1630 };
16371631
1638 const min_size: u32 = switch (elem_ty.zigTypeTag(zcu)) {1632 const min_size: u32 = switch (elem_ty.zigTypeTag(zcu)) {
...@@ -1642,20 +1636,20 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -1642,20 +1636,20 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
1642 };1636 };
16431637
1644 if (reg_ok and abi_size <= min_size) {1638 if (reg_ok and abi_size <= min_size) {
1645 if (self.register_manager.tryAllocReg(inst, self.regGeneralClassForType(elem_ty))) |reg| {1639 if (func.register_manager.tryAllocReg(inst, func.regGeneralClassForType(elem_ty))) |reg| {
1646 return .{ .register = reg };1640 return .{ .register = reg };
1647 }1641 }
1648 }1642 }
16491643
1650 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(elem_ty, zcu));1644 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(elem_ty, zcu));
1651 return .{ .load_frame = .{ .index = frame_index } };1645 return .{ .load_frame = .{ .index = frame_index } };
1652}1646}
16531647
1654/// Allocates a register from the general purpose set and returns the Register and the Lock.1648/// Allocates a register from the general purpose set and returns the Register and the Lock.
1655///1649///
1656/// Up to the caller to unlock the register later.1650/// Up to the caller to unlock the register later.
1657fn allocReg(self: *Self, reg_class: abi.RegisterClass) !struct { Register, RegisterLock } {1651fn allocReg(func: *Func, reg_class: abi.RegisterClass) !struct { Register, RegisterLock } {
1658 if (reg_class == .float and !self.hasFeature(.f))1652 if (reg_class == .float and !func.hasFeature(.f))
1659 std.debug.panic("allocReg class == float where F isn't enabled", .{});1653 std.debug.panic("allocReg class == float where F isn't enabled", .{});
16601654
1661 const class = switch (reg_class) {1655 const class = switch (reg_class) {
...@@ -1663,8 +1657,8 @@ fn allocReg(self: *Self, reg_class: abi.RegisterClass) !struct { Register, Regis...@@ -1663,8 +1657,8 @@ fn allocReg(self: *Self, reg_class: abi.RegisterClass) !struct { Register, Regis
1663 .float => abi.Registers.Float.general_purpose,1657 .float => abi.Registers.Float.general_purpose,
1664 };1658 };
16651659
1666 const reg = try self.register_manager.allocReg(null, class);1660 const reg = try func.register_manager.allocReg(null, class);
1667 const lock = self.register_manager.lockRegAssumeUnused(reg);1661 const lock = func.register_manager.lockRegAssumeUnused(reg);
1668 return .{ reg, lock };1662 return .{ reg, lock };
1669}1663}
16701664
...@@ -1677,8 +1671,8 @@ const PromoteOptions = struct {...@@ -1677,8 +1671,8 @@ const PromoteOptions = struct {
16771671
1678/// Similar to `allocReg` but will copy the MCValue into the Register unless `operand` is already1672/// Similar to `allocReg` but will copy the MCValue into the Register unless `operand` is already
1679/// a register, in which case it will return a possible lock to that register.1673/// a register, in which case it will return a possible lock to that register.
1680fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions) !struct { Register, ?RegisterLock } {1674fn promoteReg(func: *Func, ty: Type, operand: MCValue, options: PromoteOptions) !struct { Register, ?RegisterLock } {
1681 const zcu = self.bin_file.comp.module.?;1675 const zcu = func.bin_file.comp.module.?;
1682 const bit_size = ty.bitSize(zcu);1676 const bit_size = ty.bitSize(zcu);
16831677
1684 if (operand == .register) {1678 if (operand == .register) {
...@@ -1687,7 +1681,7 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)...@@ -1687,7 +1681,7 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)
1687 // we make sure to emit the truncate manually because binOp will call this function1681 // we make sure to emit the truncate manually because binOp will call this function
1688 // and it could cause an infinite loop1682 // and it could cause an infinite loop
16891683
1690 _ = try self.addInst(.{1684 _ = try func.addInst(.{
1691 .tag = .slli,1685 .tag = .slli,
1692 .ops = .rri,1686 .ops = .rri,
1693 .data = .{1687 .data = .{
...@@ -1699,7 +1693,7 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)...@@ -1699,7 +1693,7 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)
1699 },1693 },
1700 });1694 });
17011695
1702 _ = try self.addInst(.{1696 _ = try func.addInst(.{
1703 .tag = .srli,1697 .tag = .srli,
1704 .ops = .rri,1698 .ops = .rri,
1705 .data = .{1699 .data = .{
...@@ -1712,13 +1706,13 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)...@@ -1712,13 +1706,13 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)
1712 });1706 });
1713 }1707 }
17141708
1715 return .{ op_reg, self.register_manager.lockReg(operand.register) };1709 return .{ op_reg, func.register_manager.lockReg(operand.register) };
1716 }1710 }
17171711
1718 const reg, const lock = try self.allocReg(self.typeRegClass(ty));1712 const reg, const lock = try func.allocReg(func.typeRegClass(ty));
17191713
1720 if (options.zero and reg.class() == .int) {1714 if (options.zero and reg.class() == .int) {
1721 _ = try self.addInst(.{1715 _ = try func.addInst(.{
1722 .tag = .pseudo,1716 .tag = .pseudo,
1723 .ops = .pseudo_mv,1717 .ops = .pseudo_mv,
1724 .data = .{ .rr = .{1718 .data = .{ .rr = .{
...@@ -1728,26 +1722,26 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)...@@ -1728,26 +1722,26 @@ fn promoteReg(self: *Self, ty: Type, operand: MCValue, options: PromoteOptions)
1728 });1722 });
1729 }1723 }
17301724
1731 try self.genSetReg(ty, reg, operand);1725 try func.genSetReg(ty, reg, operand);
1732 return .{ reg, lock };1726 return .{ reg, lock };
1733}1727}
17341728
1735fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register {1729fn elemOffset(func: *Func, index_ty: Type, index: MCValue, elem_size: u64) !Register {
1736 const reg: Register = blk: {1730 const reg: Register = blk: {
1737 switch (index) {1731 switch (index) {
1738 .immediate => |imm| {1732 .immediate => |imm| {
1739 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`1733 // Optimisation: if index MCValue is an immediate, we can multiply in `comptime`
1740 // and set the register directly to the scaled offset as an immediate.1734 // and set the register directly to the scaled offset as an immediate.
1741 const reg = try self.register_manager.allocReg(null, self.regGeneralClassForType(index_ty));1735 const reg = try func.register_manager.allocReg(null, func.regGeneralClassForType(index_ty));
1742 try self.genSetReg(index_ty, reg, .{ .immediate = imm * elem_size });1736 try func.genSetReg(index_ty, reg, .{ .immediate = imm * elem_size });
1743 break :blk reg;1737 break :blk reg;
1744 },1738 },
1745 else => {1739 else => {
1746 const reg = try self.copyToTmpRegister(index_ty, index);1740 const reg = try func.copyToTmpRegister(index_ty, index);
1747 const lock = self.register_manager.lockRegAssumeUnused(reg);1741 const lock = func.register_manager.lockRegAssumeUnused(reg);
1748 defer self.register_manager.unlockReg(lock);1742 defer func.register_manager.unlockReg(lock);
17491743
1750 const result = try self.binOp(1744 const result = try func.binOp(
1751 .mul,1745 .mul,
1752 .{ .register = reg },1746 .{ .register = reg },
1753 index_ty,1747 index_ty,
...@@ -1761,72 +1755,72 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi...@@ -1761,72 +1755,72 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
1761 return reg;1755 return reg;
1762}1756}
17631757
1764pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {1758pub fn spillInstruction(func: *Func, reg: Register, inst: Air.Inst.Index) !void {
1765 const tracking = self.inst_tracking.getPtr(inst) orelse return;1759 const tracking = func.inst_tracking.getPtr(inst) orelse return;
1766 for (tracking.getRegs()) |tracked_reg| {1760 for (tracking.getRegs()) |tracked_reg| {
1767 if (tracked_reg.id() == reg.id()) break;1761 if (tracked_reg.id() == reg.id()) break;
1768 } else unreachable; // spilled reg not tracked with spilled instruciton1762 } else unreachable; // spilled reg not tracked with spilled instruciton
1769 try tracking.spill(self, inst);1763 try tracking.spill(func, inst);
1770 try tracking.trackSpill(self, inst);1764 try tracking.trackSpill(func, inst);
1771}1765}
17721766
1773/// Copies a value to a register without tracking the register. The register is not considered1767/// Copies a value to a register without tracking the register. The register is not considered
1774/// allocated. A second call to `copyToTmpRegister` may return the same register.1768/// allocated. A second call to `copyToTmpRegister` may return the same register.
1775/// This can have a side effect of spilling instructions to the stack to free up a register.1769/// This can have a side effect of spilling instructions to the stack to free up a register.
1776fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {1770fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {
1777 log.debug("copyToTmpRegister ty: {}", .{ty.fmt(self.bin_file.comp.module.?)});1771 log.debug("copyToTmpRegister ty: {}", .{ty.fmt(func.bin_file.comp.module.?)});
1778 const reg = try self.register_manager.allocReg(null, self.regTempClassForType(ty));1772 const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));
1779 try self.genSetReg(ty, reg, mcv);1773 try func.genSetReg(ty, reg, mcv);
1780 return reg;1774 return reg;
1781}1775}
17821776
1783/// Allocates a new register and copies `mcv` into it.1777/// Allocates a new register and copies `mcv` into it.
1784/// `reg_owner` is the instruction that gets associated with the register in the register table.1778/// `reg_owner` is the instruction that gets associated with the register in the register table.
1785/// This can have a side effect of spilling instructions to the stack to free up a register.1779/// This can have a side effect of spilling instructions to the stack to free up a register.
1786fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {1780fn copyToNewRegister(func: *Func, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
1787 const ty = self.typeOfIndex(reg_owner);1781 const ty = func.typeOfIndex(reg_owner);
1788 const reg = try self.register_manager.allocReg(reg_owner, self.regGeneralClassForType(ty));1782 const reg = try func.register_manager.allocReg(reg_owner, func.regGeneralClassForType(ty));
1789 try self.genSetReg(self.typeOfIndex(reg_owner), reg, mcv);1783 try func.genSetReg(func.typeOfIndex(reg_owner), reg, mcv);
1790 return MCValue{ .register = reg };1784 return MCValue{ .register = reg };
1791}1785}
17921786
1793fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {1787fn airAlloc(func: *Func, inst: Air.Inst.Index) !void {
1794 const result = MCValue{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } };1788 const result = MCValue{ .lea_frame = .{ .index = try func.allocMemPtr(inst) } };
1795 return self.finishAir(inst, result, .{ .none, .none, .none });1789 return func.finishAir(inst, result, .{ .none, .none, .none });
1796}1790}
17971791
1798fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {1792fn airRetPtr(func: *Func, inst: Air.Inst.Index) !void {
1799 const result: MCValue = switch (self.ret_mcv.long) {1793 const result: MCValue = switch (func.ret_mcv.long) {
1800 .none => .{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } },1794 .none => .{ .lea_frame = .{ .index = try func.allocMemPtr(inst) } },
1801 .load_frame => .{ .register_offset = .{1795 .load_frame => .{ .register_offset = .{
1802 .reg = (try self.copyToNewRegister(1796 .reg = (try func.copyToNewRegister(
1803 inst,1797 inst,
1804 self.ret_mcv.long,1798 func.ret_mcv.long,
1805 )).register,1799 )).register,
1806 .off = self.ret_mcv.short.indirect.off,1800 .off = func.ret_mcv.short.indirect.off,
1807 } },1801 } },
1808 else => |t| return self.fail("TODO: airRetPtr {s}", .{@tagName(t)}),1802 else => |t| return func.fail("TODO: airRetPtr {s}", .{@tagName(t)}),
1809 };1803 };
1810 return self.finishAir(inst, result, .{ .none, .none, .none });1804 return func.finishAir(inst, result, .{ .none, .none, .none });
1811}1805}
18121806
1813fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {1807fn airFptrunc(func: *Func, inst: Air.Inst.Index) !void {
1814 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1808 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1815 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airFptrunc for {}", .{self.target.cpu.arch});1809 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFptrunc for {}", .{func.target.cpu.arch});
1816 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1810 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1817}1811}
18181812
1819fn airFpext(self: *Self, inst: Air.Inst.Index) !void {1813fn airFpext(func: *Func, inst: Air.Inst.Index) !void {
1820 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1814 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1821 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airFpext for {}", .{self.target.cpu.arch});1815 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFpext for {}", .{func.target.cpu.arch});
1822 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1816 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1823}1817}
18241818
1825fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {1819fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
1826 const zcu = self.bin_file.comp.module.?;1820 const zcu = func.bin_file.comp.module.?;
1827 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1821 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1828 const src_ty = self.typeOf(ty_op.operand);1822 const src_ty = func.typeOf(ty_op.operand);
1829 const dst_ty = self.typeOfIndex(inst);1823 const dst_ty = func.typeOfIndex(inst);
18301824
1831 const result: MCValue = result: {1825 const result: MCValue = result: {
1832 const src_int_info = src_ty.intInfo(zcu);1826 const src_int_info = src_ty.intInfo(zcu);
...@@ -1834,20 +1828,20 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1834,20 +1828,20 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
18341828
1835 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;1829 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;
18361830
1837 const src_mcv = try self.resolveInst(ty_op.operand);1831 const src_mcv = try func.resolveInst(ty_op.operand);
18381832
1839 const src_storage_bits: u16 = switch (src_mcv) {1833 const src_storage_bits: u16 = switch (src_mcv) {
1840 .register => 64,1834 .register => 64,
1841 .load_frame => src_int_info.bits,1835 .load_frame => src_int_info.bits,
1842 else => return self.fail("airIntCast from {s}", .{@tagName(src_mcv)}),1836 else => return func.fail("airIntCast from {s}", .{@tagName(src_mcv)}),
1843 };1837 };
18441838
1845 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and1839 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and
1846 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==1840 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
1847 math.divCeil(u32, src_storage_bits, 64) catch unreachable and1841 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
1848 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {1842 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
1849 const dst_mcv = try self.allocRegOrMem(inst, true);1843 const dst_mcv = try func.allocRegOrMem(inst, true);
1850 try self.genCopy(min_ty, dst_mcv, src_mcv);1844 try func.genCopy(min_ty, dst_mcv, src_mcv);
1851 break :dst dst_mcv;1845 break :dst dst_mcv;
1852 };1846 };
18531847
...@@ -1858,53 +1852,53 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1858,53 +1852,53 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1858 break :result null; // TODO1852 break :result null; // TODO
18591853
1860 break :result dst_mcv;1854 break :result dst_mcv;
1861 } orelse return self.fail("TODO implement airIntCast from {} to {}", .{1855 } orelse return func.fail("TODO implement airIntCast from {} to {}", .{
1862 src_ty.fmt(zcu), dst_ty.fmt(zcu),1856 src_ty.fmt(zcu), dst_ty.fmt(zcu),
1863 });1857 });
18641858
1865 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1859 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1866}1860}
18671861
1868fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {1862fn airTrunc(func: *Func, inst: Air.Inst.Index) !void {
1869 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1863 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1870 if (self.liveness.isUnused(inst))1864 if (func.liveness.isUnused(inst))
1871 return self.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });1865 return func.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none });
18721866
1873 const operand = try self.resolveInst(ty_op.operand);1867 const operand = try func.resolveInst(ty_op.operand);
1874 _ = operand;1868 _ = operand;
1875 return self.fail("TODO implement trunc for {}", .{self.target.cpu.arch});1869 return func.fail("TODO implement trunc for {}", .{func.target.cpu.arch});
1876 // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1870 // return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1877}1871}
18781872
1879fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void {1873fn airIntFromBool(func: *Func, inst: Air.Inst.Index) !void {
1880 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;1874 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1881 const operand = try self.resolveInst(un_op);1875 const operand = try func.resolveInst(un_op);
1882 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else operand;1876 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else operand;
1883 return self.finishAir(inst, result, .{ un_op, .none, .none });1877 return func.finishAir(inst, result, .{ un_op, .none, .none });
1884}1878}
18851879
1886fn airNot(self: *Self, inst: Air.Inst.Index) !void {1880fn airNot(func: *Func, inst: Air.Inst.Index) !void {
1887 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1881 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1888 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1882 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
1889 const zcu = self.bin_file.comp.module.?;1883 const zcu = func.bin_file.comp.module.?;
18901884
1891 const operand = try self.resolveInst(ty_op.operand);1885 const operand = try func.resolveInst(ty_op.operand);
1892 const ty = self.typeOf(ty_op.operand);1886 const ty = func.typeOf(ty_op.operand);
18931887
1894 switch (ty.zigTypeTag(zcu)) {1888 switch (ty.zigTypeTag(zcu)) {
1895 .Bool => {1889 .Bool => {
1896 const operand_reg = blk: {1890 const operand_reg = blk: {
1897 if (operand == .register) break :blk operand.register;1891 if (operand == .register) break :blk operand.register;
1898 break :blk try self.copyToTmpRegister(ty, operand);1892 break :blk try func.copyToTmpRegister(ty, operand);
1899 };1893 };
19001894
1901 const dst_reg: Register =1895 const dst_reg: Register =
1902 if (self.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register)1896 if (func.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register)
1903 operand.register1897 operand.register
1904 else1898 else
1905 (try self.allocRegOrMem(inst, true)).register;1899 (try func.allocRegOrMem(inst, true)).register;
19061900
1907 _ = try self.addInst(.{1901 _ = try func.addInst(.{
1908 .tag = .pseudo,1902 .tag = .pseudo,
1909 .ops = .pseudo_not,1903 .ops = .pseudo_not,
1910 .data = .{1904 .data = .{
...@@ -1917,59 +1911,59 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1917,59 +1911,59 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
19171911
1918 break :result .{ .register = dst_reg };1912 break :result .{ .register = dst_reg };
1919 },1913 },
1920 .Int => return self.fail("TODO: airNot ints", .{}),1914 .Int => return func.fail("TODO: airNot ints", .{}),
1921 else => unreachable,1915 else => unreachable,
1922 }1916 }
1923 };1917 };
1924 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1918 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1925}1919}
19261920
1927fn airMinMax(1921fn airMinMax(
1928 self: *Self,1922 func: *Func,
1929 inst: Air.Inst.Index,1923 inst: Air.Inst.Index,
1930 comptime tag: enum {1924 comptime tag: enum {
1931 max,1925 max,
1932 min,1926 min,
1933 },1927 },
1934) !void {1928) !void {
1935 const zcu = self.bin_file.comp.module.?;1929 const zcu = func.bin_file.comp.module.?;
1936 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;1930 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
19371931
1938 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {1932 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
1939 const lhs = try self.resolveInst(bin_op.lhs);1933 const lhs = try func.resolveInst(bin_op.lhs);
1940 const rhs = try self.resolveInst(bin_op.rhs);1934 const rhs = try func.resolveInst(bin_op.rhs);
1941 const lhs_ty = self.typeOf(bin_op.lhs);1935 const lhs_ty = func.typeOf(bin_op.lhs);
1942 const rhs_ty = self.typeOf(bin_op.rhs);1936 const rhs_ty = func.typeOf(bin_op.rhs);
19431937
1944 const int_info = lhs_ty.intInfo(zcu);1938 const int_info = lhs_ty.intInfo(zcu);
19451939
1946 if (int_info.bits > 64) return self.fail("TODO: > 64 bit @min", .{});1940 if (int_info.bits > 64) return func.fail("TODO: > 64 bit @min", .{});
19471941
1948 const lhs_reg, const lhs_lock = blk: {1942 const lhs_reg, const lhs_lock = blk: {
1949 if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) };1943 if (lhs == .register) break :blk .{ lhs.register, func.register_manager.lockReg(lhs.register) };
19501944
1951 const lhs_reg, const lhs_lock = try self.allocReg(.int);1945 const lhs_reg, const lhs_lock = try func.allocReg(.int);
1952 try self.genSetReg(lhs_ty, lhs_reg, lhs);1946 try func.genSetReg(lhs_ty, lhs_reg, lhs);
1953 break :blk .{ lhs_reg, lhs_lock };1947 break :blk .{ lhs_reg, lhs_lock };
1954 };1948 };
1955 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);1949 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
19561950
1957 const rhs_reg, const rhs_lock = blk: {1951 const rhs_reg, const rhs_lock = blk: {
1958 if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) };1952 if (rhs == .register) break :blk .{ rhs.register, func.register_manager.lockReg(rhs.register) };
19591953
1960 const rhs_reg, const rhs_lock = try self.allocReg(.int);1954 const rhs_reg, const rhs_lock = try func.allocReg(.int);
1961 try self.genSetReg(rhs_ty, rhs_reg, rhs);1955 try func.genSetReg(rhs_ty, rhs_reg, rhs);
1962 break :blk .{ rhs_reg, rhs_lock };1956 break :blk .{ rhs_reg, rhs_lock };
1963 };1957 };
1964 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);1958 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
19651959
1966 const mask_reg, const mask_lock = try self.allocReg(.int);1960 const mask_reg, const mask_lock = try func.allocReg(.int);
1967 defer self.register_manager.unlockReg(mask_lock);1961 defer func.register_manager.unlockReg(mask_lock);
19681962
1969 const result_reg, const result_lock = try self.allocReg(.int);1963 const result_reg, const result_lock = try func.allocReg(.int);
1970 defer self.register_manager.unlockReg(result_lock);1964 defer func.register_manager.unlockReg(result_lock);
19711965
1972 _ = try self.addInst(.{1966 _ = try func.addInst(.{
1973 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,1967 .tag = if (int_info.signedness == .unsigned) .sltu else .slt,
1974 .ops = .rrr,1968 .ops = .rrr,
1975 .data = .{ .r_type = .{1969 .data = .{ .r_type = .{
...@@ -1979,7 +1973,7 @@ fn airMinMax(...@@ -1979,7 +1973,7 @@ fn airMinMax(
1979 } },1973 } },
1980 });1974 });
19811975
1982 _ = try self.addInst(.{1976 _ = try func.addInst(.{
1983 .tag = .sub,1977 .tag = .sub,
1984 .ops = .rrr,1978 .ops = .rrr,
1985 .data = .{ .r_type = .{1979 .data = .{ .r_type = .{
...@@ -1989,7 +1983,7 @@ fn airMinMax(...@@ -1989,7 +1983,7 @@ fn airMinMax(
1989 } },1983 } },
1990 });1984 });
19911985
1992 _ = try self.addInst(.{1986 _ = try func.addInst(.{
1993 .tag = .xor,1987 .tag = .xor,
1994 .ops = .rrr,1988 .ops = .rrr,
1995 .data = .{ .r_type = .{1989 .data = .{ .r_type = .{
...@@ -1999,7 +1993,7 @@ fn airMinMax(...@@ -1999,7 +1993,7 @@ fn airMinMax(
1999 } },1993 } },
2000 });1994 });
20011995
2002 _ = try self.addInst(.{1996 _ = try func.addInst(.{
2003 .tag = .@"and",1997 .tag = .@"and",
2004 .ops = .rrr,1998 .ops = .rrr,
2005 .data = .{ .r_type = .{1999 .data = .{ .r_type = .{
...@@ -2009,7 +2003,7 @@ fn airMinMax(...@@ -2009,7 +2003,7 @@ fn airMinMax(
2009 } },2003 } },
2010 });2004 });
20112005
2012 _ = try self.addInst(.{2006 _ = try func.addInst(.{
2013 .tag = .xor,2007 .tag = .xor,
2014 .ops = .rrr,2008 .ops = .rrr,
2015 .data = .{ .r_type = .{2009 .data = .{ .r_type = .{
...@@ -2021,22 +2015,22 @@ fn airMinMax(...@@ -2021,22 +2015,22 @@ fn airMinMax(
20212015
2022 break :result .{ .register = result_reg };2016 break :result .{ .register = result_reg };
2023 };2017 };
2024 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2018 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2025}2019}
20262020
2027fn airSlice(self: *Self, inst: Air.Inst.Index) !void {2021fn airSlice(func: *Func, inst: Air.Inst.Index) !void {
2028 const zcu = self.bin_file.comp.module.?;2022 const zcu = func.bin_file.comp.module.?;
2029 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2023 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2030 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2024 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
20312025
2032 const slice_ty = self.typeOfIndex(inst);2026 const slice_ty = func.typeOfIndex(inst);
2033 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, zcu));2027 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(slice_ty, zcu));
20342028
2035 const ptr_ty = self.typeOf(bin_op.lhs);2029 const ptr_ty = func.typeOf(bin_op.lhs);
2036 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, .{ .air_ref = bin_op.lhs });2030 try func.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, .{ .air_ref = bin_op.lhs });
20372031
2038 const len_ty = self.typeOf(bin_op.rhs);2032 const len_ty = func.typeOf(bin_op.rhs);
2039 try self.genSetMem(2033 try func.genSetMem(
2040 .{ .frame = frame_index },2034 .{ .frame = frame_index },
2041 @intCast(ptr_ty.abiSize(zcu)),2035 @intCast(ptr_ty.abiSize(zcu)),
2042 len_ty,2036 len_ty,
...@@ -2044,31 +2038,31 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -2044,31 +2038,31 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
2044 );2038 );
20452039
2046 const result = MCValue{ .load_frame = .{ .index = frame_index } };2040 const result = MCValue{ .load_frame = .{ .index = frame_index } };
2047 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2041 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2048}2042}
20492043
2050fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2044fn airBinOp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2051 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2045 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2052 const lhs = try self.resolveInst(bin_op.lhs);2046 const lhs = try func.resolveInst(bin_op.lhs);
2053 const rhs = try self.resolveInst(bin_op.rhs);2047 const rhs = try func.resolveInst(bin_op.rhs);
2054 const lhs_ty = self.typeOf(bin_op.lhs);2048 const lhs_ty = func.typeOf(bin_op.lhs);
2055 const rhs_ty = self.typeOf(bin_op.rhs);2049 const rhs_ty = func.typeOf(bin_op.rhs);
20562050
2057 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2051 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2058 break :result try self.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);2052 break :result try func.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);
2059 };2053 };
2060 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2054 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2061}2055}
20622056
2063fn binOp(2057fn binOp(
2064 self: *Self,2058 func: *Func,
2065 tag: Air.Inst.Tag,2059 tag: Air.Inst.Tag,
2066 lhs: MCValue,2060 lhs: MCValue,
2067 lhs_ty: Type,2061 lhs_ty: Type,
2068 rhs: MCValue,2062 rhs: MCValue,
2069 rhs_ty: Type,2063 rhs_ty: Type,
2070) InnerError!MCValue {2064) InnerError!MCValue {
2071 const zcu = self.bin_file.comp.module.?;2065 const zcu = func.bin_file.comp.module.?;
20722066
2073 switch (tag) {2067 switch (tag) {
2074 // Arithmetic operations on integers and floats2068 // Arithmetic operations on integers and floats
...@@ -2087,23 +2081,23 @@ fn binOp(...@@ -2087,23 +2081,23 @@ fn binOp(
2087 switch (lhs_ty.zigTypeTag(zcu)) {2081 switch (lhs_ty.zigTypeTag(zcu)) {
2088 .Float => {2082 .Float => {
2089 const float_bits = lhs_ty.floatBits(zcu.getTarget());2083 const float_bits = lhs_ty.floatBits(zcu.getTarget());
2090 const float_reg_bits: u32 = if (self.hasFeature(.d)) 64 else 32;2084 const float_reg_bits: u32 = if (func.hasFeature(.d)) 64 else 32;
2091 if (float_bits <= float_reg_bits) {2085 if (float_bits <= float_reg_bits) {
2092 return self.binOpFloat(tag, lhs, lhs_ty, rhs, rhs_ty);2086 return func.binOpFloat(tag, lhs, lhs_ty, rhs, rhs_ty);
2093 } else {2087 } else {
2094 return self.fail("TODO: binary operations for floats with bits > {d}", .{float_reg_bits});2088 return func.fail("TODO: binary operations for floats with bits > {d}", .{float_reg_bits});
2095 }2089 }
2096 },2090 },
2097 .Vector => return self.fail("TODO binary operations on vectors", .{}),2091 .Vector => return func.fail("TODO binary operations on vectors", .{}),
2098 .Int, .Enum, .ErrorSet => {2092 .Int, .Enum, .ErrorSet => {
2099 const int_info = lhs_ty.intInfo(zcu);2093 const int_info = lhs_ty.intInfo(zcu);
2100 if (int_info.bits <= 64) {2094 if (int_info.bits <= 64) {
2101 return self.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);2095 return func.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);
2102 } else {2096 } else {
2103 return self.fail("TODO binary operations on int with bits > 64", .{});2097 return func.fail("TODO binary operations on int with bits > 64", .{});
2104 }2098 }
2105 },2099 },
2106 else => |x| return self.fail("TOOD: binOp {s}", .{@tagName(x)}),2100 else => |x| return func.fail("TOOD: binOp {s}", .{@tagName(x)}),
2107 }2101 }
2108 },2102 },
21092103
...@@ -2126,9 +2120,9 @@ fn binOp(...@@ -2126,9 +2120,9 @@ fn binOp(
2126 else => unreachable,2120 else => unreachable,
2127 };2121 };
21282122
2129 return try self.binOpRegister(base_tag, lhs, lhs_ty, rhs, rhs_ty);2123 return try func.binOpRegister(base_tag, lhs, lhs_ty, rhs, rhs_ty);
2130 } else {2124 } else {
2131 const offset = try self.binOp(2125 const offset = try func.binOp(
2132 .mul,2126 .mul,
2133 rhs,2127 rhs,
2134 Type.usize,2128 Type.usize,
...@@ -2136,7 +2130,7 @@ fn binOp(...@@ -2136,7 +2130,7 @@ fn binOp(
2136 Type.usize,2130 Type.usize,
2137 );2131 );
21382132
2139 const addr = try self.binOp(2133 const addr = try func.binOp(
2140 tag,2134 tag,
2141 lhs,2135 lhs,
2142 Type.manyptr_u8,2136 Type.manyptr_u8,
...@@ -2155,39 +2149,39 @@ fn binOp(...@@ -2155,39 +2149,39 @@ fn binOp(
2155 .shl,2149 .shl,
2156 => {2150 => {
2157 switch (lhs_ty.zigTypeTag(zcu)) {2151 switch (lhs_ty.zigTypeTag(zcu)) {
2158 .Float => return self.fail("TODO binary operations on floats", .{}),2152 .Float => return func.fail("TODO binary operations on floats", .{}),
2159 .Vector => return self.fail("TODO binary operations on vectors", .{}),2153 .Vector => return func.fail("TODO binary operations on vectors", .{}),
2160 .Int => {2154 .Int => {
2161 const int_info = lhs_ty.intInfo(zcu);2155 const int_info = lhs_ty.intInfo(zcu);
2162 if (int_info.bits <= 64) {2156 if (int_info.bits <= 64) {
2163 return self.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);2157 return func.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty);
2164 } else {2158 } else {
2165 return self.fail("TODO binary operations on int with bits > 64", .{});2159 return func.fail("TODO binary operations on int with bits > 64", .{});
2166 }2160 }
2167 },2161 },
2168 else => unreachable,2162 else => unreachable,
2169 }2163 }
2170 },2164 },
2171 else => return self.fail("TODO binOp {}", .{tag}),2165 else => return func.fail("TODO binOp {}", .{tag}),
2172 }2166 }
2173}2167}
21742168
2175fn binOpRegister(2169fn binOpRegister(
2176 self: *Self,2170 func: *Func,
2177 tag: Air.Inst.Tag,2171 tag: Air.Inst.Tag,
2178 lhs: MCValue,2172 lhs: MCValue,
2179 lhs_ty: Type,2173 lhs_ty: Type,
2180 rhs: MCValue,2174 rhs: MCValue,
2181 rhs_ty: Type,2175 rhs_ty: Type,
2182) !MCValue {2176) !MCValue {
2183 const lhs_reg, const lhs_lock = try self.promoteReg(lhs_ty, lhs, .{ .zero = true });2177 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{ .zero = true });
2184 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);2178 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
21852179
2186 const rhs_reg, const rhs_lock = try self.promoteReg(rhs_ty, rhs, .{ .zero = true });2180 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{ .zero = true });
2187 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);2181 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
21882182
2189 const dest_reg, const dest_lock = try self.allocReg(.int);2183 const dest_reg, const dest_lock = try func.allocReg(.int);
2190 defer self.register_manager.unlockReg(dest_lock);2184 defer func.register_manager.unlockReg(dest_lock);
21912185
2192 const mir_tag: Mir.Inst.Tag = switch (tag) {2186 const mir_tag: Mir.Inst.Tag = switch (tag) {
2193 .add => .add,2187 .add => .add,
...@@ -2205,7 +2199,7 @@ fn binOpRegister(...@@ -2205,7 +2199,7 @@ fn binOpRegister(
2205 .cmp_lte,2199 .cmp_lte,
2206 => .pseudo,2200 => .pseudo,
22072201
2208 else => return self.fail("TODO: binOpRegister {s}", .{@tagName(tag)}),2202 else => return func.fail("TODO: binOpRegister {s}", .{@tagName(tag)}),
2209 };2203 };
22102204
2211 switch (mir_tag) {2205 switch (mir_tag) {
...@@ -2215,7 +2209,7 @@ fn binOpRegister(...@@ -2215,7 +2209,7 @@ fn binOpRegister(
2215 .sllw,2209 .sllw,
2216 .srlw,2210 .srlw,
2217 => {2211 => {
2218 _ = try self.addInst(.{2212 _ = try func.addInst(.{
2219 .tag = mir_tag,2213 .tag = mir_tag,
2220 .ops = .rrr,2214 .ops = .rrr,
2221 .data = .{2215 .data = .{
...@@ -2240,7 +2234,7 @@ fn binOpRegister(...@@ -2240,7 +2234,7 @@ fn binOpRegister(
2240 else => unreachable,2234 else => unreachable,
2241 };2235 };
22422236
2243 _ = try self.addInst(.{2237 _ = try func.addInst(.{
2244 .tag = .pseudo,2238 .tag = .pseudo,
2245 .ops = pseudo_op,2239 .ops = pseudo_op,
2246 .data = .{2240 .data = .{
...@@ -2257,7 +2251,7 @@ fn binOpRegister(...@@ -2257,7 +2251,7 @@ fn binOpRegister(
2257 .cmp_lte => .lte,2251 .cmp_lte => .lte,
2258 else => unreachable,2252 else => unreachable,
2259 },2253 },
2260 .size = self.memSize(lhs_ty),2254 .size = func.memSize(lhs_ty),
2261 },2255 },
2262 },2256 },
2263 });2257 });
...@@ -2270,21 +2264,21 @@ fn binOpRegister(...@@ -2270,21 +2264,21 @@ fn binOpRegister(
2270}2264}
22712265
2272fn binOpFloat(2266fn binOpFloat(
2273 self: *Self,2267 func: *Func,
2274 tag: Air.Inst.Tag,2268 tag: Air.Inst.Tag,
2275 lhs: MCValue,2269 lhs: MCValue,
2276 lhs_ty: Type,2270 lhs_ty: Type,
2277 rhs: MCValue,2271 rhs: MCValue,
2278 rhs_ty: Type,2272 rhs_ty: Type,
2279) !MCValue {2273) !MCValue {
2280 const zcu = self.bin_file.comp.module.?;2274 const zcu = func.bin_file.comp.module.?;
2281 const float_bits = lhs_ty.floatBits(zcu.getTarget());2275 const float_bits = lhs_ty.floatBits(zcu.getTarget());
22822276
2283 const lhs_reg, const lhs_lock = try self.promoteReg(lhs_ty, lhs, .{});2277 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2284 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);2278 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
22852279
2286 const rhs_reg, const rhs_lock = try self.promoteReg(rhs_ty, rhs, .{});2280 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2287 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);2281 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
22882282
2289 const mir_tag: Mir.Inst.Tag = switch (tag) {2283 const mir_tag: Mir.Inst.Tag = switch (tag) {
2290 .add => if (float_bits == 32) .fadds else .faddd,2284 .add => if (float_bits == 32) .fadds else .faddd,
...@@ -2300,7 +2294,7 @@ fn binOpFloat(...@@ -2300,7 +2294,7 @@ fn binOpFloat(
2300 .cmp_lte,2294 .cmp_lte,
2301 => .pseudo,2295 => .pseudo,
23022296
2303 else => return self.fail("TODO: binOpFloat mir_tag {s}", .{@tagName(tag)}),2297 else => return func.fail("TODO: binOpFloat mir_tag {s}", .{@tagName(tag)}),
2304 };2298 };
23052299
2306 const return_class: abi.RegisterClass = switch (tag) {2300 const return_class: abi.RegisterClass = switch (tag) {
...@@ -2320,8 +2314,8 @@ fn binOpFloat(...@@ -2320,8 +2314,8 @@ fn binOpFloat(
2320 else => unreachable,2314 else => unreachable,
2321 };2315 };
23222316
2323 const dest_reg, const dest_lock = try self.allocReg(return_class);2317 const dest_reg, const dest_lock = try func.allocReg(return_class);
2324 defer self.register_manager.unlockReg(dest_lock);2318 defer func.register_manager.unlockReg(dest_lock);
23252319
2326 switch (tag) {2320 switch (tag) {
2327 .add,2321 .add,
...@@ -2329,7 +2323,7 @@ fn binOpFloat(...@@ -2329,7 +2323,7 @@ fn binOpFloat(
2329 .mul,2323 .mul,
2330 .div_float,2324 .div_float,
2331 => {2325 => {
2332 _ = try self.addInst(.{2326 _ = try func.addInst(.{
2333 .tag = mir_tag,2327 .tag = mir_tag,
2334 .ops = .rrr,2328 .ops = .rrr,
2335 .data = .{ .r_type = .{2329 .data = .{ .r_type = .{
...@@ -2347,7 +2341,7 @@ fn binOpFloat(...@@ -2347,7 +2341,7 @@ fn binOpFloat(
2347 .cmp_lt,2341 .cmp_lt,
2348 .cmp_lte,2342 .cmp_lte,
2349 => {2343 => {
2350 _ = try self.addInst(.{2344 _ = try func.addInst(.{
2351 .tag = .pseudo,2345 .tag = .pseudo,
2352 .ops = .pseudo_compare,2346 .ops = .pseudo_compare,
2353 .data = .{2347 .data = .{
...@@ -2364,7 +2358,7 @@ fn binOpFloat(...@@ -2364,7 +2358,7 @@ fn binOpFloat(
2364 .cmp_lte => .lte,2358 .cmp_lte => .lte,
2365 else => unreachable,2359 else => unreachable,
2366 },2360 },
2367 .size = self.memSize(lhs_ty),2361 .size = func.memSize(lhs_ty),
2368 },2362 },
2369 },2363 },
2370 });2364 });
...@@ -2376,120 +2370,120 @@ fn binOpFloat(...@@ -2376,120 +2370,120 @@ fn binOpFloat(
2376 return MCValue{ .register = dest_reg };2370 return MCValue{ .register = dest_reg };
2377}2371}
23782372
2379fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {2373fn airPtrArithmetic(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
2380 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2374 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2381 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2375 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
2382 const lhs = try self.resolveInst(bin_op.lhs);2376 const lhs = try func.resolveInst(bin_op.lhs);
2383 const rhs = try self.resolveInst(bin_op.rhs);2377 const rhs = try func.resolveInst(bin_op.rhs);
2384 const lhs_ty = self.typeOf(bin_op.lhs);2378 const lhs_ty = func.typeOf(bin_op.lhs);
2385 const rhs_ty = self.typeOf(bin_op.rhs);2379 const rhs_ty = func.typeOf(bin_op.rhs);
23862380
2387 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2381 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2388 break :result try self.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);2382 break :result try func.binOp(tag, lhs, lhs_ty, rhs, rhs_ty);
2389 };2383 };
2390 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2384 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2391}2385}
23922386
2393fn airAddWrap(self: *Self, inst: Air.Inst.Index) !void {2387fn airAddWrap(func: *Func, inst: Air.Inst.Index) !void {
2394 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2388 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2395 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement addwrap for {}", .{self.target.cpu.arch});2389 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement addwrap for {}", .{func.target.cpu.arch});
2396 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2390 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2397}2391}
23982392
2399fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {2393fn airAddSat(func: *Func, inst: Air.Inst.Index) !void {
2400 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2394 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2401 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement add_sat for {}", .{self.target.cpu.arch});2395 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement add_sat for {}", .{func.target.cpu.arch});
2402 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2396 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2403}2397}
24042398
2405fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void {2399fn airSubWrap(func: *Func, inst: Air.Inst.Index) !void {
2406 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2400 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2407 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2401 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2408 // RISCV arthemtic instructions already wrap, so this is simply a sub binOp with2402 // RISCV arthemtic instructions already wrap, so this is simply a sub binOp with
2409 // no overflow checks.2403 // no overflow checks.
2410 const lhs = try self.resolveInst(bin_op.lhs);2404 const lhs = try func.resolveInst(bin_op.lhs);
2411 const rhs = try self.resolveInst(bin_op.rhs);2405 const rhs = try func.resolveInst(bin_op.rhs);
2412 const lhs_ty = self.typeOf(bin_op.lhs);2406 const lhs_ty = func.typeOf(bin_op.lhs);
2413 const rhs_ty = self.typeOf(bin_op.rhs);2407 const rhs_ty = func.typeOf(bin_op.rhs);
24142408
2415 break :result try self.binOp(.sub, lhs, lhs_ty, rhs, rhs_ty);2409 break :result try func.binOp(.sub, lhs, lhs_ty, rhs, rhs_ty);
2416 };2410 };
2417 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2411 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2418}2412}
24192413
2420fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {2414fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {
2421 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2415 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2422 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement sub_sat for {}", .{self.target.cpu.arch});2416 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement sub_sat for {}", .{func.target.cpu.arch});
2423 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2417 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2424}2418}
24252419
2426fn airMul(self: *Self, inst: Air.Inst.Index) !void {2420fn airMul(func: *Func, inst: Air.Inst.Index) !void {
2427 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2421 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2428 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2422 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2429 const lhs = try self.resolveInst(bin_op.lhs);2423 const lhs = try func.resolveInst(bin_op.lhs);
2430 const rhs = try self.resolveInst(bin_op.rhs);2424 const rhs = try func.resolveInst(bin_op.rhs);
2431 const lhs_ty = self.typeOf(bin_op.lhs);2425 const lhs_ty = func.typeOf(bin_op.lhs);
2432 const rhs_ty = self.typeOf(bin_op.rhs);2426 const rhs_ty = func.typeOf(bin_op.rhs);
24332427
2434 break :result try self.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);2428 break :result try func.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);
2435 };2429 };
2436 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2430 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2437}2431}
24382432
2439fn airDiv(self: *Self, inst: Air.Inst.Index) !void {2433fn airDiv(func: *Func, inst: Air.Inst.Index) !void {
2440 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2434 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2441 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2435 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2442 const lhs = try self.resolveInst(bin_op.lhs);2436 const lhs = try func.resolveInst(bin_op.lhs);
2443 const rhs = try self.resolveInst(bin_op.rhs);2437 const rhs = try func.resolveInst(bin_op.rhs);
2444 const lhs_ty = self.typeOf(bin_op.lhs);2438 const lhs_ty = func.typeOf(bin_op.lhs);
2445 const rhs_ty = self.typeOf(bin_op.rhs);2439 const rhs_ty = func.typeOf(bin_op.rhs);
24462440
2447 break :result try self.binOp(.div_float, lhs, lhs_ty, rhs, rhs_ty);2441 break :result try func.binOp(.div_float, lhs, lhs_ty, rhs, rhs_ty);
2448 };2442 };
2449 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2443 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2450}2444}
24512445
2452fn airMulWrap(self: *Self, inst: Air.Inst.Index) !void {2446fn airMulWrap(func: *Func, inst: Air.Inst.Index) !void {
2453 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2447 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2454 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement mulwrap for {}", .{self.target.cpu.arch});2448 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement mulwrap for {}", .{func.target.cpu.arch});
2455 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2449 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2456}2450}
24572451
2458fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {2452fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {
2459 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2453 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2460 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement mul_sat for {}", .{self.target.cpu.arch});2454 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement mul_sat for {}", .{func.target.cpu.arch});
2461 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2455 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2462}2456}
24632457
2464fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2458fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2465 const zcu = self.bin_file.comp.module.?;2459 const zcu = func.bin_file.comp.module.?;
2466 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2460 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2467 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2461 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
24682462
2469 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2463 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2470 const lhs = try self.resolveInst(extra.lhs);2464 const lhs = try func.resolveInst(extra.lhs);
2471 const rhs = try self.resolveInst(extra.rhs);2465 const rhs = try func.resolveInst(extra.rhs);
2472 const lhs_ty = self.typeOf(extra.lhs);2466 const lhs_ty = func.typeOf(extra.lhs);
2473 const rhs_ty = self.typeOf(extra.rhs);2467 const rhs_ty = func.typeOf(extra.rhs);
24742468
2475 const int_info = lhs_ty.intInfo(zcu);2469 const int_info = lhs_ty.intInfo(zcu);
24762470
2477 const tuple_ty = self.typeOfIndex(inst);2471 const tuple_ty = func.typeOfIndex(inst);
2478 const result_mcv = try self.allocRegOrMem(inst, false);2472 const result_mcv = try func.allocRegOrMem(inst, false);
2479 const offset = result_mcv.load_frame;2473 const offset = result_mcv.load_frame;
24802474
2481 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {2475 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2482 const add_result = try self.binOp(.add, lhs, lhs_ty, rhs, rhs_ty);2476 const add_result = try func.binOp(.add, lhs, lhs_ty, rhs, rhs_ty);
2483 const add_result_reg = try self.copyToTmpRegister(lhs_ty, add_result);2477 const add_result_reg = try func.copyToTmpRegister(lhs_ty, add_result);
2484 const add_result_reg_lock = self.register_manager.lockRegAssumeUnused(add_result_reg);2478 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);
2485 defer self.register_manager.unlockReg(add_result_reg_lock);2479 defer func.register_manager.unlockReg(add_result_reg_lock);
24862480
2487 const shift_amount: u6 = @intCast(Type.usize.bitSize(zcu) - int_info.bits);2481 const shift_amount: u6 = @intCast(Type.usize.bitSize(zcu) - int_info.bits);
24882482
2489 const shift_reg, const shift_lock = try self.allocReg(.int);2483 const shift_reg, const shift_lock = try func.allocReg(.int);
2490 defer self.register_manager.unlockReg(shift_lock);2484 defer func.register_manager.unlockReg(shift_lock);
24912485
2492 _ = try self.addInst(.{2486 _ = try func.addInst(.{
2493 .tag = .slli,2487 .tag = .slli,
2494 .ops = .rri,2488 .ops = .rri,
2495 .data = .{2489 .data = .{
...@@ -2501,7 +2495,7 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2501,7 +2495,7 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2501 },2495 },
2502 });2496 });
25032497
2504 _ = try self.addInst(.{2498 _ = try func.addInst(.{
2505 .tag = if (int_info.signedness == .unsigned) .srli else .srai,2499 .tag = if (int_info.signedness == .unsigned) .srli else .srai,
2506 .ops = .rri,2500 .ops = .rri,
2507 .data = .{2501 .data = .{
...@@ -2513,21 +2507,21 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2513,21 +2507,21 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2513 },2507 },
2514 });2508 });
25152509
2516 try self.genSetMem(2510 try func.genSetMem(
2517 .{ .frame = offset.index },2511 .{ .frame = offset.index },
2518 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),2512 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),
2519 lhs_ty,2513 lhs_ty,
2520 add_result,2514 add_result,
2521 );2515 );
25222516
2523 const overflow_mcv = try self.binOp(2517 const overflow_mcv = try func.binOp(
2524 .cmp_neq,2518 .cmp_neq,
2525 .{ .register = shift_reg },2519 .{ .register = shift_reg },
2526 lhs_ty,2520 lhs_ty,
2527 .{ .register = add_result_reg },2521 .{ .register = add_result_reg },
2528 lhs_ty,2522 lhs_ty,
2529 );2523 );
2530 try self.genSetMem(2524 try func.genSetMem(
2531 .{ .frame = offset.index },2525 .{ .frame = offset.index },
2532 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),2526 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2533 Type.u1,2527 Type.u1,
...@@ -2536,50 +2530,50 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2536,50 +2530,50 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
25362530
2537 break :result result_mcv;2531 break :result result_mcv;
2538 } else {2532 } else {
2539 return self.fail("TODO: less than 8 bit or non-pow 2 addition", .{});2533 return func.fail("TODO: less than 8 bit or non-pow 2 addition", .{});
2540 }2534 }
2541 };2535 };
25422536
2543 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2537 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2544}2538}
25452539
2546fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2540fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2547 const zcu = self.bin_file.comp.module.?;2541 const zcu = func.bin_file.comp.module.?;
2548 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2542 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2549 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2543 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
25502544
2551 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2545 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2552 const lhs = try self.resolveInst(extra.lhs);2546 const lhs = try func.resolveInst(extra.lhs);
2553 const rhs = try self.resolveInst(extra.rhs);2547 const rhs = try func.resolveInst(extra.rhs);
2554 const lhs_ty = self.typeOf(extra.lhs);2548 const lhs_ty = func.typeOf(extra.lhs);
2555 const rhs_ty = self.typeOf(extra.rhs);2549 const rhs_ty = func.typeOf(extra.rhs);
25562550
2557 const int_info = lhs_ty.intInfo(zcu);2551 const int_info = lhs_ty.intInfo(zcu);
25582552
2559 if (!math.isPowerOfTwo(int_info.bits) or !(int_info.bits >= 8)) {2553 if (!math.isPowerOfTwo(int_info.bits) or !(int_info.bits >= 8)) {
2560 return self.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{});2554 return func.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{});
2561 }2555 }
25622556
2563 const tuple_ty = self.typeOfIndex(inst);2557 const tuple_ty = func.typeOfIndex(inst);
2564 const result_mcv = try self.allocRegOrMem(inst, false);2558 const result_mcv = try func.allocRegOrMem(inst, false);
2565 const offset = result_mcv.load_frame;2559 const offset = result_mcv.load_frame;
25662560
2567 const lhs_reg, const lhs_lock = try self.promoteReg(lhs_ty, lhs, .{});2561 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2568 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);2562 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
25692563
2570 const rhs_reg, const rhs_lock = try self.promoteReg(rhs_ty, rhs, .{});2564 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2571 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);2565 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
25722566
2573 const dest_reg, const dest_lock = try self.allocReg(.int);2567 const dest_reg, const dest_lock = try func.allocReg(.int);
2574 defer self.register_manager.unlockReg(dest_lock);2568 defer func.register_manager.unlockReg(dest_lock);
25752569
2576 switch (int_info.signedness) {2570 switch (int_info.signedness) {
2577 .unsigned => return self.fail("TODO: airSubWithOverflow unsigned", .{}),2571 .unsigned => return func.fail("TODO: airSubWithOverflow unsigned", .{}),
2578 .signed => {2572 .signed => {
2579 switch (int_info.bits) {2573 switch (int_info.bits) {
2580 64 => {2574 64 => {
2581 // result2575 // result
2582 _ = try self.addInst(.{2576 _ = try func.addInst(.{
2583 .tag = .sub,2577 .tag = .sub,
2584 .ops = .rrr,2578 .ops = .rrr,
2585 .data = .{ .r_type = .{2579 .data = .{ .r_type = .{
...@@ -2589,7 +2583,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2589,7 +2583,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2589 } },2583 } },
2590 });2584 });
25912585
2592 try self.genSetMem(2586 try func.genSetMem(
2593 .{ .frame = offset.index },2587 .{ .frame = offset.index },
2594 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),2588 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),
2595 lhs_ty,2589 lhs_ty,
...@@ -2597,9 +2591,9 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2597,9 +2591,9 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2597 );2591 );
25982592
2599 // overflow check2593 // overflow check
2600 const overflow_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = 0 });2594 const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 });
26012595
2602 _ = try self.addInst(.{2596 _ = try func.addInst(.{
2603 .tag = .slt,2597 .tag = .slt,
2604 .ops = .rrr,2598 .ops = .rrr,
2605 .data = .{ .r_type = .{2599 .data = .{ .r_type = .{
...@@ -2609,7 +2603,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2609,7 +2603,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2609 } },2603 } },
2610 });2604 });
26112605
2612 _ = try self.addInst(.{2606 _ = try func.addInst(.{
2613 .tag = .slt,2607 .tag = .slt,
2614 .ops = .rrr,2608 .ops = .rrr,
2615 .data = .{ .r_type = .{2609 .data = .{ .r_type = .{
...@@ -2619,7 +2613,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2619,7 +2613,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2619 } },2613 } },
2620 });2614 });
26212615
2622 _ = try self.addInst(.{2616 _ = try func.addInst(.{
2623 .tag = .xor,2617 .tag = .xor,
2624 .ops = .rrr,2618 .ops = .rrr,
2625 .data = .{ .r_type = .{2619 .data = .{ .r_type = .{
...@@ -2629,7 +2623,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2629,7 +2623,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2629 } },2623 } },
2630 });2624 });
26312625
2632 const overflow_mcv = try self.binOp(2626 const overflow_mcv = try func.binOp(
2633 .cmp_neq,2627 .cmp_neq,
2634 .{ .register = overflow_reg },2628 .{ .register = overflow_reg },
2635 Type.usize,2629 Type.usize,
...@@ -2637,7 +2631,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2637,7 +2631,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2637 Type.usize,2631 Type.usize,
2638 );2632 );
26392633
2640 try self.genSetMem(2634 try func.genSetMem(
2641 .{ .frame = offset.index },2635 .{ .frame = offset.index },
2642 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),2636 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2643 Type.u1,2637 Type.u1,
...@@ -2646,47 +2640,47 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2646,47 +2640,47 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
26462640
2647 break :result result_mcv;2641 break :result result_mcv;
2648 },2642 },
2649 else => |int_bits| return self.fail("TODO: airSubWithOverflow signed {}", .{int_bits}),2643 else => |int_bits| return func.fail("TODO: airSubWithOverflow signed {}", .{int_bits}),
2650 }2644 }
2651 },2645 },
2652 }2646 }
2653 };2647 };
26542648
2655 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2649 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2656}2650}
26572651
2658fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2652fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2659 //const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];2653 //const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
2660 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2654 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2661 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2655 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
2662 const zcu = self.bin_file.comp.module.?;2656 const zcu = func.bin_file.comp.module.?;
2663 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2657 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2664 const lhs = try self.resolveInst(extra.lhs);2658 const lhs = try func.resolveInst(extra.lhs);
2665 const rhs = try self.resolveInst(extra.rhs);2659 const rhs = try func.resolveInst(extra.rhs);
2666 const lhs_ty = self.typeOf(extra.lhs);2660 const lhs_ty = func.typeOf(extra.lhs);
2667 const rhs_ty = self.typeOf(extra.rhs);2661 const rhs_ty = func.typeOf(extra.rhs);
26682662
2669 switch (lhs_ty.zigTypeTag(zcu)) {2663 switch (lhs_ty.zigTypeTag(zcu)) {
2670 else => |x| return self.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),2664 else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}),
2671 .Int => {2665 .Int => {
2672 assert(lhs_ty.eql(rhs_ty, zcu));2666 assert(lhs_ty.eql(rhs_ty, zcu));
2673 const int_info = lhs_ty.intInfo(zcu);2667 const int_info = lhs_ty.intInfo(zcu);
2674 switch (int_info.bits) {2668 switch (int_info.bits) {
2675 1...32 => {2669 1...32 => {
2676 if (self.hasFeature(.m)) {2670 if (func.hasFeature(.m)) {
2677 const dest = try self.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);2671 const dest = try func.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty);
26782672
2679 const add_result_lock = self.register_manager.lockRegAssumeUnused(dest.register);2673 const add_result_lock = func.register_manager.lockRegAssumeUnused(dest.register);
2680 defer self.register_manager.unlockReg(add_result_lock);2674 defer func.register_manager.unlockReg(add_result_lock);
26812675
2682 const tuple_ty = self.typeOfIndex(inst);2676 const tuple_ty = func.typeOfIndex(inst);
26832677
2684 const result_mcv = try self.allocRegOrMem(inst, true);2678 const result_mcv = try func.allocRegOrMem(inst, true);
26852679
2686 const result_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));2680 const result_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));
2687 const overflow_off: i32 = @intCast(tuple_ty.structFieldOffset(1, zcu));2681 const overflow_off: i32 = @intCast(tuple_ty.structFieldOffset(1, zcu));
26882682
2689 try self.genCopy(2683 try func.genCopy(
2690 lhs_ty,2684 lhs_ty,
2691 result_mcv.offset(result_off),2685 result_mcv.offset(result_off),
2692 dest,2686 dest,
...@@ -2698,13 +2692,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2698,13 +2692,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2698 1...8 => {2692 1...8 => {
2699 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;2693 const max_val = std.math.pow(u16, 2, int_info.bits) - 1;
27002694
2701 const add_reg, const add_lock = try self.promoteReg(lhs_ty, lhs, .{});2695 const add_reg, const add_lock = try func.promoteReg(lhs_ty, lhs, .{});
2702 defer if (add_lock) |lock| self.register_manager.unlockReg(lock);2696 defer if (add_lock) |lock| func.register_manager.unlockReg(lock);
27032697
2704 const overflow_reg, const overflow_lock = try self.allocReg(.int);2698 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2705 defer self.register_manager.unlockReg(overflow_lock);2699 defer func.register_manager.unlockReg(overflow_lock);
27062700
2707 _ = try self.addInst(.{2701 _ = try func.addInst(.{
2708 .tag = .andi,2702 .tag = .andi,
2709 .ops = .rri,2703 .ops = .rri,
2710 .data = .{ .i_type = .{2704 .data = .{ .i_type = .{
...@@ -2714,7 +2708,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2714,7 +2708,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2714 } },2708 } },
2715 });2709 });
27162710
2717 const overflow_mcv = try self.binOp(2711 const overflow_mcv = try func.binOp(
2718 .cmp_neq,2712 .cmp_neq,
2719 .{ .register = overflow_reg },2713 .{ .register = overflow_reg },
2720 lhs_ty,2714 lhs_ty,
...@@ -2722,7 +2716,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2722,7 +2716,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2722 lhs_ty,2716 lhs_ty,
2723 );2717 );
27242718
2725 try self.genCopy(2719 try func.genCopy(
2726 lhs_ty,2720 lhs_ty,
2727 result_mcv.offset(overflow_off),2721 result_mcv.offset(overflow_off),
2728 overflow_mcv,2722 overflow_mcv,
...@@ -2731,63 +2725,63 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2731,63 +2725,63 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2731 break :result result_mcv;2725 break :result result_mcv;
2732 },2726 },
27332727
2734 else => return self.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),2728 else => return func.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}),
2735 }2729 }
2736 } else {2730 } else {
2737 return self.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});2731 return func.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{});
2738 }2732 }
2739 } else {2733 } else {
2740 return self.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});2734 return func.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{});
2741 }2735 }
2742 } else {2736 } else {
2743 return self.fail("TODO: emulate mul for targets without M feature", .{});2737 return func.fail("TODO: emulate mul for targets without M feature", .{});
2744 }2738 }
2745 },2739 },
2746 else => return self.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),2740 else => return func.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}),
2747 }2741 }
2748 },2742 },
2749 }2743 }
2750 };2744 };
27512745
2752 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2746 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2753}2747}
27542748
2755fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2749fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2756 _ = inst;2750 _ = inst;
2757 return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch});2751 return func.fail("TODO implement airShlWithOverflow for {}", .{func.target.cpu.arch});
2758}2752}
27592753
2760fn airRem(self: *Self, inst: Air.Inst.Index) !void {2754fn airRem(func: *Func, inst: Air.Inst.Index) !void {
2761 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2755 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2762 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch});2756 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement rem for {}", .{func.target.cpu.arch});
2763 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2757 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2764}2758}
27652759
2766fn airMod(self: *Self, inst: Air.Inst.Index) !void {2760fn airMod(func: *Func, inst: Air.Inst.Index) !void {
2767 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2761 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2768 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement zcu for {}", .{self.target.cpu.arch});2762 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement zcu for {}", .{func.target.cpu.arch});
2769 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2763 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2770}2764}
27712765
2772fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {2766fn airBitAnd(func: *Func, inst: Air.Inst.Index) !void {
2773 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2767 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2774 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2768 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2775 const lhs = try self.resolveInst(bin_op.lhs);2769 const lhs = try func.resolveInst(bin_op.lhs);
2776 const rhs = try self.resolveInst(bin_op.rhs);2770 const rhs = try func.resolveInst(bin_op.rhs);
27772771
2778 const lhs_ty = self.typeOf(bin_op.lhs);2772 const lhs_ty = func.typeOf(bin_op.lhs);
2779 const rhs_ty = self.typeOf(bin_op.rhs);2773 const rhs_ty = func.typeOf(bin_op.rhs);
27802774
2781 const lhs_reg, const lhs_lock = try self.promoteReg(lhs_ty, lhs, .{});2775 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2782 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);2776 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
27832777
2784 const rhs_reg, const rhs_lock = try self.promoteReg(rhs_ty, rhs, .{});2778 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2785 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);2779 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
27862780
2787 const dest_reg, const dest_lock = try self.allocReg(.int);2781 const dest_reg, const dest_lock = try func.allocReg(.int);
2788 defer self.register_manager.unlockReg(dest_lock);2782 defer func.register_manager.unlockReg(dest_lock);
27892783
2790 _ = try self.addInst(.{2784 _ = try func.addInst(.{
2791 .tag = .@"and",2785 .tag = .@"and",
2792 .ops = .rrr,2786 .ops = .rrr,
2793 .data = .{ .r_type = .{2787 .data = .{ .r_type = .{
...@@ -2799,28 +2793,28 @@ fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {...@@ -2799,28 +2793,28 @@ fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
27992793
2800 break :result .{ .register = dest_reg };2794 break :result .{ .register = dest_reg };
2801 };2795 };
2802 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2796 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2803}2797}
28042798
2805fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {2799fn airBitOr(func: *Func, inst: Air.Inst.Index) !void {
2806 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2800 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2807 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2801 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2808 const lhs = try self.resolveInst(bin_op.lhs);2802 const lhs = try func.resolveInst(bin_op.lhs);
2809 const rhs = try self.resolveInst(bin_op.rhs);2803 const rhs = try func.resolveInst(bin_op.rhs);
28102804
2811 const lhs_ty = self.typeOf(bin_op.lhs);2805 const lhs_ty = func.typeOf(bin_op.lhs);
2812 const rhs_ty = self.typeOf(bin_op.rhs);2806 const rhs_ty = func.typeOf(bin_op.rhs);
28132807
2814 const lhs_reg, const lhs_lock = try self.promoteReg(lhs_ty, lhs, .{});2808 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
2815 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);2809 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
28162810
2817 const rhs_reg, const rhs_lock = try self.promoteReg(rhs_ty, rhs, .{});2811 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
2818 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);2812 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
28192813
2820 const dest_reg, const dest_lock = try self.allocReg(.int);2814 const dest_reg, const dest_lock = try func.allocReg(.int);
2821 defer self.register_manager.unlockReg(dest_lock);2815 defer func.register_manager.unlockReg(dest_lock);
28222816
2823 _ = try self.addInst(.{2817 _ = try func.addInst(.{
2824 .tag = .@"or",2818 .tag = .@"or",
2825 .ops = .rrr,2819 .ops = .rrr,
2826 .data = .{ .r_type = .{2820 .data = .{ .r_type = .{
...@@ -2832,72 +2826,72 @@ fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2832,72 +2826,72 @@ fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
28322826
2833 break :result .{ .register = dest_reg };2827 break :result .{ .register = dest_reg };
2834 };2828 };
2835 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2829 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2836}2830}
28372831
2838fn airXor(self: *Self, inst: Air.Inst.Index) !void {2832fn airXor(func: *Func, inst: Air.Inst.Index) !void {
2839 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2833 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2840 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement xor for {}", .{self.target.cpu.arch});2834 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement xor for {}", .{func.target.cpu.arch});
2841 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2835 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2842}2836}
28432837
2844fn airShl(self: *Self, inst: Air.Inst.Index) !void {2838fn airShl(func: *Func, inst: Air.Inst.Index) !void {
2845 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2839 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2846 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2840 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2847 const lhs = try self.resolveInst(bin_op.lhs);2841 const lhs = try func.resolveInst(bin_op.lhs);
2848 const rhs = try self.resolveInst(bin_op.rhs);2842 const rhs = try func.resolveInst(bin_op.rhs);
2849 const lhs_ty = self.typeOf(bin_op.lhs);2843 const lhs_ty = func.typeOf(bin_op.lhs);
2850 const rhs_ty = self.typeOf(bin_op.rhs);2844 const rhs_ty = func.typeOf(bin_op.rhs);
28512845
2852 break :result try self.binOp(.shl, lhs, lhs_ty, rhs, rhs_ty);2846 break :result try func.binOp(.shl, lhs, lhs_ty, rhs, rhs_ty);
2853 };2847 };
2854 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2848 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2855}2849}
28562850
2857fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {2851fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {
2858 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2852 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2859 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});2853 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement shl_sat for {}", .{func.target.cpu.arch});
2860 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2854 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2861}2855}
28622856
2863fn airShr(self: *Self, inst: Air.Inst.Index) !void {2857fn airShr(func: *Func, inst: Air.Inst.Index) !void {
2864 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2858 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2865 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {2859 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2866 const lhs = try self.resolveInst(bin_op.lhs);2860 const lhs = try func.resolveInst(bin_op.lhs);
2867 const rhs = try self.resolveInst(bin_op.rhs);2861 const rhs = try func.resolveInst(bin_op.rhs);
2868 const lhs_ty = self.typeOf(bin_op.lhs);2862 const lhs_ty = func.typeOf(bin_op.lhs);
2869 const rhs_ty = self.typeOf(bin_op.rhs);2863 const rhs_ty = func.typeOf(bin_op.rhs);
28702864
2871 break :result try self.binOp(.shr, lhs, lhs_ty, rhs, rhs_ty);2865 break :result try func.binOp(.shr, lhs, lhs_ty, rhs, rhs_ty);
2872 };2866 };
2873 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2867 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2874}2868}
28752869
2876fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {2870fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void {
2877 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2871 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2878 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .optional_payload for {}", .{self.target.cpu.arch});2872 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .optional_payload for {}", .{func.target.cpu.arch});
2879 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2873 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2880}2874}
28812875
2882fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {2876fn airOptionalPayloadPtr(func: *Func, inst: Air.Inst.Index) !void {
2883 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2877 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2884 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .optional_payload_ptr for {}", .{self.target.cpu.arch});2878 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .optional_payload_ptr for {}", .{func.target.cpu.arch});
2885 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2879 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2886}2880}
28872881
2888fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {2882fn airOptionalPayloadPtrSet(func: *Func, inst: Air.Inst.Index) !void {
2889 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2883 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2890 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .optional_payload_ptr_set for {}", .{self.target.cpu.arch});2884 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .optional_payload_ptr_set for {}", .{func.target.cpu.arch});
2891 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2885 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2892}2886}
28932887
2894fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {2888fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void {
2895 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2889 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2896 const zcu = self.bin_file.comp.module.?;2890 const zcu = func.bin_file.comp.module.?;
2897 const err_union_ty = self.typeOf(ty_op.operand);2891 const err_union_ty = func.typeOf(ty_op.operand);
2898 const err_ty = err_union_ty.errorUnionSet(zcu);2892 const err_ty = err_union_ty.errorUnionSet(zcu);
2899 const payload_ty = err_union_ty.errorUnionPayload(zcu);2893 const payload_ty = err_union_ty.errorUnionPayload(zcu);
2900 const operand = try self.resolveInst(ty_op.operand);2894 const operand = try func.resolveInst(ty_op.operand);
29012895
2902 const result: MCValue = result: {2896 const result: MCValue = result: {
2903 if (err_ty.errorSetIsEmpty(zcu)) {2897 if (err_ty.errorSetIsEmpty(zcu)) {
...@@ -2912,13 +2906,13 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2912,13 +2906,13 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
29122906
2913 switch (operand) {2907 switch (operand) {
2914 .register => |reg| {2908 .register => |reg| {
2915 const eu_lock = self.register_manager.lockReg(reg);2909 const eu_lock = func.register_manager.lockReg(reg);
2916 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);2910 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
29172911
2918 var result = try self.copyToNewRegister(inst, operand);2912 var result = try func.copyToNewRegister(inst, operand);
29192913
2920 if (err_off > 0) {2914 if (err_off > 0) {
2921 result = try self.binOp(2915 result = try func.binOp(
2922 .shr,2916 .shr,
2923 result,2917 result,
2924 err_union_ty,2918 err_union_ty,
...@@ -2932,27 +2926,27 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2932,27 +2926,27 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2932 .index = frame_addr.index,2926 .index = frame_addr.index,
2933 .off = frame_addr.off + @as(i32, @intCast(err_off)),2927 .off = frame_addr.off + @as(i32, @intCast(err_off)),
2934 } },2928 } },
2935 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),2929 else => return func.fail("TODO implement unwrap_err_err for {}", .{operand}),
2936 }2930 }
2937 };2931 };
29382932
2939 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2933 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2940}2934}
29412935
2942fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {2936fn airUnwrapErrPayload(func: *Func, inst: Air.Inst.Index) !void {
2943 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2937 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2944 const operand_ty = self.typeOf(ty_op.operand);2938 const operand_ty = func.typeOf(ty_op.operand);
2945 const operand = try self.resolveInst(ty_op.operand);2939 const operand = try func.resolveInst(ty_op.operand);
2946 const result = try self.genUnwrapErrUnionPayloadMir(operand_ty, operand);2940 const result = try func.genUnwrapErrUnionPayloadMir(operand_ty, operand);
2947 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2941 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2948}2942}
29492943
2950fn genUnwrapErrUnionPayloadMir(2944fn genUnwrapErrUnionPayloadMir(
2951 self: *Self,2945 func: *Func,
2952 err_union_ty: Type,2946 err_union_ty: Type,
2953 err_union: MCValue,2947 err_union: MCValue,
2954) !MCValue {2948) !MCValue {
2955 const zcu = self.bin_file.comp.module.?;2949 const zcu = func.bin_file.comp.module.?;
2956 const payload_ty = err_union_ty.errorUnionPayload(zcu);2950 const payload_ty = err_union_ty.errorUnionPayload(zcu);
29572951
2958 const result: MCValue = result: {2952 const result: MCValue = result: {
...@@ -2965,13 +2959,13 @@ fn genUnwrapErrUnionPayloadMir(...@@ -2965,13 +2959,13 @@ fn genUnwrapErrUnionPayloadMir(
2965 .off = frame_addr.off + payload_off,2959 .off = frame_addr.off + payload_off,
2966 } },2960 } },
2967 .register => |reg| {2961 .register => |reg| {
2968 const eu_lock = self.register_manager.lockReg(reg);2962 const eu_lock = func.register_manager.lockReg(reg);
2969 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);2963 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
29702964
2971 var result: MCValue = .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };2965 var result: MCValue = .{ .register = try func.copyToTmpRegister(err_union_ty, err_union) };
29722966
2973 if (payload_off > 0) {2967 if (payload_off > 0) {
2974 result = try self.binOp(2968 result = try func.binOp(
2975 .shr,2969 .shr,
2976 result,2970 result,
2977 err_union_ty,2971 err_union_ty,
...@@ -2982,7 +2976,7 @@ fn genUnwrapErrUnionPayloadMir(...@@ -2982,7 +2976,7 @@ fn genUnwrapErrUnionPayloadMir(
29822976
2983 break :result result;2977 break :result result;
2984 },2978 },
2985 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),2979 else => return func.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),
2986 }2980 }
2987 };2981 };
29882982
...@@ -2990,116 +2984,116 @@ fn genUnwrapErrUnionPayloadMir(...@@ -2990,116 +2984,116 @@ fn genUnwrapErrUnionPayloadMir(
2990}2984}
29912985
2992// *(E!T) -> E2986// *(E!T) -> E
2993fn airUnwrapErrErrPtr(self: *Self, inst: Air.Inst.Index) !void {2987fn airUnwrapErrErrPtr(func: *Func, inst: Air.Inst.Index) !void {
2994 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2988 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2995 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement unwrap error union error ptr for {}", .{self.target.cpu.arch});2989 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement unwrap error union error ptr for {}", .{func.target.cpu.arch});
2996 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2990 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2997}2991}
29982992
2999// *(E!T) -> *T2993// *(E!T) -> *T
3000fn airUnwrapErrPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {2994fn airUnwrapErrPayloadPtr(func: *Func, inst: Air.Inst.Index) !void {
3001 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2995 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3002 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement unwrap error union payload ptr for {}", .{self.target.cpu.arch});2996 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement unwrap error union payload ptr for {}", .{func.target.cpu.arch});
3003 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2997 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3004}2998}
30052999
3006fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {3000fn airErrUnionPayloadPtrSet(func: *Func, inst: Air.Inst.Index) !void {
3007 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3001 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3008 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement .errunion_payload_ptr_set for {}", .{self.target.cpu.arch});3002 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .errunion_payload_ptr_set for {}", .{func.target.cpu.arch});
3009 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3003 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3010}3004}
30113005
3012fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {3006fn airErrReturnTrace(func: *Func, inst: Air.Inst.Index) !void {
3013 const result: MCValue = if (self.liveness.isUnused(inst))3007 const result: MCValue = if (func.liveness.isUnused(inst))
3014 .unreach3008 .unreach
3015 else3009 else
3016 return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch});3010 return func.fail("TODO implement airErrReturnTrace for {}", .{func.target.cpu.arch});
3017 return self.finishAir(inst, result, .{ .none, .none, .none });3011 return func.finishAir(inst, result, .{ .none, .none, .none });
3018}3012}
30193013
3020fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {3014fn airSetErrReturnTrace(func: *Func, inst: Air.Inst.Index) !void {
3021 _ = inst;3015 _ = inst;
3022 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});3016 return func.fail("TODO implement airSetErrReturnTrace for {}", .{func.target.cpu.arch});
3023}3017}
30243018
3025fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {3019fn airSaveErrReturnTraceIndex(func: *Func, inst: Air.Inst.Index) !void {
3026 _ = inst;3020 _ = inst;
3027 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});3021 return func.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{func.target.cpu.arch});
3028}3022}
30293023
3030fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {3024fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void {
3031 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3025 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3032 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3026 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3033 const zcu = self.bin_file.comp.module.?;3027 const zcu = func.bin_file.comp.module.?;
3034 const optional_ty = self.typeOfIndex(inst);3028 const optional_ty = func.typeOfIndex(inst);
30353029
3036 // Optional with a zero-bit payload type is just a boolean true3030 // Optional with a zero-bit payload type is just a boolean true
3037 if (optional_ty.abiSize(zcu) == 1)3031 if (optional_ty.abiSize(zcu) == 1)
3038 break :result MCValue{ .immediate = 1 };3032 break :result MCValue{ .immediate = 1 };
30393033
3040 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});3034 return func.fail("TODO implement wrap optional for {}", .{func.target.cpu.arch});
3041 };3035 };
3042 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3036 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3043}3037}
30443038
3045/// T to E!T3039/// T to E!T
3046fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {3040fn airWrapErrUnionPayload(func: *Func, inst: Air.Inst.Index) !void {
3047 const zcu = self.bin_file.comp.module.?;3041 const zcu = func.bin_file.comp.module.?;
3048 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3042 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
30493043
3050 const eu_ty = ty_op.ty.toType();3044 const eu_ty = ty_op.ty.toType();
3051 const pl_ty = eu_ty.errorUnionPayload(zcu);3045 const pl_ty = eu_ty.errorUnionPayload(zcu);
3052 const err_ty = eu_ty.errorUnionSet(zcu);3046 const err_ty = eu_ty.errorUnionSet(zcu);
3053 const operand = try self.resolveInst(ty_op.operand);3047 const operand = try func.resolveInst(ty_op.operand);
30543048
3055 const result: MCValue = result: {3049 const result: MCValue = result: {
3056 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 };3050 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 };
30573051
3058 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));3052 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
3059 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));3053 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
3060 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));3054 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
3061 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);3055 try func.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
3062 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });3056 try func.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });
3063 break :result .{ .load_frame = .{ .index = frame_index } };3057 break :result .{ .load_frame = .{ .index = frame_index } };
3064 };3058 };
30653059
3066 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3060 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3067}3061}
30683062
3069/// E to E!T3063/// E to E!T
3070fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {3064fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void {
3071 const zcu = self.bin_file.comp.module.?;3065 const zcu = func.bin_file.comp.module.?;
3072 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3066 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
30733067
3074 const eu_ty = ty_op.ty.toType();3068 const eu_ty = ty_op.ty.toType();
3075 const pl_ty = eu_ty.errorUnionPayload(zcu);3069 const pl_ty = eu_ty.errorUnionPayload(zcu);
3076 const err_ty = eu_ty.errorUnionSet(zcu);3070 const err_ty = eu_ty.errorUnionSet(zcu);
30773071
3078 const result: MCValue = result: {3072 const result: MCValue = result: {
3079 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try self.resolveInst(ty_op.operand);3073 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try func.resolveInst(ty_op.operand);
30803074
3081 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));3075 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
3082 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));3076 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
3083 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));3077 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
3084 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);3078 try func.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);
3085 const operand = try self.resolveInst(ty_op.operand);3079 const operand = try func.resolveInst(ty_op.operand);
3086 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand);3080 try func.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand);
3087 break :result .{ .load_frame = .{ .index = frame_index } };3081 break :result .{ .load_frame = .{ .index = frame_index } };
3088 };3082 };
3089 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3083 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3090}3084}
30913085
3092fn airTry(self: *Self, inst: Air.Inst.Index) !void {3086fn airTry(func: *Func, inst: Air.Inst.Index) !void {
3093 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;3087 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
3094 const extra = self.air.extraData(Air.Try, pl_op.payload);3088 const extra = func.air.extraData(Air.Try, pl_op.payload);
3095 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);3089 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]);
3096 const operand_ty = self.typeOf(pl_op.operand);3090 const operand_ty = func.typeOf(pl_op.operand);
3097 const result = try self.genTry(inst, pl_op.operand, body, operand_ty, false);3091 const result = try func.genTry(inst, pl_op.operand, body, operand_ty, false);
3098 return self.finishAir(inst, result, .{ .none, .none, .none });3092 return func.finishAir(inst, result, .{ .none, .none, .none });
3099}3093}
31003094
3101fn genTry(3095fn genTry(
3102 self: *Self,3096 func: *Func,
3103 inst: Air.Inst.Index,3097 inst: Air.Inst.Index,
3104 operand: Air.Inst.Ref,3098 operand: Air.Inst.Ref,
3105 body: []const Air.Inst.Index,3099 body: []const Air.Inst.Index,
...@@ -3108,180 +3102,180 @@ fn genTry(...@@ -3108,180 +3102,180 @@ fn genTry(
3108) !MCValue {3102) !MCValue {
3109 _ = operand_is_ptr;3103 _ = operand_is_ptr;
31103104
3111 const liveness_cond_br = self.liveness.getCondBr(inst);3105 const liveness_cond_br = func.liveness.getCondBr(inst);
31123106
3113 const operand_mcv = try self.resolveInst(operand);3107 const operand_mcv = try func.resolveInst(operand);
3114 const is_err_mcv = try self.isErr(null, operand_ty, operand_mcv);3108 const is_err_mcv = try func.isErr(null, operand_ty, operand_mcv);
31153109
3116 // A branch to the false section. Uses beq. 1 is the default "true" state.3110 // A branch to the false section. Uses beq. 1 is the default "true" state.
3117 const reloc = try self.condBr(Type.anyerror, is_err_mcv);3111 const reloc = try func.condBr(Type.anyerror, is_err_mcv);
31183112
3119 if (self.liveness.operandDies(inst, 0)) {3113 if (func.liveness.operandDies(inst, 0)) {
3120 if (operand.toIndex()) |operand_inst| try self.processDeath(operand_inst);3114 if (operand.toIndex()) |operand_inst| try func.processDeath(operand_inst);
3121 }3115 }
31223116
3123 self.scope_generation += 1;3117 func.scope_generation += 1;
3124 const state = try self.saveState();3118 const state = try func.saveState();
31253119
3126 for (liveness_cond_br.else_deaths) |death| try self.processDeath(death);3120 for (liveness_cond_br.else_deaths) |death| try func.processDeath(death);
3127 try self.genBody(body);3121 try func.genBody(body);
3128 try self.restoreState(state, &.{}, .{3122 try func.restoreState(state, &.{}, .{
3129 .emit_instructions = false,3123 .emit_instructions = false,
3130 .update_tracking = true,3124 .update_tracking = true,
3131 .resurrect = true,3125 .resurrect = true,
3132 .close_scope = true,3126 .close_scope = true,
3133 });3127 });
31343128
3135 self.performReloc(reloc);3129 func.performReloc(reloc);
31363130
3137 for (liveness_cond_br.then_deaths) |death| try self.processDeath(death);3131 for (liveness_cond_br.then_deaths) |death| try func.processDeath(death);
31383132
3139 const result = if (self.liveness.isUnused(inst))3133 const result = if (func.liveness.isUnused(inst))
3140 .unreach3134 .unreach
3141 else3135 else
3142 try self.genUnwrapErrUnionPayloadMir(operand_ty, operand_mcv);3136 try func.genUnwrapErrUnionPayloadMir(operand_ty, operand_mcv);
31433137
3144 return result;3138 return result;
3145}3139}
31463140
3147fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {3141fn airSlicePtr(func: *Func, inst: Air.Inst.Index) !void {
3148 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3142 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3149 const result = result: {3143 const result = result: {
3150 const src_mcv = try self.resolveInst(ty_op.operand);3144 const src_mcv = try func.resolveInst(ty_op.operand);
3151 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;3145 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
31523146
3153 const dst_mcv = try self.allocRegOrMem(inst, true);3147 const dst_mcv = try func.allocRegOrMem(inst, true);
3154 const dst_ty = self.typeOfIndex(inst);3148 const dst_ty = func.typeOfIndex(inst);
3155 try self.genCopy(dst_ty, dst_mcv, src_mcv);3149 try func.genCopy(dst_ty, dst_mcv, src_mcv);
3156 break :result dst_mcv;3150 break :result dst_mcv;
3157 };3151 };
3158 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3152 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3159}3153}
31603154
3161fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {3155fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3162 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3156 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3163 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3157 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3164 const src_mcv = try self.resolveInst(ty_op.operand);3158 const src_mcv = try func.resolveInst(ty_op.operand);
3165 switch (src_mcv) {3159 switch (src_mcv) {
3166 .load_frame => |frame_addr| {3160 .load_frame => |frame_addr| {
3167 const len_mcv: MCValue = .{ .load_frame = .{3161 const len_mcv: MCValue = .{ .load_frame = .{
3168 .index = frame_addr.index,3162 .index = frame_addr.index,
3169 .off = frame_addr.off + 8,3163 .off = frame_addr.off + 8,
3170 } };3164 } };
3171 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3165 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
31723166
3173 const dst_mcv = try self.allocRegOrMem(inst, true);3167 const dst_mcv = try func.allocRegOrMem(inst, true);
3174 try self.genCopy(Type.usize, dst_mcv, len_mcv);3168 try func.genCopy(Type.usize, dst_mcv, len_mcv);
3175 break :result dst_mcv;3169 break :result dst_mcv;
3176 },3170 },
3177 .register_pair => |pair| {3171 .register_pair => |pair| {
3178 const len_mcv: MCValue = .{ .register = pair[1] };3172 const len_mcv: MCValue = .{ .register = pair[1] };
31793173
3180 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3174 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
31813175
3182 const dst_mcv = try self.allocRegOrMem(inst, true);3176 const dst_mcv = try func.allocRegOrMem(inst, true);
3183 try self.genCopy(Type.usize, dst_mcv, len_mcv);3177 try func.genCopy(Type.usize, dst_mcv, len_mcv);
3184 break :result dst_mcv;3178 break :result dst_mcv;
3185 },3179 },
3186 else => return self.fail("TODO airSliceLen for {}", .{src_mcv}),3180 else => return func.fail("TODO airSliceLen for {}", .{src_mcv}),
3187 }3181 }
3188 };3182 };
3189 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3183 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3190}3184}
31913185
3192fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {3186fn airPtrSliceLenPtr(func: *Func, inst: Air.Inst.Index) !void {
3193 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3187 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3194 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch});3188 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_len_ptr for {}", .{func.target.cpu.arch});
3195 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3189 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3196}3190}
31973191
3198fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {3192fn airPtrSlicePtrPtr(func: *Func, inst: Air.Inst.Index) !void {
3199 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3193 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3200 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch});3194 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_ptr_ptr for {}", .{func.target.cpu.arch});
3201 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3195 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3202}3196}
32033197
3204fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {3198fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void {
3205 const zcu = self.bin_file.comp.module.?;3199 const zcu = func.bin_file.comp.module.?;
3206 const is_volatile = false; // TODO3200 const is_volatile = false; // TODO
3207 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3201 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
32083202
3209 if (!is_volatile and self.liveness.isUnused(inst)) return self.finishAir(3203 if (!is_volatile and func.liveness.isUnused(inst)) return func.finishAir(
3210 inst,3204 inst,
3211 .unreach,3205 .unreach,
3212 .{ bin_op.lhs, bin_op.rhs, .none },3206 .{ bin_op.lhs, bin_op.rhs, .none },
3213 );3207 );
3214 const result: MCValue = result: {3208 const result: MCValue = result: {
3215 const slice_mcv = try self.resolveInst(bin_op.lhs);3209 const slice_mcv = try func.resolveInst(bin_op.lhs);
3216 const index_mcv = try self.resolveInst(bin_op.rhs);3210 const index_mcv = try func.resolveInst(bin_op.rhs);
32173211
3218 const slice_ty = self.typeOf(bin_op.lhs);3212 const slice_ty = func.typeOf(bin_op.lhs);
32193213
3220 const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu);3214 const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu);
32213215
3222 const index_lock: ?RegisterLock = if (index_mcv == .register)3216 const index_lock: ?RegisterLock = if (index_mcv == .register)
3223 self.register_manager.lockRegAssumeUnused(index_mcv.register)3217 func.register_manager.lockRegAssumeUnused(index_mcv.register)
3224 else3218 else
3225 null;3219 null;
3226 defer if (index_lock) |reg| self.register_manager.unlockReg(reg);3220 defer if (index_lock) |reg| func.register_manager.unlockReg(reg);
32273221
3228 const base_mcv: MCValue = switch (slice_mcv) {3222 const base_mcv: MCValue = switch (slice_mcv) {
3229 .load_frame,3223 .load_frame,
3230 .load_symbol,3224 .load_symbol,
3231 => .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, slice_mcv) },3225 => .{ .register = try func.copyToTmpRegister(slice_ptr_field_type, slice_mcv) },
3232 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),3226 else => return func.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),
3233 };3227 };
32343228
3235 const dest = try self.allocRegOrMem(inst, true);3229 const dest = try func.allocRegOrMem(inst, true);
3236 const addr = try self.binOp(.ptr_add, base_mcv, slice_ptr_field_type, index_mcv, Type.usize);3230 const addr = try func.binOp(.ptr_add, base_mcv, slice_ptr_field_type, index_mcv, Type.usize);
3237 try self.load(dest, addr, slice_ptr_field_type);3231 try func.load(dest, addr, slice_ptr_field_type);
32383232
3239 break :result dest;3233 break :result dest;
3240 };3234 };
3241 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3235 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3242}3236}
32433237
3244fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {3238fn airSliceElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3245 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3239 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3246 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;3240 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
3247 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch});3241 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement slice_elem_ptr for {}", .{func.target.cpu.arch});
3248 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });3242 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
3249}3243}
32503244
3251fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {3245fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3252 const zcu = self.bin_file.comp.module.?;3246 const zcu = func.bin_file.comp.module.?;
3253 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3247 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3254 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3248 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3255 const array_ty = self.typeOf(bin_op.lhs);3249 const array_ty = func.typeOf(bin_op.lhs);
3256 const array_mcv = try self.resolveInst(bin_op.lhs);3250 const array_mcv = try func.resolveInst(bin_op.lhs);
32573251
3258 const index_mcv = try self.resolveInst(bin_op.rhs);3252 const index_mcv = try func.resolveInst(bin_op.rhs);
3259 const index_ty = self.typeOf(bin_op.rhs);3253 const index_ty = func.typeOf(bin_op.rhs);
32603254
3261 const elem_ty = array_ty.childType(zcu);3255 const elem_ty = array_ty.childType(zcu);
3262 const elem_abi_size = elem_ty.abiSize(zcu);3256 const elem_abi_size = elem_ty.abiSize(zcu);
32633257
3264 const addr_reg, const addr_reg_lock = try self.allocReg(.int);3258 const addr_reg, const addr_reg_lock = try func.allocReg(.int);
3265 defer self.register_manager.unlockReg(addr_reg_lock);3259 defer func.register_manager.unlockReg(addr_reg_lock);
32663260
3267 switch (array_mcv) {3261 switch (array_mcv) {
3268 .register => {3262 .register => {
3269 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, zcu));3263 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, zcu));
3270 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);3264 try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);
3271 try self.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } });3265 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } });
3272 },3266 },
3273 .load_frame => |frame_addr| {3267 .load_frame => |frame_addr| {
3274 try self.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr });3268 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr });
3275 },3269 },
3276 else => try self.genSetReg(Type.usize, addr_reg, array_mcv.address()),3270 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),
3277 }3271 }
32783272
3279 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);3273 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
3280 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);3274 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3281 defer self.register_manager.unlockReg(offset_lock);3275 defer func.register_manager.unlockReg(offset_lock);
32823276
3283 const dst_mcv = try self.allocRegOrMem(inst, false);3277 const dst_mcv = try func.allocRegOrMem(inst, false);
3284 _ = try self.addInst(.{3278 _ = try func.addInst(.{
3285 .tag = .add,3279 .tag = .add,
3286 .ops = .rrr,3280 .ops = .rrr,
3287 .data = .{ .r_type = .{3281 .data = .{ .r_type = .{
...@@ -3290,138 +3284,138 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3290,138 +3284,138 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
3290 .rs2 = addr_reg,3284 .rs2 = addr_reg,
3291 } },3285 } },
3292 });3286 });
3293 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });3287 try func.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
3294 break :result dst_mcv;3288 break :result dst_mcv;
3295 };3289 };
3296 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3290 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3297}3291}
32983292
3299fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {3293fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void {
3300 const is_volatile = false; // TODO3294 const is_volatile = false; // TODO
3301 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3295 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3302 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement ptr_elem_val for {}", .{self.target.cpu.arch});3296 const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_elem_val for {}", .{func.target.cpu.arch});
3303 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3297 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3304}3298}
33053299
3306fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {3300fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3307 const zcu = self.bin_file.comp.module.?;3301 const zcu = func.bin_file.comp.module.?;
3308 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3302 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3309 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;3303 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
33103304
3311 const result = result: {3305 const result = result: {
3312 const elem_ptr_ty = self.typeOfIndex(inst);3306 const elem_ptr_ty = func.typeOfIndex(inst);
3313 const base_ptr_ty = self.typeOf(extra.lhs);3307 const base_ptr_ty = func.typeOf(extra.lhs);
33143308
3315 const base_ptr_mcv = try self.resolveInst(extra.lhs);3309 const base_ptr_mcv = try func.resolveInst(extra.lhs);
3316 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {3310 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
3317 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),3311 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3318 else => null,3312 else => null,
3319 };3313 };
3320 defer if (base_ptr_lock) |lock| self.register_manager.unlockReg(lock);3314 defer if (base_ptr_lock) |lock| func.register_manager.unlockReg(lock);
33213315
3322 if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {3316 if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {
3323 break :result if (self.reuseOperand(inst, extra.lhs, 0, base_ptr_mcv))3317 break :result if (func.reuseOperand(inst, extra.lhs, 0, base_ptr_mcv))
3324 base_ptr_mcv3318 base_ptr_mcv
3325 else3319 else
3326 try self.copyToNewRegister(inst, base_ptr_mcv);3320 try func.copyToNewRegister(inst, base_ptr_mcv);
3327 }3321 }
33283322
3329 const elem_ty = base_ptr_ty.elemType2(zcu);3323 const elem_ty = base_ptr_ty.elemType2(zcu);
3330 const elem_abi_size = elem_ty.abiSize(zcu);3324 const elem_abi_size = elem_ty.abiSize(zcu);
3331 const index_ty = self.typeOf(extra.rhs);3325 const index_ty = func.typeOf(extra.rhs);
3332 const index_mcv = try self.resolveInst(extra.rhs);3326 const index_mcv = try func.resolveInst(extra.rhs);
3333 const index_lock: ?RegisterLock = switch (index_mcv) {3327 const index_lock: ?RegisterLock = switch (index_mcv) {
3334 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),3328 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
3335 else => null,3329 else => null,
3336 };3330 };
3337 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);3331 defer if (index_lock) |lock| func.register_manager.unlockReg(lock);
33383332
3339 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);3333 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
3340 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);3334 const offset_reg_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3341 defer self.register_manager.unlockReg(offset_reg_lock);3335 defer func.register_manager.unlockReg(offset_reg_lock);
33423336
3343 break :result try self.binOp(.ptr_add, base_ptr_mcv, base_ptr_ty, .{ .register = offset_reg }, base_ptr_ty);3337 break :result try func.binOp(.ptr_add, base_ptr_mcv, base_ptr_ty, .{ .register = offset_reg }, base_ptr_ty);
3344 };3338 };
3345 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });3339 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
3346}3340}
33473341
3348fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {3342fn airSetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
3349 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3343 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3350 _ = bin_op;3344 _ = bin_op;
3351 return self.fail("TODO implement airSetUnionTag for {}", .{self.target.cpu.arch});3345 return func.fail("TODO implement airSetUnionTag for {}", .{func.target.cpu.arch});
3352 // return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3346 // return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3353}3347}
33543348
3355fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {3349fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
3356 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3350 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3357 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airGetUnionTag for {}", .{self.target.cpu.arch});3351 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airGetUnionTag for {}", .{func.target.cpu.arch});
3358 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3352 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3359}3353}
33603354
3361fn airClz(self: *Self, inst: Air.Inst.Index) !void {3355fn airClz(func: *Func, inst: Air.Inst.Index) !void {
3362 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3356 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3363 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airClz for {}", .{self.target.cpu.arch});3357 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airClz for {}", .{func.target.cpu.arch});
3364 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3358 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3365}3359}
33663360
3367fn airCtz(self: *Self, inst: Air.Inst.Index) !void {3361fn airCtz(func: *Func, inst: Air.Inst.Index) !void {
3368 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3362 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3369 _ = ty_op;3363 _ = ty_op;
3370 return self.fail("TODO: finish ctz", .{});3364 return func.fail("TODO: finish ctz", .{});
3371}3365}
33723366
3373fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {3367fn airPopcount(func: *Func, inst: Air.Inst.Index) !void {
3374 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3368 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3375 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch});3369 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airPopcount for {}", .{func.target.cpu.arch});
3376 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3370 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3377}3371}
33783372
3379fn airAbs(self: *Self, inst: Air.Inst.Index) !void {3373fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3380 const zcu = self.bin_file.comp.module.?;3374 const zcu = func.bin_file.comp.module.?;
3381 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3375 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3382 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3376 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3383 const ty = self.typeOf(ty_op.operand);3377 const ty = func.typeOf(ty_op.operand);
3384 const scalar_ty = ty.scalarType(zcu);3378 const scalar_ty = ty.scalarType(zcu);
3385 const operand = try self.resolveInst(ty_op.operand);3379 const operand = try func.resolveInst(ty_op.operand);
3386 _ = operand;3380 _ = operand;
33873381
3388 switch (scalar_ty.zigTypeTag(zcu)) {3382 switch (scalar_ty.zigTypeTag(zcu)) {
3389 .Int => if (ty.zigTypeTag(zcu) == .Vector) {3383 .Int => if (ty.zigTypeTag(zcu) == .Vector) {
3390 return self.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});3384 return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});
3391 } else {3385 } else {
3392 return self.fail("TODO: implement airAbs for Int", .{});3386 return func.fail("TODO: implement airAbs for Int", .{});
3393 },3387 },
3394 else => return self.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),3388 else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),
3395 }3389 }
33963390
3397 break :result .{.unreach};3391 break :result .{.unreach};
3398 };3392 };
3399 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3393 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3400}3394}
34013395
3402fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {3396fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {
3403 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3397 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3404 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3398 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3405 const zcu = self.bin_file.comp.module.?;3399 const zcu = func.bin_file.comp.module.?;
3406 const ty = self.typeOf(ty_op.operand);3400 const ty = func.typeOf(ty_op.operand);
3407 const operand = try self.resolveInst(ty_op.operand);3401 const operand = try func.resolveInst(ty_op.operand);
34083402
3409 const int_bits = ty.intInfo(zcu).bits;3403 const int_bits = ty.intInfo(zcu).bits;
34103404
3411 // bytes are no-op3405 // bytes are no-op
3412 if (int_bits == 8 and self.reuseOperand(inst, ty_op.operand, 0, operand)) {3406 if (int_bits == 8 and func.reuseOperand(inst, ty_op.operand, 0, operand)) {
3413 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });3407 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
3414 }3408 }
34153409
3416 const dest_mcv = try self.copyToNewRegister(inst, operand);3410 const dest_mcv = try func.copyToNewRegister(inst, operand);
3417 const dest_reg = dest_mcv.register;3411 const dest_reg = dest_mcv.register;
34183412
3419 switch (int_bits) {3413 switch (int_bits) {
3420 16 => {3414 16 => {
3421 const temp_reg, const temp_lock = try self.allocReg(.int);3415 const temp_reg, const temp_lock = try func.allocReg(.int);
3422 defer self.register_manager.unlockReg(temp_lock);3416 defer func.register_manager.unlockReg(temp_lock);
34233417
3424 _ = try self.addInst(.{3418 _ = try func.addInst(.{
3425 .tag = .srli,3419 .tag = .srli,
3426 .ops = .rri,3420 .ops = .rri,
3427 .data = .{ .i_type = .{3421 .data = .{ .i_type = .{
...@@ -3431,7 +3425,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {...@@ -3431,7 +3425,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
3431 } },3425 } },
3432 });3426 });
34333427
3434 _ = try self.addInst(.{3428 _ = try func.addInst(.{
3435 .tag = .slli,3429 .tag = .slli,
3436 .ops = .rri,3430 .ops = .rri,
3437 .data = .{ .i_type = .{3431 .data = .{ .i_type = .{
...@@ -3440,7 +3434,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {...@@ -3440,7 +3434,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
3440 .rs1 = dest_reg,3434 .rs1 = dest_reg,
3441 } },3435 } },
3442 });3436 });
3443 _ = try self.addInst(.{3437 _ = try func.addInst(.{
3444 .tag = .@"or",3438 .tag = .@"or",
3445 .ops = .rri,3439 .ops = .rri,
3446 .data = .{ .r_type = .{3440 .data = .{ .r_type = .{
...@@ -3450,49 +3444,49 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {...@@ -3450,49 +3444,49 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
3450 } },3444 } },
3451 });3445 });
3452 },3446 },
3453 else => return self.fail("TODO: {d} bits for airByteSwap", .{int_bits}),3447 else => return func.fail("TODO: {d} bits for airByteSwap", .{int_bits}),
3454 }3448 }
34553449
3456 break :result dest_mcv;3450 break :result dest_mcv;
3457 };3451 };
3458 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3452 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3459}3453}
34603454
3461fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {3455fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void {
3462 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3456 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3463 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airBitReverse for {}", .{self.target.cpu.arch});3457 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airBitReverse for {}", .{func.target.cpu.arch});
3464 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3458 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3465}3459}
34663460
3467fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {3461fn airUnaryMath(func: *Func, inst: Air.Inst.Index) !void {
3468 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];3462 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
3469 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;3463 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3470 const result: MCValue = if (self.liveness.isUnused(inst))3464 const result: MCValue = if (func.liveness.isUnused(inst))
3471 .unreach3465 .unreach
3472 else3466 else
3473 return self.fail("TODO implementairUnaryMath {s} for {}", .{ @tagName(tag), self.target.cpu.arch });3467 return func.fail("TODO implementairUnaryMath {s} for {}", .{ @tagName(tag), func.target.cpu.arch });
3474 return self.finishAir(inst, result, .{ un_op, .none, .none });3468 return func.finishAir(inst, result, .{ un_op, .none, .none });
3475}3469}
34763470
3477fn reuseOperand(3471fn reuseOperand(
3478 self: *Self,3472 func: *Func,
3479 inst: Air.Inst.Index,3473 inst: Air.Inst.Index,
3480 operand: Air.Inst.Ref,3474 operand: Air.Inst.Ref,
3481 op_index: Liveness.OperandInt,3475 op_index: Liveness.OperandInt,
3482 mcv: MCValue,3476 mcv: MCValue,
3483) bool {3477) bool {
3484 return self.reuseOperandAdvanced(inst, operand, op_index, mcv, inst);3478 return func.reuseOperandAdvanced(inst, operand, op_index, mcv, inst);
3485}3479}
34863480
3487fn reuseOperandAdvanced(3481fn reuseOperandAdvanced(
3488 self: *Self,3482 func: *Func,
3489 inst: Air.Inst.Index,3483 inst: Air.Inst.Index,
3490 operand: Air.Inst.Ref,3484 operand: Air.Inst.Ref,
3491 op_index: Liveness.OperandInt,3485 op_index: Liveness.OperandInt,
3492 mcv: MCValue,3486 mcv: MCValue,
3493 maybe_tracked_inst: ?Air.Inst.Index,3487 maybe_tracked_inst: ?Air.Inst.Index,
3494) bool {3488) bool {
3495 if (!self.liveness.operandDies(inst, op_index))3489 if (!func.liveness.operandDies(inst, op_index))
3496 return false;3490 return false;
34973491
3498 switch (mcv) {3492 switch (mcv) {
...@@ -3502,59 +3496,59 @@ fn reuseOperandAdvanced(...@@ -3502,59 +3496,59 @@ fn reuseOperandAdvanced(
3502 // If it's in the registers table, need to associate the register(s) with the3496 // If it's in the registers table, need to associate the register(s) with the
3503 // new instruction.3497 // new instruction.
3504 if (maybe_tracked_inst) |tracked_inst| {3498 if (maybe_tracked_inst) |tracked_inst| {
3505 if (!self.register_manager.isRegFree(reg)) {3499 if (!func.register_manager.isRegFree(reg)) {
3506 if (RegisterManager.indexOfRegIntoTracked(reg)) |index| {3500 if (RegisterManager.indexOfRegIntoTracked(reg)) |index| {
3507 self.register_manager.registers[index] = tracked_inst;3501 func.register_manager.registers[index] = tracked_inst;
3508 }3502 }
3509 }3503 }
3510 } else self.register_manager.freeReg(reg);3504 } else func.register_manager.freeReg(reg);
3511 },3505 },
3512 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,3506 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,
3513 else => return false,3507 else => return false,
3514 }3508 }
35153509
3516 // Prevent the operand deaths processing code from deallocating it.3510 // Prevent the operand deaths processing code from deallocating it.
3517 self.liveness.clearOperandDeath(inst, op_index);3511 func.liveness.clearOperandDeath(inst, op_index);
3518 const op_inst = operand.toIndex().?;3512 const op_inst = operand.toIndex().?;
3519 self.getResolvedInstValue(op_inst).reuse(self, maybe_tracked_inst, op_inst);3513 func.getResolvedInstValue(op_inst).reuse(func, maybe_tracked_inst, op_inst);
35203514
3521 return true;3515 return true;
3522}3516}
35233517
3524fn airLoad(self: *Self, inst: Air.Inst.Index) !void {3518fn airLoad(func: *Func, inst: Air.Inst.Index) !void {
3525 const zcu = self.bin_file.comp.module.?;3519 const zcu = func.bin_file.comp.module.?;
3526 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3520 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3527 const elem_ty = self.typeOfIndex(inst);3521 const elem_ty = func.typeOfIndex(inst);
35283522
3529 const result: MCValue = result: {3523 const result: MCValue = result: {
3530 if (!elem_ty.hasRuntimeBits(zcu))3524 if (!elem_ty.hasRuntimeBits(zcu))
3531 break :result .none;3525 break :result .none;
35323526
3533 const ptr = try self.resolveInst(ty_op.operand);3527 const ptr = try func.resolveInst(ty_op.operand);
3534 const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(zcu);3528 const is_volatile = func.typeOf(ty_op.operand).isVolatilePtr(zcu);
3535 if (self.liveness.isUnused(inst) and !is_volatile)3529 if (func.liveness.isUnused(inst) and !is_volatile)
3536 break :result .unreach;3530 break :result .unreach;
35373531
3538 const elem_size = elem_ty.abiSize(zcu);3532 const elem_size = elem_ty.abiSize(zcu);
35393533
3540 const dst_mcv: MCValue = blk: {3534 const dst_mcv: MCValue = blk: {
3541 // Pointer is 8 bytes, and if the element is more than that, we cannot reuse it.3535 // Pointer is 8 bytes, and if the element is more than that, we cannot reuse it.
3542 if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) {3536 if (elem_size <= 8 and func.reuseOperand(inst, ty_op.operand, 0, ptr)) {
3543 // The MCValue that holds the pointer can be re-used as the value.3537 // The MCValue that holds the pointer can be re-used as the value.
3544 break :blk ptr;3538 break :blk ptr;
3545 } else {3539 } else {
3546 break :blk try self.allocRegOrMem(inst, true);3540 break :blk try func.allocRegOrMem(inst, true);
3547 }3541 }
3548 };3542 };
35493543
3550 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));3544 try func.load(dst_mcv, ptr, func.typeOf(ty_op.operand));
3551 break :result dst_mcv;3545 break :result dst_mcv;
3552 };3546 };
3553 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3547 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3554}3548}
35553549
3556fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerError!void {3550fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerError!void {
3557 const zcu = self.bin_file.comp.module.?;3551 const zcu = func.bin_file.comp.module.?;
3558 const dst_ty = ptr_ty.childType(zcu);3552 const dst_ty = ptr_ty.childType(zcu);
35593553
3560 log.debug("loading {}:{} into {}", .{ ptr_mcv, ptr_ty.fmt(zcu), dst_mcv });3554 log.debug("loading {}:{} into {}", .{ ptr_mcv, ptr_ty.fmt(zcu), dst_mcv });
...@@ -3573,43 +3567,43 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro...@@ -3573,43 +3567,43 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
3573 .register_offset,3567 .register_offset,
3574 .lea_frame,3568 .lea_frame,
3575 .lea_symbol,3569 .lea_symbol,
3576 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),3570 => try func.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
35773571
3578 .memory,3572 .memory,
3579 .indirect,3573 .indirect,
3580 .load_symbol,3574 .load_symbol,
3581 .load_frame,3575 .load_frame,
3582 => {3576 => {
3583 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);3577 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);
3584 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3578 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);
3585 defer self.register_manager.unlockReg(addr_lock);3579 defer func.register_manager.unlockReg(addr_lock);
35863580
3587 try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });3581 try func.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
3588 },3582 },
3589 .air_ref => |ptr_ref| try self.load(dst_mcv, try self.resolveInst(ptr_ref), ptr_ty),3583 .air_ref => |ptr_ref| try func.load(dst_mcv, try func.resolveInst(ptr_ref), ptr_ty),
3590 }3584 }
3591}3585}
35923586
3593fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {3587fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
3594 if (safety) {3588 if (safety) {
3595 // TODO if the value is undef, write 0xaa bytes to dest3589 // TODO if the value is undef, write 0xaa bytes to dest
3596 } else {3590 } else {
3597 // TODO if the value is undef, don't lower this instruction3591 // TODO if the value is undef, don't lower this instruction
3598 }3592 }
3599 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3593 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3600 const ptr = try self.resolveInst(bin_op.lhs);3594 const ptr = try func.resolveInst(bin_op.lhs);
3601 const value = try self.resolveInst(bin_op.rhs);3595 const value = try func.resolveInst(bin_op.rhs);
3602 const ptr_ty = self.typeOf(bin_op.lhs);3596 const ptr_ty = func.typeOf(bin_op.lhs);
3603 const value_ty = self.typeOf(bin_op.rhs);3597 const value_ty = func.typeOf(bin_op.rhs);
36043598
3605 try self.store(ptr, value, ptr_ty, value_ty);3599 try func.store(ptr, value, ptr_ty, value_ty);
36063600
3607 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });3601 return func.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
3608}3602}
36093603
3610/// Loads `value` into the "payload" of `pointer`.3604/// Loads `value` into the "payload" of `pointer`.
3611fn store(self: *Self, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty: Type) !void {3605fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty: Type) !void {
3612 const zcu = self.bin_file.comp.module.?;3606 const zcu = func.bin_file.comp.module.?;
36133607
3614 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(zcu), ptr_mcv, ptr_ty.fmt(zcu) });3608 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(zcu), ptr_mcv, ptr_ty.fmt(zcu) });
36153609
...@@ -3626,40 +3620,40 @@ fn store(self: *Self, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:...@@ -3626,40 +3620,40 @@ fn store(self: *Self, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type, src_ty:
3626 .register_offset,3620 .register_offset,
3627 .lea_symbol,3621 .lea_symbol,
3628 .lea_frame,3622 .lea_frame,
3629 => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv),3623 => try func.genCopy(src_ty, ptr_mcv.deref(), src_mcv),
36303624
3631 .memory,3625 .memory,
3632 .indirect,3626 .indirect,
3633 .load_symbol,3627 .load_symbol,
3634 .load_frame,3628 .load_frame,
3635 => {3629 => {
3636 const addr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);3630 const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv);
3637 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);3631 const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg);
3638 defer self.register_manager.unlockReg(addr_lock);3632 defer func.register_manager.unlockReg(addr_lock);
36393633
3640 try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);3634 try func.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);
3641 },3635 },
3642 .air_ref => |ptr_ref| try self.store(try self.resolveInst(ptr_ref), src_mcv, ptr_ty, src_ty),3636 .air_ref => |ptr_ref| try func.store(try func.resolveInst(ptr_ref), src_mcv, ptr_ty, src_ty),
3643 }3637 }
3644}3638}
36453639
3646fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {3640fn airStructFieldPtr(func: *Func, inst: Air.Inst.Index) !void {
3647 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3641 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3648 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;3642 const extra = func.air.extraData(Air.StructField, ty_pl.payload).data;
3649 const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index);3643 const result = try func.structFieldPtr(inst, extra.struct_operand, extra.field_index);
3650 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });3644 return func.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
3651}3645}
36523646
3653fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {3647fn airStructFieldPtrIndex(func: *Func, inst: Air.Inst.Index, index: u8) !void {
3654 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3648 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3655 const result = try self.structFieldPtr(inst, ty_op.operand, index);3649 const result = try func.structFieldPtr(inst, ty_op.operand, index);
3656 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3650 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3657}3651}
36583652
3659fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {3653fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
3660 const zcu = self.bin_file.comp.module.?;3654 const zcu = func.bin_file.comp.module.?;
3661 const ptr_field_ty = self.typeOfIndex(inst);3655 const ptr_field_ty = func.typeOfIndex(inst);
3662 const ptr_container_ty = self.typeOf(operand);3656 const ptr_container_ty = func.typeOf(operand);
3663 const ptr_container_ty_info = ptr_container_ty.ptrInfo(zcu);3657 const ptr_container_ty_info = ptr_container_ty.ptrInfo(zcu);
3664 const container_ty = ptr_container_ty.childType(zcu);3658 const container_ty = ptr_container_ty.childType(zcu);
36653659
...@@ -3672,27 +3666,27 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -3672,27 +3666,27 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
3672 else3666 else
3673 @intCast(container_ty.structFieldOffset(index, zcu));3667 @intCast(container_ty.structFieldOffset(index, zcu));
36743668
3675 const src_mcv = try self.resolveInst(operand);3669 const src_mcv = try func.resolveInst(operand);
3676 const dst_mcv = if (switch (src_mcv) {3670 const dst_mcv = if (switch (src_mcv) {
3677 .immediate, .lea_frame => true,3671 .immediate, .lea_frame => true,
3678 .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),3672 .register, .register_offset => func.reuseOperand(inst, operand, 0, src_mcv),
3679 else => false,3673 else => false,
3680 }) src_mcv else try self.copyToNewRegister(inst, src_mcv);3674 }) src_mcv else try func.copyToNewRegister(inst, src_mcv);
3681 return dst_mcv.offset(field_offset);3675 return dst_mcv.offset(field_offset);
3682}3676}
36833677
3684fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {3678fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
3685 const mod = self.bin_file.comp.module.?;3679 const mod = func.bin_file.comp.module.?;
36863680
3687 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3681 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3688 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;3682 const extra = func.air.extraData(Air.StructField, ty_pl.payload).data;
3689 const operand = extra.struct_operand;3683 const operand = extra.struct_operand;
3690 const index = extra.field_index;3684 const index = extra.field_index;
36913685
3692 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3686 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3693 const zcu = self.bin_file.comp.module.?;3687 const zcu = func.bin_file.comp.module.?;
3694 const src_mcv = try self.resolveInst(operand);3688 const src_mcv = try func.resolveInst(operand);
3695 const struct_ty = self.typeOf(operand);3689 const struct_ty = func.typeOf(operand);
3696 const field_ty = struct_ty.structFieldType(index, zcu);3690 const field_ty = struct_ty.structFieldType(index, zcu);
3697 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;3691 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;
36983692
...@@ -3707,20 +3701,20 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3707,20 +3701,20 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3707 switch (src_mcv) {3701 switch (src_mcv) {
3708 .dead, .unreach => unreachable,3702 .dead, .unreach => unreachable,
3709 .register => |src_reg| {3703 .register => |src_reg| {
3710 const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);3704 const src_reg_lock = func.register_manager.lockRegAssumeUnused(src_reg);
3711 defer self.register_manager.unlockReg(src_reg_lock);3705 defer func.register_manager.unlockReg(src_reg_lock);
37123706
3713 const dst_reg = if (field_off == 0)3707 const dst_reg = if (field_off == 0)
3714 (try self.copyToNewRegister(inst, src_mcv)).register3708 (try func.copyToNewRegister(inst, src_mcv)).register
3715 else3709 else
3716 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });3710 try func.copyToTmpRegister(Type.usize, .{ .register = src_reg });
37173711
3718 const dst_mcv: MCValue = .{ .register = dst_reg };3712 const dst_mcv: MCValue = .{ .register = dst_reg };
3719 const dst_lock = self.register_manager.lockReg(dst_reg);3713 const dst_lock = func.register_manager.lockReg(dst_reg);
3720 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3714 defer if (dst_lock) |lock| func.register_manager.unlockReg(lock);
37213715
3722 if (field_off > 0) {3716 if (field_off > 0) {
3723 _ = try self.addInst(.{3717 _ = try func.addInst(.{
3724 .tag = .srli,3718 .tag = .srli,
3725 .ops = .rri,3719 .ops = .rri,
3726 .data = .{ .i_type = .{3720 .data = .{ .i_type = .{
...@@ -3731,7 +3725,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3731,7 +3725,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3731 });3725 });
3732 }3726 }
37333727
3734 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);3728 break :result if (field_off == 0) dst_mcv else try func.copyToNewRegister(inst, dst_mcv);
3735 },3729 },
3736 .load_frame => {3730 .load_frame => {
3737 const field_abi_size: u32 = @intCast(field_ty.abiSize(mod));3731 const field_abi_size: u32 = @intCast(field_ty.abiSize(mod));
...@@ -3746,57 +3740,57 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3746,57 +3740,57 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3746 @intCast(field_bit_size),3740 @intCast(field_bit_size),
3747 );3741 );
37483742
3749 const dst_reg, const dst_lock = try self.allocReg(.int);3743 const dst_reg, const dst_lock = try func.allocReg(.int);
3750 const dst_mcv = MCValue{ .register = dst_reg };3744 const dst_mcv = MCValue{ .register = dst_reg };
3751 defer self.register_manager.unlockReg(dst_lock);3745 defer func.register_manager.unlockReg(dst_lock);
37523746
3753 try self.genCopy(int_ty, dst_mcv, off_mcv);3747 try func.genCopy(int_ty, dst_mcv, off_mcv);
3754 break :result try self.copyToNewRegister(inst, dst_mcv);3748 break :result try func.copyToNewRegister(inst, dst_mcv);
3755 }3749 }
37563750
3757 const container_abi_size: u32 = @intCast(struct_ty.abiSize(mod));3751 const container_abi_size: u32 = @intCast(struct_ty.abiSize(mod));
3758 const dst_mcv = if (field_byte_off + field_abi_size <= container_abi_size and3752 const dst_mcv = if (field_byte_off + field_abi_size <= container_abi_size and
3759 self.reuseOperand(inst, operand, 0, src_mcv))3753 func.reuseOperand(inst, operand, 0, src_mcv))
3760 off_mcv3754 off_mcv
3761 else dst: {3755 else dst: {
3762 const dst_mcv = try self.allocRegOrMem(inst, true);3756 const dst_mcv = try func.allocRegOrMem(inst, true);
3763 try self.genCopy(field_ty, dst_mcv, off_mcv);3757 try func.genCopy(field_ty, dst_mcv, off_mcv);
3764 break :dst dst_mcv;3758 break :dst dst_mcv;
3765 };3759 };
3766 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {3760 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {
3767 const tmp_reg, const tmp_lock = try self.allocReg(.int);3761 const tmp_reg, const tmp_lock = try func.allocReg(.int);
3768 defer self.register_manager.unlockReg(tmp_lock);3762 defer func.register_manager.unlockReg(tmp_lock);
37693763
3770 const hi_mcv =3764 const hi_mcv =
3771 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();3765 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
3772 try self.genSetReg(Type.usize, tmp_reg, hi_mcv);3766 try func.genSetReg(Type.usize, tmp_reg, hi_mcv);
3773 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });3767 try func.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
3774 }3768 }
3775 break :result dst_mcv;3769 break :result dst_mcv;
3776 }3770 }
37773771
3778 return self.fail("TODO: airStructFieldVal load_frame field_off non multiple of 8", .{});3772 return func.fail("TODO: airStructFieldVal load_frame field_off non multiple of 8", .{});
3779 },3773 },
3780 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),3774 else => return func.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),
3781 }3775 }
3782 };3776 };
37833777
3784 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });3778 return func.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
3785}3779}
37863780
3787fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {3781fn airFieldParentPtr(func: *Func, inst: Air.Inst.Index) !void {
3788 _ = inst;3782 _ = inst;
3789 return self.fail("TODO implement codegen airFieldParentPtr", .{});3783 return func.fail("TODO implement codegen airFieldParentPtr", .{});
3790}3784}
37913785
3792fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {3786fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
3793 const zcu = self.bin_file.comp.module.?;3787 const zcu = func.bin_file.comp.module.?;
3794 const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;3788 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
3795 const ty = arg.ty.toType();3789 const ty = arg.ty.toType();
3796 const owner_decl = zcu.funcOwnerDeclIndex(self.func_index);3790 const owner_decl = zcu.funcOwnerDeclIndex(func.func_index);
3797 const name = zcu.getParamName(self.func_index, arg.src_index);3791 const name = zcu.getParamName(func.func_index, arg.src_index);
37983792
3799 switch (self.debug_output) {3793 switch (func.debug_output) {
3800 .dwarf => |dw| switch (mcv) {3794 .dwarf => |dw| switch (mcv) {
3801 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{3795 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
3802 .register = reg.dwarfLocOp(),3796 .register = reg.dwarfLocOp(),
...@@ -3809,100 +3803,100 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -3809,100 +3803,100 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3809 }3803 }
3810}3804}
38113805
3812fn airArg(self: *Self, inst: Air.Inst.Index) !void {3806fn airArg(func: *Func, inst: Air.Inst.Index) !void {
3813 var arg_index = self.arg_index;3807 var arg_index = func.arg_index;
38143808
3815 // we skip over args that have no bits3809 // we skip over args that have no bits
3816 while (self.args[arg_index] == .none) arg_index += 1;3810 while (func.args[arg_index] == .none) arg_index += 1;
3817 self.arg_index = arg_index + 1;3811 func.arg_index = arg_index + 1;
38183812
3819 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3813 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3820 const src_mcv = self.args[arg_index];3814 const src_mcv = func.args[arg_index];
3821 const arg_ty = self.typeOfIndex(inst);3815 const arg_ty = func.typeOfIndex(inst);
38223816
3823 const dst_mcv = try self.allocRegOrMem(inst, false);3817 const dst_mcv = try func.allocRegOrMem(inst, false);
38243818
3825 log.debug("airArg {} -> {}", .{ src_mcv, dst_mcv });3819 log.debug("airArg {} -> {}", .{ src_mcv, dst_mcv });
38263820
3827 try self.genCopy(arg_ty, dst_mcv, src_mcv);3821 try func.genCopy(arg_ty, dst_mcv, src_mcv);
38283822
3829 try self.genArgDbgInfo(inst, src_mcv);3823 try func.genArgDbgInfo(inst, src_mcv);
3830 break :result dst_mcv;3824 break :result dst_mcv;
3831 };3825 };
38323826
3833 return self.finishAir(inst, result, .{ .none, .none, .none });3827 return func.finishAir(inst, result, .{ .none, .none, .none });
3834}3828}
38353829
3836fn airTrap(self: *Self) !void {3830fn airTrap(func: *Func) !void {
3837 _ = try self.addInst(.{3831 _ = try func.addInst(.{
3838 .tag = .unimp,3832 .tag = .unimp,
3839 .ops = .none,3833 .ops = .none,
3840 .data = undefined,3834 .data = undefined,
3841 });3835 });
3842 return self.finishAirBookkeeping();3836 return func.finishAirBookkeeping();
3843}3837}
38443838
3845fn airBreakpoint(self: *Self) !void {3839fn airBreakpoint(func: *Func) !void {
3846 _ = try self.addInst(.{3840 _ = try func.addInst(.{
3847 .tag = .ebreak,3841 .tag = .ebreak,
3848 .ops = .none,3842 .ops = .none,
3849 .data = undefined,3843 .data = undefined,
3850 });3844 });
3851 return self.finishAirBookkeeping();3845 return func.finishAirBookkeeping();
3852}3846}
38533847
3854fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {3848fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {
3855 const dst_mcv = try self.allocRegOrMem(inst, true);3849 const dst_mcv = try func.allocRegOrMem(inst, true);
3856 try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });3850 try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });
3857 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });3851 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
3858}3852}
38593853
3860fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {3854fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {
3861 const dst_mcv = try self.allocRegOrMem(inst, true);3855 const dst_mcv = try func.allocRegOrMem(inst, true);
3862 try self.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });3856 try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });
3863 return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });3857 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
3864}3858}
38653859
3866fn airFence(self: *Self) !void {3860fn airFence(func: *Func) !void {
3867 return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch});3861 return func.fail("TODO implement fence() for {}", .{func.target.cpu.arch});
3868 //return self.finishAirBookkeeping();3862 //return func.finishAirBookkeeping();
3869}3863}
38703864
3871fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {3865fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
3872 if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{});3866 if (modifier == .always_tail) return func.fail("TODO implement tail calls for riscv64", .{});
3873 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;3867 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
3874 const callee = pl_op.operand;3868 const callee = pl_op.operand;
3875 const extra = self.air.extraData(Air.Call, pl_op.payload);3869 const extra = func.air.extraData(Air.Call, pl_op.payload);
3876 const arg_refs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);3870 const arg_refs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra.end..][0..extra.data.args_len]);
38773871
3878 const expected_num_args = 8;3872 const expected_num_args = 8;
3879 const ExpectedContents = extern struct {3873 const ExpectedContents = extern struct {
3880 vals: [expected_num_args][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),3874 vals: [expected_num_args][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
3881 };3875 };
3882 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =3876 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
3883 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);3877 std.heap.stackFallback(@sizeOf(ExpectedContents), func.gpa);
3884 const allocator = stack.get();3878 const allocator = stack.get();
38853879
3886 const arg_tys = try allocator.alloc(Type, arg_refs.len);3880 const arg_tys = try allocator.alloc(Type, arg_refs.len);
3887 defer allocator.free(arg_tys);3881 defer allocator.free(arg_tys);
3888 for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = self.typeOf(arg_ref);3882 for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = func.typeOf(arg_ref);
38893883
3890 const arg_vals = try allocator.alloc(MCValue, arg_refs.len);3884 const arg_vals = try allocator.alloc(MCValue, arg_refs.len);
3891 defer allocator.free(arg_vals);3885 defer allocator.free(arg_vals);
3892 for (arg_vals, arg_refs) |*arg_val, arg_ref| arg_val.* = .{ .air_ref = arg_ref };3886 for (arg_vals, arg_refs) |*arg_val, arg_ref| arg_val.* = .{ .air_ref = arg_ref };
38933887
3894 const call_ret = try self.genCall(.{ .air = callee }, arg_tys, arg_vals);3888 const call_ret = try func.genCall(.{ .air = callee }, arg_tys, arg_vals);
38953889
3896 var bt = self.liveness.iterateBigTomb(inst);3890 var bt = func.liveness.iterateBigTomb(inst);
3897 try self.feed(&bt, pl_op.operand);3891 try func.feed(&bt, pl_op.operand);
3898 for (arg_refs) |arg_ref| try self.feed(&bt, arg_ref);3892 for (arg_refs) |arg_ref| try func.feed(&bt, arg_ref);
38993893
3900 const result = if (self.liveness.isUnused(inst)) .unreach else call_ret;3894 const result = if (func.liveness.isUnused(inst)) .unreach else call_ret;
3901 return self.finishAirResult(inst, result);3895 return func.finishAirResult(inst, result);
3902}3896}
39033897
3904fn genCall(3898fn genCall(
3905 self: *Self,3899 func: *Func,
3906 info: union(enum) {3900 info: union(enum) {
3907 air: Air.Inst.Ref,3901 air: Air.Inst.Ref,
3908 lib: struct {3902 lib: struct {
...@@ -3915,11 +3909,11 @@ fn genCall(...@@ -3915,11 +3909,11 @@ fn genCall(
3915 arg_tys: []const Type,3909 arg_tys: []const Type,
3916 args: []const MCValue,3910 args: []const MCValue,
3917) !MCValue {3911) !MCValue {
3918 const zcu = self.bin_file.comp.module.?;3912 const zcu = func.bin_file.comp.module.?;
39193913
3920 const fn_ty = switch (info) {3914 const fn_ty = switch (info) {
3921 .air => |callee| fn_info: {3915 .air => |callee| fn_info: {
3922 const callee_ty = self.typeOf(callee);3916 const callee_ty = func.typeOf(callee);
3923 break :fn_info switch (callee_ty.zigTypeTag(zcu)) {3917 break :fn_info switch (callee_ty.zigTypeTag(zcu)) {
3924 .Fn => callee_ty,3918 .Fn => callee_ty,
3925 .Pointer => callee_ty.childType(zcu),3919 .Pointer => callee_ty.childType(zcu),
...@@ -3935,14 +3929,14 @@ fn genCall(...@@ -3935,14 +3929,14 @@ fn genCall(
39353929
3936 const fn_info = zcu.typeToFunc(fn_ty).?;3930 const fn_info = zcu.typeToFunc(fn_ty).?;
39373931
3938 const allocator = self.gpa;3932 const allocator = func.gpa;
39393933
3940 const var_args = try allocator.alloc(Type, args.len - fn_info.param_types.len);3934 const var_args = try allocator.alloc(Type, args.len - fn_info.param_types.len);
3941 defer allocator.free(var_args);3935 defer allocator.free(var_args);
3942 for (var_args, arg_tys[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;3936 for (var_args, arg_tys[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
39433937
3944 var call_info = try self.resolveCallingConventionValues(fn_info, var_args);3938 var call_info = try func.resolveCallingConventionValues(fn_info, var_args);
3945 defer call_info.deinit(self);3939 defer call_info.deinit(func);
39463940
3947 // We need a properly aligned and sized call frame to be able to call this function.3941 // We need a properly aligned and sized call frame to be able to call this function.
3948 {3942 {
...@@ -3950,7 +3944,7 @@ fn genCall(...@@ -3950,7 +3944,7 @@ fn genCall(
3950 .size = call_info.stack_byte_count,3944 .size = call_info.stack_byte_count,
3951 .alignment = call_info.stack_align,3945 .alignment = call_info.stack_align,
3952 });3946 });
3953 const frame_allocs_slice = self.frame_allocs.slice();3947 const frame_allocs_slice = func.frame_allocs.slice();
3954 const stack_frame_size =3948 const stack_frame_size =
3955 &frame_allocs_slice.items(.abi_size)[@intFromEnum(FrameIndex.call_frame)];3949 &frame_allocs_slice.items(.abi_size)[@intFromEnum(FrameIndex.call_frame)];
3956 stack_frame_size.* = @max(stack_frame_size.*, needed_call_frame.abi_size);3950 stack_frame_size.* = @max(stack_frame_size.*, needed_call_frame.abi_size);
...@@ -3962,34 +3956,34 @@ fn genCall(...@@ -3962,34 +3956,34 @@ fn genCall(
3962 var reg_locks = std.ArrayList(?RegisterLock).init(allocator);3956 var reg_locks = std.ArrayList(?RegisterLock).init(allocator);
3963 defer reg_locks.deinit();3957 defer reg_locks.deinit();
3964 try reg_locks.ensureTotalCapacity(8);3958 try reg_locks.ensureTotalCapacity(8);
3965 defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);3959 defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| func.register_manager.unlockReg(lock);
39663960
3967 const frame_indices = try allocator.alloc(FrameIndex, args.len);3961 const frame_indices = try allocator.alloc(FrameIndex, args.len);
3968 defer allocator.free(frame_indices);3962 defer allocator.free(frame_indices);
39693963
3970 switch (call_info.return_value.long) {3964 switch (call_info.return_value.long) {
3971 .none, .unreach => {},3965 .none, .unreach => {},
3972 .indirect => |reg_off| try self.register_manager.getReg(reg_off.reg, null),3966 .indirect => |reg_off| try func.register_manager.getReg(reg_off.reg, null),
3973 else => unreachable,3967 else => unreachable,
3974 }3968 }
3975 for (call_info.args, args, arg_tys, frame_indices) |dst_arg, src_arg, arg_ty, *frame_index| {3969 for (call_info.args, args, arg_tys, frame_indices) |dst_arg, src_arg, arg_ty, *frame_index| {
3976 switch (dst_arg) {3970 switch (dst_arg) {
3977 .none => {},3971 .none => {},
3978 .register => |reg| {3972 .register => |reg| {
3979 try self.register_manager.getReg(reg, null);3973 try func.register_manager.getReg(reg, null);
3980 try reg_locks.append(self.register_manager.lockReg(reg));3974 try reg_locks.append(func.register_manager.lockReg(reg));
3981 },3975 },
3982 .register_pair => |regs| {3976 .register_pair => |regs| {
3983 for (regs) |reg| try self.register_manager.getReg(reg, null);3977 for (regs) |reg| try func.register_manager.getReg(reg, null);
3984 try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));3978 try reg_locks.appendSlice(&func.register_manager.lockRegs(2, regs));
3985 },3979 },
3986 .indirect => |reg_off| {3980 .indirect => |reg_off| {
3987 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, zcu));3981 frame_index.* = try func.allocFrameIndex(FrameAlloc.initType(arg_ty, zcu));
3988 try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);3982 try func.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
3989 try self.register_manager.getReg(reg_off.reg, null);3983 try func.register_manager.getReg(reg_off.reg, null);
3990 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));3984 try reg_locks.append(func.register_manager.lockReg(reg_off.reg));
3991 },3985 },
3992 else => return self.fail("TODO: genCall set arg {s}", .{@tagName(dst_arg)}),3986 else => return func.fail("TODO: genCall set arg {s}", .{@tagName(dst_arg)}),
3993 }3987 }
3994 }3988 }
39953989
...@@ -3997,12 +3991,12 @@ fn genCall(...@@ -3997,12 +3991,12 @@ fn genCall(
3997 .none, .unreach => {},3991 .none, .unreach => {},
3998 .indirect => |reg_off| {3992 .indirect => |reg_off| {
3999 const ret_ty = Type.fromInterned(fn_info.return_type);3993 const ret_ty = Type.fromInterned(fn_info.return_type);
4000 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, zcu));3994 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, zcu));
4001 try self.genSetReg(Type.usize, reg_off.reg, .{3995 try func.genSetReg(Type.usize, reg_off.reg, .{
4002 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },3996 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4003 });3997 });
4004 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };3998 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
4005 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));3999 try reg_locks.append(func.register_manager.lockReg(reg_off.reg));
4006 },4000 },
4007 else => unreachable,4001 else => unreachable,
4008 }4002 }
...@@ -4010,16 +4004,16 @@ fn genCall(...@@ -4010,16 +4004,16 @@ fn genCall(
4010 for (call_info.args, arg_tys, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| {4004 for (call_info.args, arg_tys, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| {
4011 switch (dst_arg) {4005 switch (dst_arg) {
4012 .none, .load_frame => {},4006 .none, .load_frame => {},
4013 .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),4007 .register_pair => try func.genCopy(arg_ty, dst_arg, src_arg),
4014 .register => |dst_reg| try self.genSetReg(4008 .register => |dst_reg| try func.genSetReg(
4015 arg_ty,4009 arg_ty,
4016 dst_reg,4010 dst_reg,
4017 src_arg,4011 src_arg,
4018 ),4012 ),
4019 .indirect => |reg_off| try self.genSetReg(Type.usize, reg_off.reg, .{4013 .indirect => |reg_off| try func.genSetReg(Type.usize, reg_off.reg, .{
4020 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },4014 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4021 }),4015 }),
4022 else => return self.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),4016 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),
4023 }4017 }
4024 }4018 }
40254019
...@@ -4027,7 +4021,7 @@ fn genCall(...@@ -4027,7 +4021,7 @@ fn genCall(
4027 // on linking.4021 // on linking.
4028 switch (info) {4022 switch (info) {
4029 .air => |callee| {4023 .air => |callee| {
4030 if (try self.air.value(callee, zcu)) |func_value| {4024 if (try func.air.value(callee, zcu)) |func_value| {
4031 const func_key = zcu.intern_pool.indexToKey(func_value.ip_index);4025 const func_key = zcu.intern_pool.indexToKey(func_value.ip_index);
4032 switch (switch (func_key) {4026 switch (switch (func_key) {
4033 else => func_key,4027 else => func_key,
...@@ -4036,19 +4030,19 @@ fn genCall(...@@ -4036,19 +4030,19 @@ fn genCall(
4036 else => func_key,4030 else => func_key,
4037 } else func_key,4031 } else func_key,
4038 }) {4032 }) {
4039 .func => |func| {4033 .func => |func_val| {
4040 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4034 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
4041 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);4035 const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl);
4042 const sym = elf_file.symbol(sym_index);4036 const sym = elf_file.symbol(sym_index);
40434037
4044 if (self.mod.pic) {4038 if (func.mod.pic) {
4045 return self.fail("TODO: genCall pic", .{});4039 return func.fail("TODO: genCall pic", .{});
4046 } else {4040 } else {
4047 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);4041 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
4048 const got_addr = sym.zigGotAddress(elf_file);4042 const got_addr = sym.zigGotAddress(elf_file);
4049 try self.genSetReg(Type.usize, .ra, .{ .memory = @intCast(got_addr) });4043 try func.genSetReg(Type.usize, .ra, .{ .memory = @intCast(got_addr) });
40504044
4051 _ = try self.addInst(.{4045 _ = try func.addInst(.{
4052 .tag = .jalr,4046 .tag = .jalr,
4053 .ops = .rri,4047 .ops = .rri,
4054 .data = .{ .i_type = .{4048 .data = .{ .i_type = .{
...@@ -4064,10 +4058,10 @@ fn genCall(...@@ -4064,10 +4058,10 @@ fn genCall(
4064 const owner_decl = zcu.declPtr(extern_func.decl);4058 const owner_decl = zcu.declPtr(extern_func.decl);
4065 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);4059 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);
4066 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);4060 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);
4067 const atom_index = try self.symbolIndex();4061 const atom_index = try func.symbolIndex();
40684062
4069 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4063 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
4070 _ = try self.addInst(.{4064 _ = try func.addInst(.{
4071 .tag = .pseudo,4065 .tag = .pseudo,
4072 .ops = .pseudo_extern_fn_reloc,4066 .ops = .pseudo_extern_fn_reloc,
4073 .data = .{ .reloc = .{4067 .data = .{ .reloc = .{
...@@ -4077,15 +4071,15 @@ fn genCall(...@@ -4077,15 +4071,15 @@ fn genCall(
4077 });4071 });
4078 } else unreachable; // not a valid riscv64 format4072 } else unreachable; // not a valid riscv64 format
4079 },4073 },
4080 else => return self.fail("TODO implement calling bitcasted functions", .{}),4074 else => return func.fail("TODO implement calling bitcasted functions", .{}),
4081 }4075 }
4082 } else {4076 } else {
4083 assert(self.typeOf(callee).zigTypeTag(zcu) == .Pointer);4077 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);
4084 const addr_reg, const addr_lock = try self.allocReg(.int);4078 const addr_reg, const addr_lock = try func.allocReg(.int);
4085 defer self.register_manager.unlockReg(addr_lock);4079 defer func.register_manager.unlockReg(addr_lock);
4086 try self.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee });4080 try func.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee });
40874081
4088 _ = try self.addInst(.{4082 _ = try func.addInst(.{
4089 .tag = .jalr,4083 .tag = .jalr,
4090 .ops = .rri,4084 .ops = .rri,
4091 .data = .{ .i_type = .{4085 .data = .{ .i_type = .{
...@@ -4096,15 +4090,15 @@ fn genCall(...@@ -4096,15 +4090,15 @@ fn genCall(
4096 });4090 });
4097 }4091 }
4098 },4092 },
4099 .lib => return self.fail("TODO: lib func calls", .{}),4093 .lib => return func.fail("TODO: lib func calls", .{}),
4100 }4094 }
41014095
4102 return call_info.return_value.short;4096 return call_info.return_value.short;
4103}4097}
41044098
4105fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {4099fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4106 const zcu = self.bin_file.comp.module.?;4100 const zcu = func.bin_file.comp.module.?;
4107 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4101 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
41084102
4109 if (safety) {4103 if (safety) {
4110 // safe4104 // safe
...@@ -4112,19 +4106,19 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -4112,19 +4106,19 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
4112 // not safe4106 // not safe
4113 }4107 }
41144108
4115 const ret_ty = self.fn_type.fnReturnType(zcu);4109 const ret_ty = func.fn_type.fnReturnType(zcu);
4116 switch (self.ret_mcv.short) {4110 switch (func.ret_mcv.short) {
4117 .none => {},4111 .none => {},
4118 .register,4112 .register,
4119 .register_pair,4113 .register_pair,
4120 => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }),4114 => try func.genCopy(ret_ty, func.ret_mcv.short, .{ .air_ref = un_op }),
4121 .indirect => |reg_off| {4115 .indirect => |reg_off| {
4122 try self.register_manager.getReg(reg_off.reg, null);4116 try func.register_manager.getReg(reg_off.reg, null);
4123 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);4117 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);
4124 defer self.register_manager.unlockReg(lock);4118 defer func.register_manager.unlockReg(lock);
41254119
4126 try self.genSetReg(Type.usize, reg_off.reg, self.ret_mcv.long);4120 try func.genSetReg(Type.usize, reg_off.reg, func.ret_mcv.long);
4127 try self.genSetMem(4121 try func.genSetMem(
4128 .{ .reg = reg_off.reg },4122 .{ .reg = reg_off.reg },
4129 reg_off.off,4123 reg_off.off,
4130 ret_ty,4124 ret_ty,
...@@ -4134,52 +4128,52 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -4134,52 +4128,52 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
4134 else => unreachable,4128 else => unreachable,
4135 }4129 }
41364130
4137 self.ret_mcv.liveOut(self, inst);4131 func.ret_mcv.liveOut(func, inst);
4138 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });4132 try func.finishAir(inst, .unreach, .{ un_op, .none, .none });
41394133
4140 // Just add space for an instruction, reloced this later4134 // Just add space for an instruction, reloced this later
4141 const index = try self.addInst(.{4135 const index = try func.addInst(.{
4142 .tag = .pseudo,4136 .tag = .pseudo,
4143 .ops = .pseudo_j,4137 .ops = .pseudo_j,
4144 .data = .{ .inst = undefined },4138 .data = .{ .inst = undefined },
4145 });4139 });
41464140
4147 try self.exitlude_jump_relocs.append(self.gpa, index);4141 try func.exitlude_jump_relocs.append(func.gpa, index);
4148}4142}
41494143
4150fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {4144fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void {
4151 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4145 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4152 const ptr = try self.resolveInst(un_op);4146 const ptr = try func.resolveInst(un_op);
41534147
4154 const ptr_ty = self.typeOf(un_op);4148 const ptr_ty = func.typeOf(un_op);
4155 switch (self.ret_mcv.short) {4149 switch (func.ret_mcv.short) {
4156 .none => {},4150 .none => {},
4157 .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty),4151 .register, .register_pair => try func.load(func.ret_mcv.short, ptr, ptr_ty),
4158 .indirect => |reg_off| try self.genSetReg(ptr_ty, reg_off.reg, ptr),4152 .indirect => |reg_off| try func.genSetReg(ptr_ty, reg_off.reg, ptr),
4159 else => unreachable,4153 else => unreachable,
4160 }4154 }
4161 self.ret_mcv.liveOut(self, inst);4155 func.ret_mcv.liveOut(func, inst);
4162 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });4156 try func.finishAir(inst, .unreach, .{ un_op, .none, .none });
41634157
4164 // Just add space for an instruction, reloced this later4158 // Just add space for an instruction, reloced this later
4165 const index = try self.addInst(.{4159 const index = try func.addInst(.{
4166 .tag = .pseudo,4160 .tag = .pseudo,
4167 .ops = .pseudo_j,4161 .ops = .pseudo_j,
4168 .data = .{ .inst = undefined },4162 .data = .{ .inst = undefined },
4169 });4163 });
41704164
4171 try self.exitlude_jump_relocs.append(self.gpa, index);4165 try func.exitlude_jump_relocs.append(func.gpa, index);
4172}4166}
41734167
4174fn airCmp(self: *Self, inst: Air.Inst.Index) !void {4168fn airCmp(func: *Func, inst: Air.Inst.Index) !void {
4175 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4169 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
4176 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;4170 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
4177 const zcu = self.bin_file.comp.module.?;4171 const zcu = func.bin_file.comp.module.?;
41784172
4179 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4173 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4180 const lhs = try self.resolveInst(bin_op.lhs);4174 const lhs = try func.resolveInst(bin_op.lhs);
4181 const rhs = try self.resolveInst(bin_op.rhs);4175 const rhs = try func.resolveInst(bin_op.rhs);
4182 const lhs_ty = self.typeOf(bin_op.lhs);4176 const lhs_ty = func.typeOf(bin_op.lhs);
41834177
4184 switch (lhs_ty.zigTypeTag(zcu)) {4178 switch (lhs_ty.zigTypeTag(zcu)) {
4185 .Int,4179 .Int,
...@@ -4202,7 +4196,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4202,7 +4196,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void {
4202 } else if (lhs_ty.isPtrLikeOptional(zcu)) {4196 } else if (lhs_ty.isPtrLikeOptional(zcu)) {
4203 break :blk Type.usize;4197 break :blk Type.usize;
4204 } else {4198 } else {
4205 return self.fail("TODO riscv cmp non-pointer optionals", .{});4199 return func.fail("TODO riscv cmp non-pointer optionals", .{});
4206 }4200 }
4207 },4201 },
4208 else => unreachable,4202 else => unreachable,
...@@ -4210,43 +4204,43 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4210,43 +4204,43 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void {
42104204
4211 const int_info = int_ty.intInfo(zcu);4205 const int_info = int_ty.intInfo(zcu);
4212 if (int_info.bits <= 64) {4206 if (int_info.bits <= 64) {
4213 break :result try self.binOp(tag, lhs, int_ty, rhs, int_ty);4207 break :result try func.binOp(tag, lhs, int_ty, rhs, int_ty);
4214 } else {4208 } else {
4215 return self.fail("TODO riscv cmp for ints > 64 bits", .{});4209 return func.fail("TODO riscv cmp for ints > 64 bits", .{});
4216 }4210 }
4217 },4211 },
4218 .Float => {4212 .Float => {
4219 const float_bits = lhs_ty.floatBits(self.target.*);4213 const float_bits = lhs_ty.floatBits(func.target.*);
4220 const float_reg_size: u32 = if (self.hasFeature(.d)) 64 else 32;4214 const float_reg_size: u32 = if (func.hasFeature(.d)) 64 else 32;
4221 if (float_bits > float_reg_size) {4215 if (float_bits > float_reg_size) {
4222 return self.fail("TODO: airCmp float > 64/32 bits", .{});4216 return func.fail("TODO: airCmp float > 64/32 bits", .{});
4223 }4217 }
4224 break :result try self.binOpFloat(tag, lhs, lhs_ty, rhs, lhs_ty);4218 break :result try func.binOpFloat(tag, lhs, lhs_ty, rhs, lhs_ty);
4225 },4219 },
4226 else => unreachable,4220 else => unreachable,
4227 }4221 }
4228 };4222 };
42294223
4230 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });4224 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
4231}4225}
42324226
4233fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {4227fn airCmpVector(func: *Func, inst: Air.Inst.Index) !void {
4234 _ = inst;4228 _ = inst;
4235 return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});4229 return func.fail("TODO implement airCmpVector for {}", .{func.target.cpu.arch});
4236}4230}
42374231
4238fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {4232fn airCmpLtErrorsLen(func: *Func, inst: Air.Inst.Index) !void {
4239 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4233 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4240 const operand = try self.resolveInst(un_op);4234 const operand = try func.resolveInst(un_op);
4241 _ = operand;4235 _ = operand;
4242 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airCmpLtErrorsLen for {}", .{self.target.cpu.arch});4236 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airCmpLtErrorsLen for {}", .{func.target.cpu.arch});
4243 return self.finishAir(inst, result, .{ un_op, .none, .none });4237 return func.finishAir(inst, result, .{ un_op, .none, .none });
4244}4238}
42454239
4246fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {4240fn airDbgStmt(func: *Func, inst: Air.Inst.Index) !void {
4247 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;4241 const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
42484242
4249 _ = try self.addInst(.{4243 _ = try func.addInst(.{
4250 .tag = .pseudo,4244 .tag = .pseudo,
4251 .ops = .pseudo_dbg_line_column,4245 .ops = .pseudo_dbg_line_column,
4252 .data = .{ .pseudo_dbg_line_column = .{4246 .data = .{ .pseudo_dbg_line_column = .{
...@@ -4255,44 +4249,44 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4255,44 +4249,44 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4255 } },4249 } },
4256 });4250 });
42574251
4258 return self.finishAirBookkeeping();4252 return func.finishAirBookkeeping();
4259}4253}
42604254
4261fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {4255fn airDbgInlineBlock(func: *Func, inst: Air.Inst.Index) !void {
4262 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4256 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4263 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);4257 const extra = func.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
4264 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));4258 try func.lowerBlock(inst, @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
4265}4259}
42664260
4267fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {4261fn airDbgVar(func: *Func, inst: Air.Inst.Index) !void {
4268 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4262 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4269 const operand = pl_op.operand;4263 const operand = pl_op.operand;
4270 const ty = self.typeOf(operand);4264 const ty = func.typeOf(operand);
4271 const mcv = try self.resolveInst(operand);4265 const mcv = try func.resolveInst(operand);
42724266
4273 const name = self.air.nullTerminatedString(pl_op.payload);4267 const name = func.air.nullTerminatedString(pl_op.payload);
42744268
4275 const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4269 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
4276 try self.genVarDbgInfo(tag, ty, mcv, name);4270 try func.genVarDbgInfo(tag, ty, mcv, name);
42774271
4278 return self.finishAir(inst, .unreach, .{ operand, .none, .none });4272 return func.finishAir(inst, .unreach, .{ operand, .none, .none });
4279}4273}
42804274
4281fn genVarDbgInfo(4275fn genVarDbgInfo(
4282 self: Self,4276 func: Func,
4283 tag: Air.Inst.Tag,4277 tag: Air.Inst.Tag,
4284 ty: Type,4278 ty: Type,
4285 mcv: MCValue,4279 mcv: MCValue,
4286 name: [:0]const u8,4280 name: [:0]const u8,
4287) !void {4281) !void {
4288 const zcu = self.bin_file.comp.module.?;4282 const zcu = func.bin_file.comp.module.?;
4289 const is_ptr = switch (tag) {4283 const is_ptr = switch (tag) {
4290 .dbg_var_ptr => true,4284 .dbg_var_ptr => true,
4291 .dbg_var_val => false,4285 .dbg_var_val => false,
4292 else => unreachable,4286 else => unreachable,
4293 };4287 };
42944288
4295 switch (self.debug_output) {4289 switch (func.debug_output) {
4296 .dwarf => |dw| {4290 .dwarf => |dw| {
4297 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {4291 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
4298 .register => |reg| .{ .register = reg.dwarfLocOp() },4292 .register => |reg| .{ .register = reg.dwarfLocOp() },
...@@ -4309,47 +4303,47 @@ fn genVarDbgInfo(...@@ -4309,47 +4303,47 @@ fn genVarDbgInfo(
4309 break :blk .nop;4303 break :blk .nop;
4310 },4304 },
4311 };4305 };
4312 try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(self.func_index), is_ptr, loc);4306 try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
4313 },4307 },
4314 .plan9 => {},4308 .plan9 => {},
4315 .none => {},4309 .none => {},
4316 }4310 }
4317}4311}
43184312
4319fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {4313fn airCondBr(func: *Func, inst: Air.Inst.Index) !void {
4320 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4314 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4321 const cond = try self.resolveInst(pl_op.operand);4315 const cond = try func.resolveInst(pl_op.operand);
4322 const cond_ty = self.typeOf(pl_op.operand);4316 const cond_ty = func.typeOf(pl_op.operand);
4323 const extra = self.air.extraData(Air.CondBr, pl_op.payload);4317 const extra = func.air.extraData(Air.CondBr, pl_op.payload);
4324 const then_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.then_body_len]);4318 const then_body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end..][0..extra.data.then_body_len]);
4325 const else_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]);4319 const else_body: []const Air.Inst.Index = @ptrCast(func.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]);
4326 const liveness_cond_br = self.liveness.getCondBr(inst);4320 const liveness_cond_br = func.liveness.getCondBr(inst);
43274321
4328 // If the condition dies here in this condbr instruction, process4322 // If the condition dies here in this condbr instruction, process
4329 // that death now instead of later as this has an effect on4323 // that death now instead of later as this has an effect on
4330 // whether it needs to be spilled in the branches4324 // whether it needs to be spilled in the branches
4331 if (self.liveness.operandDies(inst, 0)) {4325 if (func.liveness.operandDies(inst, 0)) {
4332 if (pl_op.operand.toIndex()) |op_inst| try self.processDeath(op_inst);4326 if (pl_op.operand.toIndex()) |op_inst| try func.processDeath(op_inst);
4333 }4327 }
43344328
4335 self.scope_generation += 1;4329 func.scope_generation += 1;
4336 const state = try self.saveState();4330 const state = try func.saveState();
4337 const reloc = try self.condBr(cond_ty, cond);4331 const reloc = try func.condBr(cond_ty, cond);
43384332
4339 for (liveness_cond_br.then_deaths) |death| try self.processDeath(death);4333 for (liveness_cond_br.then_deaths) |death| try func.processDeath(death);
4340 try self.genBody(then_body);4334 try func.genBody(then_body);
4341 try self.restoreState(state, &.{}, .{4335 try func.restoreState(state, &.{}, .{
4342 .emit_instructions = false,4336 .emit_instructions = false,
4343 .update_tracking = true,4337 .update_tracking = true,
4344 .resurrect = true,4338 .resurrect = true,
4345 .close_scope = true,4339 .close_scope = true,
4346 });4340 });
43474341
4348 self.performReloc(reloc);4342 func.performReloc(reloc);
43494343
4350 for (liveness_cond_br.else_deaths) |death| try self.processDeath(death);4344 for (liveness_cond_br.else_deaths) |death| try func.processDeath(death);
4351 try self.genBody(else_body);4345 try func.genBody(else_body);
4352 try self.restoreState(state, &.{}, .{4346 try func.restoreState(state, &.{}, .{
4353 .emit_instructions = false,4347 .emit_instructions = false,
4354 .update_tracking = true,4348 .update_tracking = true,
4355 .resurrect = true,4349 .resurrect = true,
...@@ -4357,13 +4351,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4357,13 +4351,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4357 });4351 });
43584352
4359 // We already took care of pl_op.operand earlier, so there's nothing left to do.4353 // We already took care of pl_op.operand earlier, so there's nothing left to do.
4360 self.finishAirBookkeeping();4354 func.finishAirBookkeeping();
4361}4355}
43624356
4363fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {4357fn condBr(func: *Func, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
4364 const cond_reg = try self.copyToTmpRegister(cond_ty, condition);4358 const cond_reg = try func.copyToTmpRegister(cond_ty, condition);
43654359
4366 return try self.addInst(.{4360 return try func.addInst(.{
4367 .tag = .beq,4361 .tag = .beq,
4368 .ops = .rr_inst,4362 .ops = .rr_inst,
4369 .data = .{4363 .data = .{
...@@ -4376,111 +4370,111 @@ fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {...@@ -4376,111 +4370,111 @@ fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
4376 });4370 });
4377}4371}
43784372
4379fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {4373fn airIsNull(func: *Func, inst: Air.Inst.Index) !void {
4380 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4374 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4381 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4375 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4382 const operand = try self.resolveInst(un_op);4376 const operand = try func.resolveInst(un_op);
4383 break :result try self.isNull(operand);4377 break :result try func.isNull(operand);
4384 };4378 };
4385 return self.finishAir(inst, result, .{ un_op, .none, .none });4379 return func.finishAir(inst, result, .{ un_op, .none, .none });
4386}4380}
43874381
4388fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {4382fn airIsNullPtr(func: *Func, inst: Air.Inst.Index) !void {
4389 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4383 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4390 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4384 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4391 const operand_ptr = try self.resolveInst(un_op);4385 const operand_ptr = try func.resolveInst(un_op);
4392 const operand: MCValue = blk: {4386 const operand: MCValue = blk: {
4393 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4387 if (func.reuseOperand(inst, un_op, 0, operand_ptr)) {
4394 // The MCValue that holds the pointer can be re-used as the value.4388 // The MCValue that holds the pointer can be re-used as the value.
4395 break :blk operand_ptr;4389 break :blk operand_ptr;
4396 } else {4390 } else {
4397 break :blk try self.allocRegOrMem(inst, true);4391 break :blk try func.allocRegOrMem(inst, true);
4398 }4392 }
4399 };4393 };
4400 try self.load(operand, operand_ptr, self.typeOf(un_op));4394 try func.load(operand, operand_ptr, func.typeOf(un_op));
4401 break :result try self.isNull(operand);4395 break :result try func.isNull(operand);
4402 };4396 };
4403 return self.finishAir(inst, result, .{ un_op, .none, .none });4397 return func.finishAir(inst, result, .{ un_op, .none, .none });
4404}4398}
44054399
4406fn isNull(self: *Self, operand: MCValue) !MCValue {4400fn isNull(func: *Func, operand: MCValue) !MCValue {
4407 _ = operand;4401 _ = operand;
4408 // Here you can specialize this instruction if it makes sense to, otherwise the default4402 // Here you can specialize this instruction if it makes sense to, otherwise the default
4409 // will call isNonNull and invert the result.4403 // will call isNonNull and invert the result.
4410 return self.fail("TODO call isNonNull and invert the result", .{});4404 return func.fail("TODO call isNonNull and invert the result", .{});
4411}4405}
44124406
4413fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {4407fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void {
4414 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4408 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4415 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4409 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4416 const operand = try self.resolveInst(un_op);4410 const operand = try func.resolveInst(un_op);
4417 break :result try self.isNonNull(operand);4411 break :result try func.isNonNull(operand);
4418 };4412 };
4419 return self.finishAir(inst, result, .{ un_op, .none, .none });4413 return func.finishAir(inst, result, .{ un_op, .none, .none });
4420}4414}
44214415
4422fn isNonNull(self: *Self, operand: MCValue) !MCValue {4416fn isNonNull(func: *Func, operand: MCValue) !MCValue {
4423 _ = operand;4417 _ = operand;
4424 // Here you can specialize this instruction if it makes sense to, otherwise the default4418 // Here you can specialize this instruction if it makes sense to, otherwise the default
4425 // will call isNull and invert the result.4419 // will call isNull and invert the result.
4426 return self.fail("TODO call isNull and invert the result", .{});4420 return func.fail("TODO call isNull and invert the result", .{});
4427}4421}
44284422
4429fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {4423fn airIsNonNullPtr(func: *Func, inst: Air.Inst.Index) !void {
4430 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4424 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4431 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4425 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4432 const operand_ptr = try self.resolveInst(un_op);4426 const operand_ptr = try func.resolveInst(un_op);
4433 const operand: MCValue = blk: {4427 const operand: MCValue = blk: {
4434 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4428 if (func.reuseOperand(inst, un_op, 0, operand_ptr)) {
4435 // The MCValue that holds the pointer can be re-used as the value.4429 // The MCValue that holds the pointer can be re-used as the value.
4436 break :blk operand_ptr;4430 break :blk operand_ptr;
4437 } else {4431 } else {
4438 break :blk try self.allocRegOrMem(inst, true);4432 break :blk try func.allocRegOrMem(inst, true);
4439 }4433 }
4440 };4434 };
4441 try self.load(operand, operand_ptr, self.typeOf(un_op));4435 try func.load(operand, operand_ptr, func.typeOf(un_op));
4442 break :result try self.isNonNull(operand);4436 break :result try func.isNonNull(operand);
4443 };4437 };
4444 return self.finishAir(inst, result, .{ un_op, .none, .none });4438 return func.finishAir(inst, result, .{ un_op, .none, .none });
4445}4439}
44464440
4447fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {4441fn airIsErr(func: *Func, inst: Air.Inst.Index) !void {
4448 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4442 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4449 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4443 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4450 const operand = try self.resolveInst(un_op);4444 const operand = try func.resolveInst(un_op);
4451 const operand_ty = self.typeOf(un_op);4445 const operand_ty = func.typeOf(un_op);
4452 break :result try self.isErr(inst, operand_ty, operand);4446 break :result try func.isErr(inst, operand_ty, operand);
4453 };4447 };
4454 return self.finishAir(inst, result, .{ un_op, .none, .none });4448 return func.finishAir(inst, result, .{ un_op, .none, .none });
4455}4449}
44564450
4457fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {4451fn airIsErrPtr(func: *Func, inst: Air.Inst.Index) !void {
4458 const zcu = self.bin_file.comp.module.?;4452 const zcu = func.bin_file.comp.module.?;
4459 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4453 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4460 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4454 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4461 const operand_ptr = try self.resolveInst(un_op);4455 const operand_ptr = try func.resolveInst(un_op);
4462 const operand: MCValue = blk: {4456 const operand: MCValue = blk: {
4463 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4457 if (func.reuseOperand(inst, un_op, 0, operand_ptr)) {
4464 // The MCValue that holds the pointer can be re-used as the value.4458 // The MCValue that holds the pointer can be re-used as the value.
4465 break :blk operand_ptr;4459 break :blk operand_ptr;
4466 } else {4460 } else {
4467 break :blk try self.allocRegOrMem(inst, true);4461 break :blk try func.allocRegOrMem(inst, true);
4468 }4462 }
4469 };4463 };
4470 try self.load(operand, operand_ptr, self.typeOf(un_op));4464 try func.load(operand, operand_ptr, func.typeOf(un_op));
4471 const operand_ptr_ty = self.typeOf(un_op);4465 const operand_ptr_ty = func.typeOf(un_op);
4472 const operand_ty = operand_ptr_ty.childType(zcu);4466 const operand_ty = operand_ptr_ty.childType(zcu);
44734467
4474 break :result try self.isErr(inst, operand_ty, operand);4468 break :result try func.isErr(inst, operand_ty, operand);
4475 };4469 };
4476 return self.finishAir(inst, result, .{ un_op, .none, .none });4470 return func.finishAir(inst, result, .{ un_op, .none, .none });
4477}4471}
44784472
4479/// Generates a compare instruction which will indicate if `eu_mcv` is an error.4473/// Generates a compare instruction which will indicate if `eu_mcv` is an error.
4480///4474///
4481/// Result is in the return register.4475/// Result is in the return register.
4482fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {4476fn isErr(func: *Func, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {
4483 const zcu = self.bin_file.comp.module.?;4477 const zcu = func.bin_file.comp.module.?;
4484 const err_ty = eu_ty.errorUnionSet(zcu);4478 const err_ty = eu_ty.errorUnionSet(zcu);
4485 if (err_ty.errorSetIsEmpty(zcu)) return MCValue{ .immediate = 0 }; // always false4479 if (err_ty.errorSetIsEmpty(zcu)) return MCValue{ .immediate = 0 }; // always false
44864480
...@@ -4490,17 +4484,17 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4490,17 +4484,17 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
44904484
4491 switch (eu_mcv) {4485 switch (eu_mcv) {
4492 .register => |reg| {4486 .register => |reg| {
4493 const eu_lock = self.register_manager.lockReg(reg);4487 const eu_lock = func.register_manager.lockReg(reg);
4494 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);4488 defer if (eu_lock) |lock| func.register_manager.unlockReg(lock);
44954489
4496 const return_reg = try self.copyToTmpRegister(eu_ty, eu_mcv);4490 const return_reg = try func.copyToTmpRegister(eu_ty, eu_mcv);
4497 const return_lock = self.register_manager.lockRegAssumeUnused(return_reg);4491 const return_lock = func.register_manager.lockRegAssumeUnused(return_reg);
4498 defer self.register_manager.unlockReg(return_lock);4492 defer func.register_manager.unlockReg(return_lock);
44994493
4500 var return_mcv: MCValue = .{ .register = return_reg };4494 var return_mcv: MCValue = .{ .register = return_reg };
45014495
4502 if (err_off > 0) {4496 if (err_off > 0) {
4503 return_mcv = try self.binOp(4497 return_mcv = try func.binOp(
4504 .shr,4498 .shr,
4505 return_mcv,4499 return_mcv,
4506 eu_ty,4500 eu_ty,
...@@ -4509,7 +4503,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4509,7 +4503,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
4509 );4503 );
4510 }4504 }
45114505
4512 return try self.binOp(4506 return try func.binOp(
4513 .cmp_neq,4507 .cmp_neq,
4514 return_mcv,4508 return_mcv,
4515 Type.u16,4509 Type.u16,
...@@ -4518,7 +4512,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4518,7 +4512,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
4518 );4512 );
4519 },4513 },
4520 .load_frame => |frame_addr| {4514 .load_frame => |frame_addr| {
4521 return self.binOp(4515 return func.binOp(
4522 .cmp_neq,4516 .cmp_neq,
4523 .{ .load_frame = .{4517 .{ .load_frame = .{
4524 .index = frame_addr.index,4518 .index = frame_addr.index,
...@@ -4529,25 +4523,25 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4529,25 +4523,25 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
4529 Type.anyerror,4523 Type.anyerror,
4530 );4524 );
4531 },4525 },
4532 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),4526 else => return func.fail("TODO implement isErr for {}", .{eu_mcv}),
4533 }4527 }
4534}4528}
45354529
4536fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {4530fn airIsNonErr(func: *Func, inst: Air.Inst.Index) !void {
4537 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4531 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4538 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4532 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4539 const operand = try self.resolveInst(un_op);4533 const operand = try func.resolveInst(un_op);
4540 const ty = self.typeOf(un_op);4534 const ty = func.typeOf(un_op);
4541 break :result try self.isNonErr(inst, ty, operand);4535 break :result try func.isNonErr(inst, ty, operand);
4542 };4536 };
4543 return self.finishAir(inst, result, .{ un_op, .none, .none });4537 return func.finishAir(inst, result, .{ un_op, .none, .none });
4544}4538}
45454539
4546fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {4540fn isNonErr(func: *Func, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {
4547 const is_err_res = try self.isErr(inst, eu_ty, eu_mcv);4541 const is_err_res = try func.isErr(inst, eu_ty, eu_mcv);
4548 switch (is_err_res) {4542 switch (is_err_res) {
4549 .register => |reg| {4543 .register => |reg| {
4550 _ = try self.addInst(.{4544 _ = try func.addInst(.{
4551 .tag = .pseudo,4545 .tag = .pseudo,
4552 .ops = .pseudo_not,4546 .ops = .pseudo_not,
4553 .data = .{4547 .data = .{
...@@ -4568,53 +4562,53 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC...@@ -4568,53 +4562,53 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC
4568 }4562 }
4569}4563}
45704564
4571fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {4565fn airIsNonErrPtr(func: *Func, inst: Air.Inst.Index) !void {
4572 const zcu = self.bin_file.comp.module.?;4566 const zcu = func.bin_file.comp.module.?;
4573 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4567 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4574 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4568 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4575 const operand_ptr = try self.resolveInst(un_op);4569 const operand_ptr = try func.resolveInst(un_op);
4576 const operand: MCValue = blk: {4570 const operand: MCValue = blk: {
4577 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4571 if (func.reuseOperand(inst, un_op, 0, operand_ptr)) {
4578 // The MCValue that holds the pointer can be re-used as the value.4572 // The MCValue that holds the pointer can be re-used as the value.
4579 break :blk operand_ptr;4573 break :blk operand_ptr;
4580 } else {4574 } else {
4581 break :blk try self.allocRegOrMem(inst, true);4575 break :blk try func.allocRegOrMem(inst, true);
4582 }4576 }
4583 };4577 };
4584 const operand_ptr_ty = self.typeOf(un_op);4578 const operand_ptr_ty = func.typeOf(un_op);
4585 const operand_ty = operand_ptr_ty.childType(zcu);4579 const operand_ty = operand_ptr_ty.childType(zcu);
45864580
4587 try self.load(operand, operand_ptr, self.typeOf(un_op));4581 try func.load(operand, operand_ptr, func.typeOf(un_op));
4588 break :result try self.isNonErr(inst, operand_ty, operand);4582 break :result try func.isNonErr(inst, operand_ty, operand);
4589 };4583 };
4590 return self.finishAir(inst, result, .{ un_op, .none, .none });4584 return func.finishAir(inst, result, .{ un_op, .none, .none });
4591}4585}
45924586
4593fn airLoop(self: *Self, inst: Air.Inst.Index) !void {4587fn airLoop(func: *Func, inst: Air.Inst.Index) !void {
4594 // A loop is a setup to be able to jump back to the beginning.4588 // A loop is a setup to be able to jump back to the beginning.
4595 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4589 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4596 const loop = self.air.extraData(Air.Block, ty_pl.payload);4590 const loop = func.air.extraData(Air.Block, ty_pl.payload);
4597 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[loop.end..][0..loop.data.body_len]);4591 const body: []const Air.Inst.Index = @ptrCast(func.air.extra[loop.end..][0..loop.data.body_len]);
45984592
4599 self.scope_generation += 1;4593 func.scope_generation += 1;
4600 const state = try self.saveState();4594 const state = try func.saveState();
46014595
4602 const jmp_target: Mir.Inst.Index = @intCast(self.mir_instructions.len);4596 const jmp_target: Mir.Inst.Index = @intCast(func.mir_instructions.len);
4603 try self.genBody(body);4597 try func.genBody(body);
4604 try self.restoreState(state, &.{}, .{4598 try func.restoreState(state, &.{}, .{
4605 .emit_instructions = true,4599 .emit_instructions = true,
4606 .update_tracking = false,4600 .update_tracking = false,
4607 .resurrect = false,4601 .resurrect = false,
4608 .close_scope = true,4602 .close_scope = true,
4609 });4603 });
4610 _ = try self.jump(jmp_target);4604 _ = try func.jump(jmp_target);
46114605
4612 self.finishAirBookkeeping();4606 func.finishAirBookkeeping();
4613}4607}
46144608
4615/// Send control flow to the `index` of `self.code`.4609/// Send control flow to the `index` of `func.code`.
4616fn jump(self: *Self, index: Mir.Inst.Index) !Mir.Inst.Index {4610fn jump(func: *Func, index: Mir.Inst.Index) !Mir.Inst.Index {
4617 return self.addInst(.{4611 return func.addInst(.{
4618 .tag = .pseudo,4612 .tag = .pseudo,
4619 .ops = .pseudo_j,4613 .ops = .pseudo_j,
4620 .data = .{4614 .data = .{
...@@ -4623,79 +4617,79 @@ fn jump(self: *Self, index: Mir.Inst.Index) !Mir.Inst.Index {...@@ -4623,79 +4617,79 @@ fn jump(self: *Self, index: Mir.Inst.Index) !Mir.Inst.Index {
4623 });4617 });
4624}4618}
46254619
4626fn airBlock(self: *Self, inst: Air.Inst.Index) !void {4620fn airBlock(func: *Func, inst: Air.Inst.Index) !void {
4627 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4621 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4628 const extra = self.air.extraData(Air.Block, ty_pl.payload);4622 const extra = func.air.extraData(Air.Block, ty_pl.payload);
4629 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));4623 try func.lowerBlock(inst, @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
4630}4624}
46314625
4632fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {4626fn lowerBlock(func: *Func, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
4633 // A block is a setup to be able to jump to the end.4627 // A block is a setup to be able to jump to the end.
4634 const inst_tracking_i = self.inst_tracking.count();4628 const inst_tracking_i = func.inst_tracking.count();
4635 self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(.unreach));4629 func.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(.unreach));
46364630
4637 self.scope_generation += 1;4631 func.scope_generation += 1;
4638 try self.blocks.putNoClobber(self.gpa, inst, .{ .state = self.initRetroactiveState() });4632 try func.blocks.putNoClobber(func.gpa, inst, .{ .state = func.initRetroactiveState() });
4639 const liveness = self.liveness.getBlock(inst);4633 const liveness = func.liveness.getBlock(inst);
46404634
4641 // TODO emit debug info lexical block4635 // TODO emit debug info lexical block
4642 try self.genBody(body);4636 try func.genBody(body);
46434637
4644 var block_data = self.blocks.fetchRemove(inst).?;4638 var block_data = func.blocks.fetchRemove(inst).?;
4645 defer block_data.value.deinit(self.gpa);4639 defer block_data.value.deinit(func.gpa);
4646 if (block_data.value.relocs.items.len > 0) {4640 if (block_data.value.relocs.items.len > 0) {
4647 try self.restoreState(block_data.value.state, liveness.deaths, .{4641 try func.restoreState(block_data.value.state, liveness.deaths, .{
4648 .emit_instructions = false,4642 .emit_instructions = false,
4649 .update_tracking = true,4643 .update_tracking = true,
4650 .resurrect = true,4644 .resurrect = true,
4651 .close_scope = true,4645 .close_scope = true,
4652 });4646 });
4653 for (block_data.value.relocs.items) |reloc| self.performReloc(reloc);4647 for (block_data.value.relocs.items) |reloc| func.performReloc(reloc);
4654 }4648 }
46554649
4656 if (std.debug.runtime_safety) assert(self.inst_tracking.getIndex(inst).? == inst_tracking_i);4650 if (std.debug.runtime_safety) assert(func.inst_tracking.getIndex(inst).? == inst_tracking_i);
4657 const tracking = &self.inst_tracking.values()[inst_tracking_i];4651 const tracking = &func.inst_tracking.values()[inst_tracking_i];
4658 if (self.liveness.isUnused(inst)) try tracking.die(self, inst);4652 if (func.liveness.isUnused(inst)) try tracking.die(func, inst);
4659 self.getValueIfFree(tracking.short, inst);4653 func.getValueIfFree(tracking.short, inst);
4660 self.finishAirBookkeeping();4654 func.finishAirBookkeeping();
4661}4655}
46624656
4663fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {4657fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void {
4664 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4658 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4665 const condition = try self.resolveInst(pl_op.operand);4659 const condition = try func.resolveInst(pl_op.operand);
4666 const condition_ty = self.typeOf(pl_op.operand);4660 const condition_ty = func.typeOf(pl_op.operand);
4667 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);4661 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);
4668 var extra_index: usize = switch_br.end;4662 var extra_index: usize = switch_br.end;
4669 var case_i: u32 = 0;4663 var case_i: u32 = 0;
4670 const liveness = try self.liveness.getSwitchBr(self.gpa, inst, switch_br.data.cases_len + 1);4664 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);
4671 defer self.gpa.free(liveness.deaths);4665 defer func.gpa.free(liveness.deaths);
46724666
4673 // If the condition dies here in this switch instruction, process4667 // If the condition dies here in this switch instruction, process
4674 // that death now instead of later as this has an effect on4668 // that death now instead of later as this has an effect on
4675 // whether it needs to be spilled in the branches4669 // whether it needs to be spilled in the branches
4676 if (self.liveness.operandDies(inst, 0)) {4670 if (func.liveness.operandDies(inst, 0)) {
4677 if (pl_op.operand.toIndex()) |op_inst| try self.processDeath(op_inst);4671 if (pl_op.operand.toIndex()) |op_inst| try func.processDeath(op_inst);
4678 }4672 }
46794673
4680 self.scope_generation += 1;4674 func.scope_generation += 1;
4681 const state = try self.saveState();4675 const state = try func.saveState();
46824676
4683 while (case_i < switch_br.data.cases_len) : (case_i += 1) {4677 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
4684 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);4678 const case = func.air.extraData(Air.SwitchBr.Case, extra_index);
4685 const items: []const Air.Inst.Ref =4679 const items: []const Air.Inst.Ref =
4686 @ptrCast(self.air.extra[case.end..][0..case.data.items_len]);4680 @ptrCast(func.air.extra[case.end..][0..case.data.items_len]);
4687 const case_body: []const Air.Inst.Index =4681 const case_body: []const Air.Inst.Index =
4688 @ptrCast(self.air.extra[case.end + items.len ..][0..case.data.body_len]);4682 @ptrCast(func.air.extra[case.end + items.len ..][0..case.data.body_len]);
4689 extra_index = case.end + items.len + case_body.len;4683 extra_index = case.end + items.len + case_body.len;
46904684
4691 var relocs = try self.gpa.alloc(Mir.Inst.Index, items.len);4685 var relocs = try func.gpa.alloc(Mir.Inst.Index, items.len);
4692 defer self.gpa.free(relocs);4686 defer func.gpa.free(relocs);
46934687
4694 for (items, relocs, 0..) |item, *reloc, i| {4688 for (items, relocs, 0..) |item, *reloc, i| {
4695 // switch branches must be comptime-known, so this is stored in an immediate4689 // switch branches must be comptime-known, so this is stored in an immediate
4696 const item_mcv = try self.resolveInst(item);4690 const item_mcv = try func.resolveInst(item);
46974691
4698 const cmp_mcv: MCValue = try self.binOp(4692 const cmp_mcv: MCValue = try func.binOp(
4699 .cmp_neq,4693 .cmp_neq,
4700 condition,4694 condition,
4701 condition_ty,4695 condition_ty,
...@@ -4703,10 +4697,10 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4703,10 +4697,10 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
4703 condition_ty,4697 condition_ty,
4704 );4698 );
47054699
4706 const cmp_reg = try self.copyToTmpRegister(Type.bool, cmp_mcv);4700 const cmp_reg = try func.copyToTmpRegister(Type.bool, cmp_mcv);
47074701
4708 if (!(i < relocs.len - 1)) {4702 if (!(i < relocs.len - 1)) {
4709 _ = try self.addInst(.{4703 _ = try func.addInst(.{
4710 .tag = .pseudo,4704 .tag = .pseudo,
4711 .ops = .pseudo_not,4705 .ops = .pseudo_not,
4712 .data = .{ .rr = .{4706 .data = .{ .rr = .{
...@@ -4716,32 +4710,32 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4716,32 +4710,32 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
4716 });4710 });
4717 }4711 }
47184712
4719 reloc.* = try self.condBr(condition_ty, .{ .register = cmp_reg });4713 reloc.* = try func.condBr(condition_ty, .{ .register = cmp_reg });
4720 }4714 }
47214715
4722 for (liveness.deaths[case_i]) |operand| try self.processDeath(operand);4716 for (liveness.deaths[case_i]) |operand| try func.processDeath(operand);
47234717
4724 for (relocs[0 .. relocs.len - 1]) |reloc| self.performReloc(reloc);4718 for (relocs[0 .. relocs.len - 1]) |reloc| func.performReloc(reloc);
4725 try self.genBody(case_body);4719 try func.genBody(case_body);
4726 try self.restoreState(state, &.{}, .{4720 try func.restoreState(state, &.{}, .{
4727 .emit_instructions = false,4721 .emit_instructions = false,
4728 .update_tracking = true,4722 .update_tracking = true,
4729 .resurrect = true,4723 .resurrect = true,
4730 .close_scope = true,4724 .close_scope = true,
4731 });4725 });
47324726
4733 self.performReloc(relocs[relocs.len - 1]);4727 func.performReloc(relocs[relocs.len - 1]);
4734 }4728 }
47354729
4736 if (switch_br.data.else_body_len > 0) {4730 if (switch_br.data.else_body_len > 0) {
4737 const else_body: []const Air.Inst.Index =4731 const else_body: []const Air.Inst.Index =
4738 @ptrCast(self.air.extra[extra_index..][0..switch_br.data.else_body_len]);4732 @ptrCast(func.air.extra[extra_index..][0..switch_br.data.else_body_len]);
47394733
4740 const else_deaths = liveness.deaths.len - 1;4734 const else_deaths = liveness.deaths.len - 1;
4741 for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand);4735 for (liveness.deaths[else_deaths]) |operand| try func.processDeath(operand);
47424736
4743 try self.genBody(else_body);4737 try func.genBody(else_body);
4744 try self.restoreState(state, &.{}, .{4738 try func.restoreState(state, &.{}, .{
4745 .emit_instructions = false,4739 .emit_instructions = false,
4746 .update_tracking = true,4740 .update_tracking = true,
4747 .resurrect = true,4741 .resurrect = true,
...@@ -4750,71 +4744,71 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4750,71 +4744,71 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
4750 }4744 }
47514745
4752 // We already took care of pl_op.operand earlier, so there's nothing left to do4746 // We already took care of pl_op.operand earlier, so there's nothing left to do
4753 self.finishAirBookkeeping();4747 func.finishAirBookkeeping();
4754}4748}
47554749
4756fn performReloc(self: *Self, inst: Mir.Inst.Index) void {4750fn performReloc(func: *Func, inst: Mir.Inst.Index) void {
4757 const tag = self.mir_instructions.items(.tag)[inst];4751 const tag = func.mir_instructions.items(.tag)[inst];
4758 const ops = self.mir_instructions.items(.ops)[inst];4752 const ops = func.mir_instructions.items(.ops)[inst];
4759 const target: Mir.Inst.Index = @intCast(self.mir_instructions.len);4753 const target: Mir.Inst.Index = @intCast(func.mir_instructions.len);
47604754
4761 switch (tag) {4755 switch (tag) {
4762 .bne,4756 .bne,
4763 .beq,4757 .beq,
4764 => self.mir_instructions.items(.data)[inst].b_type.inst = target,4758 => func.mir_instructions.items(.data)[inst].b_type.inst = target,
4765 .jal => self.mir_instructions.items(.data)[inst].j_type.inst = target,4759 .jal => func.mir_instructions.items(.data)[inst].j_type.inst = target,
4766 .pseudo => switch (ops) {4760 .pseudo => switch (ops) {
4767 .pseudo_j => self.mir_instructions.items(.data)[inst].inst = target,4761 .pseudo_j => func.mir_instructions.items(.data)[inst].inst = target,
4768 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}),4762 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}),
4769 },4763 },
4770 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}),4764 else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}),
4771 }4765 }
4772}4766}
47734767
4774fn airBr(self: *Self, inst: Air.Inst.Index) !void {4768fn airBr(func: *Func, inst: Air.Inst.Index) !void {
4775 const mod = self.bin_file.comp.module.?;4769 const mod = func.bin_file.comp.module.?;
4776 const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br;4770 const br = func.air.instructions.items(.data)[@intFromEnum(inst)].br;
47774771
4778 const block_ty = self.typeOfIndex(br.block_inst);4772 const block_ty = func.typeOfIndex(br.block_inst);
4779 const block_unused =4773 const block_unused =
4780 !block_ty.hasRuntimeBitsIgnoreComptime(mod) or self.liveness.isUnused(br.block_inst);4774 !block_ty.hasRuntimeBitsIgnoreComptime(mod) or func.liveness.isUnused(br.block_inst);
4781 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;4775 const block_tracking = func.inst_tracking.getPtr(br.block_inst).?;
4782 const block_data = self.blocks.getPtr(br.block_inst).?;4776 const block_data = func.blocks.getPtr(br.block_inst).?;
4783 const first_br = block_data.relocs.items.len == 0;4777 const first_br = block_data.relocs.items.len == 0;
4784 const block_result = result: {4778 const block_result = result: {
4785 if (block_unused) break :result .none;4779 if (block_unused) break :result .none;
47864780
4787 if (!first_br) try self.getValue(block_tracking.short, null);4781 if (!first_br) try func.getValue(block_tracking.short, null);
4788 const src_mcv = try self.resolveInst(br.operand);4782 const src_mcv = try func.resolveInst(br.operand);
47894783
4790 if (self.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) {4784 if (func.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) {
4791 if (first_br) break :result src_mcv;4785 if (first_br) break :result src_mcv;
47924786
4793 try self.getValue(block_tracking.short, br.block_inst);4787 try func.getValue(block_tracking.short, br.block_inst);
4794 // .long = .none to avoid merging operand and block result stack frames.4788 // .long = .none to avoid merging operand and block result stack frames.
4795 const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv };4789 const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv };
4796 try current_tracking.materializeUnsafe(self, br.block_inst, block_tracking.*);4790 try current_tracking.materializeUnsafe(func, br.block_inst, block_tracking.*);
4797 for (current_tracking.getRegs()) |src_reg| self.register_manager.freeReg(src_reg);4791 for (current_tracking.getRegs()) |src_reg| func.register_manager.freeReg(src_reg);
4798 break :result block_tracking.short;4792 break :result block_tracking.short;
4799 }4793 }
48004794
4801 const dst_mcv = if (first_br) try self.allocRegOrMem(br.block_inst, true) else dst: {4795 const dst_mcv = if (first_br) try func.allocRegOrMem(br.block_inst, true) else dst: {
4802 try self.getValue(block_tracking.short, br.block_inst);4796 try func.getValue(block_tracking.short, br.block_inst);
4803 break :dst block_tracking.short;4797 break :dst block_tracking.short;
4804 };4798 };
4805 try self.genCopy(block_ty, dst_mcv, try self.resolveInst(br.operand));4799 try func.genCopy(block_ty, dst_mcv, try func.resolveInst(br.operand));
4806 break :result dst_mcv;4800 break :result dst_mcv;
4807 };4801 };
48084802
4809 // Process operand death so that it is properly accounted for in the State below.4803 // Process operand death so that it is properly accounted for in the State below.
4810 if (self.liveness.operandDies(inst, 0)) {4804 if (func.liveness.operandDies(inst, 0)) {
4811 if (br.operand.toIndex()) |op_inst| try self.processDeath(op_inst);4805 if (br.operand.toIndex()) |op_inst| try func.processDeath(op_inst);
4812 }4806 }
48134807
4814 if (first_br) {4808 if (first_br) {
4815 block_tracking.* = InstTracking.init(block_result);4809 block_tracking.* = InstTracking.init(block_result);
4816 try self.saveRetroactiveState(&block_data.state);4810 try func.saveRetroactiveState(&block_data.state);
4817 } else try self.restoreState(block_data.state, &.{}, .{4811 } else try func.restoreState(block_data.state, &.{}, .{
4818 .emit_instructions = true,4812 .emit_instructions = true,
4819 .update_tracking = false,4813 .update_tracking = false,
4820 .resurrect = false,4814 .resurrect = false,
...@@ -4823,35 +4817,35 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4823,35 +4817,35 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
48234817
4824 // Emit a jump with a relocation. It will be patched up after the block ends.4818 // Emit a jump with a relocation. It will be patched up after the block ends.
4825 // Leave the jump offset undefined4819 // Leave the jump offset undefined
4826 const jmp_reloc = try self.jump(undefined);4820 const jmp_reloc = try func.jump(undefined);
4827 try block_data.relocs.append(self.gpa, jmp_reloc);4821 try block_data.relocs.append(func.gpa, jmp_reloc);
48284822
4829 // Stop tracking block result without forgetting tracking info4823 // Stop tracking block result without forgetting tracking info
4830 try self.freeValue(block_tracking.short);4824 try func.freeValue(block_tracking.short);
48314825
4832 self.finishAirBookkeeping();4826 func.finishAirBookkeeping();
4833}4827}
48344828
4835fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {4829fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void {
4836 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;4830 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
4837 const tag: Air.Inst.Tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];4831 const tag: Air.Inst.Tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
48384832
4839 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {4833 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
4840 const lhs = try self.resolveInst(bin_op.lhs);4834 const lhs = try func.resolveInst(bin_op.lhs);
4841 const rhs = try self.resolveInst(bin_op.rhs);4835 const rhs = try func.resolveInst(bin_op.rhs);
4842 const lhs_ty = Type.bool;4836 const lhs_ty = Type.bool;
4843 const rhs_ty = Type.bool;4837 const rhs_ty = Type.bool;
48444838
4845 const lhs_reg, const lhs_lock = try self.promoteReg(lhs_ty, lhs, .{});4839 const lhs_reg, const lhs_lock = try func.promoteReg(lhs_ty, lhs, .{});
4846 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);4840 defer if (lhs_lock) |lock| func.register_manager.unlockReg(lock);
48474841
4848 const rhs_reg, const rhs_lock = try self.promoteReg(rhs_ty, rhs, .{});4842 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs, .{});
4849 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);4843 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
48504844
4851 const result_reg, const result_lock = try self.allocReg(.int);4845 const result_reg, const result_lock = try func.allocReg(.int);
4852 defer self.register_manager.unlockReg(result_lock);4846 defer func.register_manager.unlockReg(result_lock);
48534847
4854 _ = try self.addInst(.{4848 _ = try func.addInst(.{
4855 .tag = if (tag == .bool_or) .@"or" else .@"and",4849 .tag = if (tag == .bool_or) .@"or" else .@"and",
4856 .ops = .rrr,4850 .ops = .rrr,
4857 .data = .{ .r_type = .{4851 .data = .{ .r_type = .{
...@@ -4862,8 +4856,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4862,8 +4856,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
4862 });4856 });
48634857
4864 // safety truncate4858 // safety truncate
4865 if (self.wantSafety()) {4859 if (func.wantSafety()) {
4866 _ = try self.addInst(.{4860 _ = try func.addInst(.{
4867 .tag = .andi,4861 .tag = .andi,
4868 .ops = .rri,4862 .ops = .rri,
4869 .data = .{ .i_type = .{4863 .data = .{ .i_type = .{
...@@ -4876,35 +4870,35 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -4876,35 +4870,35 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
48764870
4877 break :result .{ .register = result_reg };4871 break :result .{ .register = result_reg };
4878 };4872 };
4879 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });4873 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
4880}4874}
48814875
4882fn airAsm(self: *Self, inst: Air.Inst.Index) !void {4876fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
4883 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4877 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4884 const extra = self.air.extraData(Air.Asm, ty_pl.payload);4878 const extra = func.air.extraData(Air.Asm, ty_pl.payload);
4885 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;4879 const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
4886 const clobbers_len: u31 = @truncate(extra.data.flags);4880 const clobbers_len: u31 = @truncate(extra.data.flags);
4887 var extra_i: usize = extra.end;4881 var extra_i: usize = extra.end;
4888 const outputs: []const Air.Inst.Ref =4882 const outputs: []const Air.Inst.Ref =
4889 @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]);4883 @ptrCast(func.air.extra[extra_i..][0..extra.data.outputs_len]);
4890 extra_i += outputs.len;4884 extra_i += outputs.len;
4891 const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]);4885 const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra_i..][0..extra.data.inputs_len]);
4892 extra_i += inputs.len;4886 extra_i += inputs.len;
48934887
4894 log.debug("airAsm input: {any}", .{inputs});4888 log.debug("airAsm input: {any}", .{inputs});
48954889
4896 const dead = !is_volatile and self.liveness.isUnused(inst);4890 const dead = !is_volatile and func.liveness.isUnused(inst);
4897 const result: MCValue = if (dead) .unreach else result: {4891 const result: MCValue = if (dead) .unreach else result: {
4898 if (outputs.len > 1) {4892 if (outputs.len > 1) {
4899 return self.fail("TODO implement codegen for asm with more than 1 output", .{});4893 return func.fail("TODO implement codegen for asm with more than 1 output", .{});
4900 }4894 }
49014895
4902 const output_constraint: ?[]const u8 = for (outputs) |output| {4896 const output_constraint: ?[]const u8 = for (outputs) |output| {
4903 if (output != .none) {4897 if (output != .none) {
4904 return self.fail("TODO implement codegen for non-expr asm", .{});4898 return func.fail("TODO implement codegen for non-expr asm", .{});
4905 }4899 }
4906 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);4900 const extra_bytes = std.mem.sliceAsBytes(func.air.extra[extra_i..]);
4907 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);4901 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);
4908 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);4902 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
4909 // This equation accounts for the fact that even if we have exactly 4 bytes4903 // This equation accounts for the fact that even if we have exactly 4 bytes
4910 // for the string, we still use the next u32 for the null terminator.4904 // for the string, we still use the next u32 for the null terminator.
...@@ -4914,7 +4908,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4914,7 +4908,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4914 } else null;4908 } else null;
49154909
4916 for (inputs) |input| {4910 for (inputs) |input| {
4917 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);4911 const input_bytes = std.mem.sliceAsBytes(func.air.extra[extra_i..]);
4918 const constraint = std.mem.sliceTo(input_bytes, 0);4912 const constraint = std.mem.sliceTo(input_bytes, 0);
4919 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);4913 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
4920 // This equation accounts for the fact that even if we have exactly 4 bytes4914 // This equation accounts for the fact that even if we have exactly 4 bytes
...@@ -4922,21 +4916,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4922,21 +4916,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4922 extra_i += (constraint.len + name.len + (2 + 3)) / 4;4916 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
49234917
4924 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {4918 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
4925 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});4919 return func.fail("unrecognized asm input constraint: '{s}'", .{constraint});
4926 }4920 }
4927 const reg_name = constraint[1 .. constraint.len - 1];4921 const reg_name = constraint[1 .. constraint.len - 1];
4928 const reg = parseRegName(reg_name) orelse4922 const reg = parseRegName(reg_name) orelse
4929 return self.fail("unrecognized register: '{s}'", .{reg_name});4923 return func.fail("unrecognized register: '{s}'", .{reg_name});
49304924
4931 const arg_mcv = try self.resolveInst(input);4925 const arg_mcv = try func.resolveInst(input);
4932 try self.register_manager.getReg(reg, null);4926 try func.register_manager.getReg(reg, null);
4933 try self.genSetReg(self.typeOf(input), reg, arg_mcv);4927 try func.genSetReg(func.typeOf(input), reg, arg_mcv);
4934 }4928 }
49354929
4936 {4930 {
4937 var clobber_i: u32 = 0;4931 var clobber_i: u32 = 0;
4938 while (clobber_i < clobbers_len) : (clobber_i += 1) {4932 while (clobber_i < clobbers_len) : (clobber_i += 1) {
4939 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);4933 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra[extra_i..]), 0);
4940 // This equation accounts for the fact that even if we have exactly 4 bytes4934 // This equation accounts for the fact that even if we have exactly 4 bytes
4941 // for the string, we still use the next u32 for the null terminator.4935 // for the string, we still use the next u32 for the null terminator.
4942 extra_i += clobber.len / 4 + 1;4936 extra_i += clobber.len / 4 + 1;
...@@ -4944,31 +4938,31 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4944,31 +4938,31 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4944 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {4938 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {
4945 // nothing really to do4939 // nothing really to do
4946 } else {4940 } else {
4947 try self.register_manager.getReg(parseRegName(clobber) orelse4941 try func.register_manager.getReg(parseRegName(clobber) orelse
4948 return self.fail("invalid clobber: '{s}'", .{clobber}), null);4942 return func.fail("invalid clobber: '{s}'", .{clobber}), null);
4949 }4943 }
4950 }4944 }
4951 }4945 }
49524946
4953 const asm_source = std.mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];4947 const asm_source = std.mem.sliceAsBytes(func.air.extra[extra_i..])[0..extra.data.source_len];
49544948
4955 if (std.meta.stringToEnum(Mir.Inst.Tag, asm_source)) |tag| {4949 if (std.meta.stringToEnum(Mir.Inst.Tag, asm_source)) |tag| {
4956 _ = try self.addInst(.{4950 _ = try func.addInst(.{
4957 .tag = tag,4951 .tag = tag,
4958 .ops = .none,4952 .ops = .none,
4959 .data = undefined,4953 .data = undefined,
4960 });4954 });
4961 } else {4955 } else {
4962 return self.fail("TODO: asm_source {s}", .{asm_source});4956 return func.fail("TODO: asm_source {s}", .{asm_source});
4963 }4957 }
49644958
4965 if (output_constraint) |output| {4959 if (output_constraint) |output| {
4966 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {4960 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
4967 return self.fail("unrecognized asm output constraint: '{s}'", .{output});4961 return func.fail("unrecognized asm output constraint: '{s}'", .{output});
4968 }4962 }
4969 const reg_name = output[2 .. output.len - 1];4963 const reg_name = output[2 .. output.len - 1];
4970 const reg = parseRegName(reg_name) orelse4964 const reg = parseRegName(reg_name) orelse
4971 return self.fail("unrecognized register: '{s}'", .{reg_name});4965 return func.fail("unrecognized register: '{s}'", .{reg_name});
4972 break :result .{ .register = reg };4966 break :result .{ .register = reg };
4973 } else {4967 } else {
4974 break :result .{ .none = {} };4968 break :result .{ .none = {} };
...@@ -4987,17 +4981,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -4987,17 +4981,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
4987 }4981 }
4988 if (buf_index + inputs.len > buf.len) break :simple;4982 if (buf_index + inputs.len > buf.len) break :simple;
4989 @memcpy(buf[buf_index..][0..inputs.len], inputs);4983 @memcpy(buf[buf_index..][0..inputs.len], inputs);
4990 return self.finishAir(inst, result, buf);4984 return func.finishAir(inst, result, buf);
4991 }4985 }
4992 var bt = self.liveness.iterateBigTomb(inst);4986 var bt = func.liveness.iterateBigTomb(inst);
4993 for (outputs) |output| if (output != .none) try self.feed(&bt, output);4987 for (outputs) |output| if (output != .none) try func.feed(&bt, output);
4994 for (inputs) |input| try self.feed(&bt, input);4988 for (inputs) |input| try func.feed(&bt, input);
4995 return self.finishAirResult(inst, result);4989 return func.finishAirResult(inst, result);
4996}4990}
49974991
4998/// Sets the value of `dst_mcv` to the value of `src_mcv`.4992/// Sets the value of `dst_mcv` to the value of `src_mcv`.
4999fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {4993fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5000 const zcu = self.bin_file.comp.module.?;4994 const zcu = func.bin_file.comp.module.?;
50014995
5002 // There isn't anything to store4996 // There isn't anything to store
5003 if (dst_mcv == .none) return;4997 if (dst_mcv == .none) return;
...@@ -5008,8 +5002,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -5008,8 +5002,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5008 }5002 }
50095003
5010 switch (dst_mcv) {5004 switch (dst_mcv) {
5011 .register => |reg| return self.genSetReg(ty, reg, src_mcv),5005 .register => |reg| return func.genSetReg(ty, reg, src_mcv),
5012 .register_offset => |dst_reg_off| try self.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) {5006 .register_offset => |dst_reg_off| try func.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) {
5013 .none,5007 .none,
5014 .unreach,5008 .unreach,
5015 .dead,5009 .dead,
...@@ -5020,49 +5014,49 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -5020,49 +5014,49 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5020 .register_offset,5014 .register_offset,
5021 => src_mcv.offset(-dst_reg_off.off),5015 => src_mcv.offset(-dst_reg_off.off),
5022 else => .{ .register_offset = .{5016 else => .{ .register_offset = .{
5023 .reg = try self.copyToTmpRegister(ty, src_mcv),5017 .reg = try func.copyToTmpRegister(ty, src_mcv),
5024 .off = -dst_reg_off.off,5018 .off = -dst_reg_off.off,
5025 } },5019 } },
5026 }),5020 }),
5027 .indirect => |reg_off| try self.genSetMem(5021 .indirect => |reg_off| try func.genSetMem(
5028 .{ .reg = reg_off.reg },5022 .{ .reg = reg_off.reg },
5029 reg_off.off,5023 reg_off.off,
5030 ty,5024 ty,
5031 src_mcv,5025 src_mcv,
5032 ),5026 ),
5033 .load_frame => |frame_addr| try self.genSetMem(5027 .load_frame => |frame_addr| try func.genSetMem(
5034 .{ .frame = frame_addr.index },5028 .{ .frame = frame_addr.index },
5035 frame_addr.off,5029 frame_addr.off,
5036 ty,5030 ty,
5037 src_mcv,5031 src_mcv,
5038 ),5032 ),
5039 .memory => return self.fail("TODO: genCopy memory", .{}),5033 .memory => return func.fail("TODO: genCopy memory", .{}),
5040 .register_pair => |dst_regs| {5034 .register_pair => |dst_regs| {
5041 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {5035 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {
5042 .register_pair, .memory, .indirect, .load_frame => null,5036 .register_pair, .memory, .indirect, .load_frame => null,
5043 .load_symbol => src: {5037 .load_symbol => src: {
5044 const src_addr_reg, const src_addr_lock = try self.promoteReg(Type.usize, src_mcv.address(), .{});5038 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address(), .{});
5045 errdefer self.register_manager.unlockReg(src_addr_lock);5039 errdefer func.register_manager.unlockReg(src_addr_lock);
50465040
5047 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };5041 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
5048 },5042 },
5049 .air_ref => |src_ref| return self.genCopy(5043 .air_ref => |src_ref| return func.genCopy(
5050 ty,5044 ty,
5051 dst_mcv,5045 dst_mcv,
5052 try self.resolveInst(src_ref),5046 try func.resolveInst(src_ref),
5053 ),5047 ),
5054 else => unreachable,5048 else => unreachable,
5055 };5049 };
50565050
5057 defer if (src_info) |info| {5051 defer if (src_info) |info| {
5058 if (info.addr_lock) |lock| {5052 if (info.addr_lock) |lock| {
5059 self.register_manager.unlockReg(lock);5053 func.register_manager.unlockReg(lock);
5060 }5054 }
5061 };5055 };
50625056
5063 var part_disp: i32 = 0;5057 var part_disp: i32 = 0;
5064 for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {5058 for (dst_regs, try func.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
5065 try self.genSetReg(dst_ty, dst_reg, switch (src_mcv) {5059 try func.genSetReg(dst_ty, dst_reg, switch (src_mcv) {
5066 .register_pair => |src_regs| .{ .register = src_regs[part_i] },5060 .register_pair => |src_regs| .{ .register = src_regs[part_i] },
5067 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),5061 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
5068 .load_symbol => .{ .indirect = .{5062 .load_symbol => .{ .indirect = .{
...@@ -5074,31 +5068,31 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -5074,31 +5068,31 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5074 part_disp += @intCast(dst_ty.abiSize(zcu));5068 part_disp += @intCast(dst_ty.abiSize(zcu));
5075 }5069 }
5076 },5070 },
5077 else => return self.fail("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),5071 else => return func.fail("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
5078 }5072 }
5079}5073}
50805074
5081fn genInlineMemcpy(5075fn genInlineMemcpy(
5082 self: *Self,5076 func: *Func,
5083 dst_ptr: MCValue,5077 dst_ptr: MCValue,
5084 src_ptr: MCValue,5078 src_ptr: MCValue,
5085 len: MCValue,5079 len: MCValue,
5086) !void {5080) !void {
5087 const regs = try self.register_manager.allocRegs(4, .{null} ** 4, abi.Registers.Integer.temporary);5081 const regs = try func.register_manager.allocRegs(4, .{null} ** 4, abi.Registers.Integer.temporary);
5088 const locks = self.register_manager.lockRegsAssumeUnused(4, regs);5082 const locks = func.register_manager.lockRegsAssumeUnused(4, regs);
5089 defer for (locks) |lock| self.register_manager.unlockReg(lock);5083 defer for (locks) |lock| func.register_manager.unlockReg(lock);
50905084
5091 const count = regs[0];5085 const count = regs[0];
5092 const tmp = regs[1];5086 const tmp = regs[1];
5093 const src = regs[2];5087 const src = regs[2];
5094 const dst = regs[3];5088 const dst = regs[3];
50955089
5096 try self.genSetReg(Type.usize, count, len);5090 try func.genSetReg(Type.usize, count, len);
5097 try self.genSetReg(Type.usize, src, src_ptr);5091 try func.genSetReg(Type.usize, src, src_ptr);
5098 try self.genSetReg(Type.usize, dst, dst_ptr);5092 try func.genSetReg(Type.usize, dst, dst_ptr);
50995093
5100 // lb tmp, 0(src)5094 // lb tmp, 0(src)
5101 const first_inst = try self.addInst(.{5095 const first_inst = try func.addInst(.{
5102 .tag = .lb,5096 .tag = .lb,
5103 .ops = .rri,5097 .ops = .rri,
5104 .data = .{5098 .data = .{
...@@ -5111,7 +5105,7 @@ fn genInlineMemcpy(...@@ -5111,7 +5105,7 @@ fn genInlineMemcpy(
5111 });5105 });
51125106
5113 // sb tmp, 0(dst)5107 // sb tmp, 0(dst)
5114 _ = try self.addInst(.{5108 _ = try func.addInst(.{
5115 .tag = .sb,5109 .tag = .sb,
5116 .ops = .rri,5110 .ops = .rri,
5117 .data = .{5111 .data = .{
...@@ -5124,7 +5118,7 @@ fn genInlineMemcpy(...@@ -5124,7 +5118,7 @@ fn genInlineMemcpy(
5124 });5118 });
51255119
5126 // dec count by 15120 // dec count by 1
5127 _ = try self.addInst(.{5121 _ = try func.addInst(.{
5128 .tag = .addi,5122 .tag = .addi,
5129 .ops = .rri,5123 .ops = .rri,
5130 .data = .{5124 .data = .{
...@@ -5137,12 +5131,12 @@ fn genInlineMemcpy(...@@ -5137,12 +5131,12 @@ fn genInlineMemcpy(
5137 });5131 });
51385132
5139 // branch if count is 05133 // branch if count is 0
5140 _ = try self.addInst(.{5134 _ = try func.addInst(.{
5141 .tag = .beq,5135 .tag = .beq,
5142 .ops = .rr_inst,5136 .ops = .rr_inst,
5143 .data = .{5137 .data = .{
5144 .b_type = .{5138 .b_type = .{
5145 .inst = @intCast(self.mir_instructions.len + 4), // points after the last inst5139 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
5146 .rs1 = count,5140 .rs1 = count,
5147 .rs2 = .zero,5141 .rs2 = .zero,
5148 },5142 },
...@@ -5150,7 +5144,7 @@ fn genInlineMemcpy(...@@ -5150,7 +5144,7 @@ fn genInlineMemcpy(
5150 });5144 });
51515145
5152 // increment the pointers5146 // increment the pointers
5153 _ = try self.addInst(.{5147 _ = try func.addInst(.{
5154 .tag = .addi,5148 .tag = .addi,
5155 .ops = .rri,5149 .ops = .rri,
5156 .data = .{5150 .data = .{
...@@ -5162,7 +5156,7 @@ fn genInlineMemcpy(...@@ -5162,7 +5156,7 @@ fn genInlineMemcpy(
5162 },5156 },
5163 });5157 });
51645158
5165 _ = try self.addInst(.{5159 _ = try func.addInst(.{
5166 .tag = .addi,5160 .tag = .addi,
5167 .ops = .rri,5161 .ops = .rri,
5168 .data = .{5162 .data = .{
...@@ -5175,7 +5169,7 @@ fn genInlineMemcpy(...@@ -5175,7 +5169,7 @@ fn genInlineMemcpy(
5175 });5169 });
51765170
5177 // jump back to start of loop5171 // jump back to start of loop
5178 _ = try self.addInst(.{5172 _ = try func.addInst(.{
5179 .tag = .pseudo,5173 .tag = .pseudo,
5180 .ops = .pseudo_j,5174 .ops = .pseudo_j,
5181 .data = .{ .inst = first_inst },5175 .data = .{ .inst = first_inst },
...@@ -5183,25 +5177,25 @@ fn genInlineMemcpy(...@@ -5183,25 +5177,25 @@ fn genInlineMemcpy(
5183}5177}
51845178
5185fn genInlineMemset(5179fn genInlineMemset(
5186 self: *Self,5180 func: *Func,
5187 dst_ptr: MCValue,5181 dst_ptr: MCValue,
5188 src_value: MCValue,5182 src_value: MCValue,
5189 len: MCValue,5183 len: MCValue,
5190) !void {5184) !void {
5191 const regs = try self.register_manager.allocRegs(3, .{null} ** 3, abi.Registers.Integer.temporary);5185 const regs = try func.register_manager.allocRegs(3, .{null} ** 3, abi.Registers.Integer.temporary);
5192 const locks = self.register_manager.lockRegsAssumeUnused(3, regs);5186 const locks = func.register_manager.lockRegsAssumeUnused(3, regs);
5193 defer for (locks) |lock| self.register_manager.unlockReg(lock);5187 defer for (locks) |lock| func.register_manager.unlockReg(lock);
51945188
5195 const count = regs[0];5189 const count = regs[0];
5196 const src = regs[1];5190 const src = regs[1];
5197 const dst = regs[2];5191 const dst = regs[2];
51985192
5199 try self.genSetReg(Type.usize, count, len);5193 try func.genSetReg(Type.usize, count, len);
5200 try self.genSetReg(Type.usize, src, src_value);5194 try func.genSetReg(Type.usize, src, src_value);
5201 try self.genSetReg(Type.usize, dst, dst_ptr);5195 try func.genSetReg(Type.usize, dst, dst_ptr);
52025196
5203 // sb src, 0(dst)5197 // sb src, 0(dst)
5204 const first_inst = try self.addInst(.{5198 const first_inst = try func.addInst(.{
5205 .tag = .sb,5199 .tag = .sb,
5206 .ops = .rri,5200 .ops = .rri,
5207 .data = .{5201 .data = .{
...@@ -5214,7 +5208,7 @@ fn genInlineMemset(...@@ -5214,7 +5208,7 @@ fn genInlineMemset(
5214 });5208 });
52155209
5216 // dec count by 15210 // dec count by 1
5217 _ = try self.addInst(.{5211 _ = try func.addInst(.{
5218 .tag = .addi,5212 .tag = .addi,
5219 .ops = .rri,5213 .ops = .rri,
5220 .data = .{5214 .data = .{
...@@ -5227,12 +5221,12 @@ fn genInlineMemset(...@@ -5227,12 +5221,12 @@ fn genInlineMemset(
5227 });5221 });
52285222
5229 // branch if count is 05223 // branch if count is 0
5230 _ = try self.addInst(.{5224 _ = try func.addInst(.{
5231 .tag = .beq,5225 .tag = .beq,
5232 .ops = .rr_inst,5226 .ops = .rr_inst,
5233 .data = .{5227 .data = .{
5234 .b_type = .{5228 .b_type = .{
5235 .inst = @intCast(self.mir_instructions.len + 4), // points after the last inst5229 .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
5236 .rs1 = count,5230 .rs1 = count,
5237 .rs2 = .zero,5231 .rs2 = .zero,
5238 },5232 },
...@@ -5240,7 +5234,7 @@ fn genInlineMemset(...@@ -5240,7 +5234,7 @@ fn genInlineMemset(
5240 });5234 });
52415235
5242 // increment the pointers5236 // increment the pointers
5243 _ = try self.addInst(.{5237 _ = try func.addInst(.{
5244 .tag = .addi,5238 .tag = .addi,
5245 .ops = .rri,5239 .ops = .rri,
5246 .data = .{5240 .data = .{
...@@ -5253,7 +5247,7 @@ fn genInlineMemset(...@@ -5253,7 +5247,7 @@ fn genInlineMemset(
5253 });5247 });
52545248
5255 // jump back to start of loop5249 // jump back to start of loop
5256 _ = try self.addInst(.{5250 _ = try func.addInst(.{
5257 .tag = .pseudo,5251 .tag = .pseudo,
5258 .ops = .pseudo_j,5252 .ops = .pseudo_j,
5259 .data = .{5253 .data = .{
...@@ -5263,8 +5257,8 @@ fn genInlineMemset(...@@ -5263,8 +5257,8 @@ fn genInlineMemset(
5263}5257}
52645258
5265/// Sets the value of `src_mcv` into `reg`. Assumes you have a lock on it.5259/// Sets the value of `src_mcv` into `reg`. Assumes you have a lock on it.
5266fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!void {5260fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!void {
5267 const zcu = self.bin_file.comp.module.?;5261 const zcu = func.bin_file.comp.module.?;
5268 const abi_size: u32 = @intCast(ty.abiSize(zcu));5262 const abi_size: u32 = @intCast(ty.abiSize(zcu));
52695263
5270 if (abi_size > 8) return std.debug.panic("tried to set reg with size {}", .{abi_size});5264 if (abi_size > 8) return std.debug.panic("tried to set reg with size {}", .{abi_size});
...@@ -5275,17 +5269,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5275,17 +5269,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5275 .dead => unreachable,5269 .dead => unreachable,
5276 .unreach, .none => return, // Nothing to do.5270 .unreach, .none => return, // Nothing to do.
5277 .undef => {5271 .undef => {
5278 if (!self.wantSafety())5272 if (!func.wantSafety())
5279 return; // The already existing value will do just fine.5273 return; // The already existing value will do just fine.
5280 // Write the debug undefined value.5274 // Write the debug undefined value.
5281 return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });5275 return func.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
5282 },5276 },
5283 .immediate => |unsigned_x| {5277 .immediate => |unsigned_x| {
5284 assert(dst_reg_class == .int);5278 assert(dst_reg_class == .int);
52855279
5286 const x: i64 = @bitCast(unsigned_x);5280 const x: i64 = @bitCast(unsigned_x);
5287 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {5281 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {
5288 _ = try self.addInst(.{5282 _ = try func.addInst(.{
5289 .tag = .addi,5283 .tag = .addi,
5290 .ops = .rri,5284 .ops = .rri,
5291 .data = .{ .i_type = .{5285 .data = .{ .i_type = .{
...@@ -5299,7 +5293,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5299,7 +5293,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5299 const carry: i32 = if (lo12 < 0) 1 else 0;5293 const carry: i32 = if (lo12 < 0) 1 else 0;
5300 const hi20: i20 = @truncate((x >> 12) +% carry);5294 const hi20: i20 = @truncate((x >> 12) +% carry);
53015295
5302 _ = try self.addInst(.{5296 _ = try func.addInst(.{
5303 .tag = .lui,5297 .tag = .lui,
5304 .ops = .ri,5298 .ops = .ri,
5305 .data = .{ .u_type = .{5299 .data = .{ .u_type = .{
...@@ -5307,7 +5301,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5307,7 +5301,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5307 .imm20 = Immediate.s(hi20),5301 .imm20 = Immediate.s(hi20),
5308 } },5302 } },
5309 });5303 });
5310 _ = try self.addInst(.{5304 _ = try func.addInst(.{
5311 .tag = .addi,5305 .tag = .addi,
5312 .ops = .rri,5306 .ops = .rri,
5313 .data = .{ .i_type = .{5307 .data = .{ .i_type = .{
...@@ -5320,17 +5314,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5320,17 +5314,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5320 // TODO: use a more advanced myriad seq to do this without a reg.5314 // TODO: use a more advanced myriad seq to do this without a reg.
5321 // see: https://github.com/llvm/llvm-project/blob/081a66ffacfe85a37ff775addafcf3371e967328/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp#L2245315 // see: https://github.com/llvm/llvm-project/blob/081a66ffacfe85a37ff775addafcf3371e967328/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp#L224
53225316
5323 const temp, const temp_lock = try self.allocReg(.int);5317 const temp, const temp_lock = try func.allocReg(.int);
5324 defer self.register_manager.unlockReg(temp_lock);5318 defer func.register_manager.unlockReg(temp_lock);
53255319
5326 const lo32: i32 = @truncate(x);5320 const lo32: i32 = @truncate(x);
5327 const carry: i32 = if (lo32 < 0) 1 else 0;5321 const carry: i32 = if (lo32 < 0) 1 else 0;
5328 const hi32: i32 = @truncate((x >> 32) +% carry);5322 const hi32: i32 = @truncate((x >> 32) +% carry);
53295323
5330 try self.genSetReg(Type.i32, temp, .{ .immediate = @bitCast(@as(i64, lo32)) });5324 try func.genSetReg(Type.i32, temp, .{ .immediate = @bitCast(@as(i64, lo32)) });
5331 try self.genSetReg(Type.i32, reg, .{ .immediate = @bitCast(@as(i64, hi32)) });5325 try func.genSetReg(Type.i32, reg, .{ .immediate = @bitCast(@as(i64, hi32)) });
53325326
5333 _ = try self.addInst(.{5327 _ = try func.addInst(.{
5334 .tag = .slli,5328 .tag = .slli,
5335 .ops = .rri,5329 .ops = .rri,
5336 .data = .{ .i_type = .{5330 .data = .{ .i_type = .{
...@@ -5340,7 +5334,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5340,7 +5334,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5340 } },5334 } },
5341 });5335 });
53425336
5343 _ = try self.addInst(.{5337 _ = try func.addInst(.{
5344 .tag = .add,5338 .tag = .add,
5345 .ops = .rrr,5339 .ops = .rrr,
5346 .data = .{ .r_type = .{5340 .data = .{ .r_type = .{
...@@ -5360,11 +5354,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5360,11 +5354,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
53605354
5361 if (src_reg_class == .float and dst_reg_class == .int) {5355 if (src_reg_class == .float and dst_reg_class == .int) {
5362 // to move from float -> int, we use FMV.X.W5356 // to move from float -> int, we use FMV.X.W
5363 return self.fail("TODO: genSetReg float -> int", .{});5357 return func.fail("TODO: genSetReg float -> int", .{});
5364 }5358 }
53655359
5366 // mv reg, src_reg5360 // mv reg, src_reg
5367 _ = try self.addInst(.{5361 _ = try func.addInst(.{
5368 .tag = .pseudo,5362 .tag = .pseudo,
5369 .ops = .pseudo_mv,5363 .ops = .pseudo_mv,
5370 .data = .{ .rr = .{5364 .data = .{ .rr = .{
...@@ -5373,9 +5367,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5373,9 +5367,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5373 } },5367 } },
5374 });5368 });
5375 },5369 },
5376 .register_pair => return self.fail("genSetReg should we allow reg -> reg_pair?", .{}),5370 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),
5377 .load_frame => |frame| {5371 .load_frame => |frame| {
5378 _ = try self.addInst(.{5372 _ = try func.addInst(.{
5379 .tag = .pseudo,5373 .tag = .pseudo,
5380 .ops = .pseudo_load_rm,5374 .ops = .pseudo_load_rm,
5381 .data = .{ .rm = .{5375 .data = .{ .rm = .{
...@@ -5384,7 +5378,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5384,7 +5378,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5384 .base = .{ .frame = frame.index },5378 .base = .{ .frame = frame.index },
5385 .mod = .{5379 .mod = .{
5386 .rm = .{5380 .rm = .{
5387 .size = self.memSize(ty),5381 .size = func.memSize(ty),
5388 .disp = frame.off,5382 .disp = frame.off,
5389 },5383 },
5390 },5384 },
...@@ -5393,9 +5387,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5393,9 +5387,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5393 });5387 });
5394 },5388 },
5395 .memory => |addr| {5389 .memory => |addr| {
5396 try self.genSetReg(ty, reg, .{ .immediate = addr });5390 try func.genSetReg(ty, reg, .{ .immediate = addr });
53975391
5398 _ = try self.addInst(.{5392 _ = try func.addInst(.{
5399 .tag = .ld,5393 .tag = .ld,
5400 .ops = .rri,5394 .ops = .rri,
5401 .data = .{ .i_type = .{5395 .data = .{ .i_type = .{
...@@ -5406,7 +5400,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5406,7 +5400,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5406 });5400 });
5407 },5401 },
5408 .lea_frame, .register_offset => {5402 .lea_frame, .register_offset => {
5409 _ = try self.addInst(.{5403 _ = try func.addInst(.{
5410 .tag = .pseudo,5404 .tag = .pseudo,
5411 .ops = .pseudo_lea_rm,5405 .ops = .pseudo_lea_rm,
5412 .data = .{ .rm = .{5406 .data = .{ .rm = .{
...@@ -5416,7 +5410,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5416,7 +5410,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5416 .base = .{ .reg = reg_off.reg },5410 .base = .{ .reg = reg_off.reg },
5417 .mod = .{5411 .mod = .{
5418 .rm = .{5412 .rm = .{
5419 .size = self.memSize(ty),5413 .size = func.memSize(ty),
5420 .disp = reg_off.off,5414 .disp = reg_off.off,
5421 },5415 },
5422 },5416 },
...@@ -5425,7 +5419,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5425,7 +5419,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5425 .base = .{ .frame = frame.index },5419 .base = .{ .frame = frame.index },
5426 .mod = .{5420 .mod = .{
5427 .rm = .{5421 .rm = .{
5428 .size = self.memSize(ty),5422 .size = func.memSize(ty),
5429 .disp = frame.off,5423 .disp = frame.off,
5430 },5424 },
5431 },5425 },
...@@ -5444,7 +5438,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5444,7 +5438,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5444 else5438 else
5445 .lb,5439 .lb,
5446 2 => if (float_class)5440 2 => if (float_class)
5447 return self.fail("TODO: genSetReg indirect 16-bit float", .{})5441 return func.fail("TODO: genSetReg indirect 16-bit float", .{})
5448 else5442 else
5449 .lh,5443 .lh,
5450 4 => if (float_class) .flw else .lw,5444 4 => if (float_class) .flw else .lw,
...@@ -5452,7 +5446,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5452,7 +5446,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5452 else => return std.debug.panic("TODO: genSetReg for size {d}", .{abi_size}),5446 else => return std.debug.panic("TODO: genSetReg for size {d}", .{abi_size}),
5453 };5447 };
54545448
5455 _ = try self.addInst(.{5449 _ = try func.addInst(.{
5456 .tag = load_tag,5450 .tag = load_tag,
5457 .ops = .rri,5451 .ops = .rri,
5458 .data = .{ .i_type = .{5452 .data = .{ .i_type = .{
...@@ -5465,12 +5459,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5465,12 +5459,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5465 .lea_symbol => |sym_off| {5459 .lea_symbol => |sym_off| {
5466 assert(sym_off.off == 0);5460 assert(sym_off.off == 0);
54675461
5468 const atom_index = try self.symbolIndex();5462 const atom_index = try func.symbolIndex();
54695463
5470 _ = try self.addInst(.{5464 _ = try func.addInst(.{
5471 .tag = .pseudo,5465 .tag = .pseudo,
5472 .ops = .pseudo_load_symbol,5466 .ops = .pseudo_load_symbol,
5473 .data = .{ .payload = try self.addExtra(Mir.LoadSymbolPayload{5467 .data = .{ .payload = try func.addExtra(Mir.LoadSymbolPayload{
5474 .register = reg.encodeId(),5468 .register = reg.encodeId(),
5475 .atom_index = atom_index,5469 .atom_index = atom_index,
5476 .sym_index = sym_off.sym,5470 .sym_index = sym_off.sym,
...@@ -5478,25 +5472,25 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5478,25 +5472,25 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5478 });5472 });
5479 },5473 },
5480 .load_symbol => {5474 .load_symbol => {
5481 const addr_reg, const addr_lock = try self.allocReg(.int);5475 const addr_reg, const addr_lock = try func.allocReg(.int);
5482 defer self.register_manager.unlockReg(addr_lock);5476 defer func.register_manager.unlockReg(addr_lock);
54835477
5484 try self.genSetReg(ty, addr_reg, src_mcv.address());5478 try func.genSetReg(ty, addr_reg, src_mcv.address());
5485 try self.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } });5479 try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } });
5486 },5480 },
5487 .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)),5481 .air_ref => |ref| try func.genSetReg(ty, reg, try func.resolveInst(ref)),
5488 else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),5482 else => return func.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
5489 }5483 }
5490}5484}
54915485
5492fn genSetMem(5486fn genSetMem(
5493 self: *Self,5487 func: *Func,
5494 base: Memory.Base,5488 base: Memory.Base,
5495 disp: i32,5489 disp: i32,
5496 ty: Type,5490 ty: Type,
5497 src_mcv: MCValue,5491 src_mcv: MCValue,
5498) InnerError!void {5492) InnerError!void {
5499 const mod = self.bin_file.comp.module.?;5493 const mod = func.bin_file.comp.module.?;
5500 const abi_size: u32 = @intCast(ty.abiSize(mod));5494 const abi_size: u32 = @intCast(ty.abiSize(mod));
5501 const dst_ptr_mcv: MCValue = switch (base) {5495 const dst_ptr_mcv: MCValue = switch (base) {
5502 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },5496 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
...@@ -5509,7 +5503,7 @@ fn genSetMem(...@@ -5509,7 +5503,7 @@ fn genSetMem(
5509 .dead,5503 .dead,
5510 .reserved_frame,5504 .reserved_frame,
5511 => unreachable,5505 => unreachable,
5512 .undef => try self.genInlineMemset(5506 .undef => try func.genInlineMemset(
5513 dst_ptr_mcv,5507 dst_ptr_mcv,
5514 src_mcv,5508 src_mcv,
5515 .{ .immediate = abi_size },5509 .{ .immediate = abi_size },
...@@ -5525,13 +5519,13 @@ fn genSetMem(...@@ -5525,13 +5519,13 @@ fn genSetMem(
5525 0 => {},5519 0 => {},
5526 1, 2, 4, 8 => {5520 1, 2, 4, 8 => {
5527 // no matter what type, it should use an integer register5521 // no matter what type, it should use an integer register
5528 const src_reg = try self.copyToTmpRegister(Type.usize, src_mcv);5522 const src_reg = try func.copyToTmpRegister(Type.usize, src_mcv);
5529 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);5523 const src_lock = func.register_manager.lockRegAssumeUnused(src_reg);
5530 defer self.register_manager.unlockReg(src_lock);5524 defer func.register_manager.unlockReg(src_lock);
55315525
5532 try self.genSetMem(base, disp, ty, .{ .register = src_reg });5526 try func.genSetMem(base, disp, ty, .{ .register = src_reg });
5533 },5527 },
5534 else => try self.genInlineMemcpy(5528 else => try func.genInlineMemcpy(
5535 dst_ptr_mcv,5529 dst_ptr_mcv,
5536 src_mcv.address(),5530 src_mcv.address(),
5537 .{ .immediate = abi_size },5531 .{ .immediate = abi_size },
...@@ -5541,8 +5535,8 @@ fn genSetMem(...@@ -5541,8 +5535,8 @@ fn genSetMem(
5541 const mem_size = switch (base) {5535 const mem_size = switch (base) {
5542 .frame => |base_fi| mem_size: {5536 .frame => |base_fi| mem_size: {
5543 assert(disp >= 0);5537 assert(disp >= 0);
5544 const frame_abi_size = self.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];5538 const frame_abi_size = func.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];
5545 const frame_spill_pad = self.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];5539 const frame_spill_pad = func.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];
5546 assert(frame_abi_size - frame_spill_pad - disp >= abi_size);5540 assert(frame_abi_size - frame_spill_pad - disp >= abi_size);
5547 break :mem_size if (frame_abi_size - frame_spill_pad - disp == abi_size)5541 break :mem_size if (frame_abi_size - frame_spill_pad - disp == abi_size)
5548 frame_abi_size5542 frame_abi_size
...@@ -5554,12 +5548,12 @@ fn genSetMem(...@@ -5554,12 +5548,12 @@ fn genSetMem(
5554 const src_size = math.ceilPowerOfTwoAssert(u32, abi_size);5548 const src_size = math.ceilPowerOfTwoAssert(u32, abi_size);
5555 const src_align = Alignment.fromNonzeroByteUnits(math.ceilPowerOfTwoAssert(u32, src_size));5549 const src_align = Alignment.fromNonzeroByteUnits(math.ceilPowerOfTwoAssert(u32, src_size));
5556 if (src_size > mem_size) {5550 if (src_size > mem_size) {
5557 const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{5551 const frame_index = try func.allocFrameIndex(FrameAlloc.init(.{
5558 .size = src_size,5552 .size = src_size,
5559 .alignment = src_align,5553 .alignment = src_align,
5560 }));5554 }));
5561 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };5555 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };
5562 _ = try self.addInst(.{5556 _ = try func.addInst(.{
5563 .tag = .pseudo,5557 .tag = .pseudo,
5564 .ops = .pseudo_store_rm,5558 .ops = .pseudo_store_rm,
5565 .data = .{ .rm = .{5559 .data = .{ .rm = .{
...@@ -5572,9 +5566,9 @@ fn genSetMem(...@@ -5572,9 +5566,9 @@ fn genSetMem(
5572 },5566 },
5573 } },5567 } },
5574 });5568 });
5575 try self.genSetMem(base, disp, ty, frame_mcv);5569 try func.genSetMem(base, disp, ty, frame_mcv);
5576 try self.freeValue(frame_mcv);5570 try func.freeValue(frame_mcv);
5577 } else _ = try self.addInst(.{5571 } else _ = try func.addInst(.{
5578 .tag = .pseudo,5572 .tag = .pseudo,
5579 .ops = .pseudo_store_rm,5573 .ops = .pseudo_store_rm,
5580 .data = .{ .rm = .{5574 .data = .{ .rm = .{
...@@ -5582,7 +5576,7 @@ fn genSetMem(...@@ -5582,7 +5576,7 @@ fn genSetMem(
5582 .m = .{5576 .m = .{
5583 .base = base,5577 .base = base,
5584 .mod = .{ .rm = .{5578 .mod = .{ .rm = .{
5585 .size = self.memSize(ty),5579 .size = func.memSize(ty),
5586 .disp = disp,5580 .disp = disp,
5587 } },5581 } },
5588 },5582 },
...@@ -5591,54 +5585,54 @@ fn genSetMem(...@@ -5591,54 +5585,54 @@ fn genSetMem(
5591 },5585 },
5592 .register_pair => |src_regs| {5586 .register_pair => |src_regs| {
5593 var part_disp: i32 = disp;5587 var part_disp: i32 = disp;
5594 for (try self.splitType(ty), src_regs) |src_ty, src_reg| {5588 for (try func.splitType(ty), src_regs) |src_ty, src_reg| {
5595 try self.genSetMem(base, part_disp, src_ty, .{ .register = src_reg });5589 try func.genSetMem(base, part_disp, src_ty, .{ .register = src_reg });
5596 part_disp += @intCast(src_ty.abiSize(mod));5590 part_disp += @intCast(src_ty.abiSize(mod));
5597 }5591 }
5598 },5592 },
5599 .immediate => {5593 .immediate => {
5600 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with5594 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with
5601 // a register allocation.5595 // a register allocation.
5602 const reg, const reg_lock = try self.promoteReg(ty, src_mcv, .{});5596 const reg, const reg_lock = try func.promoteReg(ty, src_mcv, .{});
5603 defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);5597 defer if (reg_lock) |lock| func.register_manager.unlockReg(lock);
56045598
5605 return self.genSetMem(base, disp, ty, .{ .register = reg });5599 return func.genSetMem(base, disp, ty, .{ .register = reg });
5606 },5600 },
5607 .air_ref => |src_ref| try self.genSetMem(base, disp, ty, try self.resolveInst(src_ref)),5601 .air_ref => |src_ref| try func.genSetMem(base, disp, ty, try func.resolveInst(src_ref)),
5608 }5602 }
5609}5603}
56105604
5611fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void {5605fn airIntFromPtr(func: *Func, inst: Air.Inst.Index) !void {
5612 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5606 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5613 const result = result: {5607 const result = result: {
5614 const src_mcv = try self.resolveInst(un_op);5608 const src_mcv = try func.resolveInst(un_op);
5615 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;5609 if (func.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
56165610
5617 const dst_mcv = try self.allocRegOrMem(inst, true);5611 const dst_mcv = try func.allocRegOrMem(inst, true);
5618 const dst_ty = self.typeOfIndex(inst);5612 const dst_ty = func.typeOfIndex(inst);
5619 try self.genCopy(dst_ty, dst_mcv, src_mcv);5613 try func.genCopy(dst_ty, dst_mcv, src_mcv);
5620 break :result dst_mcv;5614 break :result dst_mcv;
5621 };5615 };
5622 return self.finishAir(inst, result, .{ un_op, .none, .none });5616 return func.finishAir(inst, result, .{ un_op, .none, .none });
5623}5617}
56245618
5625fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {5619fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
5626 const zcu = self.bin_file.comp.module.?;5620 const zcu = func.bin_file.comp.module.?;
56275621
5628 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5622 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5629 const result = if (self.liveness.isUnused(inst)) .unreach else result: {5623 const result = if (func.liveness.isUnused(inst)) .unreach else result: {
5630 const src_mcv = try self.resolveInst(ty_op.operand);5624 const src_mcv = try func.resolveInst(ty_op.operand);
56315625
5632 const dst_ty = self.typeOfIndex(inst);5626 const dst_ty = func.typeOfIndex(inst);
5633 const src_ty = self.typeOf(ty_op.operand);5627 const src_ty = func.typeOf(ty_op.operand);
56345628
5635 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;5629 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;
5636 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);5630 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
56375631
5638 const dst_mcv = if (dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and5632 const dst_mcv = if (dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and
5639 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {5633 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
5640 const dst_mcv = try self.allocRegOrMem(inst, true);5634 const dst_mcv = try func.allocRegOrMem(inst, true);
5641 try self.genCopy(switch (math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {5635 try func.genCopy(switch (math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {
5642 .lt => dst_ty,5636 .lt => dst_ty,
5643 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,5637 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
5644 .gt => src_ty,5638 .gt => src_ty,
...@@ -5653,83 +5647,83 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -5653,83 +5647,83 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
5653 const bit_size = dst_ty.bitSize(zcu);5647 const bit_size = dst_ty.bitSize(zcu);
5654 if (abi_size * 8 <= bit_size) break :result dst_mcv;5648 if (abi_size * 8 <= bit_size) break :result dst_mcv;
56555649
5656 return self.fail("TODO: airBitCast {} to {}", .{ src_ty.fmt(zcu), dst_ty.fmt(zcu) });5650 return func.fail("TODO: airBitCast {} to {}", .{ src_ty.fmt(zcu), dst_ty.fmt(zcu) });
5657 };5651 };
5658 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5652 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5659}5653}
56605654
5661fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {5655fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
5662 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5656 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5663 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airArrayToSlice for {}", .{5657 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airArrayToSlice for {}", .{
5664 self.target.cpu.arch,5658 func.target.cpu.arch,
5665 });5659 });
5666 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5660 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5667}5661}
56685662
5669fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {5663fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {
5670 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5664 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5671 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airFloatFromInt for {}", .{5665 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFloatFromInt for {}", .{
5672 self.target.cpu.arch,5666 func.target.cpu.arch,
5673 });5667 });
5674 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5668 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5675}5669}
56765670
5677fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {5671fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
5678 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5672 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5679 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airIntFromFloat for {}", .{5673 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airIntFromFloat for {}", .{
5680 self.target.cpu.arch,5674 func.target.cpu.arch,
5681 });5675 });
5682 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5676 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5683}5677}
56845678
5685fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {5679fn airCmpxchg(func: *Func, inst: Air.Inst.Index) !void {
5686 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5680 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5687 const extra = self.air.extraData(Air.Block, ty_pl.payload);5681 const extra = func.air.extraData(Air.Block, ty_pl.payload);
5688 _ = extra;5682 _ = extra;
5689 return self.fail("TODO implement airCmpxchg for {}", .{5683 return func.fail("TODO implement airCmpxchg for {}", .{
5690 self.target.cpu.arch,5684 func.target.cpu.arch,
5691 });5685 });
5692 // return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });5686 // return func.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
5693}5687}
56945688
5695fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {5689fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void {
5696 _ = inst;5690 _ = inst;
5697 return self.fail("TODO implement airCmpxchg for {}", .{self.target.cpu.arch});5691 return func.fail("TODO implement airCmpxchg for {}", .{func.target.cpu.arch});
5698}5692}
56995693
5700fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {5694fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
5701 _ = inst;5695 _ = inst;
5702 return self.fail("TODO implement airAtomicLoad for {}", .{self.target.cpu.arch});5696 return func.fail("TODO implement airAtomicLoad for {}", .{func.target.cpu.arch});
5703}5697}
57045698
5705fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {5699fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {
5706 _ = inst;5700 _ = inst;
5707 _ = order;5701 _ = order;
5708 return self.fail("TODO implement airAtomicStore for {}", .{self.target.cpu.arch});5702 return func.fail("TODO implement airAtomicStore for {}", .{func.target.cpu.arch});
5709}5703}
57105704
5711fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {5705fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
5712 const zcu = self.bin_file.comp.module.?;5706 const zcu = func.bin_file.comp.module.?;
5713 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;5707 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
57145708
5715 result: {5709 result: {
5716 if (!safety and (try self.resolveInst(bin_op.rhs)) == .undef) break :result;5710 if (!safety and (try func.resolveInst(bin_op.rhs)) == .undef) break :result;
57175711
5718 const dst_ptr = try self.resolveInst(bin_op.lhs);5712 const dst_ptr = try func.resolveInst(bin_op.lhs);
5719 const dst_ptr_ty = self.typeOf(bin_op.lhs);5713 const dst_ptr_ty = func.typeOf(bin_op.lhs);
5720 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {5714 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
5721 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),5715 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
5722 else => null,5716 else => null,
5723 };5717 };
5724 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);5718 defer if (dst_ptr_lock) |lock| func.register_manager.unlockReg(lock);
57255719
5726 const src_val = try self.resolveInst(bin_op.rhs);5720 const src_val = try func.resolveInst(bin_op.rhs);
5727 const elem_ty = self.typeOf(bin_op.rhs);5721 const elem_ty = func.typeOf(bin_op.rhs);
5728 const src_val_lock: ?RegisterLock = switch (src_val) {5722 const src_val_lock: ?RegisterLock = switch (src_val) {
5729 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),5723 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
5730 else => null,5724 else => null,
5731 };5725 };
5732 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);5726 defer if (src_val_lock) |lock| func.register_manager.unlockReg(lock);
57335727
5734 const elem_abi_size: u31 = @intCast(elem_ty.abiSize(zcu));5728 const elem_abi_size: u31 = @intCast(elem_ty.abiSize(zcu));
57355729
...@@ -5747,12 +5741,12 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -5747,12 +5741,12 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
5747 .C, .Many => unreachable,5741 .C, .Many => unreachable,
5748 };5742 };
5749 const len_lock: ?RegisterLock = switch (len) {5743 const len_lock: ?RegisterLock = switch (len) {
5750 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),5744 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
5751 else => null,5745 else => null,
5752 };5746 };
5753 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);5747 defer if (len_lock) |lock| func.register_manager.unlockReg(lock);
57545748
5755 try self.genInlineMemset(ptr, src_val, len);5749 try func.genInlineMemset(ptr, src_val, len);
5756 break :result;5750 break :result;
5757 }5751 }
57585752
...@@ -5760,87 +5754,87 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -5760,87 +5754,87 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
5760 // Length zero requires a runtime check - so we handle arrays specially5754 // Length zero requires a runtime check - so we handle arrays specially
5761 // here to elide it.5755 // here to elide it.
5762 switch (dst_ptr_ty.ptrSize(zcu)) {5756 switch (dst_ptr_ty.ptrSize(zcu)) {
5763 .Slice => return self.fail("TODO: airMemset Slices", .{}),5757 .Slice => return func.fail("TODO: airMemset Slices", .{}),
5764 .One => {5758 .One => {
5765 const elem_ptr_ty = try zcu.singleMutPtrType(elem_ty);5759 const elem_ptr_ty = try zcu.singleMutPtrType(elem_ty);
57665760
5767 const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);5761 const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);
57685762
5769 assert(len != 0); // prevented by Sema5763 assert(len != 0); // prevented by Sema
5770 try self.store(dst_ptr, src_val, elem_ptr_ty, elem_ty);5764 try func.store(dst_ptr, src_val, elem_ptr_ty, elem_ty);
57715765
5772 const second_elem_ptr_reg, const second_elem_ptr_lock = try self.allocReg(.int);5766 const second_elem_ptr_reg, const second_elem_ptr_lock = try func.allocReg(.int);
5773 defer self.register_manager.unlockReg(second_elem_ptr_lock);5767 defer func.register_manager.unlockReg(second_elem_ptr_lock);
57745768
5775 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };5769 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
57765770
5777 try self.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{5771 try func.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{
5778 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),5772 .reg = try func.copyToTmpRegister(Type.usize, dst_ptr),
5779 .off = elem_abi_size,5773 .off = elem_abi_size,
5780 } });5774 } });
57815775
5782 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };5776 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
5783 try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);5777 try func.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);
5784 },5778 },
5785 .C, .Many => unreachable,5779 .C, .Many => unreachable,
5786 }5780 }
5787 }5781 }
5788 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });5782 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
5789}5783}
57905784
5791fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {5785fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
5792 _ = inst;5786 _ = inst;
5793 return self.fail("TODO implement airMemcpy for {}", .{self.target.cpu.arch});5787 return func.fail("TODO implement airMemcpy for {}", .{func.target.cpu.arch});
5794}5788}
57955789
5796fn airTagName(self: *Self, inst: Air.Inst.Index) !void {5790fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
5797 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5791 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5798 const operand = try self.resolveInst(un_op);5792 const operand = try func.resolveInst(un_op);
5799 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else {5793 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else {
5800 _ = operand;5794 _ = operand;
5801 return self.fail("TODO implement airTagName for riscv64", .{});5795 return func.fail("TODO implement airTagName for riscv64", .{});
5802 };5796 };
5803 return self.finishAir(inst, result, .{ un_op, .none, .none });5797 return func.finishAir(inst, result, .{ un_op, .none, .none });
5804}5798}
58055799
5806fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {5800fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
5807 const zcu = self.bin_file.comp.module.?;5801 const zcu = func.bin_file.comp.module.?;
5808 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5802 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
58095803
5810 const err_ty = self.typeOf(un_op);5804 const err_ty = func.typeOf(un_op);
5811 const err_mcv = try self.resolveInst(un_op);5805 const err_mcv = try func.resolveInst(un_op);
58125806
5813 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);5807 const err_reg = try func.copyToTmpRegister(err_ty, err_mcv);
5814 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);5808 const err_lock = func.register_manager.lockRegAssumeUnused(err_reg);
5815 defer self.register_manager.unlockReg(err_lock);5809 defer func.register_manager.unlockReg(err_lock);
58165810
5817 const addr_reg, const addr_lock = try self.allocReg(.int);5811 const addr_reg, const addr_lock = try func.allocReg(.int);
5818 defer self.register_manager.unlockReg(addr_lock);5812 defer func.register_manager.unlockReg(addr_lock);
58195813
5820 // this is now the base address of the error name table5814 // this is now the base address of the error name table
5821 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);5815 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);
5822 if (self.bin_file.cast(link.File.Elf)) |elf_file| {5816 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
5823 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|5817 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|
5824 return self.fail("{s} creating lazy symbol", .{@errorName(err)});5818 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
5825 const sym = elf_file.symbol(sym_index);5819 const sym = elf_file.symbol(sym_index);
5826 try self.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } });5820 try func.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } });
5827 } else {5821 } else {
5828 return self.fail("TODO: riscv non-elf", .{});5822 return func.fail("TODO: riscv non-elf", .{});
5829 }5823 }
58305824
5831 const start_reg, const start_lock = try self.allocReg(.int);5825 const start_reg, const start_lock = try func.allocReg(.int);
5832 defer self.register_manager.unlockReg(start_lock);5826 defer func.register_manager.unlockReg(start_lock);
58335827
5834 const end_reg, const end_lock = try self.allocReg(.int);5828 const end_reg, const end_lock = try func.allocReg(.int);
5835 defer self.register_manager.unlockReg(end_lock);5829 defer func.register_manager.unlockReg(end_lock);
58365830
5837 // const tmp_reg, const tmp_lock = try self.allocReg(.int);5831 // const tmp_reg, const tmp_lock = try func.allocReg(.int);
5838 // defer self.register_manager.unlockReg(tmp_lock);5832 // defer func.register_manager.unlockReg(tmp_lock);
58395833
5840 // we move the base address forward by the following formula: base + (errno * 8)5834 // we move the base address forward by the following formula: base + (errno * 8)
58415835
5842 // shifting left by 4 is the same as multiplying by 85836 // shifting left by 4 is the same as multiplying by 8
5843 _ = try self.addInst(.{5837 _ = try func.addInst(.{
5844 .tag = .slli,5838 .tag = .slli,
5845 .ops = .rri,5839 .ops = .rri,
5846 .data = .{ .i_type = .{5840 .data = .{ .i_type = .{
...@@ -5850,7 +5844,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -5850,7 +5844,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
5850 } },5844 } },
5851 });5845 });
58525846
5853 _ = try self.addInst(.{5847 _ = try func.addInst(.{
5854 .tag = .add,5848 .tag = .add,
5855 .ops = .rrr,5849 .ops = .rrr,
5856 .data = .{ .r_type = .{5850 .data = .{ .r_type = .{
...@@ -5860,7 +5854,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -5860,7 +5854,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
5860 } },5854 } },
5861 });5855 });
58625856
5863 _ = try self.addInst(.{5857 _ = try func.addInst(.{
5864 .tag = .pseudo,5858 .tag = .pseudo,
5865 .ops = .pseudo_load_rm,5859 .ops = .pseudo_load_rm,
5866 .data = .{5860 .data = .{
...@@ -5874,7 +5868,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -5874,7 +5868,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
5874 },5868 },
5875 });5869 });
58765870
5877 _ = try self.addInst(.{5871 _ = try func.addInst(.{
5878 .tag = .pseudo,5872 .tag = .pseudo,
5879 .ops = .pseudo_load_rm,5873 .ops = .pseudo_load_rm,
5880 .data = .{5874 .data = .{
...@@ -5888,64 +5882,64 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -5888,64 +5882,64 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
5888 },5882 },
5889 });5883 });
58905884
5891 const dst_mcv = try self.allocRegOrMem(inst, false);5885 const dst_mcv = try func.allocRegOrMem(inst, false);
5892 const frame = dst_mcv.load_frame;5886 const frame = dst_mcv.load_frame;
5893 try self.genSetMem(5887 try func.genSetMem(
5894 .{ .frame = frame.index },5888 .{ .frame = frame.index },
5895 frame.off,5889 frame.off,
5896 Type.usize,5890 Type.usize,
5897 .{ .register = start_reg },5891 .{ .register = start_reg },
5898 );5892 );
58995893
5900 try self.genSetMem(5894 try func.genSetMem(
5901 .{ .frame = frame.index },5895 .{ .frame = frame.index },
5902 frame.off + 8,5896 frame.off + 8,
5903 Type.usize,5897 Type.usize,
5904 .{ .register = end_reg },5898 .{ .register = end_reg },
5905 );5899 );
59065900
5907 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });5901 return func.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
5908}5902}
59095903
5910fn airSplat(self: *Self, inst: Air.Inst.Index) !void {5904fn airSplat(func: *Func, inst: Air.Inst.Index) !void {
5911 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5905 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5912 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airSplat for riscv64", .{});5906 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSplat for riscv64", .{});
5913 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5907 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5914}5908}
59155909
5916fn airSelect(self: *Self, inst: Air.Inst.Index) !void {5910fn airSelect(func: *Func, inst: Air.Inst.Index) !void {
5917 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;5911 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
5918 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;5912 const extra = func.air.extraData(Air.Bin, pl_op.payload).data;
5919 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airSelect for riscv64", .{});5913 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSelect for riscv64", .{});
5920 return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs });5914 return func.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs });
5921}5915}
59225916
5923fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {5917fn airShuffle(func: *Func, inst: Air.Inst.Index) !void {
5924 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5918 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5925 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airShuffle for riscv64", .{});5919 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShuffle for riscv64", .{});
5926 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5920 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
5927}5921}
59285922
5929fn airReduce(self: *Self, inst: Air.Inst.Index) !void {5923fn airReduce(func: *Func, inst: Air.Inst.Index) !void {
5930 const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce;5924 const reduce = func.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
5931 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement airReduce for riscv64", .{});5925 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airReduce for riscv64", .{});
5932 return self.finishAir(inst, result, .{ reduce.operand, .none, .none });5926 return func.finishAir(inst, result, .{ reduce.operand, .none, .none });
5933}5927}
59345928
5935fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {5929fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {
5936 const zcu = self.bin_file.comp.module.?;5930 const zcu = func.bin_file.comp.module.?;
5937 const result_ty = self.typeOfIndex(inst);5931 const result_ty = func.typeOfIndex(inst);
5938 const len: usize = @intCast(result_ty.arrayLen(zcu));5932 const len: usize = @intCast(result_ty.arrayLen(zcu));
5939 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5933 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5940 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);5934 const elements: []const Air.Inst.Ref = @ptrCast(func.air.extra[ty_pl.payload..][0..len]);
59415935
5942 const result: MCValue = result: {5936 const result: MCValue = result: {
5943 switch (result_ty.zigTypeTag(zcu)) {5937 switch (result_ty.zigTypeTag(zcu)) {
5944 .Struct => {5938 .Struct => {
5945 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));5939 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));
5946 if (result_ty.containerLayout(zcu) == .@"packed") {5940 if (result_ty.containerLayout(zcu) == .@"packed") {
5947 const struct_obj = zcu.typeToStruct(result_ty).?;5941 const struct_obj = zcu.typeToStruct(result_ty).?;
5948 try self.genInlineMemset(5942 try func.genInlineMemset(
5949 .{ .lea_frame = .{ .index = frame_index } },5943 .{ .lea_frame = .{ .index = frame_index } },
5950 .{ .immediate = 0 },5944 .{ .immediate = 0 },
5951 .{ .immediate = result_ty.abiSize(zcu) },5945 .{ .immediate = result_ty.abiSize(zcu) },
...@@ -5958,7 +5952,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -5958,7 +5952,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
5958 const elem_ty = result_ty.structFieldType(elem_i, zcu);5952 const elem_ty = result_ty.structFieldType(elem_i, zcu);
5959 const elem_bit_size: u32 = @intCast(elem_ty.bitSize(zcu));5953 const elem_bit_size: u32 = @intCast(elem_ty.bitSize(zcu));
5960 if (elem_bit_size > 64) {5954 if (elem_bit_size > 64) {
5961 return self.fail(5955 return func.fail(
5962 "TODO airAggregateInit implement packed structs with large fields",5956 "TODO airAggregateInit implement packed structs with large fields",
5963 .{},5957 .{},
5964 );5958 );
...@@ -5969,109 +5963,109 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -5969,109 +5963,109 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
5969 const elem_off = zcu.structPackedFieldBitOffset(struct_obj, elem_i);5963 const elem_off = zcu.structPackedFieldBitOffset(struct_obj, elem_i);
5970 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);5964 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
5971 const elem_bit_off = elem_off % elem_abi_bits;5965 const elem_bit_off = elem_off % elem_abi_bits;
5972 const elem_mcv = try self.resolveInst(elem);5966 const elem_mcv = try func.resolveInst(elem);
59735967
5974 _ = elem_byte_off;5968 _ = elem_byte_off;
5975 _ = elem_bit_off;5969 _ = elem_bit_off;
59765970
5977 const elem_lock = switch (elem_mcv) {5971 const elem_lock = switch (elem_mcv) {
5978 .register => |reg| self.register_manager.lockReg(reg),5972 .register => |reg| func.register_manager.lockReg(reg),
5979 .immediate => |imm| lock: {5973 .immediate => |imm| lock: {
5980 if (imm == 0) continue;5974 if (imm == 0) continue;
5981 break :lock null;5975 break :lock null;
5982 },5976 },
5983 else => null,5977 else => null,
5984 };5978 };
5985 defer if (elem_lock) |lock| self.register_manager.unlockReg(lock);5979 defer if (elem_lock) |lock| func.register_manager.unlockReg(lock);
59865980
5987 return self.fail("TODO: airAggregateInit packed structs", .{});5981 return func.fail("TODO: airAggregateInit packed structs", .{});
5988 }5982 }
5989 } else for (elements, 0..) |elem, elem_i| {5983 } else for (elements, 0..) |elem, elem_i| {
5990 if ((try result_ty.structFieldValueComptime(zcu, elem_i)) != null) continue;5984 if ((try result_ty.structFieldValueComptime(zcu, elem_i)) != null) continue;
59915985
5992 const elem_ty = result_ty.structFieldType(elem_i, zcu);5986 const elem_ty = result_ty.structFieldType(elem_i, zcu);
5993 const elem_off: i32 = @intCast(result_ty.structFieldOffset(elem_i, zcu));5987 const elem_off: i32 = @intCast(result_ty.structFieldOffset(elem_i, zcu));
5994 const elem_mcv = try self.resolveInst(elem);5988 const elem_mcv = try func.resolveInst(elem);
5995 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, elem_mcv);5989 try func.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, elem_mcv);
5996 }5990 }
5997 break :result .{ .load_frame = .{ .index = frame_index } };5991 break :result .{ .load_frame = .{ .index = frame_index } };
5998 },5992 },
5999 .Array => {5993 .Array => {
6000 const elem_ty = result_ty.childType(zcu);5994 const elem_ty = result_ty.childType(zcu);
6001 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));5995 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));
6002 const elem_size: u32 = @intCast(elem_ty.abiSize(zcu));5996 const elem_size: u32 = @intCast(elem_ty.abiSize(zcu));
60035997
6004 for (elements, 0..) |elem, elem_i| {5998 for (elements, 0..) |elem, elem_i| {
6005 const elem_mcv = try self.resolveInst(elem);5999 const elem_mcv = try func.resolveInst(elem);
6006 const elem_off: i32 = @intCast(elem_size * elem_i);6000 const elem_off: i32 = @intCast(elem_size * elem_i);
6007 try self.genSetMem(6001 try func.genSetMem(
6008 .{ .frame = frame_index },6002 .{ .frame = frame_index },
6009 elem_off,6003 elem_off,
6010 elem_ty,6004 elem_ty,
6011 elem_mcv,6005 elem_mcv,
6012 );6006 );
6013 }6007 }
6014 if (result_ty.sentinel(zcu)) |sentinel| try self.genSetMem(6008 if (result_ty.sentinel(zcu)) |sentinel| try func.genSetMem(
6015 .{ .frame = frame_index },6009 .{ .frame = frame_index },
6016 @intCast(elem_size * elements.len),6010 @intCast(elem_size * elements.len),
6017 elem_ty,6011 elem_ty,
6018 try self.genTypedValue(sentinel),6012 try func.genTypedValue(sentinel),
6019 );6013 );
6020 break :result .{ .load_frame = .{ .index = frame_index } };6014 break :result .{ .load_frame = .{ .index = frame_index } };
6021 },6015 },
6022 else => return self.fail("TODO: airAggregate {}", .{result_ty.fmt(zcu)}),6016 else => return func.fail("TODO: airAggregate {}", .{result_ty.fmt(zcu)}),
6023 }6017 }
6024 };6018 };
60256019
6026 if (elements.len <= Liveness.bpi - 1) {6020 if (elements.len <= Liveness.bpi - 1) {
6027 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);6021 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
6028 @memcpy(buf[0..elements.len], elements);6022 @memcpy(buf[0..elements.len], elements);
6029 return self.finishAir(inst, result, buf);6023 return func.finishAir(inst, result, buf);
6030 }6024 }
6031 var bt = self.liveness.iterateBigTomb(inst);6025 var bt = func.liveness.iterateBigTomb(inst);
6032 for (elements) |elem| try self.feed(&bt, elem);6026 for (elements) |elem| try func.feed(&bt, elem);
6033 return self.finishAirResult(inst, result);6027 return func.finishAirResult(inst, result);
6034}6028}
60356029
6036fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {6030fn airUnionInit(func: *Func, inst: Air.Inst.Index) !void {
6037 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;6031 const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
6038 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;6032 const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data;
6039 _ = extra;6033 _ = extra;
6040 return self.fail("TODO implement airUnionInit for riscv64", .{});6034 return func.fail("TODO implement airUnionInit for riscv64", .{});
6041 // return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });6035 // return func.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
6042}6036}
60436037
6044fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {6038fn airPrefetch(func: *Func, inst: Air.Inst.Index) !void {
6045 const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;6039 const prefetch = func.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
6046 // TODO: RISC-V does have prefetch instruction variants.6040 // TODO: RISC-V does have prefetch instruction variants.
6047 // see here: https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf6041 // see here: https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf
6048 return self.finishAir(inst, .unreach, .{ prefetch.ptr, .none, .none });6042 return func.finishAir(inst, .unreach, .{ prefetch.ptr, .none, .none });
6049}6043}
60506044
6051fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {6045fn airMulAdd(func: *Func, inst: Air.Inst.Index) !void {
6052 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6046 const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6053 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;6047 const extra = func.air.extraData(Air.Bin, pl_op.payload).data;
6054 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else {6048 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else {
6055 return self.fail("TODO implement airMulAdd for riscv64", .{});6049 return func.fail("TODO implement airMulAdd for riscv64", .{});
6056 };6050 };
6057 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });6051 return func.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
6058}6052}
60596053
6060fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {6054fn resolveInst(func: *Func, ref: Air.Inst.Ref) InnerError!MCValue {
6061 const zcu = self.bin_file.comp.module.?;6055 const zcu = func.bin_file.comp.module.?;
60626056
6063 // If the type has no codegen bits, no need to store it.6057 // If the type has no codegen bits, no need to store it.
6064 const inst_ty = self.typeOf(ref);6058 const inst_ty = func.typeOf(ref);
6065 if (!inst_ty.hasRuntimeBits(zcu))6059 if (!inst_ty.hasRuntimeBits(zcu))
6066 return .none;6060 return .none;
60676061
6068 const mcv = if (ref.toIndex()) |inst| mcv: {6062 const mcv = if (ref.toIndex()) |inst| mcv: {
6069 break :mcv self.inst_tracking.getPtr(inst).?.short;6063 break :mcv func.inst_tracking.getPtr(inst).?.short;
6070 } else mcv: {6064 } else mcv: {
6071 const ip_index = ref.toInterned().?;6065 const ip_index = ref.toInterned().?;
6072 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);6066 const gop = try func.const_tracking.getOrPut(func.gpa, ip_index);
6073 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(6067 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(
6074 try self.genTypedValue(Value.fromInterned(ip_index)),6068 try func.genTypedValue(Value.fromInterned(ip_index)),
6075 );6069 );
6076 break :mcv gop.value_ptr.short;6070 break :mcv gop.value_ptr.short;
6077 };6071 };
...@@ -6079,21 +6073,21 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -6079,21 +6073,21 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
6079 return mcv;6073 return mcv;
6080}6074}
60816075
6082fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {6076fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {
6083 const tracking = self.inst_tracking.getPtr(inst).?;6077 const tracking = func.inst_tracking.getPtr(inst).?;
6084 return switch (tracking.short) {6078 return switch (tracking.short) {
6085 .none, .unreach, .dead => unreachable,6079 .none, .unreach, .dead => unreachable,
6086 else => tracking,6080 else => tracking,
6087 };6081 };
6088}6082}
60896083
6090fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {6084fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
6091 const zcu = self.bin_file.comp.module.?;6085 const zcu = func.bin_file.comp.module.?;
6092 const result = try codegen.genTypedValue(6086 const result = try codegen.genTypedValue(
6093 self.bin_file,6087 func.bin_file,
6094 self.src_loc,6088 func.src_loc,
6095 val,6089 val,
6096 zcu.funcOwnerDeclIndex(self.func_index),6090 zcu.funcOwnerDeclIndex(func.func_index),
6097 );6091 );
6098 const mcv: MCValue = switch (result) {6092 const mcv: MCValue = switch (result) {
6099 .mcv => |mcv| switch (mcv) {6093 .mcv => |mcv| switch (mcv) {
...@@ -6103,11 +6097,11 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {...@@ -6103,11 +6097,11 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
6103 .immediate => |imm| .{ .immediate = imm },6097 .immediate => |imm| .{ .immediate = imm },
6104 .memory => |addr| .{ .memory = addr },6098 .memory => |addr| .{ .memory = addr },
6105 .load_got, .load_direct, .load_tlv => {6099 .load_got, .load_direct, .load_tlv => {
6106 return self.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});6100 return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)});
6107 },6101 },
6108 },6102 },
6109 .fail => |msg| {6103 .fail => |msg| {
6110 self.err_msg = msg;6104 func.err_msg = msg;
6111 return error.CodegenFail;6105 return error.CodegenFail;
6112 },6106 },
6113 };6107 };
...@@ -6120,39 +6114,39 @@ const CallMCValues = struct {...@@ -6120,39 +6114,39 @@ const CallMCValues = struct {
6120 stack_byte_count: u31,6114 stack_byte_count: u31,
6121 stack_align: Alignment,6115 stack_align: Alignment,
61226116
6123 fn deinit(self: *CallMCValues, func: *Self) void {6117 fn deinit(call: *CallMCValues, func: *Func) void {
6124 func.gpa.free(self.args);6118 func.gpa.free(call.args);
6125 self.* = undefined;6119 call.* = undefined;
6126 }6120 }
6127};6121};
61286122
6129/// Caller must call `CallMCValues.deinit`.6123/// Caller must call `CallMCValues.deinit`.
6130fn resolveCallingConventionValues(6124fn resolveCallingConventionValues(
6131 self: *Self,6125 func: *Func,
6132 fn_info: InternPool.Key.FuncType,6126 fn_info: InternPool.Key.FuncType,
6133 var_args: []const Type,6127 var_args: []const Type,
6134) !CallMCValues {6128) !CallMCValues {
6135 const zcu = self.bin_file.comp.module.?;6129 const zcu = func.bin_file.comp.module.?;
6136 const ip = &zcu.intern_pool;6130 const ip = &zcu.intern_pool;
61376131
6138 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);6132 const param_types = try func.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
6139 defer self.gpa.free(param_types);6133 defer func.gpa.free(param_types);
61406134
6141 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {6135 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
6142 dest.* = Type.fromInterned(src);6136 dest.* = Type.fromInterned(src);
6143 }6137 }
6144 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty|6138 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty|
6145 param_ty.* = self.promoteVarArg(arg_ty);6139 param_ty.* = func.promoteVarArg(arg_ty);
61466140
6147 const cc = fn_info.cc;6141 const cc = fn_info.cc;
6148 var result: CallMCValues = .{6142 var result: CallMCValues = .{
6149 .args = try self.gpa.alloc(MCValue, param_types.len),6143 .args = try func.gpa.alloc(MCValue, param_types.len),
6150 // These undefined values must be populated before returning from this function.6144 // These undefined values must be populated before returning from this function.
6151 .return_value = undefined,6145 .return_value = undefined,
6152 .stack_byte_count = 0,6146 .stack_byte_count = 0,
6153 .stack_align = undefined,6147 .stack_align = undefined,
6154 };6148 };
6155 errdefer self.gpa.free(result.args);6149 errdefer func.gpa.free(result.args);
61566150
6157 const ret_ty = Type.fromInterned(fn_info.return_type);6151 const ret_ty = Type.fromInterned(fn_info.return_type);
61586152
...@@ -6164,7 +6158,7 @@ fn resolveCallingConventionValues(...@@ -6164,7 +6158,7 @@ fn resolveCallingConventionValues(
6164 },6158 },
6165 .C, .Unspecified => {6159 .C, .Unspecified => {
6166 if (result.args.len > 8) {6160 if (result.args.len > 8) {
6167 return self.fail("RISC-V calling convention does not support more than 8 arguments", .{});6161 return func.fail("RISC-V calling convention does not support more than 8 arguments", .{});
6168 }6162 }
61696163
6170 var ret_int_reg_i: u32 = 0;6164 var ret_int_reg_i: u32 = 0;
...@@ -6211,11 +6205,11 @@ fn resolveCallingConventionValues(...@@ -6211,11 +6205,11 @@ fn resolveCallingConventionValues(
6211 };6205 };
6212 ret_tracking_i += 1;6206 ret_tracking_i += 1;
6213 },6207 },
6214 else => return self.fail("TODO: C calling convention return class {}", .{class}),6208 else => return func.fail("TODO: C calling convention return class {}", .{class}),
6215 };6209 };
62166210
6217 result.return_value = switch (ret_tracking_i) {6211 result.return_value = switch (ret_tracking_i) {
6218 else => return self.fail("ty {} took {} tracking return indices", .{ ret_ty.fmt(zcu), ret_tracking_i }),6212 else => return func.fail("ty {} took {} tracking return indices", .{ ret_ty.fmt(zcu), ret_tracking_i }),
6219 1 => ret_tracking[0],6213 1 => ret_tracking[0],
6220 2 => InstTracking.init(.{ .register_pair = .{6214 2 => InstTracking.init(.{ .register_pair = .{
6221 ret_tracking[0].short.register, ret_tracking[1].short.register,6215 ret_tracking[0].short.register, ret_tracking[1].short.register,
...@@ -6267,28 +6261,28 @@ fn resolveCallingConventionValues(...@@ -6267,28 +6261,28 @@ fn resolveCallingConventionValues(
6267 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };6261 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
6268 arg_mcv_i += 1;6262 arg_mcv_i += 1;
6269 },6263 },
6270 else => return self.fail("TODO: C calling convention arg class {}", .{class}),6264 else => return func.fail("TODO: C calling convention arg class {}", .{class}),
6271 } else {6265 } else {
6272 arg.* = switch (arg_mcv_i) {6266 arg.* = switch (arg_mcv_i) {
6273 else => return self.fail("ty {} took {} tracking arg indices", .{ ty.fmt(zcu), arg_mcv_i }),6267 else => return func.fail("ty {} took {} tracking arg indices", .{ ty.fmt(zcu), arg_mcv_i }),
6274 1 => arg_mcv[0],6268 1 => arg_mcv[0],
6275 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },6269 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },
6276 };6270 };
6277 continue;6271 continue;
6278 }6272 }
62796273
6280 return self.fail("TODO: pass args by stack", .{});6274 return func.fail("TODO: pass args by stack", .{});
6281 }6275 }
6282 },6276 },
6283 else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}),6277 else => return func.fail("TODO implement function parameters for {} on riscv64", .{cc}),
6284 }6278 }
62856279
6286 result.stack_byte_count = @intCast(result.stack_align.forward(result.stack_byte_count));6280 result.stack_byte_count = @intCast(result.stack_align.forward(result.stack_byte_count));
6287 return result;6281 return result;
6288}6282}
62896283
6290fn wantSafety(self: *Self) bool {6284fn wantSafety(func: *Func) bool {
6291 return switch (self.mod.optimize_mode) {6285 return switch (func.mod.optimize_mode) {
6292 .Debug => true,6286 .Debug => true,
6293 .ReleaseSafe => true,6287 .ReleaseSafe => true,
6294 .ReleaseFast => false,6288 .ReleaseFast => false,
...@@ -6296,39 +6290,36 @@ fn wantSafety(self: *Self) bool {...@@ -6296,39 +6290,36 @@ fn wantSafety(self: *Self) bool {
6296 };6290 };
6297}6291}
62986292
6299fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {6293fn fail(func: *Func, comptime format: []const u8, args: anytype) InnerError {
6300 @setCold(true);6294 @setCold(true);
6301 assert(self.err_msg == null);6295 assert(func.err_msg == null);
6302 self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args);6296 func.err_msg = try ErrorMsg.create(func.gpa, func.src_loc, format, args);
6303 return error.CodegenFail;6297 return error.CodegenFail;
6304}6298}
63056299
6306fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError {6300fn failSymbol(func: *Func, comptime format: []const u8, args: anytype) InnerError {
6307 @setCold(true);6301 @setCold(true);
6308 assert(self.err_msg == null);6302 assert(func.err_msg == null);
6309 self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args);6303 func.err_msg = try ErrorMsg.create(func.gpa, func.src_loc, format, args);
6310 return error.CodegenFail;6304 return error.CodegenFail;
6311}6305}
63126306
6313fn parseRegName(name: []const u8) ?Register {6307fn parseRegName(name: []const u8) ?Register {
6314 if (@hasDecl(Register, "parseRegName")) {
6315 return Register.parseRegName(name);
6316 }
6317 return std.meta.stringToEnum(Register, name);6308 return std.meta.stringToEnum(Register, name);
6318}6309}
63196310
6320fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {6311fn typeOf(func: *Func, inst: Air.Inst.Ref) Type {
6321 const zcu = self.bin_file.comp.module.?;6312 const zcu = func.bin_file.comp.module.?;
6322 return self.air.typeOf(inst, &zcu.intern_pool);6313 return func.air.typeOf(inst, &zcu.intern_pool);
6323}6314}
63246315
6325fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {6316fn typeOfIndex(func: *Func, inst: Air.Inst.Index) Type {
6326 const zcu = self.bin_file.comp.module.?;6317 const zcu = func.bin_file.comp.module.?;
6327 return self.air.typeOfIndex(inst, &zcu.intern_pool);6318 return func.air.typeOfIndex(inst, &zcu.intern_pool);
6328}6319}
63296320
6330fn hasFeature(self: *Self, feature: Target.riscv.Feature) bool {6321fn hasFeature(func: *Func, feature: Target.riscv.Feature) bool {
6331 return Target.riscv.featureSetHas(self.target.cpu.features, feature);6322 return Target.riscv.featureSetHas(func.target.cpu.features, feature);
6332}6323}
63336324
6334pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Module) u64 {6325pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Module) u64 {
...@@ -6353,8 +6344,8 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Module) u64 {...@@ -6353,8 +6344,8 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Module) u64 {
6353 }6344 }
6354}6345}
63556346
6356fn promoteInt(self: *Self, ty: Type) Type {6347fn promoteInt(func: *Func, ty: Type) Type {
6357 const mod = self.bin_file.comp.module.?;6348 const mod = func.bin_file.comp.module.?;
6358 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {6349 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
6359 .bool_type => .{ .signedness = .unsigned, .bits = 1 },6350 .bool_type => .{ .signedness = .unsigned, .bits = 1 },
6360 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,6351 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,
...@@ -6372,12 +6363,12 @@ fn promoteInt(self: *Self, ty: Type) Type {...@@ -6372,12 +6363,12 @@ fn promoteInt(self: *Self, ty: Type) Type {
6372 return ty;6363 return ty;
6373}6364}
63746365
6375fn promoteVarArg(self: *Self, ty: Type) Type {6366fn promoteVarArg(func: *Func, ty: Type) Type {
6376 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);6367 if (!ty.isRuntimeFloat()) return func.promoteInt(ty);
6377 switch (ty.floatBits(self.target.*)) {6368 switch (ty.floatBits(func.target.*)) {
6378 32, 64 => return Type.f64,6369 32, 64 => return Type.f64,
6379 else => |float_bits| {6370 else => |float_bits| {
6380 assert(float_bits == self.target.c_type_bit_size(.longdouble));6371 assert(float_bits == func.target.c_type_bit_size(.longdouble));
6381 return Type.c_longdouble;6372 return Type.c_longdouble;
6382 },6373 },
6383 }6374 }