[llvm] r223564 - IR: Disallow complicated function-local metadata
Duncan P. N. Exon Smith
dexonsmith at apple.com
Fri Dec 5 17:26:50 PST 2014
Author: dexonsmith
Date: Fri Dec 5 19:26:49 2014
New Revision: 223564
URL: http://llvm.org/viewvc/llvm-project?rev=223564&view=rev
Log:
IR: Disallow complicated function-local metadata
Disallow complex types of function-local metadata. The only valid
function-local metadata is an `MDNode` whose sole argument is a
non-metadata function-local value.
Part of PR21532.
Modified:
llvm/trunk/lib/AsmParser/LLParser.cpp
llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/trunk/lib/IR/Metadata.cpp
llvm/trunk/test/Assembler/functionlocal-metadata.ll
llvm/trunk/test/Feature/metadata.ll
llvm/trunk/test/Transforms/GlobalOpt/metadata.ll
Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=223564&r1=223563&r2=223564&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Fri Dec 5 19:26:49 2014
@@ -4668,7 +4668,11 @@ bool LLParser::ParseMDNodeVector(SmallVe
if (Lex.getKind() == lltok::rbrace)
return false;
+ bool IsLocal = false;
do {
+ if (IsLocal)
+ return TokError("unexpected operand after function-local metadata");
+
// Null is a special case since it is typeless.
if (EatIfPresent(lltok::kw_null)) {
Elts.push_back(nullptr);
@@ -4678,6 +4682,15 @@ bool LLParser::ParseMDNodeVector(SmallVe
Value *V = nullptr;
if (ParseTypeAndValue(V, PFS)) return true;
Elts.push_back(V);
+
+ if (isa<MDNode>(V) && cast<MDNode>(V)->isFunctionLocal())
+ return TokError("unexpected nested function-local metadata");
+ if (!V->getType()->isMetadataTy() && !isa<Constant>(V)) {
+ assert(PFS && "Unexpected function-local metadata without PFS");
+ if (Elts.size() > 1)
+ return TokError("unexpected function-local metadata");
+ IsLocal = true;
+ }
} while (EatIfPresent(lltok::comma));
return false;
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=223564&r1=223563&r2=223564&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Dec 5 19:26:49 2014
@@ -1072,7 +1072,6 @@ std::error_code BitcodeReader::ParseMeta
break;
}
- bool IsFunctionLocal = false;
// Read a record.
Record.clear();
unsigned Code = Stream.readRecord(Entry.ID, Record);
@@ -1100,9 +1099,34 @@ std::error_code BitcodeReader::ParseMeta
}
break;
}
- case bitc::METADATA_FN_NODE:
- IsFunctionLocal = true;
- // fall-through
+ case bitc::METADATA_FN_NODE: {
+ // This is a function-local node.
+ if (Record.size() % 2 == 1)
+ return Error(BitcodeError::InvalidRecord);
+
+ // If this isn't a single-operand node that directly references
+ // non-metadata, we're dropping it. This used to be legal, but there's
+ // no upgrade path.
+ auto dropRecord = [&] {
+ MDValueList.AssignValue(MDNode::get(Context, None), NextMDValueNo++);
+ };
+ if (Record.size() != 2) {
+ dropRecord();
+ break;
+ }
+
+ Type *Ty = getTypeByID(Record[0]);
+ if (Ty->isMetadataTy() || Ty->isVoidTy()) {
+ dropRecord();
+ break;
+ }
+
+ Value *Elts[] = {ValueList.getValueFwdRef(Record[1], Ty)};
+ Value *V = MDNode::getWhenValsUnresolved(Context, Elts,
+ /*IsFunctionLocal*/ true);
+ MDValueList.AssignValue(V, NextMDValueNo++);
+ break;
+ }
case bitc::METADATA_NODE: {
if (Record.size() % 2 == 1)
return Error(BitcodeError::InvalidRecord);
@@ -1120,8 +1144,8 @@ std::error_code BitcodeReader::ParseMeta
else
Elts.push_back(nullptr);
}
- Value *V = MDNode::getWhenValsUnresolved(Context, Elts, IsFunctionLocal);
- IsFunctionLocal = false;
+ Value *V = MDNode::getWhenValsUnresolved(Context, Elts,
+ /*IsFunctionLocal*/ false);
MDValueList.AssignValue(V, NextMDValueNo++);
break;
}
Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=223564&r1=223563&r2=223564&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Fri Dec 5 19:26:49 2014
@@ -185,43 +185,20 @@ static const Function *getFunctionForVal
return nullptr;
}
-#ifndef NDEBUG
-static const Function *assertLocalFunction(const MDNode *N) {
- if (!N->isFunctionLocal()) return nullptr;
-
- // FIXME: This does not handle cyclic function local metadata.
- const Function *F = nullptr, *NewF = nullptr;
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- if (Value *V = N->getOperand(i)) {
- if (MDNode *MD = dyn_cast<MDNode>(V))
- NewF = assertLocalFunction(MD);
- else
- NewF = getFunctionForValue(V);
- }
- if (!F)
- F = NewF;
- else
- assert((NewF == nullptr || F == NewF) &&
- "inconsistent function-local metadata");
- }
- return F;
-}
-#endif
-
// getFunction - If this metadata is function-local and recursively has a
// function-local operand, return the first such operand's parent function.
// Otherwise, return null. getFunction() should not be used for performance-
// critical code because it recursively visits all the MDNode's operands.
const Function *MDNode::getFunction() const {
-#ifndef NDEBUG
- return assertLocalFunction(this);
-#else
- if (!isFunctionLocal()) return nullptr;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- if (const Function *F = getFunctionForValue(getOperand(i)))
- return F;
- return nullptr;
-#endif
+ if (!isFunctionLocal())
+ return nullptr;
+ assert(getNumOperands() == 1 &&
+ "Expected one operand for function-local metadata");
+ assert(getOperand(0) &&
+ "Expected non-null operand for function-local metadata");
+ assert(!getOperand(0)->getType()->isMetadataTy() &&
+ "Expected non-metadata as operand of function-local metadata");
+ return getFunctionForValue(getOperand(0));
}
/// \brief Check if the Value would require a function-local MDNode.
@@ -260,6 +237,14 @@ MDNode *MDNode::getMDNode(LLVMContext &C
break;
}
+ if (isFunctionLocal) {
+ assert(Vals.size() == 1 &&
+ "Expected exactly one operand for function-local metadata");
+ assert(Vals[0] && "Expected non-null operand for function-local metadata");
+ assert(!Vals[0]->getType()->isMetadataTy() &&
+ "Expected non-metadata as operand of function-local metadata");
+ }
+
// Coallocate space for the node and Operands together, then placement new.
GenericMDNode *N =
new (Vals.size()) GenericMDNode(Context, Vals, isFunctionLocal);
@@ -323,6 +308,8 @@ void MDNode::replaceOperand(MDNodeOperan
// Handle this case by implicitly dropping the MDNode reference to null.
// Likewise if the MDNode is function-local but for a different function.
if (To && isFunctionLocalValue(To)) {
+ assert(!To->getType()->isMetadataTy() &&
+ "Expected non-metadata as operand of function-local metadata");
if (!isFunctionLocal())
To = nullptr;
else {
@@ -338,6 +325,14 @@ void MDNode::replaceOperand(MDNodeOperan
if (From == To)
return;
+ // If this MDValue was previously function-local but no longer is, clear
+ // its function-local flag.
+ if (isFunctionLocal() && !(To && isFunctionLocalValue(To))) {
+ assert(getNumOperands() == 1 &&
+ "Expected function-local metadata to have exactly one operand");
+ setValueSubclassData(getSubclassDataFromValue() & ~FunctionLocalBit);
+ }
+
// If this node is already not being uniqued (because one of the operands
// already went to null), then there is nothing else to do here.
if (isNotUniqued()) {
@@ -377,22 +372,6 @@ void MDNode::replaceOperand(MDNodeOperan
N->Hash = Key.Hash;
Store.insert(N);
-
- // If this MDValue was previously function-local but no longer is, clear
- // its function-local flag.
- if (isFunctionLocal() && !isFunctionLocalValue(To)) {
- bool isStillFunctionLocal = false;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- Value *V = getOperand(i);
- if (!V) continue;
- if (isFunctionLocalValue(V)) {
- isStillFunctionLocal = true;
- break;
- }
- }
- if (!isStillFunctionLocal)
- setValueSubclassData(getSubclassDataFromValue() & ~FunctionLocalBit);
- }
}
MDNode *MDNode::concatenate(MDNode *A, MDNode *B) {
Modified: llvm/trunk/test/Assembler/functionlocal-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/functionlocal-metadata.ll?rev=223564&r1=223563&r2=223564&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/functionlocal-metadata.ll (original)
+++ llvm/trunk/test/Assembler/functionlocal-metadata.ll Fri Dec 5 19:26:49 2014
@@ -13,19 +13,17 @@ entry:
; CHECK: call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32* %1}, metadata {{.*}})
call void @llvm.dbg.declare(metadata !{i32 %two}, metadata !{i32 %0}, metadata !{metadata !"0x102"})
; CHECK: call void @llvm.dbg.declare(metadata !{i32 %two}, metadata !{i32 %0}, metadata {{.*}})
- call void @llvm.dbg.declare(metadata !{i32 %0}, metadata !{i32* %1, i32 %0}, metadata !{metadata !"0x102"})
-; CHECK: call void @llvm.dbg.declare(metadata !{i32 %0}, metadata !{i32* %1, i32 %0}, metadata {{.*}})
- call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32 %b, i32 %0}, metadata !{metadata !"0x102"})
-; CHECK: call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32 %b, i32 %0}, metadata {{.*}})
- call void @llvm.dbg.declare(metadata !{i32 %a}, metadata !{i32 %a, metadata !"foo"}, metadata !{metadata !"0x102"})
-; CHECK: call void @llvm.dbg.declare(metadata !{i32 %a}, metadata !{i32 %a, metadata !"foo"}, metadata {{.*}})
- call void @llvm.dbg.declare(metadata !{i32 %b}, metadata !{metadata !0, i32 %two}, metadata !{metadata !"0x102"})
-; CHECK: call void @llvm.dbg.declare(metadata !{i32 %b}, metadata !{metadata ![[ID0:[0-9]+]], i32 %two}, metadata {{.*}})
+ call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32 %b}, metadata !{metadata !"0x102"})
+; CHECK: call void @llvm.dbg.declare(metadata !{i32* %1}, metadata !{i32 %b}, metadata {{.*}})
+ call void @llvm.dbg.declare(metadata !{i32 %a}, metadata !{i32 %a}, metadata !{metadata !"0x102"})
+; CHECK: call void @llvm.dbg.declare(metadata !{i32 %a}, metadata !{i32 %a}, metadata {{.*}})
+ call void @llvm.dbg.declare(metadata !{i32 %b}, metadata !{i32 %two}, metadata !{metadata !"0x102"})
+; CHECK: call void @llvm.dbg.declare(metadata !{i32 %b}, metadata !{i32 %two}, metadata {{.*}})
call void @llvm.dbg.value(metadata !{ i32 %a }, i64 0, metadata !1, metadata !{metadata !"0x102"})
; CHECK: call void @llvm.dbg.value(metadata !{i32 %a}, i64 0, metadata ![[ID1:[0-9]+]], metadata {{.*}})
call void @llvm.dbg.value(metadata !{ i32 %0 }, i64 25, metadata !0, metadata !{metadata !"0x102"})
-; CHECK: call void @llvm.dbg.value(metadata !{i32 %0}, i64 25, metadata ![[ID0]], metadata {{.*}})
+; CHECK: call void @llvm.dbg.value(metadata !{i32 %0}, i64 25, metadata ![[ID0:[0-9]+]], metadata {{.*}})
call void @llvm.dbg.value(metadata !{ i32* %1 }, i64 16, metadata !3, metadata !{metadata !"0x102"})
; CHECK: call void @llvm.dbg.value(metadata !{i32* %1}, i64 16, metadata ![[ID3:[0-9]+]], metadata {{.*}})
call void @llvm.dbg.value(metadata !3, i64 12, metadata !2, metadata !{metadata !"0x102"})
Modified: llvm/trunk/test/Feature/metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/metadata.ll?rev=223564&r1=223563&r2=223564&view=diff
==============================================================================
--- llvm/trunk/test/Feature/metadata.ll (original)
+++ llvm/trunk/test/Feature/metadata.ll Fri Dec 5 19:26:49 2014
@@ -4,7 +4,7 @@
define void @foo(i32 %x) {
call void @llvm.zonk(metadata !1, i64 0, metadata !1)
store i32 0, i32* null, !whatever !0, !whatever_else !{}, !more !{metadata !"hello"}
- store i32 0, i32* null, !whatever !{i32 %x, metadata !"hello", metadata !1, metadata !{}, metadata !2}
+ store i32 0, i32* null, !whatever !{metadata !"hello", metadata !1, metadata !{}, metadata !2}
ret void, !whatever !{i32 %x}
}
Modified: llvm/trunk/test/Transforms/GlobalOpt/metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/metadata.ll?rev=223564&r1=223563&r2=223564&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/metadata.ll (original)
+++ llvm/trunk/test/Transforms/GlobalOpt/metadata.ll Fri Dec 5 19:26:49 2014
@@ -13,14 +13,15 @@ define i32 @main(i32 %argc, i8** %argv)
}
define void @foo(i32 %x) {
- call void @llvm.foo(metadata !{i8*** @G, i32 %x})
-; CHECK: call void @llvm.foo(metadata !{null, i32 %x})
+ call void @llvm.foo(metadata !{i8*** @G})
+; CHECK: call void @llvm.foo(metadata !0)
ret void
}
declare void @llvm.foo(metadata) nounwind readnone
!named = !{!0}
+; CHECK: !named = !{!0}
!0 = metadata !{i8*** @G}
; CHECK: !0 = metadata !{null}
More information about the llvm-commits
mailing list