From 0e2b9ac7770df07212d4d1cbfb15c3aaed0bef18 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 21 Sep 2021 17:24:55 -0700 Subject: stage2: fix unsigned integer to signed integer coercion --- src/codegen/llvm.zig | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 29efa27685..3a977bc582 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2032,14 +2032,22 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; + const target = self.dg.module.getTarget(); const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const dest_ty = self.air.typeOfIndex(inst); + const dest_info = dest_ty.intInfo(target); + const dest_llvm_ty = try self.dg.llvmType(dest_ty); const operand = try self.resolveInst(ty_op.operand); - const inst_ty = self.air.typeOfIndex(inst); + const operand_ty = self.air.typeOf(ty_op.operand); + const operand_info = operand_ty.intInfo(target); - const signed = inst_ty.isSignedInt(); - // TODO: Should we use intcast here or just a simple bitcast? - // LLVM does truncation vs bitcast (+signed extension) in the intcast depending on the sizes - return self.builder.buildIntCast2(operand, try self.dg.llvmType(inst_ty), llvm.Bool.fromBool(signed), ""); + if (operand_info.bits < dest_info.bits) { + switch (operand_info.signedness) { + .signed => return self.builder.buildSExt(operand, dest_llvm_ty, ""), + .unsigned => return self.builder.buildZExt(operand, dest_llvm_ty, ""), + } + } + return self.builder.buildTrunc(operand, dest_llvm_ty, ""); } fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { -- cgit v1.2.3