diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 14 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 26 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp | 333 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h | 144 | ||||
| -rw-r--r-- | llvm/lib/IR/DebugLoc.cpp | 20 | ||||
| -rw-r--r-- | llvm/lib/MC/MCObjectFileInfo.cpp | 4 | 
7 files changed, 514 insertions, 28 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index fbee17f563a..c5726633d2a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -50,11 +50,13 @@  #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; diff --git a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt index 2ad24e1af99..b3eddac1911 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_library(LLVMAsmPrinter    ErlangGCPrinter.cpp    OcamlGCPrinter.cpp    Win64Exception.cpp +  WinCodeViewLineTables.cpp    )  add_dependencies(LLVMAsmPrinter intrinsics_gen) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 43297d23dbe..e4188c39b07 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -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/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp new file mode 100644 index 00000000000..bb8b0735e50 --- /dev/null +++ b/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp @@ -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/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h new file mode 100644 index 00000000000..f61ecc2f64c --- /dev/null +++ b/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h @@ -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 diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index c57b5a30530..fcb6f4194ea 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -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) { diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index 796d03bfeb3..a160f298e18 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -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,  | 

