Skip to content

Commit cb12ad7

Browse files
authored
Merge pull request #1359 from bjorn3/fix_llvm14-builtins-abi
Fix compiler-builtins 0.1.87 on Windows
2 parents 718574a + bb933d2 commit cb12ad7

11 files changed

+185
-204
lines changed

build_sysroot/Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build_sysroot/Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ alloc = { path = "./sysroot_src/library/alloc" }
88
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
99
test = { path = "./sysroot_src/library/test" }
1010

11-
# FIXME allow 0.1.87 and later once #1353 is fixed
12-
compiler_builtins = { version = "=0.1.86", default-features = false, features = ["no-asm"] }
11+
compiler_builtins = { version = "0.1.87", default-features = false, features = ["no-asm"] }
1312

1413
[patch.crates-io]
1514
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }

example/std_example.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ fn main() {
5858
assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
5959
assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128);
6060

61-
let _d = 0i128.checked_div(2i128);
62-
let _d = 0u128.checked_div(2u128);
61+
std::hint::black_box(std::hint::black_box(7571400400375753350092698930310845914i128) * 10);
62+
assert!(0i128.checked_div(2i128).is_some());
63+
assert!(0u128.checked_div(2u128).is_some());
6364
assert_eq!(1u128 + 2, 3);
6465

6566
assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128);

patches/0029-sysroot-Downgrade-compiler-builtins-to-0.1.86.patch

-26
This file was deleted.

src/abi/mod.rs

+50-33
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ mod comments;
44
mod pass_mode;
55
mod returning;
66

7+
use std::borrow::Cow;
8+
79
use cranelift_module::ModuleError;
810
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
911
use rustc_middle::ty::layout::FnAbiOf;
@@ -116,7 +118,52 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
116118
params: Vec<AbiParam>,
117119
returns: Vec<AbiParam>,
118120
args: &[Value],
119-
) -> &[Value] {
121+
) -> Cow<'_, [Value]> {
122+
if self.tcx.sess.target.is_like_windows {
123+
let (mut params, mut args): (Vec<_>, Vec<_>) =
124+
params
125+
.into_iter()
126+
.zip(args)
127+
.map(|(param, &arg)| {
128+
if param.value_type == types::I128 {
129+
let arg_ptr = Pointer::stack_slot(self.bcx.create_sized_stack_slot(
130+
StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16 },
131+
));
132+
arg_ptr.store(self, arg, MemFlags::trusted());
133+
(AbiParam::new(self.pointer_type), arg_ptr.get_addr(self))
134+
} else {
135+
(param, arg)
136+
}
137+
})
138+
.unzip();
139+
140+
let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128;
141+
142+
if indirect_ret_val {
143+
params.insert(0, AbiParam::new(self.pointer_type));
144+
let ret_ptr =
145+
Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData {
146+
kind: StackSlotKind::ExplicitSlot,
147+
size: 16,
148+
}));
149+
args.insert(0, ret_ptr.get_addr(self));
150+
self.lib_call_unadjusted(name, params, vec![], &args);
151+
return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]);
152+
} else {
153+
return self.lib_call_unadjusted(name, params, returns, &args);
154+
}
155+
}
156+
157+
self.lib_call_unadjusted(name, params, returns, args)
158+
}
159+
160+
pub(crate) fn lib_call_unadjusted(
161+
&mut self,
162+
name: &str,
163+
params: Vec<AbiParam>,
164+
returns: Vec<AbiParam>,
165+
args: &[Value],
166+
) -> Cow<'_, [Value]> {
120167
let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
121168
let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
122169
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
@@ -125,41 +172,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
125172
}
126173
let call_inst = self.bcx.ins().call(func_ref, args);
127174
if self.clif_comments.enabled() {
128-
self.add_comment(call_inst, format!("easy_call {}", name));
175+
self.add_comment(call_inst, format!("lib_call {}", name));
129176
}
130177
let results = self.bcx.inst_results(call_inst);
131178
assert!(results.len() <= 2, "{}", results.len());
132-
results
133-
}
134-
135-
pub(crate) fn easy_call(
136-
&mut self,
137-
name: &str,
138-
args: &[CValue<'tcx>],
139-
return_ty: Ty<'tcx>,
140-
) -> CValue<'tcx> {
141-
let (input_tys, args): (Vec<_>, Vec<_>) = args
142-
.iter()
143-
.map(|arg| {
144-
(AbiParam::new(self.clif_type(arg.layout().ty).unwrap()), arg.load_scalar(self))
145-
})
146-
.unzip();
147-
let return_layout = self.layout_of(return_ty);
148-
let return_tys = if let ty::Tuple(tup) = return_ty.kind() {
149-
tup.iter().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect()
150-
} else {
151-
vec![AbiParam::new(self.clif_type(return_ty).unwrap())]
152-
};
153-
let ret_vals = self.lib_call(name, input_tys, return_tys, &args);
154-
match *ret_vals {
155-
[] => CValue::by_ref(
156-
Pointer::const_addr(self, i64::from(self.pointer_type.bytes())),
157-
return_layout,
158-
),
159-
[val] => CValue::by_val(val, return_layout),
160-
[val, extra] => CValue::by_val_pair(val, extra, return_layout),
161-
_ => unreachable!(),
162-
}
179+
Cow::Borrowed(results)
163180
}
164181
}
165182

