Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -381,6 +381,20 @@ } 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; + +/** * @} */ @@ -488,6 +502,38 @@ * going through the C API deprecation cycle. */ unsigned LLVMGetAttributeKindForName(const char *Name, size_t SLen); +unsigned LLVMGetLastAttributeKind(); + +/** + * Create an attribute without argument. + */ +LLVMAttributeRef LLVMCreateAttribute(LLVMContextRef C, unsigned KindID, + uint64_t Val); + +/** + * Get the unique id corresponding to the target independent attribute + * passed as argument. + */ +unsigned LLVMGetAttributeKindAsEnum(LLVMAttributeRef A); + +/** + * Create a string attribute. + */ +LLVMAttributeRef LLVMCreateStringAttribute(LLVMContextRef C, + const char *N, unsigned NLength, + const char *V, unsigned VLength); + +/** + * Get the target dependent attribute name. + */ +const char *LLVMGetAttributeKindAsString(LLVMAttributeRef A, unsigned *Length); + +/** + * Check for the different kind of attributes. + */ +LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A); +LLVMBool LLVMIsIntAttribute(LLVMAttributeRef A); +LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A); /** * @} @@ -1957,6 +2003,14 @@ */ void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); +void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef A); +LLVMAttributeRef LLVMGetAttributeAtIndex(LLVMValueRef F, + LLVMAttributeIndex Idx, + unsigned KindID); +void LLVMRemoveAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + unsigned KindID); + /** * Add a target-dependent attribute to a function * @see llvm::AttrBuilder::addAttribute() Index: include/llvm-c/Types.h =================================================================== --- include/llvm-c/Types.h +++ include/llvm-c/Types.h @@ -109,6 +109,13 @@ typedef struct LLVMOpaqueUse *LLVMUseRef; /** + * Used to represent an attributes. + * + * @see llvm::Attribute + */ +typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef; + +/** * @see llvm::DiagnosticInfo */ typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef; Index: include/llvm/IR/Attributes.h =================================================================== --- include/llvm/IR/Attributes.h +++ 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 @@ 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 Index: include/llvm/IR/Function.h =================================================================== --- include/llvm/IR/Function.h +++ include/llvm/IR/Function.h @@ -205,12 +205,10 @@ /// @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 @@ /// @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 @@ 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); Index: lib/IR/AttributeImpl.h =================================================================== --- lib/IR/AttributeImpl.h +++ lib/IR/AttributeImpl.h @@ -177,6 +177,9 @@ 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; } Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -128,6 +128,45 @@ return getAttrKindFromName(StringRef(Name, SLen)); } +unsigned LLVMGetLastAttributeKind() { + return Attribute::AttrKind::EndAttrKinds; +} + +LLVMAttributeRef LLVMCreateAttribute(LLVMContextRef C, unsigned KindID, + uint64_t Val) { + return wrap(Attribute::get(*unwrap(C), (Attribute::AttrKind)KindID, Val)); +} + +unsigned LLVMGetAttributeKindAsEnum(LLVMAttributeRef A) { + return unwrap(A).getKindAsEnum(); +} + +LLVMAttributeRef LLVMCreateStringAttribute(LLVMContextRef C, + const char *N, unsigned NLength, + const char *V, unsigned VLength) { + return wrap(Attribute::get(*unwrap(C), StringRef(N, NLength), + StringRef(V, VLength))); +} + +const char *LLVMGetAttributeKindAsString(LLVMAttributeRef A, + unsigned *Length) { + auto S = unwrap(A).getKindAsString(); + *Length = S.size(); + return S.data(); +} + +LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A) { + return unwrap(A).isEnumAttribute(); +} + +LLVMBool LLVMIsIntAttribute(LLVMAttributeRef A) { + return unwrap(A).isIntAttribute(); +} + +LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A) { + return unwrap(A).isStringAttribute(); +} + char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI) { std::string MsgStorage; raw_string_ostream Stream(MsgStorage); @@ -1789,6 +1828,23 @@ Func->setAttributes(PALnew); } +void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef A) { + unwrap(F)->addAttribute(Idx, unwrap(A)); +} + +LLVMAttributeRef LLVMGetAttributeAtIndex(LLVMValueRef F, + LLVMAttributeIndex Idx, + unsigned KindID) { + return wrap(unwrap(F)->getAttribute(Idx, + (Attribute::AttrKind)KindID)); +} + +void LLVMRemoveAttributeAtIndex(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); Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -372,6 +372,12 @@ 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); Index: test/Bindings/llvm-c/invoke.ll =================================================================== --- test/Bindings/llvm-c/invoke.ll +++ test/Bindings/llvm-c/invoke.ll @@ -70,13 +70,14 @@ 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 Index: tools/llvm-c-test/echo.cpp =================================================================== --- tools/llvm-c-test/echo.cpp +++ tools/llvm-c-test/echo.cpp @@ -782,13 +782,27 @@ 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 = LLVMGetLastAttributeKind(); k < e; ++k) { + if (LLVMGetAttributeAtIndex(Cur, i, k)) { + auto A = LLVMCreateAttribute(Ctx, k, 0); + LLVMAddAttributeAtIndex(F, i, A); + } + } + } Next = LLVMGetNextFunction(Cur); if (Next == nullptr) {