| ... | ... | @@ -3797,12 +3797,150 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 3797 | 3797 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 3798 | 3798 | } |
| 3799 | 3799 | |
| 3800 | fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u32 { |
| 3801 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3802 | switch (condition) { |
| 3803 | .none => unreachable, |
| 3804 | .undef => unreachable, |
| 3805 | .dead, .unreach => unreachable, |
| 3806 | .compare_flags_signed => unreachable, |
| 3807 | .compare_flags_unsigned => unreachable, |
| 3808 | .register => |cond_reg| { |
| 3809 | switch (case) { |
| 3810 | .none => unreachable, |
| 3811 | .undef => unreachable, |
| 3812 | .dead, .unreach => unreachable, |
| 3813 | .immediate => |imm| { |
| 3814 | _ = try self.addInst(.{ |
| 3815 | .tag = .@"test", |
| 3816 | .ops = (Mir.Ops{ |
| 3817 | .reg1 = registerAlias(cond_reg, abi_size), |
| 3818 | }).encode(), |
| 3819 | .data = .{ .imm = @intCast(u32, imm) }, |
| 3820 | }); |
| 3821 | return self.addInst(.{ |
| 3822 | .tag = .cond_jmp_eq_ne, |
| 3823 | .ops = (Mir.Ops{ |
| 3824 | .flags = 0b00, |
| 3825 | }).encode(), |
| 3826 | .data = .{ .inst = undefined }, |
| 3827 | }); |
| 3828 | }, |
| 3829 | .register => |reg| { |
| 3830 | _ = try self.addInst(.{ |
| 3831 | .tag = .@"test", |
| 3832 | .ops = (Mir.Ops{ |
| 3833 | .reg1 = registerAlias(cond_reg, abi_size), |
| 3834 | .reg2 = registerAlias(reg, abi_size), |
| 3835 | }).encode(), |
| 3836 | .data = undefined, |
| 3837 | }); |
| 3838 | return self.addInst(.{ |
| 3839 | .tag = .cond_jmp_eq_ne, |
| 3840 | .ops = (Mir.Ops{ |
| 3841 | .flags = 0b00, |
| 3842 | }).encode(), |
| 3843 | .data = .{ .inst = undefined }, |
| 3844 | }); |
| 3845 | }, |
| 3846 | .stack_offset => { |
| 3847 | if (abi_size <= 8) { |
| 3848 | const reg = try self.copyToTmpRegister(ty, case); |
| 3849 | return self.genCondSwitchMir(ty, condition, .{ .register = reg }); |
| 3850 | } |
| 3851 | |
| 3852 | return self.fail("TODO implement switch mir when case is stack offset with abi larger than 8 bytes", .{}); |
| 3853 | }, |
| 3854 | else => { |
| 3855 | return self.fail("TODO implement switch mir when case is {}", .{case}); |
| 3856 | }, |
| 3857 | } |
| 3858 | }, |
| 3859 | else => { |
| 3860 | return self.fail("TODO implemenent switch mir when condition is {}", .{condition}); |
| 3861 | }, |
| 3862 | } |
| 3863 | } |
| 3864 | |
| 3800 | 3865 | fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { |
| 3801 | 3866 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3802 | | const condition = pl_op.operand; |
| 3803 | | _ = condition; |
| 3804 | | return self.fail("TODO airSwitch for {}", .{self.target.cpu.arch}); |
| 3805 | | // return self.finishAir(inst, .dead, .{ condition, .none, .none }); |
| 3867 | const condition = try self.resolveInst(pl_op.operand); |
| 3868 | const condition_ty = self.air.typeOf(pl_op.operand); |
| 3869 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 3870 | var extra_index: usize = switch_br.end; |
| 3871 | var case_i: u32 = 0; |
| 3872 | const liveness = try self.liveness.getSwitchBr( |
| 3873 | self.gpa, |
| 3874 | inst, |
| 3875 | switch_br.data.cases_len + 1, |
| 3876 | ); |
| 3877 | defer self.gpa.free(liveness.deaths); |
| 3878 | |
| 3879 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| 3880 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); |
| 3881 | const items = @bitCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]); |
| 3882 | const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len]; |
| 3883 | extra_index = case.end + items.len + case_body.len; |
| 3884 | |
| 3885 | var relocs = try self.gpa.alloc(u32, items.len); |
| 3886 | defer self.gpa.free(relocs); |
| 3887 | |
| 3888 | for (items) |item, item_i| { |
| 3889 | const item_mcv = try self.resolveInst(item); |
| 3890 | relocs[item_i] = try self.genCondSwitchMir(condition_ty, condition, item_mcv); |
| 3891 | } |
| 3892 | |
| 3893 | // Capture the state of register and stack allocation state so that we can revert to it. |
| 3894 | const parent_next_stack_offset = self.next_stack_offset; |
| 3895 | const parent_free_registers = self.register_manager.free_registers; |
| 3896 | var parent_stack = try self.stack.clone(self.gpa); |
| 3897 | defer parent_stack.deinit(self.gpa); |
| 3898 | const parent_registers = self.register_manager.registers; |
| 3899 | |
| 3900 | try self.branch_stack.append(.{}); |
| 3901 | errdefer { |
| 3902 | _ = self.branch_stack.pop(); |
| 3903 | } |
| 3904 | |
| 3905 | try self.ensureProcessDeathCapacity(liveness.deaths[case_i].len); |
| 3906 | for (liveness.deaths[case_i]) |operand| { |
| 3907 | self.processDeath(operand); |
| 3908 | } |
| 3909 | |
| 3910 | try self.genBody(case_body); |
| 3911 | |
| 3912 | // Revert to the previous register and stack allocation state. |
| 3913 | var saved_case_branch = self.branch_stack.pop(); |
| 3914 | defer saved_case_branch.deinit(self.gpa); |
| 3915 | |
| 3916 | self.register_manager.registers = parent_registers; |
| 3917 | self.stack.deinit(self.gpa); |
| 3918 | self.stack = parent_stack; |
| 3919 | parent_stack = .{}; |
| 3920 | |
| 3921 | self.next_stack_offset = parent_next_stack_offset; |
| 3922 | self.register_manager.free_registers = parent_free_registers; |
| 3923 | |
| 3924 | for (relocs) |reloc| { |
| 3925 | try self.performReloc(reloc); |
| 3926 | } |
| 3927 | } |
| 3928 | |
| 3929 | if (switch_br.data.else_body_len > 0) { |
| 3930 | return self.fail("TODO handle else branch in switch", .{}); |
| 3931 | } |
| 3932 | |
| 3933 | // const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len]; |
| 3934 | // const else_branch = self.branch_stack.addOneAssumeCapacity(); |
| 3935 | // else_branch.* = .{}; |
| 3936 | |
| 3937 | // if (else_body.len != 0) { |
| 3938 | // try self.genBody(else_body); |
| 3939 | // } else { |
| 3940 | |
| 3941 | // } |
| 3942 | |
| 3943 | return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none }); |
| 3806 | 3944 | } |
| 3807 | 3945 | |
| 3808 | 3946 | fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |