diff options
author | Bjorn Steinbrink <bsteinbr@gmail.com> | 2015-01-28 16:35:59 +0000 |
---|---|---|
committer | Bjorn Steinbrink <bsteinbr@gmail.com> | 2015-01-28 16:35:59 +0000 |
commit | a09ac0085d33695754f04a66d5e1991b3a96b724 (patch) | |
tree | 66d726a4cc166b832e6702abb60588f205c5a5d2 | |
parent | e13a9624c282e30d0ec0290166cc16dc1892918a (diff) | |
download | bcm5719-llvm-a09ac0085d33695754f04a66d5e1991b3a96b724.tar.gz bcm5719-llvm-a09ac0085d33695754f04a66d5e1991b3a96b724.zip |
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: 227319
-rw-r--r-- | llvm/lib/IR/Core.cpp | 22 | ||||
-rw-r--r-- | llvm/test/Bindings/llvm-c/add_named_metadata_operand.ll | 2 | ||||
-rw-r--r-- | llvm/test/Bindings/llvm-c/set_metadata.ll | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-c-test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-c-test/llvm-c-test.h | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-c-test/main.c | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-c-test/metadata.c | 39 |
7 files changed, 70 insertions, 4 deletions
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index a25c4d66d3b..753d9c229ec 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -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); } @@ -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 ......................................--*/ diff --git a/llvm/test/Bindings/llvm-c/add_named_metadata_operand.ll b/llvm/test/Bindings/llvm-c/add_named_metadata_operand.ll new file mode 100644 index 00000000000..fcc833d6af0 --- /dev/null +++ b/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 diff --git a/llvm/test/Bindings/llvm-c/set_metadata.ll b/llvm/test/Bindings/llvm-c/set_metadata.ll new file mode 100644 index 00000000000..0a65b8c47de --- /dev/null +++ b/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 diff --git a/llvm/tools/llvm-c-test/CMakeLists.txt b/llvm/tools/llvm-c-test/CMakeLists.txt index baf970a0278..f22dffb30e8 100644 --- a/llvm/tools/llvm-c-test/CMakeLists.txt +++ b/llvm/tools/llvm-c-test/CMakeLists.txt @@ -41,6 +41,7 @@ add_llvm_tool(llvm-c-test include-all.c main.c module.c + metadata.c object.c targets.c ) diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h index 0a25aa60619..1b4976ae142 100644 --- a/llvm/tools/llvm-c-test/llvm-c-test.h +++ b/llvm/tools/llvm-c-test/llvm-c-test.h @@ -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); diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c index 72f8b042899..59cc749fb15 100644 --- a/llvm/tools/llvm-c-test/main.c +++ b/llvm/tools/llvm-c-test/main.c @@ -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(); } diff --git a/llvm/tools/llvm-c-test/metadata.c b/llvm/tools/llvm-c-test/metadata.c new file mode 100644 index 00000000000..ee5b33c9122 --- /dev/null +++ b/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; +} |