Index: include/llvm/IR/Attributes.h =================================================================== --- include/llvm/IR/Attributes.h +++ include/llvm/IR/Attributes.h @@ -83,6 +83,7 @@ /// \brief Return a uniquified Attribute object. static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); + static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty); static Attribute get(LLVMContext &Context, StringRef Kind, StringRef Val = StringRef()); @@ -105,6 +106,9 @@ /// \brief Return true if the attribute is an integer attribute. bool isIntAttribute() const; + /// \brief Return true if the attribute is a type attribute. + bool isTypeAttribute() const; + /// \brief Return true if the attribute is a string (target-dependent) /// attribute. bool isStringAttribute() const; @@ -123,6 +127,10 @@ /// attribute be an integer attribute. uint64_t getValueAsInt() const; + /// \brief Return the attribute's value as a type. This requires that the + /// attribute is a type attribute. + Type *getValueAsType() const; + /// \brief Return the attribute's kind as a string. This requires the /// attribute to be a string attribute. StringRef getKindAsString() const; Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -1391,6 +1391,10 @@ B.addDereferenceableAttr(Record[++i]); else if (Kind == Attribute::DereferenceableOrNull) B.addDereferenceableOrNullAttr(Record[++i]); + } else if (Record[i] == 5) { // Type attribute + Attribute::AttrKind Kind; + if (std::error_code EC = parseAttrKind(Record[++i], &Kind)) + return EC; } else { // String attribute assert((Record[i] == 3 || Record[i] == 4) && "Invalid attribute group entry"); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -293,6 +293,10 @@ Record.push_back(1); Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); Record.push_back(Attr.getValueAsInt()); + } else if (Attr.isTypeAttribute()) { + Record.push_back(5); + Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); + Record.push_back(VE.getTypeID(Attr.getValueAsType())); } else { StringRef Kind = Attr.getKindAsString(); StringRef Val = Attr.getValueAsString(); @@ -2906,15 +2910,15 @@ // Emit blockinfo, which defines the standard abbreviations etc. WriteBlockInfo(VE, Stream); + // Emit information describing all of the types in the module. + WriteTypeTable(VE, Stream); + // Emit information about attribute groups. WriteAttributeGroupTable(VE, Stream); // Emit information about parameter attributes. WriteAttributeTable(VE, Stream); - // Emit information describing all of the types in the module. - WriteTypeTable(VE, Stream); - writeComdats(VE, Stream); // Emit top-level description of module, including target triple, inline asm, Index: lib/IR/AttributeImpl.h =================================================================== --- lib/IR/AttributeImpl.h +++ lib/IR/AttributeImpl.h @@ -41,6 +41,7 @@ enum AttrEntryKind { EnumAttrEntry, IntAttrEntry, + TypeAttrEntry, StringAttrEntry }; @@ -51,6 +52,7 @@ bool isEnumAttribute() const { return KindID == EnumAttrEntry; } bool isIntAttribute() const { return KindID == IntAttrEntry; } + bool isTypeAttribute() const { return KindID == TypeAttrEntry; } bool isStringAttribute() const { return KindID == StringAttrEntry; } bool hasAttribute(Attribute::AttrKind A) const; @@ -58,6 +60,7 @@ Attribute::AttrKind getKindAsEnum() const; uint64_t getValueAsInt() const; + Type *getValueAsType() const; StringRef getKindAsString() const; StringRef getValueAsString() const; @@ -67,9 +70,11 @@ void Profile(FoldingSetNodeID &ID) const { if (isEnumAttribute()) - Profile(ID, getKindAsEnum(), 0); + Profile(ID, getKindAsEnum(), (uint64_t) 0); else if (isIntAttribute()) Profile(ID, getKindAsEnum(), getValueAsInt()); + else if (isTypeAttribute()) + Profile(ID, getKindAsEnum(), getValueAsType()); else Profile(ID, getKindAsString(), getValueAsString()); } @@ -78,6 +83,11 @@ ID.AddInteger(Kind); if (Val) ID.AddInteger(Val); } + static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, + Type *Ty) { + ID.AddInteger(Kind); + if (Ty) ID.AddPointer(Ty); + } static void Profile(FoldingSetNodeID &ID, StringRef Kind, StringRef Values) { ID.AddString(Kind); if (!Values.empty()) ID.AddString(Values); @@ -125,6 +135,19 @@ uint64_t getValue() const { return Val; } }; +class TypeAttributeImpl : public EnumAttributeImpl { + void anchor() override; + Type *Val; + +public: + TypeAttributeImpl(Attribute::AttrKind Kind, Type *Val) + : EnumAttributeImpl(TypeAttrEntry, Kind), Val(Val) { + assert((Kind == Attribute::ByVal) && "Wrong kind for type attribute!"); + } + + Type *getValue() const { return Val; } +}; + class StringAttributeImpl : public AttributeImpl { virtual void anchor(); std::string Kind; Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -56,6 +56,30 @@ return Attribute(PA); } +Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, + Type *Ty) { + LLVMContextImpl *pImpl = Context.pImpl; + FoldingSetNodeID ID; + ID.AddInteger(Kind); + if (Ty) ID.AddPointer(Ty); + + void *InsertPoint; + AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); + + if (!PA) { + // If we didn't find any existing attributes of the same shape then create a + // new one and insert it. + if (!Ty) + PA = new EnumAttributeImpl(Kind); + else + PA = new TypeAttributeImpl(Kind, Ty); + pImpl->AttrsSet.InsertNode(PA, InsertPoint); + } + + // Return the Attribute that we found or created. + return Attribute(PA); +} + Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; @@ -113,13 +137,17 @@ return pImpl && pImpl->isIntAttribute(); } +bool Attribute::isTypeAttribute() const { + return pImpl && pImpl->isTypeAttribute(); +} + bool Attribute::isStringAttribute() const { return pImpl && pImpl->isStringAttribute(); } Attribute::AttrKind Attribute::getKindAsEnum() const { if (!pImpl) return None; - assert((isEnumAttribute() || isIntAttribute()) && + assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) && "Invalid attribute type to get the kind as an enum!"); return pImpl->getKindAsEnum(); } @@ -131,6 +159,13 @@ return pImpl->getValueAsInt(); } +Type *Attribute::getValueAsType() const { + if (!pImpl) return nullptr; + assert(isTypeAttribute() && + "Invalid attribute type to get the value as a type!"); + return pImpl->getValueAsType(); +} + StringRef Attribute::getKindAsString() const { if (!pImpl) return StringRef(); assert(isStringAttribute() && @@ -342,6 +377,7 @@ AttributeImpl::~AttributeImpl() {} void EnumAttributeImpl::anchor() {} void IntAttributeImpl::anchor() {} +void TypeAttributeImpl::anchor() {} void StringAttributeImpl::anchor() {} bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { @@ -355,7 +391,7 @@ } Attribute::AttrKind AttributeImpl::getKindAsEnum() const { - assert(isEnumAttribute() || isIntAttribute()); + assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute()); return static_cast(this)->getEnumKind(); } @@ -364,6 +400,11 @@ return static_cast(this)->getValue(); } +Type *AttributeImpl::getValueAsType() const { + assert(isTypeAttribute()); + return static_cast(this)->getValue(); +} + StringRef AttributeImpl::getKindAsString() const { assert(isStringAttribute()); return static_cast(this)->getStringKind(); @@ -380,17 +421,27 @@ if (isEnumAttribute()) { if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); if (AI.isIntAttribute()) return true; + if (AI.isTypeAttribute()) return true; if (AI.isStringAttribute()) return true; } if (isIntAttribute()) { if (AI.isEnumAttribute()) return false; if (AI.isIntAttribute()) return getValueAsInt() < AI.getValueAsInt(); + if (AI.isTypeAttribute()) return true; + if (AI.isStringAttribute()) return true; + } + + if (isTypeAttribute()) { + if (AI.isEnumAttribute()) return false; + if (AI.isIntAttribute()) return false; + if (AI.isTypeAttribute()) return getValueAsType() < AI.getValueAsType(); if (AI.isStringAttribute()) return true; } if (AI.isEnumAttribute()) return false; if (AI.isIntAttribute()) return false; + if (AI.isTypeAttribute()) return false; if (getKindAsString() == AI.getKindAsString()) return getValueAsString() < AI.getValueAsString(); return getKindAsString() < AI.getKindAsString(); @@ -1207,7 +1258,8 @@ for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { Attribute Attr = *I; - if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { + if (Attr.isEnumAttribute() || Attr.isIntAttribute() || + Attr.isTypeAttribute()) { removeAttribute(Attr.getKindAsEnum()); } else { assert(Attr.isStringAttribute() && "Invalid attribute type!"); Index: lib/Linker/IRMover.cpp =================================================================== --- lib/Linker/IRMover.cpp +++ lib/Linker/IRMover.cpp @@ -773,6 +773,23 @@ NewGV->copyAttributesFrom(SGV); + // Fix up type attributes. + if (auto *NewF = dyn_cast(NewGV)) { + AttributeSet Attrs = cast(SGV)->getAttributes(); + for (unsigned Slot = 0; Slot < Attrs.getNumSlots(); ++Slot) { + for (auto I = Attrs.begin(Slot), E = Attrs.end(Slot); I != E; ++I) { + Attribute A = *I; + if (!A.isTypeAttribute()) + continue; + Attribute NewA = Attribute::get(NewF->getContext(), A.getKindAsEnum(), + TypeMap.get(A.getValueAsType())); + Attrs = Attrs.addAttribute(NewF->getContext(), Attrs.getSlotIndex(Slot), + NewA); + } + } + NewF->setAttributes(Attrs); + } + // Remove these copied constants in case this stays a declaration, since // they point to the source module. If the def is linked the values will // be mapped in during linkFunctionBody.