diff options
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 8c457fcd097..b9a7d315891 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -19,6 +19,7 @@ #include "CodeGenFunction.h" #include "clang/AST/RecordLayout.h" #include "clang/CodeGen/CGFunctionInfo.h" +#include "clang/CodeGen/SwiftCallingConv.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" @@ -68,6 +69,46 @@ Address ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, ABIInfo::~ABIInfo() {} +/// Does the given lowering require more than the given number of +/// registers when expanded? +/// +/// This is intended to be the basis of a reasonable basic implementation +/// of should{Pass,Return}IndirectlyForSwift. +/// +/// For most targets, a limit of four total registers is reasonable; this +/// limits the amount of code required in order to move around the value +/// in case it wasn't produced immediately prior to the call by the caller +/// (or wasn't produced in exactly the right registers) or isn't used +/// immediately within the callee. But some targets may need to further +/// limit the register count due to an inability to support that many +/// return registers. +static bool occupiesMoreThan(CodeGenTypes &cgt, + ArrayRef<llvm::Type*> scalarTypes, + unsigned maxAllRegisters) { + unsigned intCount = 0, fpCount = 0; + for (llvm::Type *type : scalarTypes) { + if (type->isPointerTy()) { + intCount++; + } else if (auto intTy = dyn_cast<llvm::IntegerType>(type)) { + auto ptrWidth = cgt.getTarget().getPointerWidth(0); + intCount += (intTy->getBitWidth() + ptrWidth - 1) / ptrWidth; + } else { + assert(type->isVectorTy() || type->isFloatingPointTy()); + fpCount++; + } + } + + return (intCount + fpCount > maxAllRegisters); +} + +bool SwiftABIInfo::isLegalVectorTypeForSwift(CharUnits vectorSize, + llvm::Type *eltTy, + unsigned numElts) const { + // The default implementation of this assumes that the target guarantees + // 128-bit SIMD support but nothing more. + return (vectorSize.getQuantity() > 8 && vectorSize.getQuantity() <= 16); +} + static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI) { const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); @@ -866,7 +907,7 @@ struct CCState { }; /// X86_32ABIInfo - The X86-32 ABI information. -class X86_32ABIInfo : public ABIInfo { +class X86_32ABIInfo : public SwiftABIInfo { enum Class { Integer, Float @@ -935,12 +976,22 @@ public: X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, bool RetSmallStructInRegABI, bool Win32StructABI, unsigned NumRegisterParameters, bool SoftFloatABI) - : ABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI), + : SwiftABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI), IsRetSmallStructInRegABI(RetSmallStructInRegABI), IsWin32StructABI(Win32StructABI), IsSoftFloatABI(SoftFloatABI), IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()), DefaultNumRegisterParameters(NumRegisterParameters) {} + + bool shouldPassIndirectlyForSwift(CharUnits totalSize, + ArrayRef<llvm::Type*> scalars, + bool asReturnValue) const override { + // LLVM's x86-32 lowering currently only assigns up to three + // integer registers and three fp registers. Oddly, it'll use up to + // four vector registers for vectors, but those can overlap with the + // scalar registers. + return occupiesMoreThan(CGT, scalars, /*total*/ 3); + } }; class X86_32TargetCodeGenInfo : public TargetCodeGenInfo { @@ -1758,7 +1809,7 @@ static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) { } /// X86_64ABIInfo - The X86_64 ABI information. -class X86_64ABIInfo : public ABIInfo { +class X86_64ABIInfo : public SwiftABIInfo { enum Class { Integer = 0, SSE, @@ -1880,7 +1931,7 @@ class X86_64ABIInfo : public ABIInfo { public: X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) : - ABIInfo(CGT), AVXLevel(AVXLevel), + SwiftABIInfo(CGT), AVXLevel(AVXLevel), Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) { } @@ -1907,6 +1958,12 @@ public: bool has64BitPointers() const { return Has64BitPointers; } + + bool shouldPassIndirectlyForSwift(CharUnits totalSize, + ArrayRef<llvm::Type*> scalars, + bool asReturnValue) const override { + return occupiesMoreThan(CGT, scalars, /*total*/ 4); + } }; /// WinX86_64ABIInfo - The Windows X86_64 ABI information. @@ -4338,7 +4395,7 @@ PPC64TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, namespace { -class AArch64ABIInfo : public ABIInfo { +class AArch64ABIInfo : public SwiftABIInfo { public: enum ABIKind { AAPCS = 0, @@ -4349,7 +4406,8 @@ private: ABIKind Kind; public: - AArch64ABIInfo(CodeGenTypes &CGT, ABIKind Kind) : ABIInfo(CGT), Kind(Kind) {} + AArch64ABIInfo(CodeGenTypes &CGT, ABIKind Kind) + : SwiftABIInfo(CGT), Kind(Kind) {} private: ABIKind getABIKind() const { return Kind; } @@ -4382,6 +4440,12 @@ private: return isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF) : EmitAAPCSVAArg(VAListAddr, Ty, CGF); } + + bool shouldPassIndirectlyForSwift(CharUnits totalSize, + ArrayRef<llvm::Type*> scalars, + bool asReturnValue) const override { + return occupiesMoreThan(CGT, scalars, /*total*/ 4); + } }; class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { @@ -4856,7 +4920,7 @@ Address AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty, namespace { -class ARMABIInfo : public ABIInfo { +class ARMABIInfo : public SwiftABIInfo { public: enum ABIKind { APCS = 0, @@ -4869,7 +4933,8 @@ private: ABIKind Kind; public: - ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) { + ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) + : SwiftABIInfo(CGT), Kind(_Kind) { setCCs(); } @@ -4915,6 +4980,12 @@ private: llvm::CallingConv::ID getLLVMDefaultCC() const; llvm::CallingConv::ID getABIDefaultCC() const; void setCCs(); + + bool shouldPassIndirectlyForSwift(CharUnits totalSize, + ArrayRef<llvm::Type*> scalars, + bool asReturnValue) const override { + return occupiesMoreThan(CGT, scalars, /*total*/ 4); + } }; class ARMTargetCodeGenInfo : public TargetCodeGenInfo { |