diff options
author | John McCall <rjmccall@apple.com> | 2016-03-11 04:30:43 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2016-03-11 04:30:43 +0000 |
commit | b7eb03dd1c1c49828d08ec40f27284450e805913 (patch) | |
tree | 7f3044fa999d261732ae6ab8fb80d9cbe2953462 /include/clang/CodeGen/CGFunctionInfo.h | |
parent | 5af0763ee0b8a384c1f3b7026667f925f5bec866 (diff) |
Add a coerce-and-expand ABIArgInfo as a generalization of some
of the things we do with Expand / Direct.
NFC for now, but this will be used by swiftcall expansion.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@263192 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/CodeGen/CGFunctionInfo.h')
-rw-r--r-- | include/clang/CodeGen/CGFunctionInfo.h | 121 |
1 files changed, 107 insertions, 14 deletions
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h index a46547540e..d8de16a110 100644 --- a/include/clang/CodeGen/CGFunctionInfo.h +++ b/include/clang/CodeGen/CGFunctionInfo.h @@ -19,15 +19,11 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Type.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/TrailingObjects.h" #include <cassert> -namespace llvm { - class Type; - class StructType; -} - namespace clang { class Decl; @@ -64,6 +60,12 @@ public: /// are all scalar types or are themselves expandable types. Expand, + /// CoerceAndExpand - Only valid for aggregate argument types. The + /// structure should be expanded into consecutive arguments corresponding + /// to the non-array elements of the type stored in CoerceToType. + /// Array elements in the type are assumed to be padding and skipped. + CoerceAndExpand, + /// InAlloca - Pass the argument directly using the LLVM inalloca attribute. /// This is similar to indirect with byval, except it only applies to /// arguments stored in memory and forbids any implicit copies. When @@ -75,8 +77,11 @@ public: }; private: - llvm::Type *TypeData; // isDirect() || isExtend() - llvm::Type *PaddingType; + llvm::Type *TypeData; // canHaveCoerceToType() + union { + llvm::Type *PaddingType; // canHavePaddingType() + llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand() + }; union { unsigned DirectOffset; // isDirect() || isExtend() unsigned IndirectAlign; // isIndirect() @@ -91,8 +96,22 @@ private: bool InReg : 1; // isDirect() || isExtend() || isIndirect() bool CanBeFlattened: 1; // isDirect() + bool canHavePaddingType() const { + return isDirect() || isExtend() || isIndirect() || isExpand(); + } + void setPaddingType(llvm::Type *T) { + assert(canHavePaddingType()); + PaddingType = T; + } + + void setUnpaddedCoerceToType(llvm::Type *T) { + assert(isCoerceAndExpand()); + UnpaddedCoerceAndExpandType = T; + } + ABIArgInfo(Kind K) - : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {} + : TheKind(K), PaddingInReg(false), InReg(false) { + } public: ABIArgInfo() @@ -104,8 +123,8 @@ public: bool CanBeFlattened = true) { auto AI = ABIArgInfo(Direct); AI.setCoerceToType(T); - AI.setDirectOffset(Offset); AI.setPaddingType(Padding); + AI.setDirectOffset(Offset); AI.setCanBeFlattened(CanBeFlattened); return AI; } @@ -117,6 +136,7 @@ public: static ABIArgInfo getExtend(llvm::Type *T = nullptr) { auto AI = ABIArgInfo(Extend); AI.setCoerceToType(T); + AI.setPaddingType(nullptr); AI.setDirectOffset(0); return AI; } @@ -151,7 +171,9 @@ public: return AI; } static ABIArgInfo getExpand() { - return ABIArgInfo(Expand); + auto AI = ABIArgInfo(Expand); + AI.setPaddingType(nullptr); + return AI; } static ABIArgInfo getExpandWithPadding(bool PaddingInReg, llvm::Type *Padding) { @@ -161,6 +183,54 @@ public: return AI; } + /// \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) { +#ifndef NDEBUG + // Sanity checks on unpaddedCoerceToType. + + // Assert that we only have a struct type if there are multiple elements. + auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType); + assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1); + + // Assert that all the non-padding elements have a corresponding element + // in the unpadded type. + unsigned unpaddedIndex = 0; + for (auto eltType : coerceToType->elements()) { + if (isPaddingForCoerceAndExpand(eltType)) continue; + if (unpaddedStruct) { + assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType); + } else { + assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType); + } + unpaddedIndex++; + } + + // Assert that there aren't extra elements in the unpadded type. + if (unpaddedStruct) { + assert(unpaddedStruct->getNumElements() == unpaddedIndex); + } else { + assert(unpaddedIndex == 1); + } +#endif + + auto AI = ABIArgInfo(CoerceAndExpand); + AI.setCoerceToType(coerceToType); + AI.setUnpaddedCoerceToType(unpaddedCoerceToType); + return AI; + } + + static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) { + if (eltType->isArrayTy()) { + assert(eltType->getArrayElementType()->isIntegerTy(8)); + return true; + } else { + return false; + } + } + Kind getKind() const { return TheKind; } bool isDirect() const { return TheKind == Direct; } bool isInAlloca() const { return TheKind == InAlloca; } @@ -168,8 +238,11 @@ public: bool isIgnore() const { return TheKind == Ignore; } bool isIndirect() const { return TheKind == Indirect; } bool isExpand() const { return TheKind == Expand; } + bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; } - bool canHaveCoerceToType() const { return isDirect() || isExtend(); } + bool canHaveCoerceToType() const { + return isDirect() || isExtend() || isCoerceAndExpand(); + } // Direct/Extend accessors unsigned getDirectOffset() const { @@ -181,9 +254,9 @@ public: DirectOffset = Offset; } - llvm::Type *getPaddingType() const { return PaddingType; } - - void setPaddingType(llvm::Type *T) { PaddingType = T; } + llvm::Type *getPaddingType() const { + return (canHavePaddingType() ? PaddingType : nullptr); + } bool getPaddingInReg() const { return PaddingInReg; @@ -202,6 +275,26 @@ public: TypeData = T; } + llvm::StructType *getCoerceAndExpandType() const { + assert(isCoerceAndExpand()); + return cast<llvm::StructType>(TypeData); + } + + llvm::Type *getUnpaddedCoerceAndExpandType() const { + assert(isCoerceAndExpand()); + return UnpaddedCoerceAndExpandType; + } + + ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const { + assert(isCoerceAndExpand()); + if (auto structTy = + dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) { + return structTy->elements(); + } else { + return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1); + } + } + bool getInReg() const { assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); return InReg; |