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;
}
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 ......................................--*/

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
main.c
module.c
metadata.c
object.c
targets.c
)

View File

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

View File

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

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