Thanks!
2015-10-29 0:29 GMT+02:00 Reid Kleckner via cfe-commits < cfe-commits@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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits