dwarfgen: Add support for generating the debug_str_offsets section, take 2

This recommits r337910 after fixing an "ambiguous call to addAttribute"
error with some compilers (gcc circa 4.9 and MSVC). It seems that these
compilers will consider a "false -> pointer" conversion during overload
resolution. This creates ambiguity because one I added an overload which
takes a MCExpr * as an argument.

I fix this by making the new overload take MCExpr&, which avoids the
conversion. It also documents the fact that we expect a valid MCExpr
object.

Original commit message follows:

The motivation for this is D49493, where we'd like to test details of
debug_str_offsets behavior which is difficult to trigger from a
traditional test.

This adds the plubming necessary for dwarfgen to generate this section.
The more interesting changes are:
- I've moved emitStringOffsetsTableHeader function from DwarfFile to
  DwarfStringPool, so I can generate the section header more easily from
  the unit test.
- added a new addAttribute overload taking an MCExpr*. This is used to
  generate the DW_AT_str_offsets_base, which links a compile unit to the
  offset table.

I've also added a basic test for reading and writing DW_form_strx forms.

Reviewers: dblaikie, JDevlieghere, probinson

Subscribers: llvm-commits, aprantl

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

llvm-svn: 337933
diff --git a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
index b93b0cc..7f9f03e 100644
--- a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
@@ -54,16 +54,36 @@
 }
 
 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
+                                 const MCExpr &Expr) {
+  auto &DG = CU->getGenerator();
+  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+                DIEExpr(&Expr));
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
                                  StringRef String) {
   auto &DG = CU->getGenerator();
-  if (Form == DW_FORM_string) {
+  switch (Form) {
+  case DW_FORM_string:
     Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
                   new (DG.getAllocator())
                       DIEInlineString(String, DG.getAllocator()));
-  } else {
+    break;
+
+  case DW_FORM_strp:
+  case DW_FORM_GNU_str_index:
+  case DW_FORM_strx:
+  case DW_FORM_strx1:
+  case DW_FORM_strx2:
+  case DW_FORM_strx3:
+  case DW_FORM_strx4:
     Die->addValue(
         DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
         DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
+    break;
+
+  default:
+    llvm_unreachable("Unhandled form!");
   }
 }
 
@@ -427,6 +447,7 @@
   Asm->setDwarfVersion(Version);
 
   StringPool = llvm::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
+  StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");
 
   return Error::success();
 }
@@ -448,7 +469,12 @@
     CU->setLength(CUOffset - 4);
   }
   Abbreviations.Emit(Asm.get(), MOFI->getDwarfAbbrevSection());
-  StringPool->emit(*Asm, MOFI->getDwarfStrSection());
+
+  StringPool->emitStringOffsetsTableHeader(*Asm, MOFI->getDwarfStrOffSection(),
+                                           StringOffsetsStartSym);
+  StringPool->emit(*Asm, MOFI->getDwarfStrSection(),
+                   MOFI->getDwarfStrOffSection());
+
   MS->SwitchSection(MOFI->getDwarfInfoSection());
   for (auto &CU : CompileUnits) {
     uint16_t Version = CU->getVersion();