Reland r200340 - 'Add line table debug info to COFF files when using a win32 triple'
authorTimur Iskhodzhanov <timurrrr@google.com>
Thu, 30 Jan 2014 01:39:17 +0000 (01:39 +0000)
committerTimur Iskhodzhanov <timurrrr@google.com>
Thu, 30 Jan 2014 01:39:17 +0000 (01:39 +0000)
This incorporates a couple of fixes reviewed at http://llvm-reviews.chandlerc.com/D2651

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

40 files changed:
include/llvm/Support/DebugLoc.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/CMakeLists.txt
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp [new file with mode: 0644]
lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h [new file with mode: 0644]
lib/IR/DebugLoc.cpp
lib/MC/MCObjectFileInfo.cpp
test/DebugInfo/2010-03-24-MemberFn.ll
test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll
test/DebugInfo/2010-04-19-FramePtr.ll
test/DebugInfo/2010-05-10-MultipleCU.ll
test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll
test/DebugInfo/COFF/asm.ll [new file with mode: 0644]
test/DebugInfo/COFF/multifile.ll [new file with mode: 0644]
test/DebugInfo/COFF/multifunction.ll [new file with mode: 0644]
test/DebugInfo/COFF/simple.ll [new file with mode: 0644]
test/DebugInfo/X86/coff_debug_info_type.ll [new file with mode: 0644]
test/DebugInfo/X86/coff_relative_names.ll
test/DebugInfo/X86/dbg-byval-parameter.ll
test/DebugInfo/array.ll
test/DebugInfo/cu-ranges.ll
test/DebugInfo/debug-info-qualifiers.ll
test/DebugInfo/dwarf-public-names.ll
test/DebugInfo/enum.ll
test/DebugInfo/global.ll
test/DebugInfo/inlined-arguments.ll
test/DebugInfo/inlined-vars.ll
test/DebugInfo/member-order.ll
test/DebugInfo/member-pointers.ll
test/DebugInfo/namespace.ll
test/DebugInfo/template-recursive-void.ll
test/DebugInfo/tu-composite.ll
test/DebugInfo/tu-member-pointer.ll
test/DebugInfo/two-cus-from-same-file.ll
test/DebugInfo/version.ll
test/Linker/type-unique-simple-a.ll
test/Linker/type-unique-simple2-a.ll
test/Linker/type-unique-simple2.ll
test/lit.cfg

index f3887293ef6b373eb64bbe1338fd1c5e1d98915a..f6cd19a61ecfc5f0552719ffbd66e17360dd620f 100644 (file)
@@ -89,6 +89,12 @@ namespace llvm {
     void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
                               const LLVMContext &Ctx) const;
 
+    /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid.
+    MDNode *getScopeNode(const LLVMContext &Ctx) const;
+
+    // getFnDebugLoc - Walk up the scope chain of given debug loc and find line
+    // number info for the function.
+    DebugLoc getFnDebugLoc(const LLVMContext &Ctx);
 
     /// getAsMDNode - This method converts the compressed DebugLoc node into a
     /// DILocation compatible MDNode.
index fbee17f563a2c90a34de942a8bce795cb3859638..c5726633d2a4fd03e978a57f7737cb69a26226d8 100644 (file)
 #include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
 #include "llvm/Transforms/Utils/GlobalStatus.h"
+#include "WinCodeViewLineTables.h"
 using namespace llvm;
 
 static const char *const DWARFGroupName = "DWARF Emission";
-static const char *const DbgTimerName = "DWARF Debug Writer";
+static const char *const DbgTimerName = "Debug Info Emission";
 static const char *const EHTimerName = "DWARF Exception Writer";
+static const char *const CodeViewLineTablesGroupName = "CodeView Line Tables";
 
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
@@ -202,8 +204,14 @@ bool AsmPrinter::doInitialization(Module &M) {
   }
 
   if (MAI->doesSupportDebugInformation()) {
-    DD = new DwarfDebug(this, &M);
-    Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
+    if (Triple(TM.getTargetTriple()).getOS() == Triple::Win32) {
+      Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this),
+                                     DbgTimerName,
+                                     CodeViewLineTablesGroupName));
+    } else {
+      DD = new DwarfDebug(this, &M);
+      Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
+    }
   }
 
   DwarfException *DE = 0;
index 2ad24e1af99225a5164bc0b64526f9ff55ab6ba5..b3eddac1911adc31412e72254f514d88223bd2af 100644 (file)
@@ -13,6 +13,7 @@ add_llvm_library(LLVMAsmPrinter
   ErlangGCPrinter.cpp
   OcamlGCPrinter.cpp
   Win64Exception.cpp
+  WinCodeViewLineTables.cpp
   )
 
 add_dependencies(LLVMAsmPrinter intrinsics_gen)
index 43297d23dbedde199cd211aedc3de7c2e6abd940..e4188c39b074175645283c128d13b6c66f56ff6b 100644 (file)
@@ -1527,30 +1527,6 @@ void DwarfDebug::identifyScopeMarkers() {
   }
 }
 
