forked from OSchip/llvm-project
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. llvm-svn: 235785
This commit is contained in:
parent
327e9bd399
commit
3d4cd756b6
|
@ -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(Instruction &Inst) {
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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::parseTriple() {
|
|||
}
|
||||
|
||||
/// 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::ParseMetadataAttachment() {
|
|||
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::ParseFunctionBody(Function *F) {
|
|||
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:
|
||||
|
|
|
@ -1279,6 +1279,15 @@ static void WriteMetadataAttachment(const Function &F,
|
|||
// 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 &F, ValueEnumerator &VE,
|
|||
// Keep a running idea of what the instruction ID is.
|
||||
unsigned InstID = CstEnd;
|
||||
|
||||
bool NeedsMetadataAttachment = false;
|
||||
bool NeedsMetadataAttachment = F.hasMetadata();
|
||||
|
||||
MDLocation *LastDL = nullptr;
|
||||
|
||||
|
|
|
@ -348,6 +348,11 @@ ValueEnumerator::ValueEnumerator(const Module &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()) {
|
||||
|
|
|
@ -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 Function *F) {
|
|||
writeOperand(F->getPrologueData(), true);
|
||||
}
|
||||
|
||||
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
||||
F->getAllMetadata(MDs);
|
||||
printMetadataAttachments(MDs, " ");
|
||||
|
||||
if (F->isDeclaration()) {
|
||||
Out << '\n';
|
||||
} else {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue