Index: clang/lib/Basic/Targets/AArch64.h =================================================================== --- clang/lib/Basic/Targets/AArch64.h +++ clang/lib/Basic/Targets/AArch64.h @@ -120,6 +120,8 @@ int getEHDataRegisterNumber(unsigned RegNo) const override; bool hasInt128Type() const override; + + bool hasExtIntType() const override { return true; } }; class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo { Index: clang/lib/Basic/Targets/AMDGPU.h =================================================================== --- clang/lib/Basic/Targets/AMDGPU.h +++ clang/lib/Basic/Targets/AMDGPU.h @@ -354,6 +354,8 @@ } void setAuxTarget(const TargetInfo *Aux) override; + + bool hasExtIntType() const override { return true; } }; } // namespace targets Index: clang/lib/Basic/Targets/ARC.h =================================================================== --- clang/lib/Basic/Targets/ARC.h +++ clang/lib/Basic/Targets/ARC.h @@ -65,6 +65,8 @@ TargetInfo::ConstraintInfo &Info) const override { return false; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets Index: clang/lib/Basic/Targets/ARM.h =================================================================== --- clang/lib/Basic/Targets/ARM.h +++ clang/lib/Basic/Targets/ARM.h @@ -182,6 +182,8 @@ int getEHDataRegisterNumber(unsigned RegNo) const override; bool hasSjLjLowering() const override; + + bool hasExtIntType() const override { return true; } }; class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo { Index: clang/lib/Basic/Targets/Hexagon.h =================================================================== --- clang/lib/Basic/Targets/Hexagon.h +++ clang/lib/Basic/Targets/Hexagon.h @@ -138,6 +138,8 @@ // We can write more stricter checks later. return CPU.find('t') != std::string::npos; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/Basic/Targets/Lanai.h =================================================================== --- clang/lib/Basic/Targets/Lanai.h +++ clang/lib/Basic/Targets/Lanai.h @@ -86,6 +86,8 @@ } const char *getClobbers() const override { return ""; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/Basic/Targets/Mips.h =================================================================== --- clang/lib/Basic/Targets/Mips.h +++ clang/lib/Basic/Targets/Mips.h @@ -406,6 +406,7 @@ unsigned getUnwindWordWidth() const override; bool validateTarget(DiagnosticsEngine &Diags) const override; + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/Basic/Targets/NVPTX.h =================================================================== --- clang/lib/Basic/Targets/NVPTX.h +++ clang/lib/Basic/Targets/NVPTX.h @@ -160,6 +160,8 @@ return HostTarget->checkCallingConvention(CC); return CCCR_Warning; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/Basic/Targets/PNaCl.h =================================================================== --- clang/lib/Basic/Targets/PNaCl.h +++ clang/lib/Basic/Targets/PNaCl.h @@ -68,6 +68,8 @@ } const char *getClobbers() const override { return ""; } + + bool hasExtIntType() const override { return true; } }; // We attempt to use PNaCl (le32) frontend and Mips32EL backend. Index: clang/lib/Basic/Targets/PPC.h =================================================================== --- clang/lib/Basic/Targets/PPC.h +++ clang/lib/Basic/Targets/PPC.h @@ -332,6 +332,8 @@ : "u9__ieee128"; } const char *getFloat128Mangling() const override { return "u9__ieee128"; } + + bool hasExtIntType() const override { return true; } }; class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo { Index: clang/lib/Basic/Targets/RISCV.h =================================================================== --- clang/lib/Basic/Targets/RISCV.h +++ clang/lib/Basic/Targets/RISCV.h @@ -76,6 +76,8 @@ bool handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) override; + + bool hasExtIntType() const override { return true; } }; class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { public: Index: clang/lib/Basic/Targets/SPIR.h =================================================================== --- clang/lib/Basic/Targets/SPIR.h +++ clang/lib/Basic/Targets/SPIR.h @@ -100,6 +100,8 @@ // for SPIR since it is a generic target. getSupportedOpenCLOpts().supportAll(); } + + bool hasExtIntType() const override { return true; } }; class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { public: Index: clang/lib/Basic/Targets/Sparc.h =================================================================== --- clang/lib/Basic/Targets/Sparc.h +++ clang/lib/Basic/Targets/Sparc.h @@ -176,6 +176,7 @@ MacroBuilder &Builder) const override; bool hasSjLjLowering() const override { return true; } + bool hasExtIntType() const override { return true; } }; // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel. @@ -227,6 +228,8 @@ return false; return getCPUGeneration(CPU) == CG_V9; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/Basic/Targets/SystemZ.h =================================================================== --- clang/lib/Basic/Targets/SystemZ.h +++ clang/lib/Basic/Targets/SystemZ.h @@ -150,6 +150,8 @@ } const char *getLongDoubleMangling() const override { return "g"; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/Basic/Targets/WebAssembly.h =================================================================== --- clang/lib/Basic/Targets/WebAssembly.h +++ clang/lib/Basic/Targets/WebAssembly.h @@ -130,6 +130,8 @@ return CCCR_Warning; } } + + bool hasExtIntType() const override { return true; } }; class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo : public WebAssemblyTargetInfo { Index: clang/lib/Basic/Targets/XCore.h =================================================================== --- clang/lib/Basic/Targets/XCore.h +++ clang/lib/Basic/Targets/XCore.h @@ -75,6 +75,8 @@ } bool allowsLargerPreferedTypeAlignment() const override { return false; } + + bool hasExtIntType() const override { return true; } }; } // namespace targets } // namespace clang Index: clang/lib/CodeGen/ABIInfo.h =================================================================== --- clang/lib/CodeGen/ABIInfo.h +++ clang/lib/CodeGen/ABIInfo.h @@ -102,6 +102,10 @@ bool isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const; + // Implement the Type::IsPromotableIntegerType for ABI specific needs. The + // only difference is that this considers _ExtInt as well. + bool isPromotableIntegerTypeForABI(QualType Ty) const; + /// A convenience method to return an indirect ABIArgInfo with an /// expected alignment equal to the ABI alignment of the given type. CodeGen::ABIArgInfo Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -97,6 +97,17 @@ return Address::invalid(); } +bool ABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { + if (Ty->isPromotableIntegerType()) + return true; + + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() < getContext().getTypeSize(getContext().IntTy)) + return true; + + return false; +} + ABIInfo::~ABIInfo() {} /// Does the given lowering require more than the given number of @@ -701,8 +712,16 @@ if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + ASTContext &Context = getContext(); + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > + Context.getTypeSize(Context.getTargetInfo().hasInt128Type() + ? Context.Int128Ty + : Context.LongLongTy)) + return getNaturalAlignIndirect(Ty); + + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect()); } ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { @@ -716,8 +735,15 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); + if (const auto *EIT = RetTy->getAs()) + if (EIT->getNumBits() > + getContext().getTypeSize(getContext().getTargetInfo().hasInt128Type() + ? getContext().Int128Ty + : getContext().LongLongTy)) + return getNaturalAlignIndirect(RetTy); + + return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect()); } //===----------------------------------------------------------------------===// @@ -933,10 +959,15 @@ } else if (Ty->isFloatingType()) { // Floating-point types don't go inreg. return ABIArgInfo::getDirect(); + } else if (const auto *EIT = Ty->getAs()) { + // Treat extended integers as integers if <=64, otherwise pass indirectly. + if (EIT->getNumBits() > 64) + return getNaturalAlignIndirect(Ty); + return ABIArgInfo::getDirect(); } - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect()); } ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const { @@ -947,12 +978,19 @@ if (isAggregateTypeForABI(RetTy)) return getNaturalAlignIndirect(RetTy); + // Treat extended integers as integers if <=64, otherwise pass indirectly. + if (const auto *EIT = RetTy->getAs()) { + if (EIT->getNumBits() > 64) + return getNaturalAlignIndirect(RetTy); + return ABIArgInfo::getDirect(); + } + // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); + return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect()); } /// IsX86_MMXType - Return true if this is an MMX type. @@ -1498,8 +1536,12 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); + if (const auto *EIT = RetTy->getAs()) + if (EIT->getNumBits() > 64) + return getIndirectReturnResult(RetTy, State); + + return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect()); } static bool isSSEVectorType(ASTContext &Context, QualType Ty) { @@ -1816,7 +1858,7 @@ bool InReg = shouldPrimitiveUseInReg(Ty, State); - if (Ty->isPromotableIntegerType()) { + if (isPromotableIntegerTypeForABI(Ty)) { if (InReg) return ABIArgInfo::getExtendInReg(Ty); return ABIArgInfo::getExtend(Ty); @@ -2977,9 +3019,11 @@ if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); - if (!Ty->isExtIntType()) - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + if (Ty->isExtIntType()) + return getNaturalAlignIndirect(Ty); + + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect()); } return getNaturalAlignIndirect(Ty); @@ -3017,8 +3061,8 @@ if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect()); } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) @@ -3400,7 +3444,7 @@ RetTy = EnumTy->getDecl()->getIntegerType(); if (RetTy->isIntegralOrEnumerationType() && - RetTy->isPromotableIntegerType()) + isPromotableIntegerTypeForABI(RetTy)) return ABIArgInfo::getExtend(RetTy); } break; @@ -3545,7 +3589,7 @@ Ty = EnumTy->getDecl()->getIntegerType(); if (Ty->isIntegralOrEnumerationType() && - Ty->isPromotableIntegerType()) + isPromotableIntegerTypeForABI(Ty)) return ABIArgInfo::getExtend(Ty); } @@ -4662,7 +4706,7 @@ Ty = EnumTy->getDecl()->getIntegerType(); // Promotable integer types are required to be promoted by the ABI. - if (Ty->isPromotableIntegerType()) + if (isPromotableIntegerTypeForABI(Ty)) return true; // In addition to the usual promotable integer types, we also need to @@ -4676,6 +4720,10 @@ break; } + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() < 64) + return true; + return false; } @@ -4893,6 +4941,10 @@ } } + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > 128) + return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + if (isAggregateTypeForABI(Ty)) { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); @@ -4965,6 +5017,10 @@ } } + if (const auto *EIT = RetTy->getAs()) + if (EIT->getNumBits() > 128) + return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + if (isAggregateTypeForABI(RetTy)) { // ELFv2 homogeneous aggregates are returned as array types. const Type *Base = nullptr; @@ -5301,7 +5357,11 @@ if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); - return (Ty->isPromotableIntegerType() && isDarwinPCS() + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > 128) + return getNaturalAlignIndirect(Ty); + + return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS() ? ABIArgInfo::getExtend(Ty) : ABIArgInfo::getDirect()); } @@ -5378,7 +5438,11 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() && isDarwinPCS() + if (const auto *EIT = RetTy->getAs()) + if (EIT->getNumBits() > 128) + return getNaturalAlignIndirect(RetTy); + + return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS() ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect()); } @@ -6068,8 +6132,12 @@ Ty = EnumTy->getDecl()->getIntegerType(); } - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > 64) + return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect()); } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { @@ -6274,8 +6342,12 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect(); + if (const auto *EIT = RetTy->getAs()) + if (EIT->getNumBits() > 64) + return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + + return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect(); } // Are we following APCS? @@ -6528,6 +6600,8 @@ void computeInfo(CGFunctionInfo &FI) const override; Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const override; + bool isUnsupportedType(QualType T) const; + ABIArgInfo coerceToIntArrayWithLimit(QualType Ty, unsigned MaxSize) const; }; class NVPTXTargetCodeGenInfo : public TargetCodeGenInfo { @@ -6591,18 +6665,22 @@ }; /// Checks if the type is unsupported directly by the current target. -static bool isUnsupportedType(ASTContext &Context, QualType T) { +bool NVPTXABIInfo::isUnsupportedType(QualType T) const { + ASTContext &Context = getContext(); if (!Context.getTargetInfo().hasFloat16Type() && T->isFloat16Type()) return true; if (!Context.getTargetInfo().hasFloat128Type() && (T->isFloat128Type() || (T->isRealFloatingType() && Context.getTypeSize(T) == 128))) return true; + if (const auto *EIT = T->getAs()) + return EIT->getNumBits() > + (Context.getTargetInfo().hasInt128Type() ? 128 : 64); if (!Context.getTargetInfo().hasInt128Type() && T->isIntegerType() && Context.getTypeSize(T) > 64) return true; if (const auto *AT = T->getAsArrayTypeUnsafe()) - return isUnsupportedType(Context, AT->getElementType()); + return isUnsupportedType(AT->getElementType()); const auto *RT = T->getAs(); if (!RT) return false; @@ -6611,24 +6689,23 @@ // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) for (const CXXBaseSpecifier &I : CXXRD->bases()) - if (isUnsupportedType(Context, I.getType())) + if (isUnsupportedType(I.getType())) return true; for (const FieldDecl *I : RD->fields()) - if (isUnsupportedType(Context, I->getType())) + if (isUnsupportedType(I->getType())) return true; return false; } /// Coerce the given type into an array with maximum allowed size of elements. -static ABIArgInfo coerceToIntArrayWithLimit(QualType Ty, ASTContext &Context, - llvm::LLVMContext &LLVMContext, - unsigned MaxSize) { +ABIArgInfo NVPTXABIInfo::coerceToIntArrayWithLimit(QualType Ty, + unsigned MaxSize) const { // Alignment and Size are measured in bits. - const uint64_t Size = Context.getTypeSize(Ty); - const uint64_t Alignment = Context.getTypeAlign(Ty); + const uint64_t Size = getContext().getTypeSize(Ty); + const uint64_t Alignment = getContext().getTypeAlign(Ty); const unsigned Div = std::min(MaxSize, Alignment); - llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Div); + llvm::Type *IntType = llvm::Type::getIntNTy(getVMContext(), Div); const uint64_t NumElements = (Size + Div - 1) / Div; return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements)); } @@ -6638,9 +6715,8 @@ return ABIArgInfo::getIgnore(); if (getContext().getLangOpts().OpenMP && - getContext().getLangOpts().OpenMPIsDevice && - isUnsupportedType(getContext(), RetTy)) - return coerceToIntArrayWithLimit(RetTy, getContext(), getVMContext(), 64); + getContext().getLangOpts().OpenMPIsDevice && isUnsupportedType(RetTy)) + return coerceToIntArrayWithLimit(RetTy, 64); // note: this is different from default ABI if (!RetTy->isScalarType()) @@ -6650,8 +6726,8 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); + return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect()); } ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const { @@ -6674,8 +6750,15 @@ return getNaturalAlignIndirect(Ty, /* byval */ true); } - return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect()); + if (const auto *EIT = Ty->getAs()) { + if ((EIT->getNumBits() > 128) || + (!getContext().getTargetInfo().hasInt128Type() && + EIT->getNumBits() > 64)) + return getNaturalAlignIndirect(Ty, /* byval */ true); + } + + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect()); } void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const { @@ -6794,7 +6877,7 @@ SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF) : SwiftABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {} - bool isPromotableIntegerType(QualType Ty) const; + bool isPromotableIntegerTypeForABI(QualType Ty) const; bool isCompoundType(QualType Ty) const; bool isVectorArgumentType(QualType Ty) const; bool isFPArgumentType(QualType Ty) const; @@ -6831,15 +6914,19 @@ } -bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const { +bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); // Promotable integer types are required to be promoted by the ABI. - if (Ty->isPromotableIntegerType()) + if (ABIInfo::isPromotableIntegerTypeForABI(Ty)) return true; + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() < 64) + return true; + // 32-bit values must also be promoted. if (const BuiltinType *BT = Ty->getAs()) switch (BT->getKind()) { @@ -7086,8 +7173,8 @@ return ABIArgInfo::getDirect(); if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64) return getNaturalAlignIndirect(RetTy); - return (isPromotableIntegerType(RetTy) ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect()); + return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect()); } ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { @@ -7096,7 +7183,7 @@ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); // Integers and enums are extended to full register width. - if (isPromotableIntegerType(Ty)) + if (isPromotableIntegerTypeForABI(Ty)) return ABIArgInfo::getExtend(Ty); // Handle vector types and vector-like structure types. Note that @@ -7391,6 +7478,13 @@ if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); + // Make sure we pass indirectly things that are too large. + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > 128 || + (EIT->getNumBits() > 64 && + !getContext().getTargetInfo().hasInt128Type())) + return getNaturalAlignIndirect(Ty); + // All integral types are promoted to the GPR width. if (Ty->isIntegralOrEnumerationType()) return extendType(Ty); @@ -7475,7 +7569,14 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - if (RetTy->isPromotableIntegerType()) + // Make sure we pass indirectly things that are too large. + if (const auto *EIT = RetTy->getAs()) + if (EIT->getNumBits() > 128 || + (EIT->getNumBits() > 64 && + !getContext().getTargetInfo().hasInt128Type())) + return getNaturalAlignIndirect(RetTy); + + if (isPromotableIntegerTypeForABI(RetTy)) return ABIArgInfo::getExtend(RetTy); if ((RetTy->isUnsignedIntegerOrEnumerationType() || @@ -7769,8 +7870,11 @@ if (Size <= 64) HexagonAdjustRegsLeft(Size, RegsLeft); - return Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty) - : ABIArgInfo::getDirect(); + if (Size > 64 && Ty->isExtIntType()) + return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + + return isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) + : ABIArgInfo::getDirect(); } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) @@ -7822,8 +7926,11 @@ if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); - return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) - : ABIArgInfo::getDirect(); + if (Size > 64 && RetTy->isExtIntType()) + return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + + return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) + : ABIArgInfo::getDirect(); } if (isEmptyRecord(getContext(), RetTy, true)) @@ -8186,7 +8293,13 @@ Ty = EnumTy->getDecl()->getIntegerType(); bool InReg = shouldUseInReg(Ty, State); - if (Ty->isPromotableIntegerType()) { + + // Don't pass >64 bit integers in registers. + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > 64) + return getIndirectResult(Ty, /*ByVal=*/true, State); + + if (isPromotableIntegerTypeForABI(Ty)) { if (InReg) return ABIArgInfo::getDirectInReg(); return ABIArgInfo::getExtend(Ty); @@ -8896,6 +9009,10 @@ if (Size < 64 && Ty->isIntegerType()) return ABIArgInfo::getExtend(Ty); + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() < 64) + return ABIArgInfo::getExtend(Ty); + // Other non-aggregates go in registers. if (!isAggregateTypeForABI(Ty)) return ABIArgInfo::getDirect(); @@ -9145,11 +9262,15 @@ ABIArgInfo::getDirect(Result, 0, nullptr, false); } - return Ty->isPromotableIntegerType() ? - (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) : - ABIArgInfo::getExtend(Ty)) : - (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() : - ABIArgInfo::getDirect()); + if (const auto *EIT = Ty->getAs()) + if (EIT->getNumBits() > 64) + return getIndirectByValue(Ty); + + return isPromotableIntegerTypeForABI(Ty) + ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) + : ABIArgInfo::getExtend(Ty)) + : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() + : ABIArgInfo::getDirect()); } ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const { @@ -10180,6 +10301,15 @@ return extendType(Ty); } + if (const auto *EIT = Ty->getAs()) { + if (EIT->getNumBits() < XLen && !MustUseStack) + return extendType(Ty); + if (EIT->getNumBits() > 128 || + (!getContext().getTargetInfo().hasInt128Type() && + EIT->getNumBits() > 64)) + return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + } + return ABIArgInfo::getDirect(); } Index: clang/test/CodeGen/ext-int-cc.c =================================================================== --- clang/test/CodeGen/ext-int-cc.c +++ clang/test/CodeGen/ext-int-cc.c @@ -2,6 +2,32 @@ // RUN: %clang_cc1 -triple x86_64-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN64 // RUN: %clang_cc1 -triple i386-gnu-linux -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=LIN32 // RUN: %clang_cc1 -triple i386-windows-pc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN32 +// RUN: %clang_cc1 -triple le32-nacl -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=NACL +// RUN: %clang_cc1 -triple nvptx64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=NVPTX64 +// RUN: %clang_cc1 -triple nvptx -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=NVPTX +// RUN: %clang_cc1 -triple sparcv9 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SPARCV9 +// RUN: %clang_cc1 -triple sparc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SPARC +// RUN: %clang_cc1 -triple mips64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=MIPS64 +// RUN: %clang_cc1 -triple mips -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=MIPS +// RUN: %clang_cc1 -triple spir64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SPIR64 +// RUN: %clang_cc1 -triple spir -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SPIR +// RUN: %clang_cc1 -triple hexagon -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=HEX +// RUN: %clang_cc1 -triple lanai -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=LANAI +// RUN: %clang_cc1 -triple r600 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=R600 +// RUN: %clang_cc1 -triple arc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=ARC +// RUN: %clang_cc1 -triple xcore -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=XCORE +// RUN: %clang_cc1 -triple riscv64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=RISCV64 +// RUN: %clang_cc1 -triple riscv32 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=RISCV32 +// RUN: %clang_cc1 -triple wasm64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=WASM +// RUN: %clang_cc1 -triple wasm32 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=WASM +// RUN: %clang_cc1 -triple systemz -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SYSTEMZ +// RUN: %clang_cc1 -triple ppc64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=PPC64 +// RUN: %clang_cc1 -triple ppc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=PPC32 +// RUN: %clang_cc1 -triple aarch64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64 +// RUN: %clang_cc1 -triple aarch64 -target-abi darwinpcs -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64DARWIN +// RUN: %clang_cc1 -triple arm64_32-apple-ios -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64 +// RUN: %clang_cc1 -triple arm64_32-apple-ios -target-abi darwinpcs -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64DARWIN +// RUN: %clang_cc1 -triple arm -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=ARM // Make sure 128 and 64 bit versions are passed like integers, and that >128 // is passed indirectly. @@ -10,33 +36,239 @@ // WIN64: define dso_local void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}}) // LIN32: define void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}}) // WIN32: define dso_local void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}}) +// NACL: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// NVPTX64: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// NVPTX: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// SPARCV9: define void @ParamPassing(i129* %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// SPARC: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// MIPS64: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 signext %{{.+}}, i64 signext %{{.+}}) +// MIPS: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 signext %{{.+}}) +// SPIR64: define spir_func void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// SPIR: define spir_func void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// HEX: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// LANAI: define void @ParamPassing(i129* byval(i129) align 4 %{{.+}}, i128* byval(i128) align 4 %{{.+}}, i64 %{{.+}}) +// R600: define void @ParamPassing(i129 addrspace(5)* byval(i129) align 8 %{{.+}}, i128 addrspace(5)* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// ARC: define void @ParamPassing(i129* byval(i129) align 4 %{{.+}}, i128* byval(i128) align 4 %{{.+}}, i64 inreg %{{.+}}) +// XCORE: define void @ParamPassing(i129* byval(i129) align 4 %{{.+}}, i128* byval(i128) align 4 %{{.+}}, i64 %{{.+}}) +// RISCV64: define void @ParamPassing(i129* %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// RISCV32: define void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}}) +// WASM: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// SYSTEMZ: define void @ParamPassing(i129* %{{.+}}, i128* %{{.+}}, i64 %{{.+}}) +// PPC64: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// PPC32: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) +// AARCH64: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// AARCH64DARWIN: define void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128 %{{.+}}, i64 %{{.+}}) +// ARM: define arm_aapcscc void @ParamPassing(i129* byval(i129) align 8 %{{.+}}, i128* byval(i128) align 8 %{{.+}}, i64 %{{.+}}) + void ParamPassing2(_ExtInt(129) a, _ExtInt(127) b, _ExtInt(63) c) {} // LIN64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i64 %{{.+}}, i64 %{{.+}}, i64 %{{.+}}) // WIN64: define dso_local void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}}) // LIN32: define void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}}) // WIN32: define dso_local void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}}) +// NACL: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// NVPTX64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 %{{.+}}) +// NVPTX: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// SPARCV9: define void @ParamPassing2(i129* %{{.+}}, i127 %{{.+}}, i63 signext %{{.+}}) +// SPARC: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// MIPS64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 signext %{{.+}}, i63 signext %{{.+}}) +// MIPS: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 signext %{{.+}}) +// SPIR64: define spir_func void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 %{{.+}}) +// SPIR: define spir_func void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// HEX: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// LANAI: define void @ParamPassing2(i129* byval(i129) align 4 %{{.+}}, i127* byval(i127) align 4 %{{.+}}, i63 %{{.+}}) +// R600: define void @ParamPassing2(i129 addrspace(5)* byval(i129) align 8 %{{.+}}, i127 addrspace(5)* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// ARC: define void @ParamPassing2(i129* byval(i129) align 4 %{{.+}}, i127* byval(i127) align 4 %{{.+}}, i63 inreg %{{.+}}) +// XCORE: define void @ParamPassing2(i129* byval(i129) align 4 %{{.+}}, i127* byval(i127) align 4 %{{.+}}, i63 %{{.+}}) +// RISCV64: define void @ParamPassing2(i129* %{{.+}}, i127 %{{.+}}, i63 signext %{{.+}}) +// RISCV32: define void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 %{{.+}}) +// WASM: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 %{{.+}}) +// SYSTEMZ: define void @ParamPassing2(i129* %{{.+}}, i127* %{{.+}}, i63 signext %{{.+}}) +// PPC64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 signext %{{.+}}) +// PPC32: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) +// AARCH64: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 %{{.+}}) +// AARCH64DARWIN: define void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127 %{{.+}}, i63 %{{.+}}) +// ARM: define arm_aapcscc void @ParamPassing2(i129* byval(i129) align 8 %{{.+}}, i127* byval(i127) align 8 %{{.+}}, i63 %{{.+}}) + +// Make sure we follow the signext rules for promotable integer types. +void ParamPassing3(_ExtInt(15) a, _ExtInt(31) b) {} +// LIN64: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// WIN64: define dso_local void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}}) +// LIN32: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// WIN32: define dso_local void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// NACL: define void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}}) +// NVPTX64: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// NVPTX: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// SPARCV9: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// SPARC: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// MIPS64: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// MIPS: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// SPIR64: define spir_func void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// SPIR: define spir_func void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// HEX: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// LANAI: define void @ParamPassing3(i15 inreg %{{.+}}, i31 inreg %{{.+}}) +// R600: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// ARC: define void @ParamPassing3(i15 inreg signext %{{.+}}, i31 inreg signext %{{.+}}) +// XCORE: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// RISCV64: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// RISCV32: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// WASM: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// SYSTEMZ: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// PPC64: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// PPC32: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// AARCH64: define void @ParamPassing3(i15 %{{.+}}, i31 %{{.+}}) +// AARCH64DARWIN: define void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) +// ARM: define arm_aapcscc void @ParamPassing3(i15 signext %{{.+}}, i31 signext %{{.+}}) + _ExtInt(63) ReturnPassing(){} // LIN64: define i64 @ReturnPassing( // WIN64: define dso_local i63 @ReturnPassing( // LIN32: define i63 @ReturnPassing( // WIN32: define dso_local i63 @ReturnPassing( +// NACL: define i63 @ReturnPassing( +// NVPTX64: define i63 @ReturnPassing( +// NVPTX: define i63 @ReturnPassing( +// SPARCV9: define signext i63 @ReturnPassing( +// SPARC: define i63 @ReturnPassing( +// MIPS64: define i63 @ReturnPassing( +// MIPS: define i63 @ReturnPassing( +// SPIR64: define spir_func i63 @ReturnPassing( +// SPIR: define spir_func i63 @ReturnPassing( +// HEX: define i63 @ReturnPassing( +// LANAI: define i63 @ReturnPassing( +// R600: define i63 @ReturnPassing( +// ARC: define i63 @ReturnPassing( +// XCORE: define i63 @ReturnPassing( +// RISCV64: define signext i63 @ReturnPassing( +// RISCV32: define i63 @ReturnPassing( +// WASM: define i63 @ReturnPassing( +// SYSTEMZ: define signext i63 @ReturnPassing( +// PPC64: define signext i63 @ReturnPassing( +// PPC32: define i63 @ReturnPassing( +// AARCH64: define i63 @ReturnPassing( +// AARCH64DARWIN: define i63 @ReturnPassing( +// ARM: define arm_aapcscc i63 @ReturnPassing( + _ExtInt(64) ReturnPassing2(){} // LIN64: define i64 @ReturnPassing2( // WIN64: define dso_local i64 @ReturnPassing2( // LIN32: define i64 @ReturnPassing2( // WIN32: define dso_local i64 @ReturnPassing2( +// NACL: define i64 @ReturnPassing2( +// NVPTX64: define i64 @ReturnPassing2( +// NVPTX: define i64 @ReturnPassing2( +// SPARCV9: define i64 @ReturnPassing2( +// SPARC: define i64 @ReturnPassing2( +// MIPS64: define i64 @ReturnPassing2( +// MIPS: define i64 @ReturnPassing2( +// SPIR64: define spir_func i64 @ReturnPassing2( +// SPIR: define spir_func i64 @ReturnPassing2( +// HEX: define i64 @ReturnPassing2( +// LANAI: define i64 @ReturnPassing2( +// R600: define i64 @ReturnPassing2( +// ARC: define i64 @ReturnPassing2( +// XCORE: define i64 @ReturnPassing2( +// RISCV64: define i64 @ReturnPassing2( +// RISCV32: define i64 @ReturnPassing2( +// WASM: define i64 @ReturnPassing2( +// SYSTEMZ: define i64 @ReturnPassing2( +// PPC64: define i64 @ReturnPassing2( +// PPC32: define i64 @ReturnPassing2( +// AARCH64: define i64 @ReturnPassing2( +// AARCH64DARWIN: define i64 @ReturnPassing2( +// ARM: define arm_aapcscc i64 @ReturnPassing2( + _ExtInt(127) ReturnPassing3(){} // LIN64: define { i64, i64 } @ReturnPassing3( // WIN64: define dso_local void @ReturnPassing3(i127* noalias sret -// LIN32: define i127 @ReturnPassing3( -// WIN32: define dso_local i127 @ReturnPassing3( +// LIN32: define void @ReturnPassing3(i127* noalias sret +// WIN32: define dso_local void @ReturnPassing3(i127* noalias sret +// NACL: define void @ReturnPassing3(i127* noalias sret +// NVPTX/64 makes the intentional choice to put all return values direct, even +// large structures, so we do the same here. +// NVPTX64: define i127 @ReturnPassing3( +// NVPTX: define i127 @ReturnPassing3( +// SPARCV9: define i127 @ReturnPassing3( +// SPARC: define void @ReturnPassing3(i127* noalias sret +// MIPS64: define i127 @ReturnPassing3( +// MIPS: define void @ReturnPassing3(i127* noalias sret +// SPIR64: define spir_func i127 @ReturnPassing3( +// SPIR: define spir_func void @ReturnPassing3(i127* noalias sret +// HEX: define void @ReturnPassing3(i127* noalias sret +// LANAI: define void @ReturnPassing3(i127* noalias sret +// R600: define void @ReturnPassing3(i127 addrspace(5)* noalias sret +// ARC: define void @ReturnPassing3(i127* noalias sret +// XCORE: define void @ReturnPassing3(i127* noalias sret +// RISCV64: define i127 @ReturnPassing3( +// RISCV32: define void @ReturnPassing3(i127* noalias sret +// WASM: define i127 @ReturnPassing3( +// SYSTEMZ: define void @ReturnPassing3(i127* noalias sret +// PPC64: define i127 @ReturnPassing3( +// PPC32: define void @ReturnPassing3(i127* noalias sret +// AARCH64: define i127 @ReturnPassing3( +// AARCH64DARWIN: define i127 @ReturnPassing3( +// ARM: define arm_aapcscc void @ReturnPassing3(i127* noalias sret + _ExtInt(128) ReturnPassing4(){} // LIN64: define { i64, i64 } @ReturnPassing4( // WIN64: define dso_local void @ReturnPassing4(i128* noalias sret -// LIN32: define i128 @ReturnPassing4( -// WIN32: define dso_local i128 @ReturnPassing4( +// LIN32: define void @ReturnPassing4(i128* noalias sret +// WIN32: define dso_local void @ReturnPassing4(i128* noalias sret +// NACL: define void @ReturnPassing4(i128* noalias sret +// NVPTX64: define i128 @ReturnPassing4( +// NVPTX: define i128 @ReturnPassing4( +// SPARCV9: define i128 @ReturnPassing4( +// SPARC: define void @ReturnPassing4(i128* noalias sret +// MIPS64: define i128 @ReturnPassing4( +// MIPS: define void @ReturnPassing4(i128* noalias sret +// SPIR64: define spir_func i128 @ReturnPassing4( +// SPIR: define spir_func void @ReturnPassing4(i128* noalias sret +// HEX: define void @ReturnPassing4(i128* noalias sret +// LANAI: define void @ReturnPassing4(i128* noalias sret +// R600: define void @ReturnPassing4(i128 addrspace(5)* noalias sret +// ARC: define void @ReturnPassing4(i128* noalias sret +// XCORE: define void @ReturnPassing4(i128* noalias sret +// RISCV64: define i128 @ReturnPassing4( +// RISCV32: define void @ReturnPassing4(i128* noalias sret +// WASM: define i128 @ReturnPassing4( +// SYSTEMZ: define void @ReturnPassing4(i128* noalias sret +// PPC64: define i128 @ReturnPassing4( +// PPC32: define void @ReturnPassing4(i128* noalias sret +// AARCH64: define i128 @ReturnPassing4( +// AARCH64DARWIN: define i128 @ReturnPassing4( +// ARM: define arm_aapcscc void @ReturnPassing4(i128* noalias sret + _ExtInt(129) ReturnPassing5(){} // LIN64: define void @ReturnPassing5(i129* noalias sret // WIN64: define dso_local void @ReturnPassing5(i129* noalias sret -// LIN32: define i129 @ReturnPassing5( -// WIN32: define dso_local i129 @ReturnPassing5( +// LIN32: define void @ReturnPassing5(i129* noalias sret +// WIN32: define dso_local void @ReturnPassing5(i129* noalias sret +// NACL: define void @ReturnPassing5(i129* noalias sret +// NVPTX64: define i129 @ReturnPassing5( +// NVPTX: define i129 @ReturnPassing5( +// SPARCV9: define i129 @ReturnPassing5( +// SPARC: define void @ReturnPassing5(i129* noalias sret +// MIPS64: define void @ReturnPassing5(i129* noalias sret +// MIPS: define void @ReturnPassing5(i129* noalias sret +// SPIR64: define spir_func void @ReturnPassing5(i129* noalias sret +// SPIR: define spir_func void @ReturnPassing5(i129* noalias sret +// HEX: define void @ReturnPassing5(i129* noalias sret +// LANAI: define void @ReturnPassing5(i129* noalias sret +// R600: define void @ReturnPassing5(i129 addrspace(5)* noalias sret +// ARC: define void @ReturnPassing5(i129* inreg noalias sret +// XCORE: define void @ReturnPassing5(i129* noalias sret +// RISCV64: define void @ReturnPassing5(i129* noalias sret +// RISCV32: define void @ReturnPassing5(i129* noalias sret +// WASM: define void @ReturnPassing5(i129* noalias sret +// SYSTEMZ: define void @ReturnPassing5(i129* noalias sret +// PPC64: define void @ReturnPassing5(i129* noalias sret +// PPC32: define void @ReturnPassing5(i129* noalias sret +// AARCH64: define void @ReturnPassing5(i129* noalias sret +// AARCH64DARWIN: define void @ReturnPassing5(i129* noalias sret +// ARM: define arm_aapcscc void @ReturnPassing5(i129* noalias sret + +// SparcV9 is odd in that it has a return-size limit of 256, not 128 or 64 +// like other platforms, so test to make sure this behavior will still work. +_ExtInt(256) ReturnPassing6() {} +// SPARCV9: define i256 @ReturnPassing6( +_ExtInt(257) ReturnPassing7() {} +// SPARCV9: define void @ReturnPassing7(i257* noalias sret Index: clang/test/CodeGen/ext-int-sanitizer.cpp =================================================================== --- clang/test/CodeGen/ext-int-sanitizer.cpp +++ clang/test/CodeGen/ext-int-sanitizer.cpp @@ -145,8 +145,7 @@ // Also triggers signed integer overflow. E / E; - // CHECK: %[[E1LOAD:.+]] = load i11 - // CHECK: store i11 %[[E1LOAD]], i11* %[[EADDR:.+]] + // CHECK: %[[EADDR:.+]] = alloca i11 // CHECK: %[[E:.+]] = load i11, i11* %[[EADDR]] // CHECK: %[[E2:.+]] = load i11, i11* %[[EADDR]] // CHECK: %[[NEZERO:.+]] = icmp ne i11 %[[E2]], 0 @@ -163,8 +162,7 @@ // CHECK: define void @_Z6ShiftsU7_ExtIntILi9EEi void Shifts(_ExtInt(9) E) { E >> E; - // CHECK: %[[E1LOAD:.+]] = load i9, i9* - // CHECK: store i9 %[[E1LOAD]], i9* %[[EADDR:.+]] + // CHECK: %[[EADDR:.+]] = alloca i9 // CHECK: %[[LHSE:.+]] = load i9, i9* %[[EADDR]] // CHECK: %[[RHSE:.+]] = load i9, i9* %[[EADDR]] // CHECK: %[[CMP:.+]] = icmp ule i9 %[[RHSE]], 8 @@ -227,8 +225,7 @@ unsigned _ExtInt(23) SmallE, unsigned _ExtInt(35) BigE) { u = SmallE + SmallE; - // CHECK: %[[LOADBIGGESTE2:.+]] = load i23 - // CHECK: store i23 %[[LOADBIGGESTE2]], i23* %[[BIGGESTEADDR:.+]] + // CHECK: %[[BIGGESTEADDR:.+]] = alloca i23 // CHECK: %[[LOADE1:.+]] = load i23, i23* %[[BIGGESTEADDR]] // CHECK: %[[LOADE2:.+]] = load i23, i23* %[[BIGGESTEADDR]] // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADE1]], i23 %[[LOADE2]]) Index: clang/test/CodeGenCXX/ext-int.cpp =================================================================== --- clang/test/CodeGenCXX/ext-int.cpp +++ clang/test/CodeGenCXX/ext-int.cpp @@ -98,7 +98,7 @@ }; void UnderlyingTypeUsage(AsEnumUnderlyingType Param) { - // LIN: define void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i16 % + // LIN: define void @_Z19UnderlyingTypeUsage20AsEnumUnderlyingType(i9 signext % // WIN: define dso_local void @"?UnderlyingTypeUsage@@YAXW4AsEnumUnderlyingType@@@Z"(i9 % AsEnumUnderlyingType Var; // CHECK: alloca i9, align 2 Index: clang/test/Sema/ext-int-not-supported.c =================================================================== --- clang/test/Sema/ext-int-not-supported.c +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify %s - -void foo() { - _ExtInt(33) a; // expected-error{{_ExtInt is not supported on this target}} -}