-// Get MDNode for DebugLoc's scope.
-static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) {
-  if (MDNode *InlinedAt = DL.getInlinedAt(Ctx))
-    return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx);
-  return DL.getScope(Ctx);
-}
-
-// Walk up the scope chain of given debug loc and find line number info
-// for the function.
-static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) {
-  const MDNode *Scope = getScopeNode(DL, Ctx);
-  DISubprogram SP = getDISubprogram(Scope);
-  if (SP.isSubprogram()) {
-    // Check for number of operands since the compatibility is
-    // cheap here.
-    if (SP->getNumOperands() > 19)
-      return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
-    else
-      return DebugLoc::get(SP.getLineNumber(), 0, SP);
-  }
-
-  return DebugLoc();
-}
-
 // Gather pre-function debug information.  Assumes being called immediately
 // after the function entry point has been emitted.
 void DwarfDebug::beginFunction(const MachineFunction *MF) {
@@ -1745,7 +1721,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
   // Record beginning of function.
   if (!PrologEndLoc.isUnknown()) {
     DebugLoc FnStartDL =
-        getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext());
+        PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext());
     recordSourceLine(
         FnStartDL.getLine(), FnStartDL.getCol(),
         FnStartDL.getScope(MF->getFunction()->getContext()),
diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp
new file mode 100644 (file)
index 0000000..bb8b073
--- /dev/null
@@ -0,0 +1,333 @@
+//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp --*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing line tables info into COFF files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WinCodeViewLineTables.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/COFF.h"
+
+namespace llvm {
+
+StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) {
+  assert(S);
+  DIDescriptor D(S);
+  assert((D.isCompileUnit() || D.isFile() || D.isSubprogram() ||
+          D.isLexicalBlockFile() || D.isLexicalBlock()) &&
+         "Unexpected scope info");
+
+  DIScope Scope(S);
+  StringRef Dir = Scope.getDirectory(),
+            Filename = Scope.getFilename();
+  char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)];
+  if (Result != 0)
+    return Result;
+
+  // Clang emits directory and relative filename info into the IR, but CodeView
+  // operates on full paths.  We could change Clang to emit full paths too, but
+  // that would increase the IR size and probably not needed for other users.
+  // For now, just concatenate and canonicalize the path here.
+  std::string Filepath;
+  if (Filename.find(':') == 1)
+    Filepath = Filename;
+  else
+    Filepath = (Dir + Twine("\\") + Filename).str();
+
+  // Canonicalize the path.  We have to do it textually because we may no longer
+  // have access the file in the filesystem.
+  // First, replace all slashes with backslashes.
+  std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
+
+  // Remove all "\.\" with "\".
+  size_t Cursor = 0;
+  while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
+    Filepath.erase(Cursor, 2);
+
+  // Replace all "\XXX\..\" with "\".  Don't try too hard though as the original
+  // path should be well-formatted, e.g. start with a drive letter, etc.
+  Cursor = 0;
+  while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
+    // Something's wrong if the path starts with "\..\", abort.
+    if (Cursor == 0)
+      break;
+
+    size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
+    if (PrevSlash == std::string::npos)
+      // Something's wrong, abort.
+      break;
+
+    Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
+    // The next ".." might be following the one we've just erased.
+    Cursor = PrevSlash;
+  }
+
+  // Remove all duplicate backslashes.
+  Cursor = 0;
+  while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
+    Filepath.erase(Cursor, 1);
+
+  Result = strdup(Filepath.c_str());
+  return StringRef(Result);
+}
+
+void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL,
+                                                const MachineFunction *MF) {
+  const MDNode *Scope = DL.getScope(MF->getFunction()->getContext());
+  if (!Scope)
+    return;
+  StringRef Filename = getFullFilepath(Scope);
+
+  // Skip this instruction if it has the same file:line as the previous one.
+  assert(CurFn);
+  if (!CurFn->Instrs.empty()) {
+    const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()];
+    if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine())
+      return;
+  }
+  FileNameRegistry.add(Filename);
+
+  MCSymbol *MCL = Asm->MMI->getContext().CreateTempSymbol();
+  Asm->OutStreamer.EmitLabel(MCL);
+  CurFn->Instrs.push_back(MCL);
+  InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine());
+}
+
+WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP)
+    : Asm(0), CurFn(0) {
+  MachineModuleInfo *MMI = AP->MMI;
+
+  // If module doesn't have named metadata anchors or COFF debug section
+  // is not available, skip any debug info related stuff.
+  if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
+      !AP->getObjFileLowering().getCOFFDebugSymbolsSection())
+    return;
+
+  // Tell MMI that we have debug info.
+  MMI->setDebugInfoAvailability(true);
+  Asm = AP;
+}
+
+static void EmitLabelDiff(MCStreamer &Streamer,
+                          const MCSymbol *From, const MCSymbol *To) {
+  MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+  MCContext &Context = Streamer.getContext();
+  const MCExpr *FromRef = MCSymbolRefExpr::Create(From, Variant, Context),
+               *ToRef   = MCSymbolRefExpr::Create(To, Variant, Context);
+  const MCExpr *AddrDelta =
+      MCBinaryExpr::Create(MCBinaryExpr::Sub, ToRef, FromRef, Context);
+  Streamer.EmitValue(AddrDelta, 4);
+}
+
+void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) {
+  // For each function there is a separate subsection
+  // which holds the PC to file:line table.
+  const MCSymbol *Fn = Asm->getSymbol(GV);
+  const FunctionInfo &FI = FnDebugInfo[GV];
+  assert(Fn);
+  assert(FI.Instrs.size() > 0);
+
+  // PCs/Instructions are grouped into segments sharing the same filename.
+  // Pre-calculate the lengths (in instructions) of these segments and store
+  // them in a map for convenience.  Each index in the map is the sequential
+  // number of the respective instruction that starts a new segment.
+  DenseMap<size_t, size_t> FilenameSegmentLengths;
+  size_t LastSegmentEnd = 0;
+  StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename;
+  for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
+    if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename)
+      continue;
+    FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
+    LastSegmentEnd = J;
+    PrevFilename = InstrInfo[FI.Instrs[J]].Filename;
+  }
+  FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
+
+  // Emit the control code of the subsection followed by the payload size.
+  Asm->OutStreamer.AddComment(
+      "Linetable subsection for " + Twine(Fn->getName()));
+  Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION);
+  MCSymbol *SubsectionBegin = Asm->MMI->getContext().CreateTempSymbol(),
+           *SubsectionEnd = Asm->MMI->getContext().CreateTempSymbol();
+  EmitLabelDiff(Asm->OutStreamer, SubsectionBegin, SubsectionEnd);
+  Asm->OutStreamer.EmitLabel(SubsectionBegin);
+
+  // Identify the function this subsection is for.
+  Asm->OutStreamer.EmitCOFFSecRel32(Fn);
+  Asm->OutStreamer.EmitCOFFSectionIndex(Fn);
+
+  // Length of the function's code, in bytes.
+  EmitLabelDiff(Asm->OutStreamer, Fn, FI.End);
+
+  // PC-to-linenumber lookup table:
+  MCSymbol *FileSegmentEnd = 0;
+  for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
+    MCSymbol *Instr = FI.Instrs[J];
+    assert(InstrInfo.count(Instr));
+
+    if (FilenameSegmentLengths.count(J)) {
+      // We came to a beginning of a new filename segment.
+      if (FileSegmentEnd)
+        Asm->OutStreamer.EmitLabel(FileSegmentEnd);
+      StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename;
+      assert(FileNameRegistry.Infos.count(CurFilename));
+      size_t IndexInStringTable =
+          FileNameRegistry.Infos[CurFilename].FilenameID;
+      // Each segment starts with the offset of the filename
+      // in the string table.
+      Asm->OutStreamer.AddComment(
+          "Segment for file '" + Twine(CurFilename) + "' begins");
+      MCSymbol *FileSegmentBegin = Asm->MMI->getContext().CreateTempSymbol();
+      Asm->OutStreamer.EmitLabel(FileSegmentBegin);
+      Asm->EmitInt32(8 * IndexInStringTable);
+
+      // Number of PC records in the lookup table.
+      size_t SegmentLength = FilenameSegmentLengths[J];
+      Asm->EmitInt32(SegmentLength);
+
+      // Full size of the segment for this filename, including the prev two
+      // records.
+      FileSegmentEnd = Asm->MMI->getContext().CreateTempSymbol();
+      EmitLabelDiff(Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
+    }
+
+    // The first PC with the given linenumber and the linenumber itself.
+    EmitLabelDiff(Asm->OutStreamer, Fn, Instr);
+    Asm->EmitInt32(InstrInfo[Instr].LineNumber);
+  }
+
+  if (FileSegmentEnd)
+    Asm->OutStreamer.EmitLabel(FileSegmentEnd);
+  Asm->OutStreamer.EmitLabel(SubsectionEnd);
+}
+
+void WinCodeViewLineTables::endModule() {
+  if (FnDebugInfo.empty())
+    return;
+
+  assert(Asm != 0);
+  Asm->OutStreamer.SwitchSection(
+      Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
+  Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
+
+  // The COFF .debug$S section consists of several subsections, each starting
+  // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
+  // of the payload followed by the payload itself.  The subsections are 4-byte
+  // aligned.
+
+  for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
+    emitDebugInfoForFunction(VisitedFunctions[I]);
+
+  // This subsection holds a file index to offset in string table table.
+  Asm->OutStreamer.AddComment("File index to string table offset subsection");
+  Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION);
+  size_t NumFilenames = FileNameRegistry.Infos.size();
+  Asm->EmitInt32(8 * NumFilenames);
+  for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
+    StringRef Filename = FileNameRegistry.Filenames[I];
+    // For each unique filename, just write it's offset in the string table.
+    Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
+    // The function name offset is not followed by any additional data.
+    Asm->EmitInt32(0);
+  }
+
+  // This subsection holds the string table.
+  Asm->OutStreamer.AddComment("String table");
+  Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION);
+  Asm->EmitInt32(FileNameRegistry.LastOffset);
+  // The payload starts with a null character.
+  Asm->EmitInt8(0);
+
+  for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
+    // Just emit unique filenames one by one, separated by a null character.
+    Asm->OutStreamer.EmitBytes(FileNameRegistry.Filenames[I]);
+    Asm->EmitInt8(0);
+  }
+
+  // No more subsections. Fill with zeros to align the end of the section by 4.
+  Asm->OutStreamer.EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
+
+  clear();
+}
+
+void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) {
+  assert(!CurFn && "Can't process two functions at once!");
+
+  if (!Asm || !Asm->MMI->hasDebugInfo())
+    return;
+
+  // Grab the lexical scopes for the function, if we don't have any of those
+  // then we're not going to be able to do anything.
+  LScopes.initialize(*MF);
+  if (LScopes.empty())
+    return;
+
+  const Function *GV = MF->getFunction();
+  assert(FnDebugInfo.count(GV) == false);
+  VisitedFunctions.push_back(GV);
+  CurFn = &FnDebugInfo[GV];
+
+  // Find the end of the function prolog.
+  // FIXME: is there a simpler a way to do this? Can we just search
+  // for the first instruction of the function, not the last of the prolog?
+  DebugLoc PrologEndLoc;
+  bool EmptyPrologue = true;
+  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
+       I != E && PrologEndLoc.isUnknown(); ++I) {
+    for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
+         II != IE; ++II) {
+      const MachineInstr *MI = II;
+      if (MI->isDebugValue())
+        continue;
+
+      // First known non-DBG_VALUE and non-frame setup location marks
+      // the beginning of the function body.
+      // FIXME: do we need the first subcondition?
+      if (!MI->getFlag(MachineInstr::FrameSetup) &&
+          (!MI->getDebugLoc().isUnknown())) {
+        PrologEndLoc = MI->getDebugLoc();
+        break;
+      }
+      EmptyPrologue = false;
+    }
+  }
+  // Record beginning of function if we have a non-empty prologue.
+  if (!PrologEndLoc.isUnknown() && !EmptyPrologue) {
+    DebugLoc FnStartDL =
+        PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext());
+    maybeRecordLocation(FnStartDL, MF);
+  }
+}
+
+void WinCodeViewLineTables::endFunction(const MachineFunction *) {
+  if (!Asm || !CurFn)  // We haven't created any debug info for this function.
+    return;
+
+  if (CurFn->Instrs.empty())
+    llvm_unreachable("Can this ever happen?");
+
+  // Define end label for subprogram.
+  MCSymbol *FunctionEndSym = Asm->OutStreamer.getContext().CreateTempSymbol();
+  Asm->OutStreamer.EmitLabel(FunctionEndSym);
+  CurFn->End = FunctionEndSym;
+  CurFn = 0;
+}
+
+void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) {
+  // Ignore DBG_VALUE locations and function prologue.
+  if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
+    return;
+  DebugLoc DL = MI->getDebugLoc();
+  if (DL == PrevInstLoc || DL.isUnknown())
+    return;
+  maybeRecordLocation(DL, Asm->MF);
+}
+}
diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h
new file mode 100644 (file)
index 0000000..f61ecc2
--- /dev/null
@@ -0,0 +1,144 @@
+//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h ----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing line tables info into COFF files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__
+#define CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__
+
+#include "AsmPrinterHandler.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/DebugLoc.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+namespace llvm {
+/// \brief Collects and handles line tables information in a CodeView format.
+class WinCodeViewLineTables : public AsmPrinterHandler {
+  AsmPrinter *Asm;
+  DebugLoc PrevInstLoc;
+  LexicalScopes LScopes;
+
+  // For each function, store a vector of labels to its instructions, as well as
+  // to the end of the function.
+  struct FunctionInfo {
+    SmallVector<MCSymbol *, 10> Instrs;
+    MCSymbol *End;
+  } *CurFn;
+
+  typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
+  FnDebugInfoTy FnDebugInfo;
+  // Store the functions we've visited in a vector so we can maintain a stable
+  // order while emitting subsections.
+  SmallVector<const Function *, 10> VisitedFunctions;
+
+  // InstrInfoTy - Holds the Filename:LineNumber information for every
+  // instruction with a unique debug location.
+  struct InstrInfoTy {
+    StringRef Filename;
+    unsigned LineNumber;
+
+    InstrInfoTy() : LineNumber(0) {}
+
+    InstrInfoTy(StringRef Filename, unsigned LineNumber)
+        : Filename(Filename), LineNumber(LineNumber) {}
+  };
+  DenseMap<MCSymbol *, InstrInfoTy> InstrInfo;
+
+  // FileNameRegistry - Manages filenames observed while generating debug info
+  // by filtering out duplicates and bookkeeping the offsets in the string
+  // table to be generated.
+  struct FileNameRegistryTy {
+    SmallVector<StringRef, 10> Filenames;
+    struct PerFileInfo {
+      size_t FilenameID, StartOffset;
+    };
+    StringMap<PerFileInfo> Infos;
+
+    // The offset in the string table where we'll write the next unique
+    // filename.
+    size_t LastOffset;
+
+    FileNameRegistryTy() {
+      clear();
+    }
+
+    // Add Filename to the registry, if it was not observed before.
+    void add(StringRef Filename) {
+      if (Infos.count(Filename))
+        return;
+      size_t OldSize = Infos.size();
+      Infos[Filename].FilenameID = OldSize;
+      Infos[Filename].StartOffset = LastOffset;
+      LastOffset += Filename.size() + 1;
+      Filenames.push_back(Filename);
+    }
+
+    void clear() {
+      LastOffset = 1;
+      Infos.clear();
+      Filenames.clear();
+    }
+  } FileNameRegistry;
+
+  typedef std::map<std::pair<StringRef, StringRef>, char *>
+      DirAndFilenameToFilepathMapTy;
+  DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap;
+  StringRef getFullFilepath(const MDNode *S);
+
+  void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);
+
+  void clear() {
+    assert(CurFn == 0);
+    FileNameRegistry.clear();
+    InstrInfo.clear();
+  }
+
+  void emitDebugInfoForFunction(const Function *GV);
+
+public:
+  WinCodeViewLineTables(AsmPrinter *Asm);
+
+  ~WinCodeViewLineTables() {
+    for (DirAndFilenameToFilepathMapTy::iterator
+             I = DirAndFilenameToFilepathMap.begin(),
+             E = DirAndFilenameToFilepathMap.end();
+         I != E; ++I)
+      free(I->second);
+  }
+
+  virtual void setSymbolSize(const llvm::MCSymbol *, uint64_t) {}
+
+  /// \brief Emit the COFF section that holds the line table information.
+  virtual void endModule();
+
+  /// \brief Gather pre-function debug information.
+  virtual void beginFunction(const MachineFunction *MF);
+
+  /// \brief Gather post-function debug information.
+  virtual void endFunction(const MachineFunction *);
+
+  /// \brief Process beginning of an instruction.
+  virtual void beginInstruction(const MachineInstr *MI);
+
+  /// \brief Process end of an instruction.
+  virtual void endInstruction() {}
+};
+} // End of namespace llvm
+
+#endif
index c57b5a3053035ea8f5e04ac6af0b2699919e3a2b..fcb6f4194ea9853eaad761d491131f12d43e41d6 100644 (file)
@@ -70,6 +70,26 @@ void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
   IA    = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
 }
 
+MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const {
+  if (MDNode *InlinedAt = getInlinedAt(Ctx))
+    return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(Ctx);
+  return getScope(Ctx);
+}
+
+DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) {
+  const MDNode *Scope = getScopeNode(Ctx);
+  DISubprogram SP = getDISubprogram(Scope);
+  if (SP.isSubprogram()) {
+    // Check for number of operands since the compatibility is
+    // cheap here.  FIXME: Name the magic constant.
+    if (SP->getNumOperands() > 19)
+      return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
+    else
+      return DebugLoc::get(SP.getLineNumber(), 0, SP);
+  }
+
+  return DebugLoc();
+}
 
 DebugLoc DebugLoc::get(unsigned Line, unsigned Col,
                        MDNode *Scope, MDNode *InlinedAt) {
index 796d03bfeb3c138acaaf99c07fa0d7cd4e4b1cd2..a160f298e180dfbb6f5274106f8f417a372ae4f2 100644 (file)
@@ -150,6 +150,8 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) {
   LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0,
                                      SectionKind::getReadOnlyWithRel());
 
+  COFFDebugSymbolsSection = 0;
+
   if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) {
     CompactUnwindSection =
       Ctx->getMachOSection("__LD", "__compact_unwind",
@@ -458,6 +460,8 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
                        ELF::SHF_ALLOC,
                        SectionKind::getReadOnly());
 
+  COFFDebugSymbolsSection = 0;
+
   // Debug Info Sections.
   DwarfAbbrevSection =
     Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0,
index 1689fe6c91a867bfc6e1fac2a59e77a05b174c33..4ea9d2cf98616a5ec452f428a46b0bccad337a62 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc -O0 < %s | grep AT_decl_file |  grep 2
+; RUN: %llc_dwarf -O0 < %s | grep AT_decl_file |  grep 2
 ; Here _ZN1S3fooEv is defined in header file identified as AT_decl_file no. 2 in debug info.
 %struct.S = type <{ i8 }>
 
index 4d4d61665c07d93f656eb5e45c6985bb57f1fe59..bec0318a33fd20be6fa9c17a5bc3aa69c565341b 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -asm-verbose -O0 | grep AT_specification | count 2
+; RUN: llvm-as < %s | %llc_dwarf -asm-verbose -O0 | grep AT_specification | count 2
 ; Radar 7833483
 ; Do not emit AT_specification for nested function foo.
 
index 4af2fdcdfa8a959e66b08b14a2be106171fc1172..6c772230d93cddfcc0aa2a9cd6d046bbe86491a2 100644 (file)
@@ -1,6 +1,6 @@
-; RUN: llc -asm-verbose -O1 -o %t < %s 
+; RUN: %llc_dwarf -asm-verbose -O1 -o %t < %s
 ; RUN: grep DW_AT_APPLE_omit_frame_ptr %t
-; RUN: llc -disable-fp-elim -asm-verbose -O1 -o %t < %s 
+; RUN: %llc_dwarf -disable-fp-elim -asm-verbose -O1 -o %t < %s
 ; RUN: grep -v DW_AT_APPLE_omit_frame_ptr %t
 
 
index 870f059521f5a9d7fca5466416872431779e5a3c..75d2e7084d219bce27a7f54b546d05e318b574f7 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -O0 -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
 
 ; Check that two compile units are generated
 
index 50a34222fe634ea81bbddca529cc971900f74d4f..35530e6d99b4cba03292257690f6481941cc8ce6 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc -O2 %s -o - | FileCheck %s
+; RUN: %llc_dwarf -O2 %s -o - | FileCheck %s
 ; Check struct X for dead variable xyz from inlined function foo.
 
 ; CHECK:       DW_TAG_structure_type
diff --git a/test/DebugInfo/COFF/asm.ll b/test/DebugInfo/COFF/asm.ll
new file mode 100644 (file)
index 0000000..1c6fbbf
--- /dev/null
@@ -0,0 +1,183 @@
+; RUN: llc -mtriple=i686-pc-win32 -O0 < %s | FileCheck --check-prefix=X86 %s
+; RUN: llc -mtriple=i686-pc-win32 -o - -O0 < %s | llvm-mc -triple=i686-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ32 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -O0 < %s | FileCheck --check-prefix=X64 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -o - -O0 < %s | llvm-mc -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ64 %s
+
+; This LL file was generated by running clang on the following code:
+; D:\asm.c:
+;  1 void g(void);
+;  2
+;  3 void f(void) {
+;  4   __asm align 4;
+;  5   g();
+;  6 }
+
+; X86: _f:
+; X86-NEXT: # BB
+; X86-NEXT: [[ASM_LINE:^L.*]]:{{$}}
+; X86:      [[CALL_LINE:^L.*]]:{{$}}
+; X86-NEXT: calll   _g
+; X86-NEXT: [[RETURN_STMT:.*]]:
+; X86-NEXT: ret
+; X86-NEXT: [[END_OF_F:.*]]:
+;
+; X86: .section        .debug$S,"rn"
+; X86-NEXT: .long   4
+; X86-NEXT: .long   242
+; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X86-NEXT: [[F2_START]]:
+; X86-NEXT: .secrel32 _f
+; X86-NEXT: .secidx _f
+; X86-NEXT: .long [[END_OF_F]]-_f
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   3
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[ASM_LINE]]-_f
+; X86-NEXT: .long   4
+; X86-NEXT: .long [[CALL_LINE]]-_f
+; X86-NEXT: .long   5
+; X86-NEXT: .long [[RETURN_STMT]]-_f
+; X86-NEXT: .long   6
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; X86-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X86-NEXT: .long   244
+; X86-NEXT: .long   8
+; X86-NEXT: .long   1
+; X86-NEXT: .long   0
+; String table
+; X86-NEXT: .long   243
+; X86-NEXT: .long   10
+; X86-NEXT: .byte   0
+; X86-NEXT: .ascii  "D:\\asm.c"
+; X86-NEXT: .byte   0
+; Padding
+; X86-NEXT: .zero   2
+
+; OBJ32:    Section {
+; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      ]
+; OBJ32:      Relocations [
+; OBJ32-NEXT:   0xC IMAGE_REL_I386_SECREL _f
+; OBJ32-NEXT:   0x10 IMAGE_REL_I386_SECTION _f
+; OBJ32-NEXT: ]
+; OBJ32:      FunctionLineTable [
+; OBJ32-NEXT:   Name: _f
+; OBJ32-NEXT:   CodeSize: 0x6
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\asm.c
+; FIXME: An empty __asm stmt creates an extra entry.
+; We seem to know that these offsets are the same statically during the
+; execution of endModule().
+; OBJ32-NEXT:     +0x0: 4
+; OBJ32-NEXT:     +0x0: 5
+; OBJ32-NEXT:     +0x5: 6
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT: ]
+; OBJ32:    }
+
+; X64: f:
+; X64-NEXT: [[START:.*]]:{{$}}
+; X64-NEXT: # BB
+; X64-NEXT: subq    $40, %rsp
+; X64-NEXT: [[ASM_LINE:.*]]:{{$}}
+; X64:      [[CALL_LINE:.*]]:{{$}}
+; X64-NEXT: callq   g
+; X64-NEXT: [[EPILOG_AND_RET:.*]]:
+; X64-NEXT: addq    $40, %rsp
+; X64-NEXT: ret
+; X64-NEXT: [[END_OF_F:.*]]:
+;
+; X64: .section        .debug$S,"rn"
+; X64-NEXT: .long   4
+; X64-NEXT: .long   242
+; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X64-NEXT: [[F2_START]]:
+; X64-NEXT: .secrel32 f
+; X64-NEXT: .secidx f
+; X64-NEXT: .long [[END_OF_F]]-f
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   0
+; X64-NEXT: .long   4
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[START]]-f
+; X64-NEXT: .long   3
+; X64-NEXT: .long [[ASM_LINE]]-f
+; X64-NEXT: .long   4
+; X64-NEXT: .long [[CALL_LINE]]-f
+; X64-NEXT: .long   5
+; X64-NEXT: .long [[EPILOG_AND_RET]]-f
+; X64-NEXT: .long   6
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; X64-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X64-NEXT: .long   244
+; X64-NEXT: .long   8
+; X64-NEXT: .long   1
+; X64-NEXT: .long   0
+; String table
+; X64-NEXT: .long   243
+; X64-NEXT: .long   10
+; X64-NEXT: .byte   0
+; X64-NEXT: .ascii  "D:\\asm.c"
+; X64-NEXT: .byte   0
+; Padding
+; X64-NEXT: .zero   2
+
+; OBJ64:    Section {
+; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      ]
+; OBJ64:      Relocations [
+; OBJ64-NEXT:   0xC IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0x10 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: ]
+; OBJ64:      FunctionLineTable [
+; OBJ64-NEXT:   Name: f
+; OBJ64-NEXT:   CodeSize: 0xE
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\asm.c
+; OBJ64-NEXT:     +0x0: 3
+; FIXME: An empty __asm stmt creates an extra entry.
+; OBJ64-NEXT:     +0x4: 4
+; OBJ64-NEXT:     +0x4: 5
+; OBJ64-NEXT:     +0x9: 6
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT: ]
+; OBJ64:    }
+
+; Function Attrs: nounwind
+define void @f() #0 {
+entry:
+  call void asm sideeffect inteldialect ".align 4", "~{dirflag},~{fpsr},~{flags}"() #2, !dbg !12
+  call void @g(), !dbg !13
+  ret void, !dbg !14
+}
+
+declare void @g() #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [D:\/<unknown>] [DW_LANG_C99]
+!1 = metadata !{metadata !"<unknown>", metadata !"D:\5C"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"f", metadata !"f", metadata !"", i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @f, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [f]
+!5 = metadata !{metadata !"asm.c", metadata !"D:\5C"}
+!6 = metadata !{i32 786473, metadata !5}          ; [ DW_TAG_file_type ] [D:\/asm.c]
+!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!8 = metadata !{null}
+!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
+!11 = metadata !{metadata !"clang version 3.5 "}
+!12 = metadata !{i32 4, i32 0, metadata !4, null}
+!13 = metadata !{i32 5, i32 0, metadata !4, null}
+!14 = metadata !{i32 6, i32 0, metadata !4, null}
diff --git a/test/DebugInfo/COFF/multifile.ll b/test/DebugInfo/COFF/multifile.ll
new file mode 100644 (file)
index 0000000..f218522
--- /dev/null
@@ -0,0 +1,257 @@
+; RUN: llc -mtriple=i686-pc-win32 -O0 < %s | FileCheck --check-prefix=X86 %s
+; RUN: llc -mtriple=i686-pc-win32 -o - -O0 < %s | llvm-mc -triple=i686-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ32 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -O0 < %s | FileCheck --check-prefix=X64 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -o - -O0 < %s | llvm-mc -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ64 %s
+
+; This LL file was generated by running clang on the following code:
+; D:\input.c:
+;  1 void g(void);
+;  2
+;  3 void f() {
+;  4 #line 1 "one.c"
+;  5   g(void);
+;  6 #line 2 "two.c"
+;  7   g(void);
+;  8 #line 7 "one.c"
+;  9   g(void);
+; 10 }
+
+; X86: _f:
+; X86-NEXT: # BB
+; X86-NEXT: [[CALL_LINE_1:.*]]:{{$}}
+; X86-NEXT: calll   _g
+; X86-NEXT: [[CALL_LINE_2:.*]]:{{$}}
+; X86-NEXT: calll   _g
+; X86-NEXT: [[CALL_LINE_3:.*]]:{{$}}
+; X86-NEXT: calll   _g
+; X86-NEXT: [[RETURN_STMT:.*]]:
+; X86-NEXT: ret
+; X86-NEXT: [[END_OF_F:.*]]:
+;
+; X86: .section        .debug$S,"rn"
+; X86-NEXT: .long   4
+; X86-NEXT: .long   242
+; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X86-NEXT: [[F2_START]]:
+; X86-NEXT: .secrel32 _f
+; X86-NEXT: .secidx _f
+; X86-NEXT: .long [[END_OF_F]]-_f
+; Segment for file 'D:\\one.c' begins
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   1
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[CALL_LINE_1]]-_f
+; X86-NEXT: .long   1
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; Segment for file 'D:\\two.c' begins
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   8
+; X86-NEXT: .long   1
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[CALL_LINE_2]]-_f
+; X86-NEXT: .long   2
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; A new segment for file 'D:\\one.c' begins
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   2
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[CALL_LINE_3]]-_f
+; X86-NEXT: .long   7
+; X86-NEXT: .long [[RETURN_STMT]]-_f
+; X86-NEXT: .long   8
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; X86-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X86-NEXT: .long   244
+; X86-NEXT: .long   16
+; X86-NEXT: .long   1
+; X86-NEXT: .long   0
+; X86-NEXT: .long   10
+; X86-NEXT: .long   0
+; String table
+; X86-NEXT: .long   243
+; X86-NEXT: .long   19
+; X86-NEXT: .byte   0
+; X86-NEXT: .ascii  "D:\\one.c"
+; X86-NEXT: .byte   0
+; X86-NEXT: .ascii  "D:\\two.c"
+; X86-NEXT: .byte   0
+; X86-NEXT: .zero   1
+
+; OBJ32:    Section {
+; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      ]
+; OBJ32:      Relocations [
+; OBJ32-NEXT:   0xC IMAGE_REL_I386_SECREL _f
+; OBJ32-NEXT:   0x10 IMAGE_REL_I386_SECTION _f
+; OBJ32-NEXT: ]
+; OBJ32:      FunctionLineTable [
+; OBJ32-NEXT:   Name: _f
+; OBJ32-NEXT:   CodeSize: 0x10
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\one.c
+; OBJ32-NEXT:     +0x0: 1
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\two.c
+; OBJ32-NEXT:     +0x5: 2
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\one.c
+; OBJ32-NEXT:     +0xA: 7
+; OBJ32-NEXT:     +0xF: 8
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT: ]
+; OBJ32:    }
+
+; X64: f:
+; X64-NEXT: [[START:.*]]:{{$}}
+; X64-NEXT: # BB
+; X64-NEXT: subq    $40, %rsp
+; X64-NEXT: [[CALL_LINE_1:.*]]:{{$}}
+; X64-NEXT: callq   g
+; X64-NEXT: [[CALL_LINE_2:.*]]:{{$}}
+; X64-NEXT: callq   g
+; X64-NEXT: [[CALL_LINE_3:.*]]:{{$}}
+; X64-NEXT: callq   g
+; X64-NEXT: [[EPILOG_AND_RET:.*]]:
+; X64-NEXT: addq    $40, %rsp
+; X64-NEXT: ret
+; X64-NEXT: [[END_OF_F:.*]]:
+;
+; X64: .section        .debug$S,"rn"
+; X64-NEXT: .long   4
+; X64-NEXT: .long   242
+; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X64-NEXT: [[F2_START]]:
+; X64-NEXT: .secrel32 f
+; X64-NEXT: .secidx f
+; X64-NEXT: .long [[END_OF_F]]-f
+; Segment for file 'D:\\input.c' begins
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   0
+; X64-NEXT: .long   1
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[START]]-f
+; X64-NEXT: .long   3
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; Segment for file 'D:\\one.c' begins
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   8
+; X64-NEXT: .long   1
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[CALL_LINE_1]]-f
+; X64-NEXT: .long   1
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; Segment for file 'D:\\two.c' begins
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   16
+; X64-NEXT: .long   1
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[CALL_LINE_2]]-f
+; X64-NEXT: .long   2
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; A new segment for file 'D:\\one.c' begins
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   8
+; X64-NEXT: .long   2
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[CALL_LINE_3]]-f
+; X64-NEXT: .long   7
+; X64-NEXT: .long [[EPILOG_AND_RET]]-f
+; X64-NEXT: .long   8
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; X64-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X64-NEXT: .long   244
+; X64-NEXT: .long   24
+; X64-NEXT: .long   1
+; X64-NEXT: .long   0
+; X64-NEXT: .long   12
+; X64-NEXT: .long   0
+; X64-NEXT: .long   21
+; X64-NEXT: .long   0
+; String table
+; X64-NEXT: .long   243
+; X64-NEXT: .long   30
+; X64-NEXT: .byte   0
+; X64-NEXT: .ascii  "D:\\input.c"
+; X64-NEXT: .byte   0
+; X64-NEXT: .ascii  "D:\\one.c"
+; X64-NEXT: .byte   0
+; X64-NEXT: .ascii  "D:\\two.c"
+; X64-NEXT: .byte   0
+; X64-NEXT: .zero   2
+
+; OBJ64:    Section {
+; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      ]
+; OBJ64:      Relocations [
+; OBJ64-NEXT:   0xC IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0x10 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: ]
+; OBJ64:      FunctionLineTable [
+; OBJ64-NEXT:   Name: f
+; OBJ64-NEXT:   CodeSize: 0x18
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\input.c
+; OBJ64-NEXT:     +0x0: 3
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\one.c
+; OBJ64-NEXT:     +0x4: 1
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\two.c
+; OBJ64-NEXT:     +0x9: 2
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\one.c
+; OBJ64-NEXT:     +0xE: 7
+; OBJ64-NEXT:     +0x13: 8
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT: ]
+; OBJ64:    }
+
+; Function Attrs: nounwind
+define void @f() #0 {
+entry:
+  call void @g(), !dbg !12
+  call void @g(), !dbg !15
+  call void @g(), !dbg !18
+  ret void, !dbg !19
+}
+
+declare void @g() #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [D:\/<unknown>] [DW_LANG_C99]
+!1 = metadata !{metadata !"<unknown>", metadata !"D:\5C"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"f", metadata !"f", metadata !"", i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @f, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [f]
+!5 = metadata !{metadata !"input.c", metadata !"D:\5C"}
+!6 = metadata !{i32 786473, metadata !5}          ; [ DW_TAG_file_type ] [D:\/input.c]
+!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!8 = metadata !{null}
+!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
+!11 = metadata !{metadata !"clang version 3.5 "}
+!12 = metadata !{i32 1, i32 0, metadata !13, null}
+!13 = metadata !{i32 786443, metadata !14, metadata !4} ; [ DW_TAG_lexical_block ] [D:\/one.c]
+!14 = metadata !{metadata !"one.c", metadata !"D:\5C"}
+!15 = metadata !{i32 2, i32 0, metadata !16, null}
+!16 = metadata !{i32 786443, metadata !17, metadata !4} ; [ DW_TAG_lexical_block ] [D:\/two.c]
+!17 = metadata !{metadata !"two.c", metadata !"D:\5C"}
+!18 = metadata !{i32 7, i32 0, metadata !13, null}
+!19 = metadata !{i32 8, i32 0, metadata !13, null} ; [ DW_TAG_imported_declaration ]
diff --git a/test/DebugInfo/COFF/multifunction.ll b/test/DebugInfo/COFF/multifunction.ll
new file mode 100644 (file)
index 0000000..f051db9
--- /dev/null
@@ -0,0 +1,378 @@
+; RUN: llc -mtriple=i686-pc-win32 -O0 < %s | FileCheck --check-prefix=X86 %s
+; RUN: llc -mtriple=i686-pc-win32 -o - -O0 < %s | llvm-mc -triple=i686-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ32 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -O0 < %s | FileCheck --check-prefix=X64 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -o - -O0 < %s | llvm-mc -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ64 %s
+
+; This LL file was generated by running clang on the following code:
+; D:\source.c:
+;  1 void z(void);
+;  2
+;  3 void x(void) {
+;  4   z();
+;  5 }
+;  6
+;  7 void y(void) {
+;  8   z();
+;  9 }
+; 10
+; 11 void f(void) {
+; 12   x();
+; 13   y();
+; 14   z();
+; 15 }
+
+
+; X86: _x:
+; X86-NEXT: # BB
+; X86-NEXT: [[X_CALL:.*]]:{{$}}
+; X86-NEXT: calll   _z
+; X86-NEXT: [[X_RETURN:.*]]:
+; X86-NEXT: ret
+; X86-NEXT: [[END_OF_X:.*]]:
+;
+; X86: _y:
+; X86-NEXT: # BB
+; X86-NEXT: [[Y_CALL:.*]]:{{$}}
+; X86-NEXT: calll   _z
+; X86-NEXT: [[Y_RETURN:.*]]:
+; X86-NEXT: ret
+; X86-NEXT: [[END_OF_Y:.*]]:
+;
+; X86: _f:
+; X86-NEXT: # BB
+; X86-NEXT: [[F_CALLS_X:.*]]:{{$}}
+; X86-NEXT: calll   _x
+; X86-NEXT: [[F_CALLS_Y:.*]]:
+; X86-NEXT: calll   _y
+; X86-NEXT: [[F_CALLS_Z:.*]]:
+; X86-NEXT: calll   _z
+; X86-NEXT: [[F_RETURN:.*]]:
+; X86-NEXT: ret
+; X86-NEXT: [[END_OF_F:.*]]:
+;
+; X86: .section        .debug$S,"rn"
+; X86-NEXT: .long   4
+; Line table subsection for x
+; X86-NEXT: .long   242
+; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X86-NEXT: [[F2_START]]:
+; X86-NEXT: .secrel32       _x
+; X86-NEXT: .secidx _x
+; X86-NEXT: .long [[END_OF_X]]-_x
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   2
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[X_CALL]]-_x
+; X86-NEXT: .long   4
+; X86-NEXT: .long [[X_RETURN]]-_x
+; X86-NEXT: .long   5
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; X86-NEXT: [[F2_END]]:
+; Line table subsection for y
+; X86-NEXT: .long   242
+; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X86-NEXT: [[F2_START]]:
+; X86-NEXT: .secrel32       _y
+; X86-NEXT: .secidx _y
+; X86-NEXT: .long [[END_OF_Y]]-_y
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   2
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[Y_CALL]]-_y
+; X86-NEXT: .long   8
+; X86-NEXT: .long [[Y_RETURN]]-_y
+; X86-NEXT: .long   9
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; X86-NEXT: [[F2_END]]:
+; Line table subsection for f
+; X86-NEXT: .long   242
+; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X86-NEXT: [[F2_START]]:
+; X86-NEXT: .secrel32 _f
+; X86-NEXT: .secidx _f
+; X86-NEXT: .long [[END_OF_F]]-_f
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   4
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[F_CALLS_X]]-_f
+; X86-NEXT: .long   12
+; X86-NEXT: .long [[F_CALLS_Y]]-_f
+; X86-NEXT: .long   13
+; X86-NEXT: .long [[F_CALLS_Z]]-_f
+; X86-NEXT: .long   14
+; X86-NEXT: .long [[F_RETURN]]-_f
+; X86-NEXT: .long   15
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; X86-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X86-NEXT: .long   244
+; X86-NEXT: .long   8
+; X86-NEXT: .long   1
+; X86-NEXT: .long   0
+; String table
+; X86-NEXT: .long   243
+; X86-NEXT: .long   13
+; X86-NEXT: .byte   0
+; X86-NEXT: .ascii  "D:\\source.c"
+; X86-NEXT: .byte   0
+; X86-NEXT: .zero   3
+
+; OBJ32:    Section {
+; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      ]
+; OBJ32:      Relocations [
+; OBJ32-NEXT:   0xC IMAGE_REL_I386_SECREL _x
+; OBJ32-NEXT:   0x10 IMAGE_REL_I386_SECTION _x
+; OBJ32-NEXT:   0x3C IMAGE_REL_I386_SECREL _y
+; OBJ32-NEXT:   0x40 IMAGE_REL_I386_SECTION _y
+; OBJ32-NEXT:   0x6C IMAGE_REL_I386_SECREL _f
+; OBJ32-NEXT:   0x70 IMAGE_REL_I386_SECTION _f
+; OBJ32-NEXT: ]
+; OBJ32:      FunctionLineTable [
+; OBJ32-NEXT:   Name: _x
+; OBJ32-NEXT:   CodeSize: 0x6
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\source.c
+; OBJ32-NEXT:     +0x0: 4
+; OBJ32-NEXT:     +0x5: 5
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT: ]
+; OBJ32-NEXT: FunctionLineTable [
+; OBJ32-NEXT:   Name: _y
+; OBJ32-NEXT:   CodeSize: 0x6
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\source.c
+; OBJ32-NEXT:     +0x0: 8
+; OBJ32-NEXT:     +0x5: 9
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT: ]
+; OBJ32-NEXT: FunctionLineTable [
+; OBJ32-NEXT:   Name: _f
+; OBJ32-NEXT:   CodeSize: 0x10
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\source.c
+; OBJ32-NEXT:     +0x0: 12
+; OBJ32-NEXT:     +0x5: 13
+; OBJ32-NEXT:     +0xA: 14
+; OBJ32-NEXT:     +0xF: 15
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT: ]
+; OBJ32:    }
+
+; X64: x:
+; X64-NEXT: [[X_START:.*]]:{{$}}
+; X64-NEXT: # BB
+; X64-NEXT: subq    $40, %rsp
+; X64-NEXT: [[X_CALL_LINE:.*]]:{{$}}
+; X64-NEXT: callq   z
+; X64-NEXT: [[X_EPILOG_AND_RET:.*]]:
+; X64-NEXT: addq    $40, %rsp
+; X64-NEXT: ret
+; X64-NEXT: [[END_OF_X:.*]]:
+;
+; X64: y:
+; X64-NEXT: [[Y_START:.*]]:{{$}}
+; X64-NEXT: # BB
+; X64-NEXT: subq    $40, %rsp
+; X64-NEXT: [[Y_CALL_LINE:.*]]:{{$}}
+; X64-NEXT: callq   z
+; X64-NEXT: [[Y_EPILOG_AND_RET:.*]]:
+; X64-NEXT: addq    $40, %rsp
+; X64-NEXT: ret
+; X64-NEXT: [[END_OF_Y:.*]]:
+;
+; X64: f:
+; X64-NEXT: [[F_START:.*]]:{{$}}
+; X64-NEXT: # BB
+; X64-NEXT: subq    $40, %rsp
+; X64-NEXT: [[F_CALLS_X:.*]]:{{$}}
+; X64-NEXT: callq   x
+; X64-NEXT: [[F_CALLS_Y:.*]]:
+; X64-NEXT: callq   y
+; X64-NEXT: [[F_CALLS_Z:.*]]:
+; X64-NEXT: callq   z
+; X64-NEXT: [[F_EPILOG_AND_RET:.*]]:
+; X64-NEXT: addq    $40, %rsp
+; X64-NEXT: ret
+; X64-NEXT: [[END_OF_F:.*]]:
+;
+; X64: .section        .debug$S,"rn"
+; X64-NEXT: .long   4
+; Line table subsection for x
+; X64-NEXT: .long   242
+; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X64-NEXT: [[F2_START]]:
+; X64-NEXT: .secrel32 x
+; X64-NEXT: .secidx x
+; X64-NEXT: .long [[END_OF_X]]-x
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   0
+; X64-NEXT: .long   3
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[X_START]]-x
+; X64-NEXT: .long   3
+; X64-NEXT: .long [[X_CALL_LINE]]-x
+; X64-NEXT: .long   4
+; X64-NEXT: .long [[X_EPILOG_AND_RET]]-x
+; X64-NEXT: .long   5
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; X64-NEXT: [[F2_END]]:
+; Line table subsection for y
+; X64-NEXT: .long   242
+; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X64-NEXT: [[F2_START]]:
+; X64-NEXT: .secrel32 y
+; X64-NEXT: .secidx y
+; X64-NEXT: .long [[END_OF_Y]]-y
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   0
+; X64-NEXT: .long   3
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[Y_START]]-y
+; X64-NEXT: .long   7
+; X64-NEXT: .long [[Y_CALL_LINE]]-y
+; X64-NEXT: .long   8
+; X64-NEXT: .long [[Y_EPILOG_AND_RET]]-y
+; X64-NEXT: .long   9
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; X64-NEXT: [[F2_END]]:
+; Line table subsection for f
+; X64-NEXT: .long   242
+; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X64-NEXT: [[F2_START]]:
+; X64-NEXT: .secrel32 f
+; X64-NEXT: .secidx f
+; X64-NEXT: .long [[END_OF_F]]-f
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   0
+; X64-NEXT: .long   5
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[F_START]]-f
+; X64-NEXT: .long   11
+; X64-NEXT: .long [[F_CALLS_X]]-f
+; X64-NEXT: .long   12
+; X64-NEXT: .long [[F_CALLS_Y]]-f
+; X64-NEXT: .long   13
+; X64-NEXT: .long [[F_CALLS_Z]]-f
+; X64-NEXT: .long   14
+; X64-NEXT: .long [[F_EPILOG_AND_RET]]-f
+; X64-NEXT: .long   15
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; X64-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X64-NEXT: .long   244
+; X64-NEXT: .long   8
+; X64-NEXT: .long   1
+; X64-NEXT: .long   0
+; String table
+; X64-NEXT: .long   243
+; X64-NEXT: .long   13
+; X64-NEXT: .byte   0
+; X64-NEXT: .ascii  "D:\\source.c"
+; X64-NEXT: .byte   0
+; X64-NEXT: .zero   3
+
+; OBJ64:    Section {
+; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      ]
+; OBJ64:      Relocations [
+; OBJ64-NEXT:   0xC IMAGE_REL_AMD64_SECREL x
+; OBJ64-NEXT:   0x10 IMAGE_REL_AMD64_SECTION x
+; OBJ64-NEXT:   0x44 IMAGE_REL_AMD64_SECREL y
+; OBJ64-NEXT:   0x48 IMAGE_REL_AMD64_SECTION y
+; OBJ64-NEXT:   0x7C IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0x80 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: ]
+; OBJ64:      FunctionLineTable [
+; OBJ64-NEXT:   Name: x
+; OBJ64-NEXT:   CodeSize: 0xE
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\source.c
+; OBJ64-NEXT:     +0x0: 3
+; OBJ64-NEXT:     +0x4: 4
+; OBJ64-NEXT:     +0x9: 5
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT: ]
+; OBJ64-NEXT: FunctionLineTable [
+; OBJ64-NEXT:   Name: y
+; OBJ64-NEXT:   CodeSize: 0xE
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\source.c
+; OBJ64-NEXT:     +0x0: 7
+; OBJ64-NEXT:     +0x4: 8
+; OBJ64-NEXT:     +0x9: 9
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT: ]
+; OBJ64-NEXT: FunctionLineTable [
+; OBJ64-NEXT:   Name: f
+; OBJ64-NEXT:   CodeSize: 0x18
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\source.c
+; OBJ64-NEXT:     +0x0: 11
+; OBJ64-NEXT:     +0x4: 12
+; OBJ64-NEXT:     +0x9: 13
+; OBJ64-NEXT:     +0xE: 14
+; OBJ64-NEXT:     +0x13: 15
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT: ]
+; OBJ64:    }
+
+; Function Attrs: nounwind
+define void @x() #0 {
+entry:
+  call void @z(), !dbg !14
+  ret void, !dbg !15
+}
+
+declare void @z() #1
+
+; Function Attrs: nounwind
+define void @y() #0 {
+entry:
+  call void @z(), !dbg !16
+  ret void, !dbg !17
+}
+
+; Function Attrs: nounwind
+define void @f() #0 {
+entry:
+  call void @x(), !dbg !18
+  call void @y(), !dbg !19
+  call void @z(), !dbg !20
+  ret void, !dbg !21
+}
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12}
+!llvm.ident = !{!13}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [D:\/<unknown>] [DW_LANG_C99]
+!1 = metadata !{metadata !"<unknown>", metadata !"D:\5C"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4, metadata !9, metadata !10}
+!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"x", metadata !"x", metadata !"", i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @x, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [x]
+!5 = metadata !{metadata !"source.c", metadata !"D:\5C"}
+!6 = metadata !{i32 786473, metadata !5}          ; [ DW_TAG_file_type ] [D:\/source.c]
+!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!8 = metadata !{null}
+!9 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"y", metadata !"y", metadata !"", i32 7, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @y, null, null, metadata !2, i32 7} ; [ DW_TAG_subprogram ] [line 7] [def] [y]
+!10 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"f", metadata !"f", metadata !"", i32 11, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @f, null, null, metadata !2, i32 11} ; [ DW_TAG_subprogram ] [line 11] [def] [f]
+!11 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!12 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
+!13 = metadata !{metadata !"clang version 3.5 "}
+!14 = metadata !{i32 4, i32 0, metadata !4, null}
+!15 = metadata !{i32 5, i32 0, metadata !4, null}
+!16 = metadata !{i32 8, i32 0, metadata !9, null} ; [ DW_TAG_imported_declaration ]
+!17 = metadata !{i32 9, i32 0, metadata !9, null}
+!18 = metadata !{i32 12, i32 0, metadata !10, null}
+!19 = metadata !{i32 13, i32 0, metadata !10, null}
+!20 = metadata !{i32 14, i32 0, metadata !10, null}
+!21 = metadata !{i32 15, i32 0, metadata !10, null}
diff --git a/test/DebugInfo/COFF/simple.ll b/test/DebugInfo/COFF/simple.ll
new file mode 100644 (file)
index 0000000..2b3ab87
--- /dev/null
@@ -0,0 +1,167 @@
+; RUN: llc -mtriple=i686-pc-win32 -O0 < %s | FileCheck --check-prefix=X86 %s
+; RUN: llc -mtriple=i686-pc-win32 -o - -O0 < %s | llvm-mc -triple=i686-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ32 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -O0 < %s | FileCheck --check-prefix=X64 %s
+; RUN: llc -mtriple=x86_64-pc-win32 -o - -O0 < %s | llvm-mc -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj -s -sr -codeview-linetables | FileCheck --check-prefix=OBJ64 %s
+
+; This LL file was generated by running clang on the following code:
+; D:\test.c:
+; 1 void g(void);
+; 2
+; 3 void f(void) {
+; 4   g();
+; 5 }
+
+; X86: _f:
+; X86-NEXT: # BB
+; X86-NEXT: [[CALL_LINE:^L.*]]:{{$}}
+; X86-NEXT: calll   _g
+; X86-NEXT: [[RETURN_STMT:.*]]:
+; X86-NEXT: ret
+; X86-NEXT: [[END_OF_F:.*]]:
+;
+; X86: .section        .debug$S,"rn"
+; X86-NEXT: .long   4
+; X86-NEXT: .long   242
+; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X86-NEXT: [[F2_START]]:
+; X86-NEXT: .secrel32 _f
+; X86-NEXT: .secidx _f
+; X86-NEXT: .long [[END_OF_F]]-_f
+; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X86-NEXT: .long   0
+; X86-NEXT: .long   2
+; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X86-NEXT: .long [[CALL_LINE]]-_f
+; X86-NEXT: .long   4
+; X86-NEXT: .long [[RETURN_STMT]]-_f
+; X86-NEXT: .long   5
+; X86-NEXT: [[FILE_SEGMENT_END]]:
+; X86-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X86-NEXT: .long   244
+; X86-NEXT: .long   8
+; X86-NEXT: .long   1
+; X86-NEXT: .long   0
+; String table
+; X86-NEXT: .long   243
+; X86-NEXT: .long   11
+; X86-NEXT: .byte   0
+; X86-NEXT: .ascii  "D:\\test.c"
+; X86-NEXT: .byte   0
+; Padding
+; X86-NEXT: .zero   1
+
+; OBJ32:    Section {
+; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      ]
+; OBJ32:      Relocations [
+; OBJ32-NEXT:   0xC IMAGE_REL_I386_SECREL _f
+; OBJ32-NEXT:   0x10 IMAGE_REL_I386_SECTION _f
+; OBJ32-NEXT: ]
+; OBJ32:      FunctionLineTable [
+; OBJ32-NEXT:   Name: _f
+; OBJ32-NEXT:   CodeSize: 0x6
+; OBJ32-NEXT:   FilenameSegment [
+; OBJ32-NEXT:     Filename: D:\test.c
+; OBJ32-NEXT:     +0x0: 4
+; OBJ32-NEXT:     +0x5: 5
+; OBJ32-NEXT:   ]
+; OBJ32-NEXT: ]
+; OBJ32:    }
+
+; X64: f:
+; X64-NEXT: [[START:.*]]:{{$}}
+; X64-NEXT: # BB
+; X64-NEXT: subq    $40, %rsp
+; X64-NEXT: [[CALL_LINE:.*]]:{{$}}
+; X64-NEXT: callq   g
+; X64-NEXT: [[EPILOG_AND_RET:.*]]:
+; X64-NEXT: addq    $40, %rsp
+; X64-NEXT: ret
+; X64-NEXT: [[END_OF_F:.*]]:
+;
+; X64: .section        .debug$S,"rn"
+; X64-NEXT: .long   4
+; X64-NEXT: .long   242
+; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
+; X64-NEXT: [[F2_START]]:
+; X64-NEXT: .secrel32 f
+; X64-NEXT: .secidx f
+; X64-NEXT: .long [[END_OF_F]]-f
+; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
+; X64-NEXT: .long   0
+; X64-NEXT: .long   3
+; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
+; X64-NEXT: .long [[START]]-f
+; X64-NEXT: .long   3
+; X64-NEXT: .long [[CALL_LINE]]-f
+; X64-NEXT: .long   4
+; X64-NEXT: .long [[EPILOG_AND_RET]]-f
+; X64-NEXT: .long   5
+; X64-NEXT: [[FILE_SEGMENT_END]]:
+; X64-NEXT: [[F2_END]]:
+; File index to string table offset subsection
+; X64-NEXT: .long   244
+; X64-NEXT: .long   8
+; X64-NEXT: .long   1
+; X64-NEXT: .long   0
+; String table
+; X64-NEXT: .long   243
+; X64-NEXT: .long   11
+; X64-NEXT: .byte   0
+; X64-NEXT: .ascii  "D:\\test.c"
+; X64-NEXT: .byte   0
+; Padding
+; X64-NEXT: .zero   1
+
+; OBJ64:    Section {
+; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
+; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      ]
+; OBJ64:      Relocations [
+; OBJ64-NEXT:   0xC IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0x10 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: ]
+; OBJ64:      FunctionLineTable [
+; OBJ64-NEXT:   Name: f
+; OBJ64-NEXT:   CodeSize: 0xE
+; OBJ64-NEXT:   FilenameSegment [
+; OBJ64-NEXT:     Filename: D:\test.c
+; OBJ64-NEXT:     +0x0: 3
+; OBJ64-NEXT:     +0x4: 4
+; OBJ64-NEXT:     +0x9: 5
+; OBJ64-NEXT:   ]
+; OBJ64-NEXT: ]
+; OBJ64:    }
+
+; Function Attrs: nounwind
+define void @f() #0 {
+entry:
+  call void @g(), !dbg !12
+  ret void, !dbg !13
+}
+
+declare void @g() #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [D:\/<unknown>] [DW_LANG_C99]
+!1 = metadata !{metadata !"<unknown>", metadata !"D:\5C"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !5, metadata !6, metadata !"f", metadata !"f", metadata !"", i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @f, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [f]
+!5 = metadata !{metadata !"test.c", metadata !"D:\5C"}
+!6 = metadata !{i32 786473, metadata !5}          ; [ DW_TAG_file_type ] [D:\/test.c]
+!7 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!8 = metadata !{null}
+!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
+!11 = metadata !{metadata !"clang version 3.5 "}
+!12 = metadata !{i32 4, i32 0, metadata !4, null}
+!13 = metadata !{i32 5, i32 0, metadata !4, null}
diff --git a/test/DebugInfo/X86/coff_debug_info_type.ll b/test/DebugInfo/X86/coff_debug_info_type.ll
new file mode 100644 (file)
index 0000000..2d63f58
--- /dev/null
@@ -0,0 +1,39 @@
+; RUN: llc -mtriple=i686-pc-mingw32 -filetype=asm -O0 < %s | FileCheck %s
+; RUN: llc -mtriple=i686-pc-cygwin -filetype=asm -O0 < %s | FileCheck %s
+; RUN: llc -mtriple=i686-w64-mingw32 -filetype=asm -O0 < %s | FileCheck %s
+; CHECK:    .section  .debug_info
+
+; RUN: llc -mtriple=i686-pc-win32 -filetype=asm -O0 < %s | FileCheck -check-prefix=WIN32 %s
+; WIN32:    .section .debug$S,"rn"
+
+; generated from:
+; clang -g -S -emit-llvm test.c -o test.ll
+; int main()
+; {
+;      return 0;
+; }
+
+define i32 @main() #0 {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval
+  ret i32 0, !dbg !10
+}
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !11}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [C:\Projects/test.c] [DW_LANG_C99]
+!1 = metadata !{metadata !"test.c", metadata !"C:\5CProjects"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"main", metadata !"main", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, i32 ()* @main, null, null, metadata !2, i32 2} ; [ DW_TAG_subprogram ] [line 1] [def] [scope 2] [main]
+!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ] [C:\Projects/test.c]
+!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = metadata !{metadata !8}
+!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 3}
+!10 = metadata !{i32 3, i32 0, metadata !4, null}
+!11 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
index 4cc38a63bebfdf4c7368e11c58beaf9e277e6d6b..e5a5446063493e7e7c92ad7c5d7dc5e8af06d2c8 100644 (file)
 ;      return 0;
 ; }
 
-; ModuleID = 'test.c'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"
-target triple = "i686-pc-win32"
-
 ; Function Attrs: nounwind
 define i32 @main() #0 {
 entry:
index d66486d14ae5fffb32c05dcd827b6047d214879a..c658b5050269700941780687a5014ae7ba9de720 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc -march=x86 -asm-verbose < %s | grep DW_TAG_formal_parameter
+; RUN: %llc_dwarf -march=x86 -asm-verbose < %s | grep DW_TAG_formal_parameter
 
 
 %struct.Pt = type { double, double }
index e5e07ffe994204e8d920934b59f5c686a0c431bb..72b0b994c4de57b30bb17b8efa9322ef17778fe4 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc -O0 < %s | FileCheck %s
+; RUN: %llc_dwarf -O0 < %s | FileCheck %s
 ; Do not emit AT_upper_bound for an unbounded array.
 ; radar 9241695
 define i32 @main() nounwind ssp {
index 6901f5e5c6013f8fbd0ee7646df85e6cc76152f3..d927980c8d6cdc7ce1d6fc7ca9b2da477aefae43 100644 (file)
@@ -1,5 +1,5 @@
 ; REQUIRES: object-emission
-; RUN: llc -O0 -filetype=obj -generate-dwarf-cu-ranges %s -o %t
+; RUN: %llc_dwarf -O0 -filetype=obj -generate-dwarf-cu-ranges %s -o %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; Check that we emit ranges for this when the -generate-dwarf-cu-ranges flag is passed.
index 2cfe624f7935d4a8bc793b02ac7fd4a7b1b9e698..264d8e32a292155b7718f130743d1d9355571df5 100644 (file)
@@ -14,7 +14,7 @@
 ;   auto pr = &A::r;
 ; }
 ;
