Merge pull request #1359 from bjorn3/fix_llvm14-builtins-abi

Fix compiler-builtins 0.1.87 on Windows
This commit is contained in:
bjorn3 2023-02-18 19:17:43 +01:00 committed by GitHub
commit cb12ad7397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 185 additions and 204 deletions

View File

@ -50,9 +50,9 @@ dependencies = [
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.86" version = "0.1.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dae98c88e576098d7ab13ebcb40cc43e5114b2beafe61a87cda9200649ff205" checksum = "f867ce54c09855ccd135ad4a50c777182a0c7af5ff20a8f537617bd648b10d50"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]

View File

@ -8,8 +8,7 @@ alloc = { path = "./sysroot_src/library/alloc" }
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
test = { path = "./sysroot_src/library/test" } test = { path = "./sysroot_src/library/test" }
# FIXME allow 0.1.87 and later once #1353 is fixed compiler_builtins = { version = "0.1.87", default-features = false, features = ["no-asm"] }
compiler_builtins = { version = "=0.1.86", default-features = false, features = ["no-asm"] }
[patch.crates-io] [patch.crates-io]
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" } rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }

View File

@ -58,8 +58,9 @@ fn main() {
assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128); assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128);
let _d = 0i128.checked_div(2i128); std::hint::black_box(std::hint::black_box(7571400400375753350092698930310845914i128) * 10);
let _d = 0u128.checked_div(2u128); assert!(0i128.checked_div(2i128).is_some());
assert!(0u128.checked_div(2u128).is_some());
assert_eq!(1u128 + 2, 3); assert_eq!(1u128 + 2, 3);
assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128); assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128);

View File

@ -1,26 +0,0 @@
From ff23f6113098987318b674088b924e22750be18c Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Fri, 17 Feb 2023 18:37:48 +0100
Subject: [PATCH] Downgrade compiler-builtins to 0.1.86
0.1.87 doesn't work on Windows when using cg_clif
---
library/std/Cargo.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 349cd91..300f812 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.87" }
+compiler_builtins = { version = "0.1.86" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
--
2.26.2.7.g19db9cfb68

View File

@ -4,6 +4,8 @@ mod comments;
mod pass_mode; mod pass_mode;
mod returning; mod returning;
use std::borrow::Cow;
use cranelift_module::ModuleError; use cranelift_module::ModuleError;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::FnAbiOf;
@ -116,7 +118,52 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
params: Vec<AbiParam>, params: Vec<AbiParam>,
returns: Vec<AbiParam>, returns: Vec<AbiParam>,
args: &[Value], args: &[Value],
) -> &[Value] { ) -> Cow<'_, [Value]> {
if self.tcx.sess.target.is_like_windows {
let (mut params, mut args): (Vec<_>, Vec<_>) =
params
.into_iter()
.zip(args)
.map(|(param, &arg)| {
if param.value_type == types::I128 {
let arg_ptr = Pointer::stack_slot(self.bcx.create_sized_stack_slot(
StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16 },
));
arg_ptr.store(self, arg, MemFlags::trusted());
(AbiParam::new(self.pointer_type), arg_ptr.get_addr(self))
} else {
(param, arg)
}
})
.unzip();
let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128;
if indirect_ret_val {
params.insert(0, AbiParam::new(self.pointer_type));
let ret_ptr =
Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData {
kind: StackSlotKind::ExplicitSlot,
size: 16,
}));
args.insert(0, ret_ptr.get_addr(self));
self.lib_call_unadjusted(name, params, vec![], &args);
return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]);
} else {
return self.lib_call_unadjusted(name, params, returns, &args);
}
}
self.lib_call_unadjusted(name, params, returns, args)
}
pub(crate) fn lib_call_unadjusted(
&mut self,
name: &str,
params: Vec<AbiParam>,
returns: Vec<AbiParam>,
args: &[Value],
) -> Cow<'_, [Value]> {
let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
@ -125,41 +172,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
} }
let call_inst = self.bcx.ins().call(func_ref, args); let call_inst = self.bcx.ins().call(func_ref, args);
if self.clif_comments.enabled() { if self.clif_comments.enabled() {
self.add_comment(call_inst, format!("easy_call {}", name)); self.add_comment(call_inst, format!("lib_call {}", name));
} }
let results = self.bcx.inst_results(call_inst); let results = self.bcx.inst_results(call_inst);
assert!(results.len() <= 2, "{}", results.len()); assert!(results.len() <= 2, "{}", results.len());
results Cow::Borrowed(results)
}
pub(crate) fn easy_call(
&mut self,
name: &str,
args: &[CValue<'tcx>],
return_ty: Ty<'tcx>,
) -> CValue<'tcx> {
let (input_tys, args): (Vec<_>, Vec<_>) = args
.iter()
.map(|arg| {
(AbiParam::new(self.clif_type(arg.layout().ty).unwrap()), arg.load_scalar(self))
})
.unzip();
let return_layout = self.layout_of(return_ty);
let return_tys = if let ty::Tuple(tup) = return_ty.kind() {
tup.iter().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect()
} else {
vec![AbiParam::new(self.clif_type(return_ty).unwrap())]
};
let ret_vals = self.lib_call(name, input_tys, return_tys, &args);
match *ret_vals {
[] => CValue::by_ref(
Pointer::const_addr(self, i64::from(self.pointer_type.bytes())),
return_layout,
),
[val] => CValue::by_val(val, return_layout),
[val, extra] => CValue::by_val_pair(val, extra, return_layout),
_ => unreachable!(),
}
} }
} }

