IR: Add assembly/bitcode support for function metadata attachments
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Fri, 24 Apr 2015 22:04:41 +0000 (22:04 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Fri, 24 Apr 2015 22:04:41 +0000 (22:04 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235785 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/Bitcode/Writer/ValueEnumerator.cpp
lib/IR/AsmWriter.cpp
test/Assembler/metadata.ll

index f2a6056d15c7925236525333b4416a5bfb16b010..172f309204845ed09c68040f5aea2e0d865e7a04 100644 (file)
@@ -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
index ea18b58d32f509e159fe82352515298ea9e34c8f..a43a4b06a946723f37addf47a8128c37085cabb3 100644 (file)
@@ -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);
index 5f7a5ea12919a9c83d750175831480a5770b88d7..b6528cbbeccb2ba7df4f44b86d8864d772c6e22d 100644 (file)
@@ -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:
index 52a5d480fddcee4e6da8fee2d668ca55bd364517..b8baabd22d8ad23f8cd35eb46fb278ba5aa0d627 100644 (file)
@@ -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;
 
index 7f576d758bd58d60f4e70cde48d3d38e7328f239..652851f4cc1645ffaffc5af2287cde4be022a89e 100644 (file)
@@ -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()) {
index 299665531f3fec846977bd306e823e230dcacd70..0564513c94ab13167df6431906e8c4c331411519 100644 (file)
@@ -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 {
index b483fc3f4cfc6b26b769668236daee0503d23d2e..21a47ddb73482404ec45139d5876d9d2f0e63030 100644 (file)
@@ -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