Skip to content

Commit d484836

Browse files
authored
Merge pull request rust-lang#349 from rust-lang/fix/128-bit-ints-operations
Fix/128 bit ints operations
2 parents c6447be + b3c10d4 commit d484836

File tree

2 files changed

+57
-18
lines changed

2 files changed

+57
-18
lines changed

Readme.md

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_
113113
<dd>Display the time it took to perform codegen for a crate</dd>
114114
<dt>CG_RUSTFLAGS</dt>
115115
<dd>Send additional flags to rustc. Can be used to build the sysroot without unwinding by setting `CG_RUSTFLAGS=-Cpanic=abort`.</dd>
116+
<dt>CG_GCCJIT_DUMP_TO_FILE</dt>
117+
<dd>Dump a C-like representation to /tmp/gccjit_dumps and enable debug info in order to debug this C-like representation.</dd>
116118
</dl>
117119

118120
## Licensing

src/int.rs

+55-18
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
3636
self.cx.context.new_unary_op(None, operation, typ, a)
3737
}
3838
else {
39-
// TODO(antoyo): use __negdi2 and __negti2 instead?
4039
let element_type = typ.dyncast_array().expect("element type");
4140
let values = [
4241
self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)),
@@ -52,9 +51,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
5251
self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
5352
}
5453
else {
55-
let param_a = self.context.new_parameter(None, a_type, "a");
56-
let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a], "__negti2", false);
57-
self.context.new_call(None, func, &[a])
54+
self.gcc_add(self.gcc_not(a), self.gcc_int(a_type, 1))
5855
}
5956
}
6057

@@ -353,23 +350,63 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
353350
(res.dereference(None).to_rvalue(), overflow)
354351
}
355352

356-
pub fn gcc_icmp(&self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
353+
pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
357354
let a_type = lhs.get_type();
358355
let b_type = rhs.get_type();
359356
if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) {
360-
let signed = a_type.is_compatible_with(self.i128_type);
361-
let sign =
362-
if signed {
363-
""
364-
}
365-
else {
366-
"u"
367-
};
368-
let func_name = format!("__{}cmpti2", sign);
369-
let param_a = self.context.new_parameter(None, a_type, "a");
370-
let param_b = self.context.new_parameter(None, b_type, "b");
371-
let func = self.context.new_function(None, FunctionType::Extern, self.int_type, &[param_a, param_b], func_name, false);
372-
let cmp = self.context.new_call(None, func, &[lhs, rhs]);
357+
// This algorithm is based on compiler-rt's __cmpti2:
358+
// https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21
359+
let result = self.current_func().new_local(None, self.int_type, "icmp_result");
360+
let block1 = self.current_func().new_block("block1");
361+
let block2 = self.current_func().new_block("block2");
362+
let block3 = self.current_func().new_block("block3");
363+
let block4 = self.current_func().new_block("block4");
364+
let block5 = self.current_func().new_block("block5");
365+
let block6 = self.current_func().new_block("block6");
366+
let block7 = self.current_func().new_block("block7");
367+
let block8 = self.current_func().new_block("block8");
368+
let after = self.current_func().new_block("after");
369+
370+
let native_int_type = a_type.dyncast_array().expect("get element type");
371+
// NOTE: cast low to its unsigned type in order to perform a comparison correctly (e.g.
372+
// the sign is only on high).
373+
let unsigned_type = native_int_type.to_unsigned(&self.cx);
374+
375+
let lhs_low = self.context.new_cast(None, self.low(lhs), unsigned_type);
376+
let rhs_low = self.context.new_cast(None, self.low(rhs), unsigned_type);
377+
378+
let condition = self.context.new_comparison(None, ComparisonOp::LessThan, self.high(lhs), self.high(rhs));
379+
self.llbb().end_with_conditional(None, condition, block1, block2);
380+
381+
block1.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
382+
block1.end_with_jump(None, after);
383+
384+
let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs));
385+
block2.end_with_conditional(None, condition, block3, block4);
386+
387+
block3.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
388+
block3.end_with_jump(None, after);
389+
390+
let condition = self.context.new_comparison(None, ComparisonOp::LessThan, lhs_low, rhs_low);
391+
block4.end_with_conditional(None, condition, block5, block6);
392+
393+
block5.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
394+
block5.end_with_jump(None, after);
395+
396+
let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, lhs_low, rhs_low);
397+
block6.end_with_conditional(None, condition, block7, block8);
398+
399+
block7.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
400+
block7.end_with_jump(None, after);
401+
402+
block8.add_assignment(None, result, self.context.new_rvalue_one(self.int_type));
403+
block8.end_with_jump(None, after);
404+
405+
// NOTE: since jumps were added in a place rustc does not expect, the current block in the
406+
// state need to be updated.
407+
self.switch_to_block(after);
408+
409+
let cmp = result.to_rvalue();
373410
let (op, limit) =
374411
match op {
375412
IntPredicate::IntEQ => {

0 commit comments

Comments
 (0)