Merge commit 'b7091eca6d8eb0fe88b58cc9a7aec405d8de5b85' into subtree-update_cg_gcc_2025-06-28

This commit is contained in:
Guillaume Gomez
2025-06-28 23:37:08 +02:00
12 changed files with 150 additions and 117 deletions

View File

@@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.block
}
fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
let func = cx.rvalue_as_function(func);
fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> {
func.new_block(name)
}
@@ -782,6 +781,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
return self.context.new_call(self.location, fmod, &[a, b]);
}
TypeKind::FP128 => {
// TODO(antoyo): use get_simple_function_f128_2args.
let f128_type = self.type_f128();
let fmodf128 = self.context.new_function(
None,
@@ -938,22 +938,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
let block = self.llbb();
let function = block.get_function();
// NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
// For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
// Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
//
// From GCCs perspective:
// __int128_t __attribute__((aligned(16))) __attribute__((aligned(16)))
// and:
// __int128_t __attribute__((aligned(16)))
// are 2 distinct, incompatible types.
//
// So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
// but the GCC APIs to facilitate this just aren't quite there yet.
// This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
// Otherwise, this may be an under-aligned load, so we will still call get_aligned.
let mut can_skip_align = (pointee_ty == self.cx.u128_type
|| pointee_ty == self.cx.i128_type)
&& align == self.int128_align;
// We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
can_skip_align = can_skip_align
|| (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type)
&& align.bytes() == 1;
// Skip the call to `get_aligned` when possible.
let aligned_type =
if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) };
let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
// NOTE: instead of returning the dereference here, we have to assign it to a variable in
// the current basic block. Otherwise, it could be used in another basic block, causing a
// dereference after a drop, for instance.
// FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
// Ideally, we shouldn't need to do this check.
// FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if
// the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle
// under-aligned loads correctly.
let aligned_type = if (pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type)
&& align == self.int128_align
{
pointee_ty
} else {
pointee_ty.get_aligned(align.bytes())
};
let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
let deref = ptr.dereference(self.location).to_rvalue();
let loaded_value = function.new_local(
self.location,
@@ -1105,7 +1119,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// TODO(antoyo)
}
fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
fn store(&mut self, mut val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
if self.structs_as_pointer.borrow().contains(&val) {
// NOTE: hack to workaround a limitation of the rustc API: see comment on
// CodegenCx.structs_as_pointer
val = val.dereference(self.location).to_rvalue();
}
self.store_with_flags(val, ptr, align, MemFlags::empty())
}
@@ -1551,16 +1571,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
aggregate_value
}
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
fn set_personality_fn(&mut self, _personality: Function<'gcc>) {
#[cfg(feature = "master")]
{
let personality = self.rvalue_as_function(_personality);
self.current_func().set_personality_function(personality);
}
self.current_func().set_personality_function(_personality);
}
#[cfg(feature = "master")]
fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
self.set_personality_fn(pers_fn);
// NOTE: insert the current block in a variable so that a later call to invoke knows to
@@ -1581,7 +1598,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
#[cfg(not(feature = "master"))]
fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
let value1 = self
.current_func()
.new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
@@ -1591,7 +1608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
(value1, value2)
}
fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) {
fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
// TODO(antoyo): generate the correct landing pad
self.cleanup_landing_pad(pers_fn);
}