| ... | ... | @@ -2132,8 +2132,38 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 2132 | 2132 | if (self.liveness.isUnused(inst)) { |
| 2133 | 2133 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 2134 | 2134 | } |
| 2135 | | return self.fail("TODO implement airGetUnionTag for {}", .{self.target.cpu.arch}); |
| 2136 | | // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2135 | |
| 2136 | const tag_ty = self.air.typeOfIndex(inst); |
| 2137 | const union_ty = self.air.typeOf(ty_op.operand); |
| 2138 | const layout = union_ty.unionGetLayout(self.target.*); |
| 2139 | |
| 2140 | if (layout.tag_size == 0) { |
| 2141 | return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none }); |
| 2142 | } |
| 2143 | |
| 2144 | // TODO reusing the operand |
| 2145 | const operand = try self.resolveInst(ty_op.operand); |
| 2146 | operand.freezeIfRegister(&self.register_manager); |
| 2147 | defer operand.unfreezeIfRegister(&self.register_manager); |
| 2148 | |
| 2149 | const tag_abi_size = tag_ty.abiSize(self.target.*); |
| 2150 | const offset: i32 = if (layout.tag_align < layout.payload_align) @intCast(i32, layout.payload_size) else 0; |
| 2151 | const dst_mcv: MCValue = blk: { |
| 2152 | switch (operand) { |
| 2153 | .stack_offset => |off| { |
| 2154 | if (tag_abi_size <= 8) { |
| 2155 | break :blk try self.copyToRegisterWithInstTracking(inst, tag_ty, .{ |
| 2156 | .stack_offset = off - offset, |
| 2157 | }); |
| 2158 | } |
| 2159 | |
| 2160 | return self.fail("TODO implement get_union_tag for ABI larger than 8 bytes and operand {}", .{operand}); |
| 2161 | }, |
| 2162 | else => return self.fail("TODO implement get_union_tag for {}", .{operand}), |
| 2163 | } |
| 2164 | }; |
| 2165 | |
| 2166 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 2137 | 2167 | } |
| 2138 | 2168 | |
| 2139 | 2169 | fn airClz(self: *Self, inst: Air.Inst.Index) !void { |