Skip to content

Commit

Permalink
[codeview] Emit S_BUILDINFO and LF_BUILDINFO with cwd and source file
Browse files Browse the repository at this point in the history
Summary: We can fill in the command line and compiler path later if we want.

Reviewers: zturner

Subscribers: hiraditya, llvm-commits

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

llvm-svn: 344393
  • Loading branch information
rnk committed Oct 12, 2018
1 parent 6c17e80 commit 810687c
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 1 deletion.
12 changes: 11 additions & 1 deletion llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
Expand Up @@ -655,7 +655,17 @@ class BuildInfoRecord : public TypeRecord {

ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }

SmallVector<TypeIndex, 4> ArgIndices;
/// Indices of known build info arguments.
enum BuildInfoArg {
CurrentDirectory, //< Absolute CWD path
BuildTool, //< Absolute compiler path
SourceFile, //< Path to main source file, relative or absolute
TypeServerPDB, //< Absoulte path of type server PDB (/Fd)
CommandLine, //< Full canonical command line (maybe -cc1)
MaxArgs
};

SmallVector<TypeIndex, MaxArgs> ArgIndices;
};

// LF_VFTABLE
Expand Down
48 changes: 48 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
Expand Up @@ -561,6 +561,11 @@ void CodeViewDebug::endModule() {
OS.AddComment("String table");
OS.EmitCVStringTableDirective();

// Emit S_BUILDINFO, which points to LF_BUILDINFO. Put this in its own symbol
// subsection in the generic .debug$S section at the end. There is no
// particular reason for this ordering other than to match MSVC.
emitBuildInfo();

// Emit type information and hashes last, so that any types we translate while
// emitting function info are included.
emitTypeInformation();
Expand Down Expand Up @@ -772,6 +777,49 @@ void CodeViewDebug::emitCompilerInformation() {
OS.EmitLabel(CompilerEnd);
}

static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable,
StringRef S) {
StringIdRecord SIR(TypeIndex(0x0), S);
return TypeTable.writeLeafType(SIR);
}

void CodeViewDebug::emitBuildInfo() {
// First, make LF_BUILDINFO. It's a sequence of strings with various bits of
// build info. The known prefix is:
// - Absolute path of current directory
// - Compiler path
// - Main source file path, relative to CWD or absolute
// - Type server PDB file
// - Canonical compiler command line
// If frontend and backend compilation are separated (think llc or LTO), it's
// not clear if the compiler path should refer to the executable for the
// frontend or the backend. Leave it blank for now.
TypeIndex BuildInfoArgs[BuildInfoRecord::MaxArgs] = {};
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs.
const auto *CU = cast<DICompileUnit>(Node);
const DIFile *MainSourceFile = CU->getFile();
BuildInfoArgs[BuildInfoRecord::CurrentDirectory] =
getStringIdTypeIdx(TypeTable, MainSourceFile->getDirectory());
BuildInfoArgs[BuildInfoRecord::SourceFile] =
getStringIdTypeIdx(TypeTable, MainSourceFile->getFilename());
// FIXME: Path to compiler and command line. PDB is intentionally blank unless
// we implement /Zi type servers.
BuildInfoRecord BIR(BuildInfoArgs);
TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);

// Make a new .debug$S subsection for the S_BUILDINFO record, which points
// from the module symbols into the type stream.
MCSymbol *BuildInfoEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
OS.AddComment("Record length");
OS.EmitIntValue(6, 2);
OS.AddComment("Record kind: S_BUILDINFO");
OS.EmitIntValue(unsigned(SymbolKind::S_BUILDINFO), 2);
OS.AddComment("LF_BUILDINFO index");
OS.EmitIntValue(BuildInfoIndex.getIndex(), 4);
endCVSubsection(BuildInfoEnd);
}

void CodeViewDebug::emitInlineeLinesSubsection() {
if (InlinedSubprograms.empty())
return;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
Expand Up @@ -272,6 +272,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {

void emitCompilerInformation();

void emitBuildInfo();

void emitInlineeLinesSubsection();

void emitDebugInfoForThunk(const Function *GV,
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/DebugInfo/COFF/build-info.ll
@@ -0,0 +1,39 @@
; RUN: llc -filetype=obj -mtriple i686-pc-windows-msvc %s -o %t.o
; RUN: llvm-pdbutil dump %t.o -symbols -types | FileCheck %s

; CHECK: [[INFO_IDX:0x[^ ]*]] | LF_BUILDINFO
; CHECK-NEXT: 0x{{.*}}: `D:\src\scopes\clang`
; CHECK-NEXT: <no type>: ``
; CHECK-NEXT: 0x{{.*}}: `D:\src\scopes\foo.cpp`
; CHECK-NEXT: <no type>: ``
; CHECK-NEXT: <no type>: ``

; CHECK: {{.*}} | S_BUILDINFO [size = 8] BuildId = `[[INFO_IDX]]`

; ModuleID = 'D:\src\scopes\foo.cpp'
source_filename = "D:\5Csrc\5Cscopes\5Cfoo.cpp"
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc19.0.23918"

define i32 @"?foo@@YAHXZ"() !dbg !10 {
entry:
ret i32 42, !dbg !14
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!7, !8}
!llvm.ident = !{!9}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
; One .debug$S section should contain an S_COMPILE3 record that identifies the
; source language and the version of the compiler based on the DICompileUnit.
!1 = !DIFile(filename: "D:\5Csrc\5Cscopes\5Cfoo.cpp", directory: "D:\5Csrc\5Cscopes\5Cclang")
!2 = !{}
!7 = !{i32 2, !"CodeView", i32 1}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{!"clang version 4.0.0 "}
!10 = distinct !DISubprogram(name: "foo", linkageName: "\01?foo@@YAHXZ", scope: !1, file: !1, line: 1, type: !11, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!11 = !DISubroutineType(types: !12)
!12 = !{!13}
!13 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!14 = !DILocation(line: 2, scope: !10)

0 comments on commit 810687c

Please sign in to comment.