authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-07-10 17:04:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-10 20:52:29-07:00
log2b5215436c47e7546cbe5000345cd81fc45019b8
tree62d4c9456e5caae29dc59c792371f3e1d4e04a3f
parentd182e2ebda89e65f6503eadc21bdb0e600f21ea1

stage2: Lower libcalls on Windows x86-64 correctly

This change is the Zig counterpart to https://reviews.llvm.org/D110413 Same as the prior commit, but for stage2

1 files changed, 30 insertions(+), 11 deletions(-)

src/codegen/llvm.zig+30-11
......@@ -4802,7 +4802,7 @@ pub const FuncGen = struct {
48024802 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));
48034803 const rt_int_bits = compilerRtIntBits(operand_bits);
48044804 const rt_int_ty = self.context.intType(rt_int_bits);
4805 const extended = e: {
4805 var extended = e: {
48064806 if (operand_scalar_ty.isSignedInt()) {
48074807 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");
48084808 } else {
......@@ -4819,7 +4819,16 @@ pub const FuncGen = struct {
48194819 compiler_rt_operand_abbrev,
48204820 compiler_rt_dest_abbrev,
48214821 }) catch unreachable;
4822 const param_types = [1]*const llvm.Type{rt_int_ty};
4822
4823 var param_types = [1]*const llvm.Type{rt_int_ty};
4824 if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) {
4825 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
4826 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
4827 const v2i64 = self.context.intType(64).vectorType(2);
4828 extended = self.builder.buildBitCast(extended, v2i64, "");
4829 param_types = [1]*const llvm.Type{v2i64};
4830 }
4831
48234832 const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty);
48244833 const params = [1]*const llvm.Value{extended};
48254834
......@@ -4851,7 +4860,12 @@ pub const FuncGen = struct {
48514860 }
48524861
48534862 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target)));
4854 const libc_ret_ty = self.context.intType(rt_int_bits);
4863 const ret_ty = self.context.intType(rt_int_bits);
4864 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {
4865 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
4866 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
4867 break :b self.context.intType(64).vectorType(2);
4868 } else ret_ty;
48554869
48564870 const operand_bits = operand_scalar_ty.floatBits(target);
48574871 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
......@@ -4871,13 +4885,11 @@ pub const FuncGen = struct {
48714885 const libc_fn = self.getLibcFunction(fn_name, &param_types, libc_ret_ty);
48724886 const params = [1]*const llvm.Value{operand};
48734887
4874 const result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
4875
4876 if (libc_ret_ty == dest_llvm_ty) {
4877 return result;
4878 }
4888 var result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
48794889
4880 return self.builder.buildTrunc(result, dest_llvm_ty, "");
4890 if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, "");
4891 if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, "");
4892 return result;
48814893 }
48824894
48834895 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {
......@@ -6490,8 +6502,15 @@ pub const FuncGen = struct {
64906502 const one = int_llvm_ty.constInt(1, .False);
64916503 const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False);
64926504 const sign_mask = one.constShl(shift_amt);
6493 const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, "");
6494 const result = self.builder.buildXor(bitcasted_operand, sign_mask, "");
6505 const result = if (ty.zigTypeTag() == .Vector) blk: {
6506 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(), sign_mask, "");
6507 const cast_ty = int_llvm_ty.vectorType(ty.vectorLen());
6508 const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, "");
6509 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");
6510 } else blk: {
6511 const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, "");
6512 break :blk self.builder.buildXor(bitcasted_operand, sign_mask, "");
6513 };
64956514 return self.builder.buildBitCast(result, llvm_ty, "");
64966515 },
64976516 .add, .sub, .div, .mul => FloatOpStrat{