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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits