Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -842,6 +842,61 @@ */ LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); +/** + * Obtain an iterator to the first NamedMDNode in a Module. + * + * @see llvm::Module::named_metadata_begin() + */ +LLVMMetadataRef LLVMGetFirstNamedMetadata(LLVMModuleRef M); + +/** + * Obtain an iterator to the last NamedMDNode in a Module. + * + * @see llvm::Module::named_metadata_end() + */ +LLVMMetadataRef LLVMGetLastNamedMetadata(LLVMModuleRef M); + +/** + * Advance a NamedMDNode iterator to the next NamedMDNode. + * + * Returns NULL if the iterator was already at the end and there are no more + * named metadata nodes. + */ +LLVMMetadataRef LLVMGetNextNamedMetadata(LLVMMetadataRef NamedMDNode); + +/** + * Decrement a NamedMDNode iterator to the previous NamedMDNode. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous named metadata nodes. + */ +LLVMMetadataRef LLVMGetPreviousNamedMetadata(LLVMMetadataRef NamedMDNode); + +/** + * Retrieve a NamedMDNode with the given name, returning NULL if no such + * node exists. + * + * @see llvm::Module::getNamedMetadata() + */ +LLVMMetadataRef LLVMGetNamedMetadata(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Retrieve a NamedMDNode with the given name, creating a new node if no such + * node exists. + * + * @see llvm::Module::getOrInsertNamedMetadata() + */ +LLVMMetadataRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Retrieve the name of a NamedMDNode. + * + * @see llvm::NamedMDNode::getName() + */ +const char *LLVMGetNamedMetadataName(LLVMMetadataRef NamedMD, size_t *NameLen); + /** * Obtain the number of operands for named metadata in a module. * Index: include/llvm/IR/Metadata.h =================================================================== --- include/llvm/IR/Metadata.h +++ include/llvm/IR/Metadata.h @@ -1318,9 +1318,7 @@ /// /// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong /// to modules, have names, and contain lists of MDNodes. -/// -/// TODO: Inherit from Metadata. -class NamedMDNode : public ilist_node { +class NamedMDNode : public Metadata, public ilist_node { friend class LLVMContextImpl; friend class Module; @@ -1418,6 +1416,11 @@ inline iterator_range operands() const { return make_range(op_begin(), op_end()); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == NamedMDNodeKind; + } }; } // end namespace llvm Index: include/llvm/IR/Metadata.def =================================================================== --- include/llvm/IR/Metadata.def +++ include/llvm/IR/Metadata.def @@ -78,6 +78,7 @@ HANDLE_METADATA_LEAF(ConstantAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata) HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder) +HANDLE_METADATA_LEAF(NamedMDNode) HANDLE_MDNODE_BRANCH(MDNode) HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation) Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -1065,6 +1065,54 @@ return cast(MD->getMetadata())->getNumOperands(); } +LLVMMetadataRef LLVMGetFirstNamedMetadata(LLVMModuleRef M) { + Module *Mod = unwrap(M); + Module::named_metadata_iterator I = Mod->named_metadata_begin(); + if (I == Mod->named_metadata_end()) + return nullptr; + return wrap(&*I); +} + +LLVMMetadataRef LLVMGetLastNamedMetadata(LLVMModuleRef M) { + Module *Mod = unwrap(M); + Module::named_metadata_iterator I = Mod->named_metadata_end(); + if (I == Mod->named_metadata_begin()) + return nullptr; + return wrap(&*--I); +} + +LLVMMetadataRef LLVMGetNextNamedMetadata(LLVMMetadataRef NMD) { + NamedMDNode *NamedNode = unwrap(NMD); + Module::named_metadata_iterator I(NamedNode); + if (++I == NamedNode->getParent()->named_metadata_end()) + return nullptr; + return wrap(&*I); +} + +LLVMMetadataRef LLVMGetPreviousNamedMetadata(LLVMMetadataRef NMD) { + NamedMDNode *NamedNode = unwrap(NMD); + Module::named_metadata_iterator I(NamedNode); + if (I == NamedNode->getParent()->named_metadata_begin()) + return nullptr; + return wrap(&*--I); +} + +LLVMMetadataRef LLVMGetNamedMetadata(LLVMModuleRef M, + const char *Name, size_t NameLen) { + return wrap(unwrap(M)->getNamedMetadata(StringRef(Name, NameLen))); +} + +LLVMMetadataRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M, + const char *Name, size_t NameLen) { + return wrap(unwrap(M)->getOrInsertNamedMetadata({Name, NameLen})); +} + +const char *LLVMGetNamedMetadataName(LLVMMetadataRef NMD, size_t *NameLen) { + NamedMDNode *NamedNode = unwrap(NMD); + *NameLen = NamedNode->getName().size(); + return NamedNode->getName().data(); +} + void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest) { auto *MD = cast(unwrap(V)); if (auto *MDV = dyn_cast(MD->getMetadata())) { Index: lib/IR/Metadata.cpp =================================================================== --- lib/IR/Metadata.cpp +++ lib/IR/Metadata.cpp @@ -1067,7 +1067,8 @@ } NamedMDNode::NamedMDNode(const Twine &N) - : Name(N.str()), Operands(new SmallVector()) {} + : Metadata(NamedMDNodeKind, Uniqued), Name(N.str()), + Operands(new SmallVector()) {} NamedMDNode::~NamedMDNode() { dropAllReferences(); Index: test/Bindings/llvm-c/echo.ll =================================================================== --- test/Bindings/llvm-c/echo.ll +++ test/Bindings/llvm-c/echo.ll @@ -166,6 +166,11 @@ ret void } -!llvm.module.flags = !{!1} - -!1 = !{i32 2, !"Debug Info Version", i32 3} +!llvm.module.flags = !{!0} +!named = !{!1, !2, !3} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !{} +!2 = distinct !{} +!3 = !{!4} +!4 = distinct !{} Index: tools/llvm-c-test/echo.cpp =================================================================== --- tools/llvm-c-test/echo.cpp +++ tools/llvm-c-test/echo.cpp @@ -916,7 +916,7 @@ if (!Begin) { if (End != nullptr) report_fatal_error("Range has an end but no beginning"); - return; + goto NamedMDDecl; } Cur = Begin; @@ -943,6 +943,38 @@ Cur = Next; } + +NamedMDDecl: + LLVMMetadataRef BeginMD = LLVMGetFirstNamedMetadata(Src); + LLVMMetadataRef EndMD = LLVMGetLastNamedMetadata(Src); + if (!BeginMD) { + if (EndMD != nullptr) + report_fatal_error("Range has an end but no beginning"); + return; + } + + LLVMMetadataRef CurMD = BeginMD; + LLVMMetadataRef NextMD = nullptr; + while (true) { + size_t NameLen; + const char *Name = LLVMGetNamedMetadataName(CurMD, &NameLen); + if (LLVMGetNamedMetadata(M, Name, NameLen)) + report_fatal_error("Named Metadata Node already cloned"); + LLVMGetOrInsertNamedMetadata(M, Name, NameLen); + + NextMD = LLVMGetNextNamedMetadata(CurMD); + if (NextMD == nullptr) { + if (CurMD != EndMD) + report_fatal_error(""); + break; + } + + LLVMMetadataRef PrevMD = LLVMGetPreviousNamedMetadata(NextMD); + if (PrevMD != CurMD) + report_fatal_error("Next.Previous global is not Current"); + + CurMD = NextMD; + } } static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) { @@ -1041,7 +1073,7 @@ if (!Begin) { if (End != nullptr) report_fatal_error("Range has an end but no beginning"); - return; + goto NamedMDClone; } Cur = Begin; @@ -1073,6 +1105,47 @@ Cur = Next; } + +NamedMDClone: + LLVMMetadataRef BeginMD = LLVMGetFirstNamedMetadata(Src); + LLVMMetadataRef EndMD = LLVMGetLastNamedMetadata(Src); + if (!BeginMD) { + if (EndMD != nullptr) + report_fatal_error("Range has an end but no beginning"); + return; + } + + LLVMMetadataRef CurMD = BeginMD; + LLVMMetadataRef NextMD = nullptr; + while (true) { + size_t NameLen; + const char *Name = LLVMGetNamedMetadataName(CurMD, &NameLen); + LLVMMetadataRef NamedMD = LLVMGetNamedMetadata(M, Name, NameLen); + if (!NamedMD) + report_fatal_error("Named MD Node must have been declared already"); + + unsigned OperandCount = LLVMGetNamedMetadataNumOperands(Src, Name); + LLVMValueRef *OperandBuf = static_cast( + safe_malloc(OperandCount * sizeof(LLVMValueRef))); + LLVMGetNamedMetadataOperands(Src, Name, OperandBuf); + for (unsigned i = 0, e = OperandCount; i != e; ++i) { + LLVMAddNamedMetadataOperand(M, Name, OperandBuf[i]); + } + free(OperandBuf); + + NextMD = LLVMGetNextNamedMetadata(CurMD); + if (NextMD == nullptr) { + if (CurMD != EndMD) + report_fatal_error("Last Named MD Node does not match End"); + break; + } + + LLVMMetadataRef PrevMD = LLVMGetPreviousNamedMetadata(NextMD); + if (PrevMD != CurMD) + report_fatal_error("Next.Previous Named MD Node is not Current"); + + CurMD = NextMD; + } } int llvm_echo(void) { @@ -1089,18 +1162,6 @@ LLVMSetSourceFileName(M, SourceFileName, SourceFileLen); LLVMSetModuleIdentifier(M, ModuleName, ModuleIdentLen); - size_t SourceFlagsLen; - LLVMModuleFlagEntry *ModuleFlags = - LLVMCopyModuleFlagsMetadata(Src, &SourceFlagsLen); - for (unsigned i = 0; i < SourceFlagsLen; ++i) { - size_t EntryNameLen; - const char *EntryName = - LLVMModuleFlagEntriesGetKey(ModuleFlags, i, &EntryNameLen); - LLVMAddModuleFlag(M, LLVMModuleFlagEntriesGetFlagBehavior(ModuleFlags, i), - EntryName, EntryNameLen, - LLVMModuleFlagEntriesGetMetadata(ModuleFlags, i)); - } - LLVMSetTarget(M, LLVMGetTarget(Src)); LLVMSetModuleDataLayout(M, LLVMGetModuleDataLayout(Src)); if (strcmp(LLVMGetDataLayoutStr(M), LLVMGetDataLayoutStr(Src))) @@ -1115,7 +1176,6 @@ char *Str = LLVMPrintModuleToString(M); fputs(Str, stdout); - LLVMDisposeModuleFlagsMetadata(ModuleFlags); LLVMDisposeMessage(Str); LLVMDisposeModule(Src); LLVMDisposeModule(M);