diff options
Diffstat (limited to 'compiler/rustc_codegen_gcc/src/builder.rs')
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/builder.rs | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 68c6156fa4b..a2e34d1f8fb 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -765,7 +765,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(feature = "master")] match self.cx.type_kind(a_type) { - TypeKind::Half | TypeKind::Float => { + TypeKind::Half => { + let fmodf = self.context.get_builtin_function("fmodf"); + let f32_type = self.type_f32(); + let a = self.context.new_cast(self.location, a, f32_type); + let b = self.context.new_cast(self.location, b, f32_type); + let result = self.context.new_call(self.location, fmodf, &[a, b]); + return self.context.new_cast(self.location, result, a_type); + } + TypeKind::Float => { let fmodf = self.context.get_builtin_function("fmodf"); return self.context.new_call(self.location, fmodf, &[a, b]); } @@ -774,8 +782,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { return self.context.new_call(self.location, fmod, &[a, b]); } TypeKind::FP128 => { - let fmodl = self.context.get_builtin_function("fmodl"); - return self.context.new_call(self.location, fmodl, &[a, b]); + let f128_type = self.type_f128(); + let fmodf128 = self.context.new_function( + None, + gccjit::FunctionType::Extern, + f128_type, + &[ + self.context.new_parameter(None, f128_type, "a"), + self.context.new_parameter(None, f128_type, "b"), + ], + "fmodf128", + false, + ); + return self.context.new_call(self.location, fmodf128, &[a, b]); } _ => (), } @@ -924,7 +943,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // 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. - let aligned_type = if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type { + // 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()) @@ -1010,13 +1034,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let b_offset = a.size(self).align_to(b.align(self).abi); let mut load = |i, scalar: &abi::Scalar, align| { - let llptr = if i == 0 { + let ptr = if i == 0 { place.val.llval } else { self.inbounds_ptradd(place.val.llval, self.const_usize(b_offset.bytes())) }; let llty = place.layout.scalar_pair_element_gcc_type(self, i); - let load = self.load(llty, llptr, align); + let load = self.load(llty, ptr, align); scalar_load_metadata(self, load, scalar); if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load } }; |
