Skip to content

Commit

Permalink
[LLVM-C] Add Bindings For Named Metadata
Browse files Browse the repository at this point in the history
Summary: Add a new type for named metadata nodes.  Use this to implement iterators and accessors for NamedMDNodes and extend the echo test to use them to copy module-level debug information.

Reviewers: whitequark, deadalnix, aprantl, dexonsmith

Reviewed By: whitequark

Subscribers: Wallbraker, JDevlieghere, llvm-commits, harlanhaskins

Differential Revision: https://reviews.llvm.org/D47179

llvm-svn: 341085
  • Loading branch information
CodaFi committed Aug 30, 2018
1 parent 8d39ed8 commit 0a35b76
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 21 deletions.
57 changes: 57 additions & 0 deletions llvm/include/llvm-c/Core.h
Expand Up @@ -842,6 +842,63 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M);
*/
LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name);

/**
* Obtain an iterator to the first NamedMDNode in a Module.
*
* @see llvm::Module::named_metadata_begin()
*/
LLVMNamedMDNodeRef LLVMGetFirstNamedMetadata(LLVMModuleRef M);

/**
* Obtain an iterator to the last NamedMDNode in a Module.
*
* @see llvm::Module::named_metadata_end()
*/
LLVMNamedMDNodeRef 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.
*/
LLVMNamedMDNodeRef LLVMGetNextNamedMetadata(LLVMNamedMDNodeRef 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.
*/
LLVMNamedMDNodeRef LLVMGetPreviousNamedMetadata(LLVMNamedMDNodeRef NamedMDNode);

/**
* Retrieve a NamedMDNode with the given name, returning NULL if no such
* node exists.
*
* @see llvm::Module::getNamedMetadata()
*/
LLVMNamedMDNodeRef 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()
*/
LLVMNamedMDNodeRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M,
const char *Name,
size_t NameLen);

/**
* Retrieve the name of a NamedMDNode.
*
* @see llvm::NamedMDNode::getName()
*/
const char *LLVMGetNamedMetadataName(LLVMNamedMDNodeRef NamedMD,
size_t *NameLen);

/**
* Obtain the number of operands for named metadata in a module.
*
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm-c/Types.h
Expand Up @@ -89,6 +89,13 @@ typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
*/
typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;

/**
* Represents an LLVM Named Metadata Node.
*
* This models llvm::NamedMDNode.
*/
typedef struct LLVMOpaqueNamedMDNode *LLVMNamedMDNodeRef;

/**
* Represents an LLVM basic block builder.
*
Expand Down
10 changes: 7 additions & 3 deletions llvm/include/llvm/IR/Metadata.h
Expand Up @@ -1316,10 +1316,11 @@ class DistinctMDOperandPlaceholder : public Metadata {
//===----------------------------------------------------------------------===//
/// A tuple of MDNodes.
///
/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong
/// to modules, have names, and contain lists of MDNodes.
/// Despite its name, a NamedMDNode isn't itself an MDNode.
///
/// TODO: Inherit from Metadata.
/// NamedMDNodes are named module-level entities that contain lists of MDNodes.
///
/// It is illegal for a NamedMDNode to appear as an operand of an MDNode.
class NamedMDNode : public ilist_node<NamedMDNode> {
friend class LLVMContextImpl;
friend class Module;
Expand Down Expand Up @@ -1420,6 +1421,9 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
}
};

// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_ISA_CONVERSION_FUNCTIONS(NamedMDNode, LLVMNamedMDNodeRef)

} // end namespace llvm

#endif // LLVM_IR_METADATA_H
48 changes: 48 additions & 0 deletions llvm/lib/IR/Core.cpp
Expand Up @@ -1065,6 +1065,54 @@ unsigned LLVMGetMDNodeNumOperands(LLVMValueRef V) {
return cast<MDNode>(MD->getMetadata())->getNumOperands();
}

LLVMNamedMDNodeRef 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);
}

LLVMNamedMDNodeRef 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);
}

LLVMNamedMDNodeRef LLVMGetNextNamedMetadata(LLVMNamedMDNodeRef NMD) {
NamedMDNode *NamedNode = unwrap<NamedMDNode>(NMD);
Module::named_metadata_iterator I(NamedNode);
if (++I == NamedNode->getParent()->named_metadata_end())
return nullptr;
return wrap(&*I);
}

LLVMNamedMDNodeRef LLVMGetPreviousNamedMetadata(LLVMNamedMDNodeRef NMD) {
NamedMDNode *NamedNode = unwrap<NamedMDNode>(NMD);
Module::named_metadata_iterator I(NamedNode);
if (I == NamedNode->getParent()->named_metadata_begin())
return nullptr;
return wrap(&*--I);
}

LLVMNamedMDNodeRef LLVMGetNamedMetadata(LLVMModuleRef M,
const char *Name, size_t NameLen) {
return wrap(unwrap(M)->getNamedMetadata(StringRef(Name, NameLen)));
}

LLVMNamedMDNodeRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M,
const char *Name, size_t NameLen) {
return wrap(unwrap(M)->getOrInsertNamedMetadata({Name, NameLen}));
}

const char *LLVMGetNamedMetadataName(LLVMNamedMDNodeRef NMD, size_t *NameLen) {
NamedMDNode *NamedNode = unwrap<NamedMDNode>(NMD);
*NameLen = NamedNode->getName().size();
return NamedNode->getName().data();
}

void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest) {
auto *MD = cast<MetadataAsValue>(unwrap(V));
if (auto *MDV = dyn_cast<ValueAsMetadata>(MD->getMetadata())) {
Expand Down
11 changes: 8 additions & 3 deletions llvm/test/Bindings/llvm-c/echo.ll
Expand Up @@ -166,6 +166,11 @@ exit:
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 !{}
90 changes: 75 additions & 15 deletions llvm/tools/llvm-c-test/echo.cpp
Expand Up @@ -916,7 +916,7 @@ static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
if (!Begin) {
if (End != nullptr)
report_fatal_error("Range has an end but no beginning");
return;
goto NamedMDDecl;
}

Cur = Begin;
Expand All @@ -943,6 +943,38 @@ static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) {

Cur = Next;
}

NamedMDDecl:
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
if (!BeginMD) {
if (EndMD != nullptr)
report_fatal_error("Range has an end but no beginning");
return;
}

LLVMNamedMDNodeRef CurMD = BeginMD;
LLVMNamedMDNodeRef 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;
}

LLVMNamedMDNodeRef 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) {
Expand Down Expand Up @@ -1041,7 +1073,7 @@ static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
if (!Begin) {
if (End != nullptr)
report_fatal_error("Range has an end but no beginning");
return;
goto NamedMDClone;
}

Cur = Begin;
Expand Down Expand Up @@ -1073,6 +1105,47 @@ static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {

Cur = Next;
}

NamedMDClone:
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
if (!BeginMD) {
if (EndMD != nullptr)
report_fatal_error("Range has an end but no beginning");
return;
}

LLVMNamedMDNodeRef CurMD = BeginMD;
LLVMNamedMDNodeRef NextMD = nullptr;
while (true) {
size_t NameLen;
const char *Name = LLVMGetNamedMetadataName(CurMD, &NameLen);
LLVMNamedMDNodeRef 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<LLVMValueRef *>(
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;
}

LLVMNamedMDNodeRef PrevMD = LLVMGetPreviousNamedMetadata(NextMD);
if (PrevMD != CurMD)
report_fatal_error("Next.Previous Named MD Node is not Current");

CurMD = NextMD;
}
}

int llvm_echo(void) {
Expand All @@ -1089,18 +1162,6 @@ int llvm_echo(void) {
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)))
Expand All @@ -1115,7 +1176,6 @@ int llvm_echo(void) {
char *Str = LLVMPrintModuleToString(M);
fputs(Str, stdout);

LLVMDisposeModuleFlagsMetadata(ModuleFlags);
LLVMDisposeMessage(Str);
LLVMDisposeModule(Src);
LLVMDisposeModule(M);
Expand Down

0 comments on commit 0a35b76

Please sign in to comment.