[llvm] r235785 - IR: Add assembly/bitcode support for function metadata attachments
Duncan P. N. Exon Smith
dexonsmith at apple.com
Fri Apr 24 15:04:42 PDT 2015
Author: dexonsmith
Date: Fri Apr 24 17:04:41 2015
New Revision: 235785
URL: http://llvm.org/viewvc/llvm-project?rev=235785&view=rev
Log:
IR: Add assembly/bitcode support for function metadata attachments
Add serialization support for function metadata attachments (added in
r235783). The syntax is:
define @foo() !attach !0 {
Metadata attachments are only allowed on functions with bodies. Since
they come before the `{`, they're not really part of the body; since
they require a body, they're not really part of the header. In
`LLParser` I gave them a separate function called from `ParseDefine()`,
`ParseOptionalFunctionMetadata()`.
In bitcode, I'm using the same `METADATA_ATTACHMENT` record used by
instructions. Instruction metadata attachments are included in a
special "attachment" block at the end of a `Function`. The attachment
records are laid out like this:
InstID (KindID MetadataID)+
Note that these records always have an odd number of fields. The new
code takes advantage of this to recognize function attachments (which
don't need an instruction ID):
(KindID MetadataID)+
This means we can use the same attachment block already used for
instructions.
This is part of PR23340.
Modified:
llvm/trunk/lib/AsmParser/LLParser.cpp
llvm/trunk/lib/AsmParser/LLParser.h
llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
llvm/trunk/lib/IR/AsmWriter.cpp
llvm/trunk/test/Assembler/metadata.ll
Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Fri Apr 24 17:04:41 2015
@@ -360,13 +360,14 @@ bool LLParser::ParseDeclare() {
}
/// toplevelentity
-/// ::= 'define' FunctionHeader '{' ...
+/// ::= 'define' FunctionHeader (!dbg !56)* '{' ...
bool LLParser::ParseDefine() {
assert(Lex.getKind() == lltok::kw_define);
Lex.Lex();
Function *F;
return ParseFunctionHeader(F, true) ||
+ ParseOptionalFunctionMetadata(*F) ||
ParseFunctionBody(*F);
}
@@ -1523,6 +1524,20 @@ bool LLParser::ParseInstructionMetadata(
return false;
}
+/// ParseOptionalFunctionMetadata
+/// ::= (!dbg !57)*
+bool LLParser::ParseOptionalFunctionMetadata(Function &F) {
+ while (Lex.getKind() == lltok::MetadataVar) {
+ unsigned MDK;
+ MDNode *N;
+ if (ParseMetadataAttachment(MDK, N))
+ return true;
+
+ F.setMetadata(MDK, N);
+ }
+ return false;
+}
+
/// ParseOptionalAlignment
/// ::= /* empty */
/// ::= 'align' 4
Modified: llvm/trunk/lib/AsmParser/LLParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.h (original)
+++ llvm/trunk/lib/AsmParser/LLParser.h Fri Apr 24 17:04:41 2015
@@ -394,6 +394,7 @@ namespace llvm {
bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &MDs);
bool ParseMetadataAttachment(unsigned &Kind, MDNode *&MD);
bool ParseInstructionMetadata(Instruction &Inst);
+ bool ParseOptionalFunctionMetadata(Function &F);
template <class FieldTy>
bool ParseMDField(LocTy Loc, StringRef Name, FieldTy &Result);
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Apr 24 17:04:41 2015
@@ -370,7 +370,7 @@ private:
std::error_code GlobalCleanup();
std::error_code ResolveGlobalAndAliasInits();
std::error_code ParseMetadata();
- std::error_code ParseMetadataAttachment();
+ std::error_code ParseMetadataAttachment(Function &F);
ErrorOr<std::string> parseModuleTriple();
std::error_code ParseUseLists();
std::error_code InitStream();
@@ -3215,7 +3215,7 @@ ErrorOr<std::string> BitcodeReader::pars
}
/// ParseMetadataAttachment - Parse metadata attachments.
-std::error_code BitcodeReader::ParseMetadataAttachment() {
+std::error_code BitcodeReader::ParseMetadataAttachment(Function &F) {
if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
return Error("Invalid record");
@@ -3241,8 +3241,21 @@ std::error_code BitcodeReader::ParseMeta
break;
case bitc::METADATA_ATTACHMENT: {
unsigned RecordLength = Record.size();
- if (Record.empty() || (RecordLength - 1) % 2 == 1)
+ if (Record.empty())
return Error("Invalid record");
+ if (RecordLength % 2 == 0) {
+ // A function attachment.
+ for (unsigned I = 0; I != RecordLength; I += 2) {
+ auto K = MDKindMap.find(Record[I]);
+ if (K == MDKindMap.end())
+ return Error("Invalid ID");
+ Metadata *MD = MDValueList.getValueFwdRef(Record[I + 1]);
+ F.setMetadata(K->second, cast<MDNode>(MD));
+ }
+ continue;
+ }
+
+ // An instruction attachment.
Instruction *Inst = InstructionList[Record[0]];
for (unsigned i = 1; i != RecordLength; i = i+2) {
unsigned Kind = Record[i];
@@ -3319,7 +3332,7 @@ std::error_code BitcodeReader::ParseFunc
return EC;
break;
case bitc::METADATA_ATTACHMENT_ID:
- if (std::error_code EC = ParseMetadataAttachment())
+ if (std::error_code EC = ParseMetadataAttachment(*F))
return EC;
break;
case bitc::METADATA_BLOCK_ID:
Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Fri Apr 24 17:04:41 2015
@@ -1279,6 +1279,15 @@ static void WriteMetadataAttachment(cons
// Write metadata attachments
// METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ F.getAllMetadata(MDs);
+ if (!MDs.empty()) {
+ for (const auto &I : MDs) {
+ Record.push_back(I.first);
+ Record.push_back(VE.getMetadataID(I.second));
+ }
+ Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
+ Record.clear();
+ }
for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
@@ -2091,7 +2100,7 @@ static void WriteFunction(const Function
// Keep a running idea of what the instruction ID is.
unsigned InstID = CstEnd;
- bool NeedsMetadataAttachment = false;
+ bool NeedsMetadataAttachment = F.hasMetadata();
MDLocation *LastDL = nullptr;
Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Fri Apr 24 17:04:41 2015
@@ -348,6 +348,11 @@ ValueEnumerator::ValueEnumerator(const M
for (const Argument &A : F.args())
EnumerateType(A.getType());
+ // Enumerate metadata attached to this function.
+ F.getAllMetadata(MDs);
+ for (const auto &I : MDs)
+ EnumerateMetadata(I.second);
+
for (const BasicBlock &BB : F)
for (const Instruction &I : BB) {
for (const Use &Op : I.operands()) {
Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Fri Apr 24 17:04:41 2015
@@ -776,12 +776,12 @@ void SlotTracker::processFunction() {
if (!BB.hasName())
CreateFunctionSlot(&BB);
+ processFunctionMetadata(*TheFunction);
+
for (auto &I : BB) {
if (!I.getType()->isVoidTy() && !I.hasName())
CreateFunctionSlot(&I);
- processInstructionMetadata(I);
-
// We allow direct calls to any llvm.foo function here, because the
// target may not be linked into the optimizer.
if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
@@ -804,9 +804,15 @@ void SlotTracker::processFunction() {
}
void SlotTracker::processFunctionMetadata(const Function &F) {
- for (auto &BB : F)
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ for (auto &BB : F) {
+ F.getAllMetadata(MDs);
+ for (auto &MD : MDs)
+ CreateMetadataSlot(MD.second);
+
for (auto &I : BB)
processInstructionMetadata(I);
+ }
}
void SlotTracker::processInstructionMetadata(const Instruction &I) {
@@ -2541,6 +2547,10 @@ void AssemblyWriter::printFunction(const
writeOperand(F->getPrologueData(), true);
}
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ F->getAllMetadata(MDs);
+ printMetadataAttachments(MDs, " ");
+
if (F->isDeclaration()) {
Out << '\n';
} else {
Modified: llvm/trunk/test/Assembler/metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/metadata.ll?rev=235785&r1=235784&r2=235785&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/metadata.ll (original)
+++ llvm/trunk/test/Assembler/metadata.ll Fri Apr 24 17:04:41 2015
@@ -11,8 +11,22 @@ define void @test() {
ret void, !foo !0, !bar !1
}
+; CHECK: define void @test2() !foo !2 !baz !3
+define void @test2() !foo !2 !baz !3 {
+ unreachable
+}
+
+; CHECK: define void @test3() !bar !3
+; CHECK: unreachable, !bar !4
+define void @test3() !bar !3 {
+ unreachable, !bar !4
+}
+
!0 = !MDLocation(line: 662302, column: 26, scope: !1)
!1 = !MDSubprogram(name: "foo")
+!2 = distinct !{}
+!3 = distinct !{}
+!4 = distinct !{}
declare void @llvm.dbg.func.start(metadata) nounwind readnone
More information about the llvm-commits
mailing list