Merge commit '98ed962c7d3eebe12c97588e61245273d265e72f' into master

This commit is contained in:
Guillaume Gomez
2024-07-10 12:44:23 +02:00
68 changed files with 2682 additions and 1135 deletions

View File

@@ -2,8 +2,6 @@
//! This module exists because some integer types are not supported on some gcc platforms, e.g.
//! 128-bit integers on 32-bit platforms and thus require to be handled manually.
use std::convert::TryFrom;
use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
@@ -40,7 +38,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
self.cx.context.new_unary_op(self.location, operation, typ, a)
} else {
let element_type = typ.dyncast_array().expect("element type");
self.from_low_high_rvalues(
self.concat_low_high_rvalues(
typ,
self.cx.context.new_unary_op(
self.location,
@@ -83,7 +81,19 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let b = self.context.new_cast(self.location, b, a_type);
a >> b
} else {
a >> b
let a_size = a_type.get_size();
let b_size = b_type.get_size();
match a_size.cmp(&b_size) {
std::cmp::Ordering::Less => {
let a = self.context.new_cast(self.location, a, b_type);
a >> b
}
std::cmp::Ordering::Equal => a >> b,
std::cmp::Ordering::Greater => {
let b = self.context.new_cast(self.location, b, a_type);
a >> b
}
}
}
} else if a_type.is_vector() && a_type.is_vector() {
a >> b
@@ -114,7 +124,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let shift_value = self.gcc_sub(b, sixty_four);
let high = self.high(a);
let sign = if a_type.is_signed(self) { high >> sixty_three } else { zero };
let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign);
let array_value = self.concat_low_high_rvalues(a_type, high >> shift_value, sign);
then_block.add_assignment(self.location, result, array_value);
then_block.end_with_jump(self.location, after_block);
@@ -126,12 +136,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let shift_value = self.gcc_sub(sixty_four, b);
// NOTE: cast low to its unsigned type in order to perform a logical right shift.
let unsigned_type = native_int_type.to_unsigned(&self.cx);
let unsigned_type = native_int_type.to_unsigned(self.cx);
let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type);
let shifted_low = casted_low >> self.context.new_cast(self.location, b, unsigned_type);
let shifted_low = self.context.new_cast(self.location, shifted_low, native_int_type);
let array_value =
self.from_low_high_rvalues(a_type, (high << shift_value) | shifted_low, high >> b);
let array_value = self.concat_low_high_rvalues(
a_type,
(high << shift_value) | shifted_low,
high >> b,
);
actual_else_block.add_assignment(self.location, result, array_value);
actual_else_block.end_with_jump(self.location, after_block);
@@ -255,10 +268,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) {
use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
let new_kind = match typ.kind() {
let new_kind = match *typ.kind() {
Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
t @ (Uint(_) | Int(_)) => t.clone(),
t @ (Uint(_) | Int(_)) => t,
_ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
};
@@ -344,7 +357,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
}
};
let intrinsic = self.context.get_builtin_function(&name);
let intrinsic = self.context.get_builtin_function(name);
let res = self
.current_func()
// TODO(antoyo): is it correct to use rhs type instead of the parameter typ?
@@ -454,7 +467,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
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 unsigned_type = native_int_type.to_unsigned(self.cx);
let lhs_low = self.context.new_cast(self.location, self.low(lhs), unsigned_type);
let rhs_low = self.context.new_cast(self.location, self.low(rhs), unsigned_type);
@@ -589,7 +602,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
| IntPredicate::IntULT
| IntPredicate::IntULE => {
if !a_type.is_vector() {
let unsigned_type = a_type.to_unsigned(&self.cx);
let unsigned_type = a_type.to_unsigned(self.cx);
lhs = self.context.new_cast(self.location, lhs, unsigned_type);
rhs = self.context.new_cast(self.location, rhs, unsigned_type);
}
@@ -612,7 +625,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
{
a ^ b
} else {
self.from_low_high_rvalues(
self.concat_low_high_rvalues(
a_type,
self.low(a) ^ self.low(b),
self.high(a) ^ self.high(b),
@@ -635,7 +648,19 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let b = self.context.new_cast(self.location, b, a_type);
a << b
} else {
a << b
let a_size = a_type.get_size();
let b_size = b_type.get_size();
match a_size.cmp(&b_size) {
std::cmp::Ordering::Less => {
let a = self.context.new_cast(self.location, a, b_type);
a << b
}
std::cmp::Ordering::Equal => a << b,
std::cmp::Ordering::Greater => {
let b = self.context.new_cast(self.location, b, a_type);
a << b
}
}
}
} else if a_type.is_vector() && a_type.is_vector() {
a << b
@@ -661,7 +686,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
self.llbb().end_with_conditional(self.location, condition, then_block, else_block);
let array_value =
self.from_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four));
self.concat_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four));
then_block.add_assignment(self.location, result, array_value);
then_block.end_with_jump(self.location, after_block);
@@ -673,13 +698,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
// NOTE: cast low to its unsigned type in order to perform a logical right shift.
// TODO(antoyo): adjust this ^ comment.
let unsigned_type = native_int_type.to_unsigned(&self.cx);
let unsigned_type = native_int_type.to_unsigned(self.cx);
let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type);
let shift_value = self.context.new_cast(self.location, sixty_four - b, unsigned_type);
let high_low =
self.context.new_cast(self.location, casted_low >> shift_value, native_int_type);
let array_value = self.from_low_high_rvalues(
let array_value = self.concat_low_high_rvalues(
a_type,
self.low(a) << b,
(self.high(a) << b) | high_low,
@@ -708,7 +733,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
// NOTE: we also need to swap the two elements here, in addition to swapping inside
// the elements themselves like done above.
return self.from_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
return self.concat_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
}
// TODO(antoyo): check if it's faster to use string literals and a
@@ -727,10 +752,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn gcc_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
if self.is_native_int_type_or_bool(typ) {
self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from"))
self.context.new_rvalue_from_long(typ, int)
} else {
// NOTE: set the sign in high.
self.from_low_high(typ, int, -(int.is_negative() as i64))
self.concat_low_high(typ, int, -(int.is_negative() as i64))
}
}
@@ -740,10 +765,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let num = self.context.new_rvalue_from_long(self.u64_type, int as i64);
self.gcc_int_cast(num, typ)
} else if self.is_native_int_type_or_bool(typ) {
self.context
.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
self.context.new_rvalue_from_long(typ, int as i64)
} else {
self.from_low_high(typ, int as i64, 0)
self.concat_low_high(typ, int as i64, 0)
}
}
@@ -760,7 +784,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let shift = high << sixty_four;
shift | self.context.new_cast(None, low, typ)
} else {
self.from_low_high(typ, low as i64, high as i64)
self.concat_low_high(typ, low as i64, high as i64)
}
} else if typ.is_i128(self) {
// FIXME(antoyo): libgccjit cannot create 128-bit values yet.
@@ -775,7 +799,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
if self.is_native_int_type_or_bool(typ) {
self.context.new_rvalue_zero(typ)
} else {
self.from_low_high(typ, 0, 0)
self.concat_low_high(typ, 0, 0)
}
}
@@ -813,7 +837,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
"both types should either be native or non-native for or operation"
);
let native_int_type = a_type.dyncast_array().expect("get element type");
self.from_low_high_rvalues(
self.concat_low_high_rvalues(
a_type,
self.context.new_binary_op(
loc,
@@ -858,7 +882,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let is_negative =
self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
self.from_low_high_rvalues(
self.concat_low_high_rvalues(
dest_typ,
self.context.new_cast(None, value, dest_element_type),
self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
@@ -926,7 +950,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
return self.context.new_cast(None, value, dest_typ);
}
debug_assert!(value_type.dyncast_array().is_some());
debug_assert!(dest_typ.dyncast_array().is_some());
let name_suffix = match self.type_kind(value_type) {
TypeKind::Float => "sfti",
TypeKind::Double => "dfti",
@@ -978,7 +1002,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
.to_rvalue()
}
fn from_low_high_rvalues(
fn concat_low_high_rvalues(
&self,
typ: Type<'gcc>,
low: RValue<'gcc>,
@@ -993,7 +1017,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
self.context.new_array_constructor(None, typ, &values)
}
fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
fn concat_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
let (first, last) = match self.sess().target.options.endian {
Endian::Little => (low, high),
Endian::Big => (high, low),