[WebAssembly] Add languages from debug info to producers section

Reviewers: aheejin, dschuff, sbc100

Subscribers: aprantl, jgravelle-google, hiraditya, sunfish

Differential Revision: https://reviews.llvm.org/D56889

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351507 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/WebAssembly/LLVMBuild.txt b/lib/Target/WebAssembly/LLVMBuild.txt
index 055c32b..a5ad42f 100644
--- a/lib/Target/WebAssembly/LLVMBuild.txt
+++ b/lib/Target/WebAssembly/LLVMBuild.txt
@@ -30,5 +30,5 @@
 type = Library
 name = WebAssemblyCodeGen
 parent = WebAssembly
-required_libraries = Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target TransformUtils WebAssemblyAsmPrinter WebAssemblyDesc WebAssemblyInfo
+required_libraries = Analysis AsmPrinter BinaryFormat CodeGen Core MC Scalar SelectionDAG Support Target TransformUtils WebAssemblyAsmPrinter WebAssemblyDesc WebAssemblyInfo
 add_to_library_groups = WebAssembly
diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 6d5647a..4d1c28f 100644
--- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -30,6 +30,7 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCSectionWasm.h"
@@ -148,31 +149,55 @@
     }
   }
 
+  EmitProducerInfo(M);
+}
+
+void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
+  llvm::SmallVector<std::pair<std::string, std::string>, 4> Languages;
+  if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) {
+     llvm::SmallSet<StringRef, 4> SeenLanguages;
+    for (size_t i = 0, e = Debug->getNumOperands(); i < e; ++i) {
+      const auto *CU = cast<DICompileUnit>(Debug->getOperand(i));
+      StringRef Language = dwarf::LanguageString(CU->getSourceLanguage());
+      Language.consume_front("DW_LANG_");
+      if (SeenLanguages.insert(Language).second)
+        Languages.emplace_back(Language.str(), "");
+    }
+  }
+
+  llvm::SmallVector<std::pair<std::string, std::string>, 4> Tools;
   if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
     llvm::SmallSet<StringRef, 4> SeenTools;
-    llvm::SmallVector<std::pair<StringRef, StringRef>, 4> Tools;
     for (size_t i = 0, e = Ident->getNumOperands(); i < e; ++i) {
       const auto *S = cast<MDString>(Ident->getOperand(i)->getOperand(0));
       std::pair<StringRef, StringRef> Field = S->getString().split("version");
       StringRef Name = Field.first.trim();
       StringRef Version = Field.second.trim();
-      if (!SeenTools.insert(Name).second)
-        continue;
-      Tools.emplace_back(Name, Version);
+      if (SeenTools.insert(Name).second)
+        Tools.emplace_back(Name.str(), Version.str());
     }
+  }
+
+  int FieldCount = int(!Languages.empty()) + int(!Tools.empty());
+  if (FieldCount != 0) {
     MCSectionWasm *Producers = OutContext.getWasmSection(
         ".custom_section.producers", SectionKind::getMetadata());
     OutStreamer->PushSection();
     OutStreamer->SwitchSection(Producers);
-    OutStreamer->EmitULEB128IntValue(1);
-    OutStreamer->EmitULEB128IntValue(strlen("processed-by"));
-    OutStreamer->EmitBytes("processed-by");
-    OutStreamer->EmitULEB128IntValue(Tools.size());
-    for (auto &Tool : Tools) {
-      OutStreamer->EmitULEB128IntValue(Tool.first.size());
-      OutStreamer->EmitBytes(Tool.first);
-      OutStreamer->EmitULEB128IntValue(Tool.second.size());
-      OutStreamer->EmitBytes(Tool.second);
+    OutStreamer->EmitULEB128IntValue(FieldCount);
+    for (auto &Producers : {std::make_pair("language", &Languages),
+            std::make_pair("processed-by", &Tools)}) {
+      if (Producers.second->empty())
+        continue;
+      OutStreamer->EmitULEB128IntValue(strlen(Producers.first));
+      OutStreamer->EmitBytes(Producers.first);
+      OutStreamer->EmitULEB128IntValue(Producers.second->size());
+      for (auto &Producer : *Producers.second) {
+        OutStreamer->EmitULEB128IntValue(Producer.first.size());
+        OutStreamer->EmitBytes(Producer.first);
+        OutStreamer->EmitULEB128IntValue(Producer.second.size());
+        OutStreamer->EmitBytes(Producer.second);
+      }
     }
     OutStreamer->PopSection();
   }
diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
index f6cb561..5f6ef4d 100644
--- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -59,6 +59,7 @@
   //===------------------------------------------------------------------===//
 
   void EmitEndOfAsmFile(Module &M) override;
+  void EmitProducerInfo(Module &M);
   void EmitJumpTableInfo() override;
   void EmitConstantPool() override;
   void EmitFunctionBodyStart() override;
diff --git a/test/CodeGen/WebAssembly/custom-sections.ll b/test/CodeGen/WebAssembly/custom-sections.ll
index e92c0f8..78fe3c5 100644
--- a/test/CodeGen/WebAssembly/custom-sections.ll
+++ b/test/CodeGen/WebAssembly/custom-sections.ll
@@ -13,6 +13,13 @@
 !llvm.ident = !{!3}
 !3 = !{!"clang version 123"}
 
+!llvm.module.flags = !{!4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+
+!llvm.dbg.cu = !{!5}
+!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !6)
+!6 = !DIFile(filename: "test", directory: "testdir")
+
 ; CHECK:      .section	.custom_section.red,"",@
 ; CHECK-NEXT: .ascii	"foo"
 
@@ -23,7 +30,13 @@
 ; CHECK-NEXT: .ascii	"qux"
 
 ; CHECK:      .section	.custom_section.producers,"",@
+; CHECK-NEXT: .int8	2
+; CHECK-NEXT: .int8	8
+; CHECK-NEXT: .ascii	"language"
 ; CHECK-NEXT: .int8	1
+; CHECK-NEXT: .int8	3
+; CHECK-NEXT: .ascii	"C99"
+; CHECK-NEXT: .int8	0
 ; CHECK-NEXT: .int8	12
 ; CHECK-NEXT: .ascii	"processed-by"
 ; CHECK-NEXT: .int8	1
diff --git a/test/MC/WebAssembly/debug-info.ll b/test/MC/WebAssembly/debug-info.ll
index 06c3949..7dca33a 100644
--- a/test/MC/WebAssembly/debug-info.ll
+++ b/test/MC/WebAssembly/debug-info.ll
@@ -126,7 +126,7 @@
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
-; CHECK-NEXT:    Size: 62
+; CHECK-NEXT:    Size: 77
 ; CHECK-NEXT:    Offset: 1021
 ; CHECK-NEXT:    Name: producers
 ; CHECK-NEXT:  }