[CodeView] Use assembler directives for line tables

Adds a new family of .cv_* directives to LLVM's variant of GAS syntax:

- .cv_file: Similar to DWARF .file directives

- .cv_loc: Similar to the DWARF .loc directive, but starts with a
  function id. CodeView line tables are emitted by function instead of
  by compilation unit, so we needed an extra field to communicate this.
  Rather than overloading the .loc direction further, we decided it was
  better to have our own directive.

- .cv_stringtable: Emits the codeview string table at the current
  position. Currently this just contains the filenames as
  null-terminated strings.

- .cv_filechecksums: Emits the file checksum table for all files used
  with .cv_file so far. There is currently no support for emitting
  actual checksums, just filenames.

This moves the line table emission code down into the assembler.  This
is in preparation for implementing the inlined call site line table
format. The inline line table format encoding algorithm requires knowing
the absolute code offsets, so it must run after the assembler has laid
out the code.

David Majnemer collaborated on this patch.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259117 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner
2016-01-28 23:31:52 +00:00
parent eac4c34846
commit 200dc330a0
25 changed files with 1109 additions and 775 deletions
+47 -8
View File
@@ -16,7 +16,22 @@
using namespace llvm;
StringTableBuilder::StringTableBuilder(Kind K) : K(K) {}
StringTableBuilder::StringTableBuilder(Kind K) : K(K) {
// Account for leading bytes in table so that offsets returned from add are
// correct.
switch (K) {
case RAW:
Size = 0;
break;
case MachO:
case ELF:
Size = 1;
break;
case WinCOFF:
Size = 4;
break;
}
}
typedef std::pair<StringRef, size_t> StringPair;
@@ -62,13 +77,32 @@ tailcall:
}
void StringTableBuilder::finalize() {
std::vector<std::pair<StringRef, size_t> *> Strings;
finalizeStringTable(/*Optimize=*/true);
}
void StringTableBuilder::finalizeInOrder() {
finalizeStringTable(/*Optimize=*/false);
}
void StringTableBuilder::finalizeStringTable(bool Optimize) {
typedef std::pair<StringRef, size_t> StringOffsetPair;
std::vector<StringOffsetPair *> Strings;
Strings.reserve(StringIndexMap.size());
for (std::pair<StringRef, size_t> &P : StringIndexMap)
for (StringOffsetPair &P : StringIndexMap)
Strings.push_back(&P);
if (!Strings.empty())
multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
if (!Strings.empty()) {
// If we're optimizing, sort by name. If not, sort by previously assigned
// offset.
if (Optimize) {
multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
} else {
std::sort(Strings.begin(), Strings.end(),
[](const StringOffsetPair *LHS, const StringOffsetPair *RHS) {
return LHS->second < RHS->second;
});
}
}
switch (K) {
case RAW:
@@ -85,17 +119,22 @@ void StringTableBuilder::finalize() {
}
StringRef Previous;
for (std::pair<StringRef, size_t> *P : Strings) {
for (StringOffsetPair *P : Strings) {
StringRef S = P->first;
if (K == WinCOFF)
assert(S.size() > COFF::NameSize && "Short string in COFF string table!");
if (Previous.endswith(S)) {
if (Optimize && Previous.endswith(S)) {
P->second = StringTable.size() - S.size() - (K != RAW);
continue;
}
P->second = StringTable.size();
if (Optimize)
P->second = StringTable.size();
else
assert(P->second == StringTable.size() &&
"different strtab offset after finalization");
StringTable += S;
if (K != RAW)
StringTable += '\x00';