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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227319 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bjorn Steinbrink 2015-01-28 16:35:59 +00:00
parent 9c49a6d449
commit 920382c5aa
7 changed files with 70 additions and 4 deletions

View File

@ -563,9 +563,23 @@ LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) {
return nullptr; return nullptr;
} }
void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) { // MetadataAsValue uses a canonical format which strips the actual MDNode for
MDNode *N = // MDNode with just a single constant value, storing just a ConstantAsMetadata
MD ? cast<MDNode>(unwrap<MetadataAsValue>(MD)->getMetadata()) : nullptr; // 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); unwrap<Instruction>(Inst)->setMetadata(KindID, N);
} }
@ -795,7 +809,7 @@ void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char* name,
return; return;
if (!Val) if (!Val)
return; return;
N->addOperand(cast<MDNode>(unwrap<MetadataAsValue>(Val)->getMetadata())); N->addOperand(extractMDNode(unwrap<MetadataAsValue>(Val)));
} }
/*--.. Operations on scalar constants ......................................--*/ /*--.. Operations on scalar constants ......................................--*/

View File

@ -0,0 +1,2 @@
; RUN: llvm-c-test --add-named-metadata-operand < /dev/null
; This used to trigger an assertion

View File

@ -0,0 +1,2 @@
; RUN: llvm-c-test --set-metadata < /dev/null
; This used to trigger an assertion

View File

@ -41,6 +41,7 @@ add_llvm_tool(llvm-c-test
include-all.c include-all.c
main.c main.c
module.c module.c
metadata.c
object.c object.c
targets.c targets.c
) )

View File

@ -27,6 +27,10 @@ int calc(void);
// disassemble.c // disassemble.c
int disassemble(void); int disassemble(void);
// metadata.c
int add_named_metadata_operand(void);
int set_metadata(void);
// object.c // object.c
int object_list_sections(void); int object_list_sections(void);
int object_list_symbols(void); int object_list_symbols(void);

View File

@ -65,6 +65,10 @@ int main(int argc, char **argv) {
return disassemble(); return disassemble();
} else if (argc == 2 && !strcmp(argv[1], "--calc")) { } else if (argc == 2 && !strcmp(argv[1], "--calc")) {
return 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 { } else {
print_usage(); print_usage();
} }

View File

@ -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;
}