rogfer01 created this revision. rogfer01 added a reviewer: rjmccall. This is WIP and it is motivated by the suggestions in http://lists.llvm.org/pipermail/cfe-dev/2018-June/058263.html
First attempt, piggybacking the extend information in a structure where the bit-width of the integer represents the exact extension intended. There is a bit of overlapping with the original Extend but I'm not convinced we win anything from rewriting it into the new representation. I plan to test this using unit tests but I can link a diff with the current usage in case it helps. https://reviews.llvm.org/D48589 Files: include/clang/CodeGen/CGFunctionInfo.h lib/CodeGen/CGCall.cpp
Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1951,7 +1951,6 @@ case ABIArgInfo::CoerceAndExpand: break; - case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } @@ -1987,6 +1986,8 @@ llvm::AttributeSet::get(getLLVMContext(), Attrs); } + SmallVector<llvm::AttrBuilder, 4> CoerceAndExpandAttrs(IRFunctionArgs.totalIRArgs()); + bool CoerceAndExpandHasAttributes = false; unsigned ArgNo = 0; for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(), E = FI.arg_end(); @@ -2055,9 +2056,39 @@ } case ABIArgInfo::Ignore: case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: break; + case ABIArgInfo::CoerceAndExpand: + if (AI.getExtendSeq()) { + // Handle extends in expanded items + unsigned FirstIRArg, NumIRArgs; + std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); + llvm::StructType *CoercionType = AI.getCoerceAndExpandType(); + for (unsigned I = 0, Ext = 0; I < NumIRArgs; I++) { + llvm::Type *EltType = CoercionType->getElementType(I); + if (ABIArgInfo::isPaddingForCoerceAndExpand(EltType)) + continue; + llvm::Type *ExtendKind = AI.getExtendSeq()->getElementType(Ext++); + switch (ABIArgInfo::getExtendKind(ExtendKind)) { + case ABIArgInfo::ExtendKind::None: + break; + case ABIArgInfo::ExtendKind::SignExt: { + CoerceAndExpandHasAttributes = true; + CoerceAndExpandAttrs[FirstIRArg + I].addAttribute( + llvm::Attribute::SExt); + break; + } + case ABIArgInfo::ExtendKind::ZeroExt: { + CoerceAndExpandHasAttributes = true; + CoerceAndExpandAttrs[FirstIRArg + I].addAttribute( + llvm::Attribute::ZExt); + break; + } + } + } + } + + break; case ABIArgInfo::InAlloca: // inalloca disables readnone and readonly. FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly) @@ -2112,12 +2143,16 @@ if (FI.getExtParameterInfo(ArgNo).isNoEscape()) Attrs.addAttribute(llvm::Attribute::NoCapture); - if (Attrs.hasAttributes()) { + if (Attrs.hasAttributes() || CoerceAndExpandHasAttributes) { unsigned FirstIRArg, NumIRArgs; std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); for (unsigned i = 0; i < NumIRArgs; i++) + { + llvm::AttrBuilder CoerceAndExpandMergedAttrs(Attrs); + CoerceAndExpandMergedAttrs.merge(CoerceAndExpandAttrs[FirstIRArg + i]); ArgAttrs[FirstIRArg + i] = - llvm::AttributeSet::get(getLLVMContext(), Attrs); + llvm::AttributeSet::get(getLLVMContext(), CoerceAndExpandMergedAttrs); + } } } assert(ArgNo == FI.arg_size()); Index: include/clang/CodeGen/CGFunctionInfo.h =================================================================== --- include/clang/CodeGen/CGFunctionInfo.h +++ include/clang/CodeGen/CGFunctionInfo.h @@ -25,6 +25,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/TrailingObjects.h" #include <cassert> +#include <type_traits> namespace clang { namespace CodeGen { @@ -76,16 +77,20 @@ KindLast = InAlloca }; + enum class ExtendKind : unsigned { None = 1, SignExt = 2, ZeroExt = 3 }; + private: + llvm::Type *TypeData; // canHaveCoerceToType() union { llvm::Type *PaddingType; // canHavePaddingType() llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand() }; union { - unsigned DirectOffset; // isDirect() || isExtend() - unsigned IndirectAlign; // isIndirect() - unsigned AllocaFieldIndex; // isInAlloca() + llvm::StructType *ExtendSeq; // isCoerceAndExpand() + unsigned DirectOffset; // isDirect() || isExtend() + unsigned IndirectAlign; // isIndirect() + unsigned AllocaFieldIndex; // isInAlloca() }; Kind TheKind; bool PaddingInReg : 1; @@ -110,13 +115,16 @@ UnpaddedCoerceAndExpandType = T; } - ABIArgInfo(Kind K) - : TheKind(K), PaddingInReg(false), InReg(false) { + void setExtendSet(llvm::StructType *ES) { + assert(isCoerceAndExpand()); + ExtendSeq = ES; } + ABIArgInfo(Kind K) : TheKind(K), PaddingInReg(false), InReg(false) {} + public: ABIArgInfo() - : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), + : TypeData(nullptr), PaddingType(nullptr), ExtendSeq(nullptr), TheKind(Direct), PaddingInReg(false), InReg(false) {} static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, @@ -210,8 +218,15 @@ /// \param unpaddedCoerceToType The coerce-to type with padding elements /// removed, canonicalized to a single element if it would otherwise /// have exactly one element. - static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, - llvm::Type *unpaddedCoerceToType) { + /// \param extendSet The extension to be applied to the expanded type. It is + // represented by a struct of integers of bit-width one of the values + // of ExtendKind. If null no extension is applied. If not null it has + // as many elements as unpaddedCoerceToType. Only integral-types can have + // an extension other than None. + static ABIArgInfo + getCoerceAndExpand(llvm::StructType *coerceToType, + llvm::Type *unpaddedCoerceToType, + llvm::StructType *extendSet = nullptr) { #ifndef NDEBUG // Sanity checks on unpaddedCoerceToType. @@ -238,11 +253,44 @@ } else { assert(unpaddedIndex == 1); } + + if (extendSet) { + // Assert that the size of the extend struct agrees with the unpadded + // struct and it only attempts to extend integral types. + if (unpaddedStruct) { + assert(extendSet->getNumElements() == unpaddedStruct->getNumElements()); + unsigned Idx = 0; + for (auto EltType : unpaddedStruct->elements()) { + llvm::Type *ExtendType = extendSet->getElementType(Idx); + assert((ExtendType->isIntegerTy( + static_cast<unsigned>(ExtendKind::None)) || + ((ExtendType->isIntegerTy( + static_cast<unsigned>(ExtendKind::ZeroExt)) || + ExtendType->isIntegerTy( + static_cast<unsigned>(ExtendKind::SignExt))) && + EltType->isIntegerTy())) && + "Invalid extend applied to non-integral type"); + Idx++; + } + } else { + assert(extendSet->getNumElements() == 1); + llvm::Type *ExtendType = extendSet->getElementType(0); + assert( + (ExtendType->isIntegerTy(static_cast<unsigned>(ExtendKind::None)) || + ((ExtendType->isIntegerTy( + static_cast<unsigned>(ExtendKind::ZeroExt)) || + ExtendType->isIntegerTy( + static_cast<unsigned>(ExtendKind::SignExt))) && + unpaddedCoerceToType->isIntegerTy())) && + "Invalid extend applied to non-integral type"); + } + } #endif auto AI = ABIArgInfo(CoerceAndExpand); AI.setCoerceToType(coerceToType); AI.setUnpaddedCoerceToType(unpaddedCoerceToType); + AI.setExtendSet(extendSet); return AI; } @@ -255,6 +303,16 @@ } } + static ExtendKind getExtendKind(llvm::Type *T) { + unsigned S = cast<llvm::IntegerType>(T)->getBitWidth(); + ExtendKind EK = static_cast<ExtendKind>(S); + if (EK == ExtendKind::None || EK == ExtendKind::SignExt || + EK == ExtendKind::ZeroExt) { + return EK; + } + llvm_unreachable("Unexpected integer kind"); + } + Kind getKind() const { return TheKind; } bool isDirect() const { return TheKind == Direct; } bool isInAlloca() const { return TheKind == InAlloca; } @@ -318,6 +376,11 @@ return UnpaddedCoerceAndExpandType; } + llvm::StructType *getExtendSeq() const { + assert(isCoerceAndExpand()); + return ExtendSeq; + } + ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const { assert(isCoerceAndExpand()); if (auto structTy = @@ -409,6 +472,10 @@ void dump() const; }; +static_assert(std::is_trivially_copyable<ABIArgInfo>::value, + "ABIArgInfo must be trivially copyable as it is embedded as trailing " + "data of CGFunctionInfo"); + /// A class for recording the number of arguments that a function /// signature requires. class RequiredArgs {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits