Skip to content

Commit

Permalink
Merging r227319:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r227319 | bsteinbr | 2015-01-28 08:35:59 -0800 (Wed, 28 Jan 2015) | 10 lines

Fix LLVMSetMetadata and LLVMAddNamedMetadataOperand for single value MDNodes

Summary:
MetadataAsValue uses a canonical format that strips the MDNode if it
contains only a single constant value. This triggers an assertion when
trying to cast the value to a MDNode.

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D7165
------------------------------------------------------------------------

llvm-svn: 227475
  • Loading branch information
zmodem committed Jan 29, 2015
1 parent 81f37c0 commit ac43b52
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 4 deletions.
22 changes: 18 additions & 4 deletions llvm/lib/IR/Core.cpp
Expand Up @@ -563,9 +563,23 @@ LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) {
return nullptr;
}

void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) {
MDNode *N =
MD ? cast<MDNode>(unwrap<MetadataAsValue>(MD)->getMetadata()) : nullptr;
// MetadataAsValue uses a canonical format which strips the actual MDNode for
// MDNode with just a single constant value, storing just a ConstantAsMetadata
// This undoes this canonicalization, reconstructing the MDNode.
static MDNode *extractMDNode(MetadataAsValue *MAV) {
Metadata *MD = MAV->getMetadata();
assert((isa<MDNode>(MD) || isa<ConstantAsMetadata>(MD)) &&
"Expected a metadata node or a canonicalized constant");

if (MDNode *N = dyn_cast<MDNode>(MD))
return N;

return MDNode::get(MAV->getContext(), MD);
}

void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef Val) {
MDNode *N = Val ? extractMDNode(unwrap<MetadataAsValue>(Val)) : nullptr;

unwrap<Instruction>(Inst)->setMetadata(KindID, N);
}

Expand Down Expand Up @@ -795,7 +809,7 @@ void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char* name,
return;
if (!Val)
return;
N->addOperand(cast<MDNode>(unwrap<MetadataAsValue>(Val)->getMetadata()));
N->addOperand(extractMDNode(unwrap<MetadataAsValue>(Val)));
}

/*--.. Operations on scalar constants ......................................--*/
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/Bindings/llvm-c/add_named_metadata_operand.ll
@@ -0,0 +1,2 @@
; RUN: llvm-c-test --add-named-metadata-operand < /dev/null
; This used to trigger an assertion
2 changes: 2 additions & 0 deletions llvm/test/Bindings/llvm-c/set_metadata.ll
@@ -0,0 +1,2 @@
; RUN: llvm-c-test --set-metadata < /dev/null
; This used to trigger an assertion
1 change: 1 addition & 0 deletions llvm/tools/llvm-c-test/CMakeLists.txt
Expand Up @@ -41,6 +41,7 @@ add_llvm_tool(llvm-c-test
include-all.c
main.c
module.c
metadata.c
object.c
targets.c
)
Expand Down
4 changes: 4 additions & 0 deletions llvm/tools/llvm-c-test/llvm-c-test.h
Expand Up @@ -27,6 +27,10 @@ int calc(void);
// disassemble.c
int disassemble(void);

// metadata.c
int add_named_metadata_operand(void);
int set_metadata(void);

// object.c
int object_list_sections(void);
int object_list_symbols(void);
Expand Down
4 changes: 4 additions & 0 deletions llvm/tools/llvm-c-test/main.c
Expand Up @@ -65,6 +65,10 @@ int main(int argc, char **argv) {
return disassemble();
} else if (argc == 2 && !strcmp(argv[1], "--calc")) {
return calc();
} else if (argc == 2 && !strcmp(argv[1], "--add-named-metadata-operand")) {
return add_named_metadata_operand();
} else if (argc == 2 && !strcmp(argv[1], "--set-metadata")) {
return set_metadata();
} else {
print_usage();
}
Expand Down
39 changes: 39 additions & 0 deletions llvm/tools/llvm-c-test/metadata.c
@@ -0,0 +1,39 @@
/*===-- object.c - tool for testing libLLVM and llvm-c API ----------------===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This file implements the --add-named-metadata-operand and --set-metadata *|
|* commands in llvm-c-test. *|
|* *|
\*===----------------------------------------------------------------------===*/

#include "llvm-c-test.h"
#include "llvm-c/Core.h"

int add_named_metadata_operand(void) {
LLVMModuleRef m = LLVMModuleCreateWithName("Mod");
LLVMValueRef values[] = { LLVMConstInt(LLVMInt32Type(), 0, 0) };

// This used to trigger an assertion
LLVMAddNamedMetadataOperand(m, "name", LLVMMDNode(values, 1));

return 0;
}

int set_metadata(void) {
LLVMBuilderRef b = LLVMCreateBuilder();
LLVMValueRef values[] = { LLVMConstInt(LLVMInt32Type(), 0, 0) };

// This used to trigger an assertion
LLVMSetMetadata(
LLVMBuildRetVoid(b),
LLVMGetMDKindID("kind", 4),
LLVMMDNode(values, 1));

return 0;
}

0 comments on commit ac43b52

Please sign in to comment.