mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Fix 128-bit non-native integers comparison
This commit is contained in:
parent
71febd94f4
commit
b3fecae7d7
@ -113,6 +113,8 @@ $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_
|
||||
<dd>Display the time it took to perform codegen for a crate</dd>
|
||||
<dt>CG_RUSTFLAGS</dt>
|
||||
<dd>Send additional flags to rustc. Can be used to build the sysroot without unwinding by setting `CG_RUSTFLAGS=-Cpanic=abort`.</dd>
|
||||
<dt>CG_GCCJIT_DUMP_TO_FILE</dt>
|
||||
<dd>Dump a C-like representation to /tmp/gccjit_dumps and enable debug info in order to debug this C-like representation.</dd>
|
||||
</dl>
|
||||
|
||||
## Licensing
|
||||
|
68
src/int.rs
68
src/int.rs
@ -353,23 +353,63 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
(res.dereference(None).to_rvalue(), overflow)
|
||||
}
|
||||
|
||||
pub fn gcc_icmp(&self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) {
|
||||
let signed = a_type.is_compatible_with(self.i128_type);
|
||||
let sign =
|
||||
if signed {
|
||||
""
|
||||
}
|
||||
else {
|
||||
"u"
|
||||
};
|
||||
let func_name = format!("__{}cmpti2", sign);
|
||||
let param_a = self.context.new_parameter(None, a_type, "a");
|
||||
let param_b = self.context.new_parameter(None, b_type, "b");
|
||||
let func = self.context.new_function(None, FunctionType::Extern, self.int_type, &[param_a, param_b], func_name, false);
|
||||
let cmp = self.context.new_call(None, func, &[lhs, rhs]);
|
||||
// This algorithm is based on compiler-rt's __cmpti2:
|
||||
// https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21
|
||||
let result = self.current_func().new_local(None, self.int_type, "icmp_result");
|
||||
let block1 = self.current_func().new_block("block1");
|
||||
let block2 = self.current_func().new_block("block2");
|
||||
let block3 = self.current_func().new_block("block3");
|
||||
let block4 = self.current_func().new_block("block4");
|
||||
let block5 = self.current_func().new_block("block5");
|
||||
let block6 = self.current_func().new_block("block6");
|
||||
let block7 = self.current_func().new_block("block7");
|
||||
let block8 = self.current_func().new_block("block8");
|
||||
let after = self.current_func().new_block("after");
|
||||
|
||||
let native_int_type = a_type.dyncast_array().expect("get element type");
|
||||
// NOTE: cast low to its unsigned type in order to perform a comparison correctly (e.g.
|
||||
// the sign is only on high).
|
||||
let unsigned_type = native_int_type.to_unsigned(&self.cx);
|
||||
|
||||
let lhs_low = self.context.new_cast(None, self.low(lhs), unsigned_type);
|
||||
let rhs_low = self.context.new_cast(None, self.low(rhs), unsigned_type);
|
||||
|
||||
let condition = self.context.new_comparison(None, ComparisonOp::LessThan, self.high(lhs), self.high(rhs));
|
||||
self.llbb().end_with_conditional(None, condition, block1, block2);
|
||||
|
||||
block1.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
|
||||
block1.end_with_jump(None, after);
|
||||
|
||||
let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs));
|
||||
block2.end_with_conditional(None, condition, block3, block4);
|
||||
|
||||
block3.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
|
||||
block3.end_with_jump(None, after);
|
||||
|
||||
let condition = self.context.new_comparison(None, ComparisonOp::LessThan, lhs_low, rhs_low);
|
||||
block4.end_with_conditional(None, condition, block5, block6);
|
||||
|
||||
block5.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
|
||||
block5.end_with_jump(None, after);
|
||||
|
||||
let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, lhs_low, rhs_low);
|
||||
block6.end_with_conditional(None, condition, block7, block8);
|
||||
|
||||
block7.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
|
||||
block7.end_with_jump(None, after);
|
||||
|
||||
block8.add_assignment(None, result, self.context.new_rvalue_one(self.int_type));
|
||||
block8.end_with_jump(None, after);
|
||||
|
||||
// NOTE: since jumps were added in a place rustc does not expect, the current block in the
|
||||
// state need to be updated.
|
||||
self.switch_to_block(after);
|
||||
|
||||
let cmp = result.to_rvalue();
|
||||
let (op, limit) =
|
||||
match op {
|
||||
IntPredicate::IntEQ => {
|
||||
|
Loading…
Reference in New Issue
Block a user