src/cast.rs

+29-21
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,12 @@ pub(crate) fn clif_int_or_float_cast(
6464
},
6565
);
6666

67-
let from_rust_ty = if from_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
68-
69-
let to_rust_ty = match to_ty {
70-
types::F32 => fx.tcx.types.f32,
71-
types::F64 => fx.tcx.types.f64,
72-
_ => unreachable!(),
73-
};
74-
75-
return fx
76-
.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
77-
.load_scalar(fx);
67+
return fx.lib_call(
68+
&name,
69+
vec![AbiParam::new(types::I128)],
70+
vec![AbiParam::new(to_ty)],
71+
&[from],
72+
)[0];
7873
}
7974

8075
// int-like -> float
@@ -101,16 +96,29 @@ pub(crate) fn clif_int_or_float_cast(
10196
},
10297
);
10398

104-
let from_rust_ty = match from_ty {
105-
types::F32 => fx.tcx.types.f32,
106-
types::F64 => fx.tcx.types.f64,
107-
_ => unreachable!(),
108-
};
109-
110-
let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
111-
112-
fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
113-
.load_scalar(fx)
99+
if fx.tcx.sess.target.is_like_windows {
100+
let ret = fx.lib_call(
101+
&name,
102+
vec![AbiParam::new(from_ty)],
103+
vec![AbiParam::new(types::I64X2)],
104+
&[from],
105+
)[0];
106+
// FIXME use bitcast instead of store to get from i64x2 to i128
107+
let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
108+
kind: StackSlotKind::ExplicitSlot,
109+
size: 16,
110+
});
111+
let ret_ptr = Pointer::stack_slot(stack_slot);
112+
ret_ptr.store(fx, ret, MemFlags::trusted());
113+
ret_ptr.load(fx, types::I128, MemFlags::trusted())
114+
} else {
115+
fx.lib_call(
116+
&name,
117+
vec![AbiParam::new(from_ty)],
118+
vec![AbiParam::new(types::I128)],
119+
&[from],
120+
)[0]
121+
}
114122
} else if to_ty == types::I8 || to_ty == types::I16 {
115123
// FIXME implement fcvt_to_*int_sat.i8/i16
116124
let val = if to_signed {

src/codegen_i128.rs

+28-57
Original file line numberDiff line numberDiff line change
@@ -29,39 +29,24 @@ pub(crate) fn maybe_codegen<'tcx>(
2929
BinOp::Add | BinOp::Sub if !checked => None,
3030
BinOp::Mul if !checked || is_signed => {
3131
if !checked {
32-
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
33-
if fx.tcx.sess.target.is_like_windows {
34-
let ret_place = CPlace::new_stack_slot(fx, lhs.layout());
35-
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
36-
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
37-
assert!(lhs_extra.is_none());
38-
assert!(rhs_extra.is_none());
39-
let args = [
40-
ret_place.to_ptr().get_addr(fx),
41-
lhs_ptr.get_addr(fx),
42-
rhs_ptr.get_addr(fx),
43-
];
44-
fx.lib_call(
45-
"__multi3",
46-
vec![
47-
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
48-
AbiParam::new(fx.pointer_type),
49-
AbiParam::new(fx.pointer_type),
50-
],
51-
vec![],
52-
&args,
53-
);
54-
Some(ret_place.to_cvalue(fx))
55-
} else {
56-
Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty))
57-
}
32+
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
33+
let ret_val = fx.lib_call(
34+
"__multi3",
35+
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
36+
vec![AbiParam::new(types::I128)],
37+
&args,
38+
)[0];
39+
Some(CValue::by_val(
40+
ret_val,
41+
fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }),
42+
))
5843
} else {
5944
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
6045
let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
6146
let lhs = lhs.load_scalar(fx);
6247
let rhs = rhs.load_scalar(fx);
6348
let oflow_ptr = oflow.to_ptr().get_addr(fx);
64-
let res = fx.lib_call(
49+
let res = fx.lib_call_unadjusted(
6550
"__muloti4",
6651
vec![
6752
AbiParam::new(types::I128),
@@ -80,29 +65,12 @@ pub(crate) fn maybe_codegen<'tcx>(
8065
assert!(checked);
8166
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
8267
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
83-
let (param_types, args) = if fx.tcx.sess.target.is_like_windows {
84-
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
85-
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
86-
assert!(lhs_extra.is_none());
87-
assert!(rhs_extra.is_none());
88-
(
89-
vec![
90-
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
91-
AbiParam::new(fx.pointer_type),
92-
AbiParam::new(fx.pointer_type),
93-
],
94-
[out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)],
95-
)
96-
} else {
97-
(
98-
vec![
99-
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
100-
AbiParam::new(types::I128),
101-
AbiParam::new(types::I128),
102-
],
103-
[out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)],
104-
)
105-
};
68+
let param_types = vec![
69+
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
70+
AbiParam::new(types::I128),
71+
AbiParam::new(types::I128),
72+
];
73+
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
10674
let name = match (bin_op, is_signed) {
10775
(BinOp::Add, false) => "__rust_u128_addo",
10876
(BinOp::Add, true) => "__rust_i128_addo",
@@ -125,14 +93,10 @@ pub(crate) fn maybe_codegen<'tcx>(
12593
_ => unreachable!(),
12694
};
12795
if fx.tcx.sess.target.is_like_windows {
128-
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
129-
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
130-
assert!(lhs_extra.is_none());
131-
assert!(rhs_extra.is_none());
132-
let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)];
96+
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
13397
let ret = fx.lib_call(
13498
name,
135-
vec![AbiParam::new(fx.pointer_type), AbiParam::new(fx.pointer_type)],
99+
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
136100
vec![AbiParam::new(types::I64X2)],
137101
&args,
138102
)[0];
@@ -141,7 +105,14 @@ pub(crate) fn maybe_codegen<'tcx>(
141105
ret_place.to_ptr().store(fx, ret, MemFlags::trusted());
142106
Some(ret_place.to_cvalue(fx))
143107
} else {
144-
Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty))
108+
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
109+
let ret_val = fx.lib_call(
110+
name,
111+
vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
112+
vec![AbiParam::new(types::I128)],
113+
&args,
114+
)[0];
115+
Some(CValue::by_val(ret_val, lhs.layout()))
145116
}
146117
}
147118
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {

src/compiler_builtins.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ builtin_functions! {
3939

4040
// integers
4141
fn __multi3(a: i128, b: i128) -> i128;
42+
fn __muloti4(n: i128, d: i128, oflow: &mut i32) -> i128;
4243
fn __udivti3(n: u128, d: u128) -> u128;
4344
fn __divti3(n: i128, d: i128) -> i128;
4445
fn __umodti3(n: u128, d: u128) -> u128;

0 commit comments

Comments
 (0)