r251567 - Fix the calling convention of Mingw64 long double values
Yaron Keren via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 28 22:58:10 PDT 2015
Thanks!
2015-10-29 0:29 GMT+02:00 Reid Kleckner via cfe-commits <
cfe-commits at lists.llvm.org>:
> Author: rnk
> Date: Wed Oct 28 17:29:52 2015
> New Revision: 251567
>
> URL: http://llvm.org/viewvc/llvm-project?rev=251567&view=rev
> Log:
> Fix the calling convention of Mingw64 long double values
>
> GCC uses the x87DoubleExtended model for long doubles, and passes them
> indirectly by address through function calls.
>
> Also replace the existing mingw-long-double assembly emitting test with
> an IR-level test.
>
> Modified:
> cfe/trunk/lib/Basic/Targets.cpp
> cfe/trunk/lib/CodeGen/TargetInfo.cpp
> cfe/trunk/test/CodeGen/mingw-long-double.c
>
> Modified: cfe/trunk/lib/Basic/Targets.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=251567&r1=251566&r2=251567&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Basic/Targets.cpp (original)
> +++ cfe/trunk/lib/Basic/Targets.cpp Wed Oct 28 17:29:52 2015
> @@ -4009,7 +4009,13 @@ public:
> class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
> public:
> MinGWX86_64TargetInfo(const llvm::Triple &Triple)
> - : WindowsX86_64TargetInfo(Triple) {}
> + : WindowsX86_64TargetInfo(Triple) {
> + // Mingw64 rounds long double size and alignment up to 16 bytes, but
> sticks
> + // with x86 FP ops. Weird.
> + LongDoubleWidth = LongDoubleAlign = 128;
> + LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
> + }
> +
> void getTargetDefines(const LangOptions &Opts,
> MacroBuilder &Builder) const override {
> WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
>
> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=251567&r1=251566&r2=251567&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Wed Oct 28 17:29:52 2015
> @@ -1772,12 +1772,10 @@ public:
>
> /// WinX86_64ABIInfo - The Windows X86_64 ABI information.
> class WinX86_64ABIInfo : public ABIInfo {
> -
> - ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs,
> - bool IsReturnType) const;
> -
> public:
> - WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
> + WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT)
> + : ABIInfo(CGT),
> + IsMingw64(getTarget().getTriple().isWindowsGNUEnvironment()) {}
>
> void computeInfo(CGFunctionInfo &FI) const override;
>
> @@ -1794,6 +1792,12 @@ public:
> // FIXME: Assumes vectorcall is in use.
> return isX86VectorCallAggregateSmallEnough(NumMembers);
> }
> +
> +private:
> + ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs,
> + bool IsReturnType) const;
> +
> + bool IsMingw64;
> };
>
> class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
> @@ -3317,7 +3321,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(Qu
>
> TypeInfo Info = getContext().getTypeInfo(Ty);
> uint64_t Width = Info.Width;
> - unsigned Align =
> getContext().toCharUnitsFromBits(Info.Align).getQuantity();
> + CharUnits Align = getContext().toCharUnitsFromBits(Info.Align);
>
> const RecordType *RT = Ty->getAs<RecordType>();
> if (RT) {
> @@ -3330,9 +3334,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(Qu
> return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
>
> // FIXME: mingw-w64-gcc emits 128-bit struct as i128
> - if (Width == 128 && getTarget().getTriple().isWindowsGNUEnvironment())
> - return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
> - Width));
> + if (Width == 128 && IsMingw64)
> + return ABIArgInfo::getDirect(
> + llvm::IntegerType::get(getVMContext(), Width));
> }
>
> // vectorcall adds the concept of a homogenous vector aggregate,
> similar to
> @@ -3346,8 +3350,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(Qu
> return ABIArgInfo::getDirect();
> return ABIArgInfo::getExpand();
> }
> - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(Align),
> - /*ByVal=*/false);
> + return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
> }
>
>
> @@ -3375,6 +3378,14 @@ ABIArgInfo WinX86_64ABIInfo::classify(Qu
> if (BT && BT->getKind() == BuiltinType::Bool)
> return ABIArgInfo::getExtend();
>
> + // Mingw64 GCC uses the old 80 bit extended precision floating point
> unit. It
> + // passes them indirectly through memory.
> + if (IsMingw64 && BT && BT->getKind() == BuiltinType::LongDouble) {
> + const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
> + if (LDF == &llvm::APFloat::x87DoubleExtended)
> + return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
> + }
> +
> return ABIArgInfo::getDirect();
> }
>
>
> Modified: cfe/trunk/test/CodeGen/mingw-long-double.c
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mingw-long-double.c?rev=251567&r1=251566&r2=251567&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGen/mingw-long-double.c (original)
> +++ cfe/trunk/test/CodeGen/mingw-long-double.c Wed Oct 28 17:29:52 2015
> @@ -1,12 +1,41 @@
> -// REQUIRES: x86-registered-target
> -// RUN: %clang_cc1 -triple i686-pc-windows-gnu -S %s -o - | FileCheck %s
> -check-prefix=CHECK_I686
> -// CHECK_I686: _lda,12
> -// CHECK_I686: _lds,16
> -// RUN: %clang_cc1 -triple x86_64-pc-windows-gnu -S %s -o - | FileCheck
> %s -check-prefix=CHECK_X86_64
> -// CHECK_X86_64: lda,16
> -// CHECK_X86_64: lds,32
> -long double lda;
> +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -o - %s \
> +// RUN: | FileCheck %s --check-prefix=GNU32
> +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -o - %s \
> +// RUN: | FileCheck %s --check-prefix=GNU64
> +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s \
> +// RUN: | FileCheck %s --check-prefix=MSC64
> +
> struct {
> char c;
> long double ldb;
> -} lds;
> +} agggregate_LD = {};
> +// GNU32: %struct.anon = type { i8, x86_fp80 }
> +// GNU32: @agggregate_LD = global %struct.anon zeroinitializer, align 4
> +// GNU64: %struct.anon = type { i8, x86_fp80 }
> +// GNU64: @agggregate_LD = global %struct.anon zeroinitializer, align 16
> +// MSC64: %struct.anon = type { i8, double }
> +// MSC64: @agggregate_LD = global %struct.anon zeroinitializer, align 8
> +
> +long double dataLD = 1.0L;
> +// GNU32: @dataLD = global x86_fp80 0xK3FFF8000000000000000, align 4
> +// GNU64: @dataLD = global x86_fp80 0xK3FFF8000000000000000, align 16
> +// MSC64: @dataLD = global double 1.000000e+00, align 8
> +
> +long double _Complex dataLDC = {1.0L, 1.0L};
> +// GNU32: @dataLDC = global { x86_fp80, x86_fp80 } { x86_fp80
> 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 4
> +// GNU64: @dataLDC = global { x86_fp80, x86_fp80 } { x86_fp80
> 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 16
> +// MSC64: @dataLDC = global { double, double } { double 1.000000e+00,
> double 1.000000e+00 }, align 8
> +
> +long double TestLD(long double x) {
> + return x * x;
> +}
> +// GNU32: define x86_fp80 @TestLD(x86_fp80 %x)
> +// GNU64: define void @TestLD(x86_fp80* noalias sret %agg.result,
> x86_fp80*)
> +// MSC64: define double @TestLD(double %x)
> +
> +long double _Complex TestLDC(long double _Complex x) {
> + return x * x;
> +}
> +// GNU32: define void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret
> %agg.result, { x86_fp80, x86_fp80 }* byval align 4 %x)
> +// GNU64: define void @TestLDC({ x86_fp80, x86_fp80 }* noalias sret
> %agg.result, { x86_fp80, x86_fp80 }* %x)
> +// MSC64: define void @TestLDC({ double, double }* noalias sret
> %agg.result, { double, double }* %x)
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20151029/f5e9df4b/attachment-0001.html>
More information about the cfe-commits
mailing list