View File

@ -64,17 +64,12 @@ pub(crate) fn clif_int_or_float_cast(
}, },
); );
let from_rust_ty = if from_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; return fx.lib_call(
&name,
let to_rust_ty = match to_ty { vec![AbiParam::new(types::I128)],
types::F32 => fx.tcx.types.f32, vec![AbiParam::new(to_ty)],
types::F64 => fx.tcx.types.f64, &[from],
_ => unreachable!(), )[0];
};
return fx
.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
.load_scalar(fx);
} }
// int-like -> float // int-like -> float
@ -101,16 +96,29 @@ pub(crate) fn clif_int_or_float_cast(
}, },
); );
let from_rust_ty = match from_ty { if fx.tcx.sess.target.is_like_windows {
types::F32 => fx.tcx.types.f32, let ret = fx.lib_call(
types::F64 => fx.tcx.types.f64, &name,
_ => unreachable!(), vec![AbiParam::new(from_ty)],
}; vec![AbiParam::new(types::I64X2)],
&[from],
let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; )[0];
// FIXME use bitcast instead of store to get from i64x2 to i128
fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
.load_scalar(fx) kind: StackSlotKind::ExplicitSlot,
size: 16,
});
let ret_ptr = Pointer::stack_slot(stack_slot);
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]
}
} else if to_ty == types::I8 || to_ty == types::I16 { } else if to_ty == types::I8 || to_ty == types::I16 {
// FIXME implement fcvt_to_*int_sat.i8/i16 // FIXME implement fcvt_to_*int_sat.i8/i16
let val = if to_signed { let val = if to_signed {

View File

@ -29,39 +29,24 @@ pub(crate) fn maybe_codegen<'tcx>(
BinOp::Add | BinOp::Sub if !checked => None, BinOp::Add | BinOp::Sub if !checked => None,
BinOp::Mul if !checked || is_signed => { BinOp::Mul if !checked || is_signed => {
if !checked { if !checked {
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
if fx.tcx.sess.target.is_like_windows { let ret_val = fx.lib_call(
let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); "__multi3",
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); vec![AbiParam::new(types::I128)],
assert!(lhs_extra.is_none()); &args,
assert!(rhs_extra.is_none()); )[0];
let args = [ Some(CValue::by_val(
ret_place.to_ptr().get_addr(fx), ret_val,
lhs_ptr.get_addr(fx), fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }),
rhs_ptr.get_addr(fx), ))
];
fx.lib_call(
"__multi3",
vec![
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
AbiParam::new(fx.pointer_type),
AbiParam::new(fx.pointer_type),
],
vec![],
&args,
);
Some(ret_place.to_cvalue(fx))
} else {
Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty))
}
} else { } else {
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
let lhs = lhs.load_scalar(fx); let lhs = lhs.load_scalar(fx);
let rhs = rhs.load_scalar(fx); let rhs = rhs.load_scalar(fx);
let oflow_ptr = oflow.to_ptr().get_addr(fx); let oflow_ptr = oflow.to_ptr().get_addr(fx);
let res = fx.lib_call( let res = fx.lib_call_unadjusted(
"__muloti4", "__muloti4",
vec![ vec![
AbiParam::new(types::I128), AbiParam::new(types::I128),
@ -80,29 +65,12 @@ pub(crate) fn maybe_codegen<'tcx>(
assert!(checked); assert!(checked);
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
let (param_types, args) = if fx.tcx.sess.target.is_like_windows { let param_types = vec![
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); AbiParam::new(types::I128),
assert!(lhs_extra.is_none()); AbiParam::new(types::I128),
assert!(rhs_extra.is_none()); ];
( let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
vec![
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
AbiParam::new(fx.pointer_type),
AbiParam::new(fx.pointer_type),
],
[out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)],
)
} else {
(
vec![
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
AbiParam::new(types::I128),
AbiParam::new(types::I128),
],
[out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)],
)
};
let name = match (bin_op, is_signed) { let name = match (bin_op, is_signed) {
(BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, false) => "__rust_u128_addo",
(BinOp::Add, true) => "__rust_i128_addo", (BinOp::Add, true) => "__rust_i128_addo",
@ -125,14 +93,10 @@ pub(crate) fn maybe_codegen<'tcx>(
_ => unreachable!(), _ => unreachable!(),
}; };
if fx.tcx.sess.target.is_like_windows { if fx.tcx.sess.target.is_like_windows {
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
assert!(lhs_extra.is_none());
assert!(rhs_extra.is_none());
let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)];
let ret = fx.lib_call( let ret = fx.lib_call(
name, name,
vec![AbiParam::new(fx.pointer_type), AbiParam::new(fx.pointer_type)], vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
vec![AbiParam::new(types::I64X2)], vec![AbiParam::new(types::I64X2)],
&args, &args,
)[0]; )[0];
@ -141,7 +105,14 @@ pub(crate) fn maybe_codegen<'tcx>(
ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); ret_place.to_ptr().store(fx, ret, MemFlags::trusted());
Some(ret_place.to_cvalue(fx)) Some(ret_place.to_cvalue(fx))
} else { } else {
Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty)) 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::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {

View File

@ -39,6 +39,7 @@ builtin_functions! {
// integers // integers
fn __multi3(a: i128, b: i128) -> i128; fn __multi3(a: i128, b: i128) -> i128;
fn __muloti4(n: i128, d: i128, oflow: &mut i32) -> i128;
fn __udivti3(n: u128, d: u128) -> u128; fn __udivti3(n: u128, d: u128) -> u128;
fn __divti3(n: i128, d: i128) -> i128; fn __divti3(n: i128, d: i128) -> i128;
fn __umodti3(n: u128, d: u128) -> u128; fn __umodti3(n: u128, d: u128) -> u128;

View File

@ -251,41 +251,41 @@ fn codegen_float_intrinsic_call<'tcx>(
args: &[mir::Operand<'tcx>], args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>, ret: CPlace<'tcx>,
) -> bool { ) -> bool {
let (name, arg_count, ty) = match intrinsic { let (name, arg_count, ty, clif_ty) = match intrinsic {
sym::expf32 => ("expf", 1, fx.tcx.types.f32), sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32),
sym::expf64 => ("exp", 1, fx.tcx.types.f64), sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64),
sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32), sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32),
sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64), sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64),
sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32), sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32),
sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64), sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64),
sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32), // compiler-builtins sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32, types::F32), // compiler-builtins
sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64), // compiler-builtins sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64, types::F64), // compiler-builtins
sym::powf32 => ("powf", 2, fx.tcx.types.f32), sym::powf32 => ("powf", 2, fx.tcx.types.f32, types::F32),
sym::powf64 => ("pow", 2, fx.tcx.types.f64), sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64),
sym::logf32 => ("logf", 1, fx.tcx.types.f32), sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32),
sym::logf64 => ("log", 1, fx.tcx.types.f64), sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64),
sym::log2f32 => ("log2f", 1, fx.tcx.types.f32), sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32),
sym::log2f64 => ("log2", 1, fx.tcx.types.f64), sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64),
sym::log10f32 => ("log10f", 1, fx.tcx.types.f32), sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32),
sym::log10f64 => ("log10", 1, fx.tcx.types.f64), sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64),
sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32), sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32),
sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64), sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64),
sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32),
sym::fmaf64 => ("fma", 3, fx.tcx.types.f64), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64),
sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32), sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32),
sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64), sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64),
sym::floorf32 => ("floorf", 1, fx.tcx.types.f32), sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32),
sym::floorf64 => ("floor", 1, fx.tcx.types.f64), sym::floorf64 => ("floor", 1, fx.tcx.types.f64, types::F64),
sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32), sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32, types::F32),
sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64), sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64),
sym::truncf32 => ("truncf", 1, fx.tcx.types.f32), sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32),
sym::truncf64 => ("trunc", 1, fx.tcx.types.f64), sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64),
sym::roundf32 => ("roundf", 1, fx.tcx.types.f32), sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32),
sym::roundf64 => ("round", 1, fx.tcx.types.f64), sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64),
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32), sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32),
sym::sinf64 => ("sin", 1, fx.tcx.types.f64), sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64),
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32), sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32),
sym::cosf64 => ("cos", 1, fx.tcx.types.f64), sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64),
_ => return false, _ => return false,
}; };
@ -296,15 +296,19 @@ fn codegen_float_intrinsic_call<'tcx>(
let (a, b, c); let (a, b, c);
let args = match args { let args = match args {
[x] => { [x] => {
a = [codegen_operand(fx, x)]; a = [codegen_operand(fx, x).load_scalar(fx)];
&a as &[_] &a as &[_]
} }
[x, y] => { [x, y] => {
b = [codegen_operand(fx, x), codegen_operand(fx, y)]; b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)];
&b &b
} }
[x, y, z] => { [x, y, z] => {
c = [codegen_operand(fx, x), codegen_operand(fx, y), codegen_operand(fx, z)]; c = [
codegen_operand(fx, x).load_scalar(fx),
codegen_operand(fx, y).load_scalar(fx),
codegen_operand(fx, z).load_scalar(fx),
];
&c &c
} }
_ => unreachable!(), _ => unreachable!(),
@ -313,15 +317,10 @@ fn codegen_float_intrinsic_call<'tcx>(
let layout = fx.layout_of(ty); let layout = fx.layout_of(ty);
let res = match intrinsic { let res = match intrinsic {
sym::fmaf32 | sym::fmaf64 => { sym::fmaf32 | sym::fmaf64 => {
let a = args[0].load_scalar(fx); CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout)
let b = args[1].load_scalar(fx);
let c = args[2].load_scalar(fx);
CValue::by_val(fx.bcx.ins().fma(a, b, c), layout)
} }
sym::copysignf32 | sym::copysignf64 => { sym::copysignf32 | sym::copysignf64 => {
let a = args[0].load_scalar(fx); CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout)
let b = args[1].load_scalar(fx);
CValue::by_val(fx.bcx.ins().fcopysign(a, b), layout)
} }
sym::fabsf32 sym::fabsf32
| sym::fabsf64 | sym::fabsf64
@ -331,21 +330,29 @@ fn codegen_float_intrinsic_call<'tcx>(
| sym::ceilf64 | sym::ceilf64
| sym::truncf32 | sym::truncf32
| sym::truncf64 => { | sym::truncf64 => {
let a = args[0].load_scalar(fx);
let val = match intrinsic { let val = match intrinsic {
sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(a), sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]),
sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(a), sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(a), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(a), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
_ => unreachable!(), _ => unreachable!(),
}; };
CValue::by_val(val, layout) CValue::by_val(val, layout)
} }
// These intrinsics aren't supported natively by Cranelift. // These intrinsics aren't supported natively by Cranelift.
// Lower them to a libcall. // Lower them to a libcall.
_ => fx.easy_call(name, &args, ty), sym::powif32 | sym::powif64 => {
let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), AbiParam::new(types::I32)];
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0];
CValue::by_val(ret_val, fx.layout_of(ty))
}
_ => {
let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect();
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0];
CValue::by_val(ret_val, fx.layout_of(ty))
}
}; };
ret.write_cvalue(fx, res); ret.write_cvalue(fx, res);

View File

@ -347,12 +347,20 @@ pub(crate) fn codegen_float_binop<'tcx>(
BinOp::Mul => b.fmul(lhs, rhs), BinOp::Mul => b.fmul(lhs, rhs),
BinOp::Div => b.fdiv(lhs, rhs), BinOp::Div => b.fdiv(lhs, rhs),
BinOp::Rem => { BinOp::Rem => {
let name = match in_lhs.layout().ty.kind() { let (name, ty) = match in_lhs.layout().ty.kind() {
ty::Float(FloatTy::F32) => "fmodf", ty::Float(FloatTy::F32) => ("fmodf", types::F32),
ty::Float(FloatTy::F64) => "fmod", ty::Float(FloatTy::F64) => ("fmod", types::F64),
_ => bug!(), _ => bug!(),
}; };
return fx.easy_call(name, &[in_lhs, in_rhs], in_lhs.layout().ty);
let ret_val = fx.lib_call(
name,
vec![AbiParam::new(ty), AbiParam::new(ty)],
vec![AbiParam::new(ty)],
&[lhs, rhs],
)[0];
return CValue::by_val(ret_val, in_lhs.layout());
} }
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
let fltcc = match bin_op { let fltcc = match bin_op {

View File

@ -30,11 +30,6 @@ impl Pointer {
Pointer { base: PointerBase::Stack(stack_slot), offset: Offset32::new(0) } Pointer { base: PointerBase::Stack(stack_slot), offset: Offset32::new(0) }
} }
pub(crate) fn const_addr(fx: &mut FunctionCx<'_, '_, '_>, addr: i64) -> Self {
let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
}
pub(crate) fn dangling(align: Align) -> Self { pub(crate) fn dangling(align: Align) -> Self {
Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) } Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) }
} }