summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-11-16 21:05:53 +0000
committerReid Kleckner <rnk@google.com>2015-11-16 21:05:53 +0000
commit433e5b9b122a0f25b5db40013931d33d1b0220d2 (patch)
tree345462ea61b91dd5f16405b689cd9132843106f5
parentc8123ca00e2cce1a2162dd439ab7c238cf97a1b3 (diff)
downloadllvm-433e5b9b122a0f25b5db40013931d33d1b0220d2.tar.gz
Merge r251567:
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. llvm-svn: 253250
-rw-r--r--clang/lib/Basic/Targets.cpp8
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp25
2 files changed, 25 insertions, 8 deletions
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index e4db004b4948..9e44f7d9be63 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -3968,7 +3968,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);
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 960028a9a86d..fa31dc3d66a6 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1552,12 +1552,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;
@@ -1574,6 +1572,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 {
@@ -3059,7 +3063,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
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) {
@@ -3070,7 +3074,6 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
if (RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
-
}
// vectorcall adds the concept of a homogenous vector aggregate, similar to
@@ -3112,6 +3115,14 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
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();
}