| ... | ... | @@ -4154,7 +4154,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4154 | 4154 | return self.fail("TODO: Implement overflow arithmetic for integer bitsize: {d}", .{int_info.bits}); |
| 4155 | 4155 | }; |
| 4156 | 4156 | |
| 4157 | | if (wasm_bits == 64) { |
| 4157 | if (wasm_bits > 32) { |
| 4158 | 4158 | return self.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits}); |
| 4159 | 4159 | } |
| 4160 | 4160 | |
| ... | ... | @@ -4236,32 +4236,26 @@ fn airMaxMin(self: *Self, inst: Air.Inst.Index, op: enum { max, min }) InnerErro |
| 4236 | 4236 | return self.fail("TODO: `@maximum` and `@minimum` for vectors", .{}); |
| 4237 | 4237 | } |
| 4238 | 4238 | |
| 4239 | | if (ty.abiSize(self.target) > 8) { |
| 4240 | | return self.fail("TODO: `@maximum` and `@minimum` for types larger than 8 bytes", .{}); |
| 4239 | if (ty.abiSize(self.target) > 16) { |
| 4240 | return self.fail("TODO: `@maximum` and `@minimum` for types larger than 16 bytes", .{}); |
| 4241 | 4241 | } |
| 4242 | 4242 | |
| 4243 | 4243 | const lhs = try self.resolveInst(bin_op.lhs); |
| 4244 | 4244 | const rhs = try self.resolveInst(bin_op.rhs); |
| 4245 | 4245 | |
| 4246 | | // operands to select from |
| 4247 | | try self.emitWValue(lhs); |
| 4248 | | try self.emitWValue(rhs); |
| 4246 | const cmp_result = try self.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt); |
| 4249 | 4247 | |
| 4250 | | // operands to compare |
| 4251 | | try self.emitWValue(lhs); |
| 4252 | | try self.emitWValue(rhs); |
| 4253 | | const opcode = buildOpcode(.{ |
| 4254 | | .op = if (op == .max) .gt else .lt, |
| 4255 | | .signedness = if (ty.isSignedInt()) .signed else .unsigned, |
| 4256 | | .valtype1 = typeToValtype(ty, self.target), |
| 4257 | | }); |
| 4258 | | try self.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 4248 | // operands to select from |
| 4249 | try self.lowerToStack(lhs); |
| 4250 | try self.lowerToStack(rhs); |
| 4251 | try self.emitWValue(cmp_result); |
| 4259 | 4252 | |
| 4260 | 4253 | // based on the result from comparison, return operand 0 or 1. |
| 4261 | 4254 | try self.addTag(.select); |
| 4262 | 4255 | |
| 4263 | 4256 | // store result in local |
| 4264 | | const result = try self.allocLocal(ty); |
| 4257 | const result_ty = if (isByRef(ty, self.target)) Type.u32 else ty; |
| 4258 | const result = try self.allocLocal(result_ty); |
| 4265 | 4259 | try self.addLabel(.local_set, result.local); |
| 4266 | 4260 | return result; |
| 4267 | 4261 | } |
| ... | ... | @@ -4302,31 +4296,39 @@ fn airClz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4302 | 4296 | return self.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); |
| 4303 | 4297 | }; |
| 4304 | 4298 | |
| 4305 | | try self.emitWValue(operand); |
| 4306 | 4299 | switch (wasm_bits) { |
| 4307 | 4300 | 32 => { |
| 4301 | try self.emitWValue(operand); |
| 4308 | 4302 | try self.addTag(.i32_clz); |
| 4309 | | |
| 4310 | | if (wasm_bits != int_info.bits) { |
| 4311 | | const tmp = try self.allocLocal(ty); |
| 4312 | | try self.addLabel(.local_set, tmp.local); |
| 4313 | | const val: i32 = -@intCast(i32, wasm_bits - int_info.bits); |
| 4314 | | return self.wrapBinOp(tmp, .{ .imm32 = @bitCast(u32, val) }, ty, .add); |
| 4315 | | } |
| 4316 | 4303 | }, |
| 4317 | 4304 | 64 => { |
| 4305 | try self.emitWValue(operand); |
| 4318 | 4306 | try self.addTag(.i64_clz); |
| 4307 | try self.addTag(.i32_wrap_i64); |
| 4308 | }, |
| 4309 | 128 => { |
| 4310 | const msb = try self.load(operand, Type.u64, 0); |
| 4311 | const lsb = try self.load(operand, Type.u64, 8); |
| 4312 | const neq = try self.cmp(lsb, .{ .imm64 = 0 }, Type.u64, .neq); |
| 4319 | 4313 | |
| 4320 | | if (wasm_bits != int_info.bits) { |
| 4321 | | const tmp = try self.allocLocal(ty); |
| 4322 | | try self.addLabel(.local_set, tmp.local); |
| 4323 | | const val: i64 = -@intCast(i64, wasm_bits - int_info.bits); |
| 4324 | | return self.wrapBinOp(tmp, .{ .imm64 = @bitCast(u64, val) }, ty, .add); |
| 4325 | | } |
| 4314 | try self.emitWValue(lsb); |
| 4315 | try self.addTag(.i64_clz); |
| 4316 | try self.emitWValue(msb); |
| 4317 | try self.addTag(.i64_clz); |
| 4318 | try self.emitWValue(.{ .imm64 = 64 }); |
| 4319 | try self.addTag(.i64_add); |
| 4320 | try self.emitWValue(neq); |
| 4321 | try self.addTag(.select); |
| 4322 | try self.addTag(.i32_wrap_i64); |
| 4326 | 4323 | }, |
| 4327 | 4324 | else => unreachable, |
| 4328 | 4325 | } |
| 4329 | 4326 | |
| 4327 | if (wasm_bits != int_info.bits) { |
| 4328 | try self.emitWValue(.{ .imm32 = wasm_bits - int_info.bits }); |
| 4329 | try self.addTag(.i32_sub); |
| 4330 | } |
| 4331 | |
| 4330 | 4332 | const result = try self.allocLocal(result_ty); |
| 4331 | 4333 | try self.addLabel(.local_set, result.local); |
| 4332 | 4334 | return result; |
| ... | ... | @@ -4365,12 +4367,34 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4365 | 4367 | } else try self.emitWValue(operand); |
| 4366 | 4368 | try self.addTag(.i64_ctz); |
| 4367 | 4369 | }, |
| 4370 | 128 => { |
| 4371 | const msb = try self.load(operand, Type.u64, 0); |
| 4372 | const lsb = try self.load(operand, Type.u64, 8); |
| 4373 | const neq = try self.cmp(msb, .{ .imm64 = 0 }, Type.u64, .neq); |
| 4374 | |
| 4375 | try self.emitWValue(msb); |
| 4376 | try self.addTag(.i64_ctz); |
| 4377 | try self.emitWValue(lsb); |
| 4378 | if (wasm_bits != int_info.bits) { |
| 4379 | try self.addImm64(@as(u64, 1) << @intCast(u6, int_info.bits - 64)); |
| 4380 | try self.addTag(.i64_or); |
| 4381 | } |
| 4382 | try self.addTag(.i64_ctz); |
| 4383 | try self.addImm64(64); |
| 4384 | if (wasm_bits != int_info.bits) { |
| 4385 | try self.addTag(.i64_or); |
| 4386 | } else { |
| 4387 | try self.addTag(.i64_add); |
| 4388 | } |
| 4389 | try self.emitWValue(neq); |
| 4390 | try self.addTag(.select); |
| 4391 | }, |
| 4368 | 4392 | else => unreachable, |
| 4369 | 4393 | } |
| 4370 | 4394 | |
| 4371 | | const result = try self.allocLocal(result_ty); |
| 4395 | const result = try self.allocLocal(ty); |
| 4372 | 4396 | try self.addLabel(.local_set, result.local); |
| 4373 | | return result; |
| 4397 | return self.intcast(result, ty, result_ty); |
| 4374 | 4398 | } |
| 4375 | 4399 | |
| 4376 | 4400 | fn airDbgVar(self: *Self, inst: Air.Inst.Index, is_ptr: bool) !WValue { |