From 5db224e1f041e2d21bbf4eb0db7a1e8c0cd8439d Mon Sep 17 00:00:00 2001 From: Amaury Sechet Date: Sun, 12 Jun 2016 06:17:24 +0000 Subject: [PATCH] Make sure we have a Add/Remove/Has function for various thing that can have attribute. Summary: This also deprecated the get attribute function familly. Reviewers: Wallbraker, whitequark, joker.eph, echristo, rafael, jyknight Subscribers: axw, joker.eph, llvm-commits Differential Revision: http://reviews.llvm.org/D19181 llvm-svn: 272504 --- llvm/docs/ReleaseNotes.rst | 8 +++- llvm/include/llvm-c/Core.h | 67 ++++++++++++++++++++++++++- llvm/include/llvm-c/Types.h | 7 +++ llvm/include/llvm/IR/Attributes.h | 21 +++++++++ llvm/include/llvm/IR/Function.h | 17 +++++-- llvm/lib/IR/AttributeImpl.h | 3 ++ llvm/lib/IR/Core.cpp | 70 ++++++++++++++++++++++++++++- llvm/lib/IR/Function.cpp | 6 +++ llvm/test/Bindings/llvm-c/invoke.ll | 9 ++-- llvm/tools/llvm-c-test/echo.cpp | 17 ++++++- 10 files changed, 210 insertions(+), 15 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index e680a979c31e5..654ad5d365b0e 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -54,8 +54,12 @@ Non-comprehensive list of changes in this release * The C API function LLVMGetDataLayout is deprecated in favor of LLVMGetDataLayoutStr. -* The C API enum LLVMAttribute is deprecated in favor of - LLVMGetAttributeKindForName. +* The C API enum LLVMAttribute and associated API is deprecated in favor of + the new LLVMAttributeRef API. The deprecated functions are + LLVMAddFunctionAttr, LLVMAddTargetDependentFunctionAttr, + LLVMRemoveFunctionAttr, LLVMGetFunctionAttr, LLVMAddAttribute, + LLVMRemoveAttribute, LLVMGetAttribute, LLVMAddInstrAttribute and + LLVMRemoveInstrAttribute. * ``TargetFrameLowering::eliminateCallFramePseudoInstr`` now returns an iterator to the next instruction instead of ``void``. Targets that previously diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 674b93ffd5f6b..3db6f36b3af57 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -380,6 +380,20 @@ typedef enum { LLVMDSNote } LLVMDiagnosticSeverity; +/** + * Attribute index are either LLVMAttributeReturnIndex, + * LLVMAttributeFunctionIndex or a parameter number from 1 to N. + */ +enum { + LLVMAttributeReturnIndex = 0U, + // ISO C restricts enumerator values to range of 'int' + // (4294967295 is too large) + // LLVMAttributeFunctionIndex = ~0U, + LLVMAttributeFunctionIndex = -1, +}; + +typedef unsigned LLVMAttributeIndex; + /** * @} */ @@ -477,7 +491,7 @@ unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char *Name, unsigned LLVMGetMDKindID(const char *Name, unsigned SLen); /** - * Return an unique id given the name of a target independent attribute, + * Return an unique id given the name of a enum attribute, * or 0 if no attribute by that name exists. * * See http://llvm.org/docs/LangRef.html#parameter-attributes @@ -487,7 +501,48 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen); * NB: Attribute names and/or id are subject to change without * going through the C API deprecation cycle. */ -unsigned LLVMGetAttributeKindForName(const char *Name, size_t SLen); +unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen); +unsigned LLVMGetLastEnumAttributeKind(); + +/** + * Create an enum attribute. + */ +LLVMAttributeRef LLVMCreateEnumAttribute(LLVMContextRef C, unsigned KindID, + uint64_t Val); + +/** + * Get the unique id corresponding to the enum attribute + * passed as argument. + */ +unsigned LLVMGetEnumAttributeKind(LLVMAttributeRef A); + +/** + * Get the enum attribute's value. 0 is returned if none exists. + */ +uint64_t LLVMGetEnumAttributeValue(LLVMAttributeRef A); + +/** + * Create a string attribute. + */ +LLVMAttributeRef LLVMCreateStringAttribute(LLVMContextRef C, + const char *K, unsigned KLength, + const char *V, unsigned VLength); + +/** + * Get the string attribute's kind. + */ +const char *LLVMGetStringAttributeKind(LLVMAttributeRef A, unsigned *Length); + +/** + * Get the string attribute's value. + */ +const char *LLVMGetStringAttributeValue(LLVMAttributeRef A, unsigned *Length); + +/** + * Check for the different types of attributes. + */ +LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A); +LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A); /** * @} @@ -1957,6 +2012,14 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name); */ void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); +void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef A); +LLVMAttributeRef LLVMGetEnumAttributeAtIndex(LLVMValueRef F, + LLVMAttributeIndex Idx, + unsigned KindID); +void LLVMRemoveEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + unsigned KindID); + /** * Add a target-dependent attribute to a function * @see llvm::AttrBuilder::addAttribute() diff --git a/llvm/include/llvm-c/Types.h b/llvm/include/llvm-c/Types.h index 19029584efccc..3d472a6bf47d0 100644 --- a/llvm/include/llvm-c/Types.h +++ b/llvm/include/llvm-c/Types.h @@ -108,6 +108,13 @@ typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef; * @see llvm::Use */ typedef struct LLVMOpaqueUse *LLVMUseRef; +/** + * Used to represent an attributes. + * + * @see llvm::Attribute + */ +typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef; + /** * @see llvm::DiagnosticInfo */ diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index 55b8ba8e7dabf..5a3e07e0ea976 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -21,6 +21,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm-c/Types.h" #include #include #include @@ -169,8 +170,28 @@ class Attribute { void Profile(FoldingSetNodeID &ID) const { ID.AddPointer(pImpl); } + + /// \brief Return a raw pointer that uniquely identifies this attribute. + void *getRawPointer() const { + return pImpl; + } + + /// \brief Get an attribute from a raw pointer created by getRawPointer. + static Attribute fromRawPointer(void *RawPtr) { + return Attribute(reinterpret_cast(RawPtr)); + } }; +// Specialized opaque value conversions. +inline LLVMAttributeRef wrap(Attribute Attr) { + return reinterpret_cast(Attr.getRawPointer()); +} + +// Specialized opaque value conversions. +inline Attribute unwrap(LLVMAttributeRef Attr) { + return Attribute::fromRawPointer(Attr); +} + //===----------------------------------------------------------------------===// /// \class /// \brief This class holds the attributes for a function, its return value, and diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index dd21f2d723cd6..7b6a68accbb11 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -205,12 +205,10 @@ class Function : public GlobalObject, public ilist_node { /// @brief Return the attribute for the given attribute kind. Attribute getFnAttribute(Attribute::AttrKind Kind) const { - if (!hasFnAttribute(Kind)) - return Attribute(); - return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + return getAttribute(AttributeSet::FunctionIndex, Kind); } Attribute getFnAttribute(StringRef Kind) const { - return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + return getAttribute(AttributeSet::FunctionIndex, Kind); } /// \brief Return the stack alignment for the function. @@ -232,6 +230,9 @@ class Function : public GlobalObject, public ilist_node { /// @brief adds the attribute to the list of attributes. void addAttribute(unsigned i, Attribute::AttrKind attr); + /// @brief adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute Attr); + /// @brief adds the attributes to the list of attributes. void addAttributes(unsigned i, AttributeSet attrs); @@ -246,6 +247,14 @@ class Function : public GlobalObject, public ilist_node { return getAttributes().hasAttribute(i, attr); } + Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { + return AttributeSets.getAttribute(i, Kind); + } + + Attribute getAttribute(unsigned i, StringRef Kind) const { + return AttributeSets.getAttribute(i, Kind); + } + /// @brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h index 7b4b3bb18e780..45e6337e8ab89 100644 --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -177,6 +177,9 @@ class AttributeSetNode final static AttributeSetNode *get(LLVMContext &C, ArrayRef Attrs); + /// \brief Return the number of attributes this AttributeSet contains. + unsigned getNumAttributes() const { return NumAttrs; } + bool hasAttribute(Attribute::AttrKind Kind) const { return AvailableAttrs & ((uint64_t)1) << Kind; } diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 8429ef1a5e039..1dbdccb794a30 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -124,10 +124,60 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen) { #define GET_ATTR_KIND_FROM_NAME #include "AttributesCompatFunc.inc" -unsigned LLVMGetAttributeKindForName(const char *Name, size_t SLen) { +unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen) { return getAttrKindFromName(StringRef(Name, SLen)); } +unsigned LLVMGetLastEnumAttributeKind() { + return Attribute::AttrKind::EndAttrKinds; +} + +LLVMAttributeRef LLVMCreateEnumAttribute(LLVMContextRef C, unsigned KindID, + uint64_t Val) { + return wrap(Attribute::get(*unwrap(C), (Attribute::AttrKind)KindID, Val)); +} + +unsigned LLVMGetEnumAttributeKind(LLVMAttributeRef A) { + return unwrap(A).getKindAsEnum(); +} + +uint64_t LLVMGetEnumAttributeValue(LLVMAttributeRef A) { + auto Attr = unwrap(A); + if (Attr.isEnumAttribute()) + return 0; + return Attr.getValueAsInt(); +} + +LLVMAttributeRef LLVMCreateStringAttribute(LLVMContextRef C, + const char *K, unsigned KLength, + const char *V, unsigned VLength) { + return wrap(Attribute::get(*unwrap(C), StringRef(K, KLength), + StringRef(V, VLength))); +} + +const char *LLVMGetStringAttributeKind(LLVMAttributeRef A, + unsigned *Length) { + auto S = unwrap(A).getKindAsString(); + *Length = S.size(); + return S.data(); +} + +const char *LLVMGetStringAttributeValue(LLVMAttributeRef A, + unsigned *Length) { + auto S = unwrap(A).getValueAsString(); + *Length = S.size(); + return S.data(); +} + +LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A) { + auto Attr = unwrap(A); + return Attr.isEnumAttribute() || Attr.isIntAttribute(); +} + +LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A) { + return unwrap(A).isStringAttribute(); +} + char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI) { std::string MsgStorage; raw_string_ostream Stream(MsgStorage); @@ -1789,6 +1839,23 @@ void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Func->setAttributes(PALnew); } +void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef A) { + unwrap(F)->addAttribute(Idx, unwrap(A)); +} + +LLVMAttributeRef LLVMGetEnumAttributeAtIndex(LLVMValueRef F, + LLVMAttributeIndex Idx, + unsigned KindID) { + return wrap(unwrap(F)->getAttribute(Idx, + (Attribute::AttrKind)KindID)); +} + +void LLVMRemoveEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + unsigned KindID) { + unwrap(F)->removeAttribute(Idx, (Attribute::AttrKind)KindID); +} + void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, const char *V) { Function *Func = unwrap(Fn); @@ -1894,7 +1961,6 @@ LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg) { Raw(A->getArgNo()+1); } - void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align) { Argument *A = unwrap(Arg); AttrBuilder B; diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 815922593e5af..d7eaf7190c474 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -372,6 +372,12 @@ void Function::addAttribute(unsigned i, Attribute::AttrKind attr) { setAttributes(PAL); } +void Function::addAttribute(unsigned i, Attribute Attr) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addAttribute(getContext(), i, Attr); + setAttributes(PAL); +} + void Function::addAttributes(unsigned i, AttributeSet attrs) { AttributeSet PAL = getAttributes(); PAL = PAL.addAttributes(getContext(), i, attrs); diff --git a/llvm/test/Bindings/llvm-c/invoke.ll b/llvm/test/Bindings/llvm-c/invoke.ll index 22e3c8523ab12..0cd70a74e4800 100644 --- a/llvm/test/Bindings/llvm-c/invoke.ll +++ b/llvm/test/Bindings/llvm-c/invoke.ll @@ -70,13 +70,14 @@ unwind7: ; preds = %unwind5 declare void @_D6object6Object6__ctorFMC6object6ObjectZv(%C6object6Object*) -declare i8* @_d_allocmemory(i64) +declare noalias i8* @_d_allocmemory(i64) declare i32 @__sd_eh_personality(i32, i32, i64, i8*, i8*) -declare void @__sd_eh_throw(%C6object9Throwable*) +declare void @__sd_eh_throw(%C6object9Throwable* nonnull) #0 ; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #0 +declare i32 @llvm.eh.typeid.for(i8*) #1 -attributes #0 = { nounwind readnone } \ No newline at end of file +attributes #0 = { noreturn } +attributes #1 = { nounwind readnone } \ No newline at end of file diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 2c2a6dae803ef..73444b46d93c9 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -782,13 +782,28 @@ static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) { return; } + auto Ctx = LLVMGetModuleContext(M); + Cur = Begin; Next = nullptr; while (true) { const char *Name = LLVMGetValueName(Cur); if (LLVMGetNamedFunction(M, Name)) report_fatal_error("Function already cloned"); - LLVMAddFunction(M, Name, LLVMGetElementType(TypeCloner(M).Clone(Cur))); + auto Ty = LLVMGetElementType(TypeCloner(M).Clone(Cur)); + auto F = LLVMAddFunction(M, Name, Ty); + + // Copy attributes + for (int i = LLVMAttributeFunctionIndex, c = LLVMCountParams(F); + i <= c; ++i) { + for (unsigned k = 0, e = LLVMGetLastEnumAttributeKind(); k < e; ++k) { + if (auto SrcA = LLVMGetEnumAttributeAtIndex(Cur, i, k)) { + auto Val = LLVMGetEnumAttributeValue(SrcA); + auto DstA = LLVMCreateEnumAttribute(Ctx, k, Val); + LLVMAddAttributeAtIndex(F, i, DstA); + } + } + } Next = LLVMGetNextFunction(Cur); if (Next == nullptr) {