Skip to content

Commit

Permalink
Windows x86: Change i128 to return via the vector ABI with Cranelift
Browse files Browse the repository at this point in the history
Clang and GCC both return `i128` in xmm0 on windows-msvc and windows-gnu
but Rust returns the type on the stack. The LLVM backend was changed to
use the same convention as the C compilers; change Cranelift libcalls to
do the same.

Link: rust-lang#134288
  • Loading branch information
tgross35 committed Dec 17, 2024
1 parent e40fa57 commit 2813a65
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 51 deletions.
22 changes: 12 additions & 10 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
&mut self,
name: &str,
params: Vec<AbiParam>,
returns: Vec<AbiParam>,
mut returns: Vec<AbiParam>,
args: &[Value],
) -> Cow<'_, [Value]> {
// Pass i128 arguments by-ref on Windows.
Expand All @@ -146,15 +146,17 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
(params, args.into())
};

// Return i128 using a return area pointer on Windows and s390x.
let adjust_ret_param =
if self.tcx.sess.target.is_like_windows || self.tcx.sess.target.arch == "s390x" {
returns.len() == 1 && returns[0].value_type == types::I128
} else {
false
};

if adjust_ret_param {
// Return i128 using the vector ABI on Windows
let ret_single_i128 = returns.len() == 1 && returns[0].value_type == types::I128;
if ret_single_i128 && self.tcx.sess.target.is_like_windows {
returns[0].value_type = types::I64X2;
let ret = self.lib_call_unadjusted(name, params, returns, &args)[0];
// FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128
let ret_ptr = self.create_stack_slot(16, 16);
ret_ptr.store(self, ret, MemFlags::trusted());
Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())])
} else if ret_single_i128 && self.tcx.sess.target.arch == "s390x" {
// Return i128 using a return area pointer on s390x.
let mut params = params;
let mut args = args.to_vec();

Expand Down
22 changes: 3 additions & 19 deletions compiler/rustc_codegen_cranelift/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,25 +96,9 @@ pub(crate) fn clif_int_or_float_cast(
},
);

if fx.tcx.sess.target.is_like_windows {
let ret = fx.lib_call(
&name,
vec![AbiParam::new(from_ty)],
vec![AbiParam::new(types::I64X2)],
&[from],
)[0];
// FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128
let ret_ptr = fx.create_stack_slot(16, 16);
ret_ptr.store(fx, ret, MemFlags::trusted());
ret_ptr.load(fx, types::I128, MemFlags::trusted())
} else {
fx.lib_call(
&name,
vec![AbiParam::new(from_ty)],
vec![AbiParam::new(types::I128)],
&[from],
)[0]
}
fx.lib_call(&name, vec![AbiParam::new(from_ty)], vec![AbiParam::new(types::I128)], &[
from,
])[0]
} else if to_ty == types::I8 || to_ty == types::I16 {
// FIXME implement fcvt_to_*int_sat.i8/i16
let val = if to_signed {
Expand Down
30 changes: 8 additions & 22 deletions compiler/rustc_codegen_cranelift/src/codegen_i128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,14 @@ pub(crate) fn maybe_codegen<'tcx>(
(BinOp::Rem, true) => "__modti3",
_ => unreachable!(),
};
if fx.tcx.sess.target.is_like_windows {
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
let ret = fx.lib_call(
name,
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
vec![AbiParam::new(types::I64X2)],
&args,
)[0];
// FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128
let ret_place = CPlace::new_stack_slot(fx, lhs.layout());
ret_place.to_ptr().store(fx, ret, MemFlags::trusted());
Some(ret_place.to_cvalue(fx))
} else {
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
let ret_val = fx.lib_call(
name,
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
vec![AbiParam::new(types::I128)],
&args,
)[0];
Some(CValue::by_val(ret_val, lhs.layout()))
}
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
let ret_val = fx.lib_call(
name,
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
vec![AbiParam::new(types::I128)],
&args,
)[0];
Some(CValue::by_val(ret_val, lhs.layout()))
}
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne | BinOp::Cmp => None,
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
Expand Down

0 comments on commit 2813a65

Please sign in to comment.