-; RUN: llc -filetype=obj -O0 < %s | llvm-dwarfdump - | FileCheck %s
+; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump - | FileCheck %s
 ; CHECK: DW_TAG_subroutine_type     DW_CHILDREN_yes
 ; CHECK-NEXT: DW_AT_reference  DW_FORM_flag_present
 ; CHECK: DW_TAG_subroutine_type     DW_CHILDREN_yes
index fc3363133e68f3aee87c57ed210482363f5f291e..399ba179eb75a8421bac194bdadb10dc98361ba6 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -generate-dwarf-pub-sections=Enable -filetype=obj -o %t.o < %s
+; RUN: %llc_dwarf -generate-dwarf-pub-sections=Enable -filetype=obj -o %t.o < %s
 ; RUN: llvm-dwarfdump -debug-dump=pubnames %t.o | FileCheck %s
 ; ModuleID = 'dwarf-public-names.cpp'
 ;
index bc09846bb8e18027bdef9b178ce94642ad57dec4..3796fb4afbeb1fc7d674e59fedf69066f27403d7 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -O0 -filetype=obj < %s > %t
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; IR generated from the following code compiled with clang -g:
index 9a0c32ad91a372244205087da6791a7173918c0d..c826fc07ebe95598fd7792a8285e579f663121a9 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -O0 -filetype=obj < %s > %t
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; generated from the following source compiled to bitcode with clang -g -O1
index 1dd5b2c07f9430024704b5126f7825d9374ff5dd..a96301a096e56efaa66c766689347a019819cbba 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -filetype=obj < %s > %t
+; RUN: %llc_dwarf -filetype=obj < %s > %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; IR generated from clang -O -g with the following source
index 34c5101a14260404d523afb895fe25fd0af89cc8..446c28b32e6b966d6827cd024522bce1a4e5302e 100644 (file)
@@ -1,5 +1,5 @@
-; RUN: llc -O0 < %s | FileCheck %s -check-prefix ARGUMENT
-; RUN: llc -O0 < %s | FileCheck %s -check-prefix VARIABLE
+; RUN: %llc_dwarf -O0 < %s | FileCheck %s -check-prefix ARGUMENT
+; RUN: %llc_dwarf -O0 < %s | FileCheck %s -check-prefix VARIABLE
 ; PR 13202
 
 define i32 @main() uwtable {
index a0c283db5a1626bc76d6eaf64849498604852f00..3c955bc27ca874996443cce5c4b1a1eb63f8b66d 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
 
 ; generated by clang from:
 ; struct foo {
index 0bc4ee67265b2ad2171d9c5dcf746169823264b4..4d5adaa566550a5d679ce9bd45e5a0907fb43358 100644 (file)
@@ -1,7 +1,7 @@
 ; REQUIRES: object-emission
 ; XFAIL: hexagon
 
-; RUN: llc -filetype=obj -O0 < %s > %t
+; RUN: %llc_dwarf -filetype=obj -O0 < %s > %t
 ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
 ; CHECK: DW_TAG_ptr_to_member_type
 ; CHECK: DW_TAG_ptr_to_member_type
index 9d0b25c74bae3cd45b40172a389b87fb39d6b57f..f36688d1a3889ee73baedbdc619bc62a1a1565ef 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -O0 -filetype=obj < %s > %t
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 ; CHECK: debug_info contents
 ; CHECK: [[NS1:0x[0-9a-f]*]]:{{ *}}DW_TAG_namespace
index 2ed57a6576f333918ba996b64b80d88c2667566b..e51b76c3766ab3d8b73d08a7ca6039ff532ee50d 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -O0 -filetype=obj < %s > %t
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; This was pulled from clang's debug-info-template-recursive.cpp test.
index f838eca72a67846e4dfbf3768b581b42a73a459c..50876f79e1c6df5d86e341ca24873c5b4226a862 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -filetype=obj -O0 < %s > %t
+; RUN: %llc_dwarf -filetype=obj -O0 < %s > %t
 ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
 ; CHECK: [[TYPE:.*]]: DW_TAG_structure_type
 ; Make sure we correctly handle containing type of a struct being a type identifier.
index b746d3b6d4f16418f139ee5be670ed6a4c54e998..e6fc41f508f95a94781bf4c078c2ed2d7d875135 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -filetype=obj -O0 < %s > %t
+; RUN: %llc_dwarf -filetype=obj -O0 < %s > %t
 ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
 ; CHECK: DW_TAG_ptr_to_member_type
 ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4]       (cu + {{.*}} => {[[TYPE:0x[0-9a-f]+]]})
index 8589840a695533803047d830992299d9fb421f15..560bd00084c3624a201b483d4111137f9b60aaaf 100644 (file)
@@ -5,7 +5,7 @@
 
 ; REQUIRES: object-emission
 
-; RUN: llc %s -o %t -filetype=obj -O0
+; RUN: %llc_dwarf %s -o %t -filetype=obj -O0
 ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
 
 ; ModuleID = 'test.bc'
index f4dde0a24988e50fb4b4f5b814304fb642552310..bfc2f9fabfa7bc7a273b264cd5703a5996106231 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -O0 -filetype=obj < %s > %t
+; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; Make sure we are generating DWARF version 3 when module flag says so.
index 4bfdff977d10c89eacfe6b290113803a3bac36b5..ef70ba293daf17382ad287edc79f1b0b865dc04d 100644 (file)
@@ -2,7 +2,7 @@
 
 ; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o %t
 ; RUN: cat %t | FileCheck %s -check-prefix=LINK
-; RUN: llc -filetype=obj -O0 < %t > %t2
+; RUN: %llc_dwarf -filetype=obj -O0 < %t > %t2
 ; RUN: llvm-dwarfdump -debug-dump=info %t2 | FileCheck %s
 
 ; Make sure the backend generates a single DIE and uses ref_addr.
index bb18292b43cfce8e08791a5da6f203a7dcf526f5..782bbac4e7bac5fa345c9c6796b2a794bd55d96f 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 ;
-; RUN: llvm-link %s %p/type-unique-simple2-b.ll -S -o - | llc -filetype=obj -O0 | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+; RUN: llvm-link %s %p/type-unique-simple2-b.ll -S -o - | %llc_dwarf -filetype=obj -O0 | llvm-dwarfdump -debug-dump=info - | FileCheck %s
 ;
 ; Tests for a merge error where attributes are inserted twice into the same DIE.
 ;
index ead91df6da1569103e887b0b326447b32c6f3131..8a56e2e80c67465e6be608ec9c75834d606bcfc8 100644 (file)
@@ -2,5 +2,5 @@
 
 ; RUN: llvm-link %S/Inputs/type-unique-simple2-a.ll %S/Inputs/type-unique-simple2-b.ll -S -o %t
 ; RUN: cat %t | FileCheck %S/Inputs/type-unique-simple2-a.ll -check-prefix=LINK
-; RUN: llc -filetype=obj -O0 < %t > %t2
+; RUN: %llc_dwarf -filetype=obj -O0 < %t > %t2
 ; RUN: llvm-dwarfdump -debug-dump=info %t2 | FileCheck %S/Inputs/type-unique-simple2-a.ll
index 622f6ede1a126ec9ee3db97f07a0b64ffab59365..962728d0cb4caa63ec8d3bdd5227e1e7a2c5b7fe 100644 (file)
@@ -156,6 +156,12 @@ if re.search(r'cygwin|mingw32|win32', config.host_triple):
   lli_mcjit += ' -mtriple='+config.host_triple+'-elf'
 config.substitutions.append( ('%lli_mcjit', lli_mcjit) )
 
+# Similarly, have a macro to use llc with DWARF even when the host is win32.
+llc_dwarf = 'llc'
+if re.search(r'win32', config.target_triple):
+  llc_dwarf += ' -mtriple='+config.target_triple.replace('-win32', '-mingw32')
+config.substitutions.append( ('%llc_dwarf', llc_dwarf) )
+
 # Provide a substition for those tests that need to run the jit to obtain data
 # but simply want use the currently considered most reliable jit for platform
 # FIXME: ppc32 is not ready for mcjit.