[llvm-commits] [PATCH/RFC] Add support for CodeView debug information

Kai kai at redstar.de
Sun Dec 2 23:15:10 PST 2012


Hi!

I started to work on support for emitting CodeView debug information.

In order to support other debug information I extracted the used 
interface of the DwarfDebug class into an abstract class. After that I 
changed the AsmPrinter class to use the new interface. (Patch 0001)

The next step is to enumerate all debug information types. The boolean 
variable SupportsDebugInformation is replaced by DebugInformationType 
which is based on an enumeration. (Patch 0002)

During development I noticed that there is no possibility to get the 
return type from DISubprogramm if the return type is modelled as DIType. 
Because I need this functionality I added the support. (Patch 0003)
(BTW: Does DISubprogram.Verify check the right thing in case the return
type is modelled as DIType?)

Finally I created the classes needed for CodeView debug symbol output. 
This is really work-in-progress and is not ready yet. Nevertheless it 
can output type information for simply signatures like int add(int,int). 
It is a proof of concept that the interface is working. (Patch 0004)

I like to get review and comments on patches 0001-0003. Is my approach
ok? If yes then I like to get these patches committed so that further
updates to debug related classes can consider the new interface.

Thank you very much!

Regards
Kai
-------------- next part --------------
>From ec58ea989007668b6c36d3d041689e7f9e3cd21e Mon Sep 17 00:00:00 2001
From: kai <kai at redstar.de>
Date: Wed, 28 Nov 2012 21:01:02 +0100
Subject: [PATCH 1/4] Extract interface from DwarfDebug.

This patch is a refactoring of DwarfDebug. It extracts the interface
of the class into a new abstract class AsmDebug and changes the sole
user AsmPrinter to use this interface. In order tp emphasize the usage
of the interface the instance variable DD ("DwarfDebug") in AsmPrinter
is renamed to DI ("DebugInformation").
No functional change intended.

Patch by Kai Nacke.
---
 include/llvm/CodeGen/AsmPrinter.h     |  6 +--
 lib/CodeGen/AsmPrinter/AsmDebug.h     | 74 +++++++++++++++++++++++++++++++++++
 lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 27 +++++++------
 lib/CodeGen/AsmPrinter/DwarfDebug.cpp |  2 +-
 lib/CodeGen/AsmPrinter/DwarfDebug.h   |  8 +---
 5 files changed, 94 insertions(+), 23 deletions(-)
 create mode 100644 lib/CodeGen/AsmPrinter/AsmDebug.h

diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 751199b..722427d 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -22,6 +22,7 @@
 #include "llvm/Support/ErrorHandling.h"
 
 namespace llvm {
+  class AsmDebug;
   class BlockAddress;
   class GCStrategy;
   class Constant;
@@ -44,7 +45,6 @@ namespace llvm {
   class MCStreamer;
   class MCSymbol;
   class MDNode;
-  class DwarfDebug;
   class DwarfException;
   class Mangler;
   class TargetLoweringObjectFile;
@@ -107,8 +107,8 @@ namespace llvm {
     /// function.
     MachineLoopInfo *LI;
 
-    /// DD - If the target supports dwarf debug info, this pointer is non-null.
-    DwarfDebug *DD;
+    /// DI - If the target supports debug info, this pointer is non-null.
+    AsmDebug *DI;
 
     /// DE - If the target supports dwarf exception info, this pointer is
     /// non-null.
diff --git a/lib/CodeGen/AsmPrinter/AsmDebug.h b/lib/CodeGen/AsmPrinter/AsmDebug.h
new file mode 100644
index 0000000..74836b6
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/AsmDebug.h
@@ -0,0 +1,74 @@
+//===----- llvm/CodeGen/AsmDebug.cpp - Asm Debug Framework ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the support interface for writing debug
+/// information into asm files.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_ASMDEBUG_H__
+#define CODEGEN_ASMPRINTER_ASMDEBUG_H__
+
+#include "llvm/DebugInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/MC/MachineLocation.h"
+
+namespace llvm {
+
+class MachineFrameInfo;
+class MachineModuleInfo;
+class MachineOperand;
+class MCAsmInfo;
+
+class AsmDebug {
+protected:
+  /// Asm - Target of debug information emission.
+  AsmPrinter *Asm;
+
+  /// MMI - Collected machine module information.
+  MachineModuleInfo *MMI;
+
+public:
+  //===--------------------------------------------------------------------===//
+  // Main entry points.
+  //
+  AsmDebug(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {}
+  virtual ~AsmDebug() {}
+
+  /// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such
+  /// as llvm.dbg.enum and llvm.dbg.ty
+  virtual void collectInfoFromNamedMDNodes(const Module *M) = 0;
+
+  /// beginModule - Emit all debug information sections that should come prior
+  /// to the content.
+  virtual void beginModule() = 0;
+
+  /// endModule - Emit all debug information sections that should come after
+  /// the content.
+  virtual void endModule() = 0;
+
+  /// beginFunction - Gather pre-function debug information.  Assumes being
+  /// emitted immediately after the function entry point.
+  virtual void beginFunction(const MachineFunction *MF) = 0;
+
+  /// endFunction - Gather and emit post-function debug information.
+  ///
+  virtual void endFunction(const MachineFunction *MF) = 0;
+
+  /// beginInstruction - Process beginning of an instruction.
+  virtual void beginInstruction(const MachineInstr *MI) = 0;
+
+  /// endInstruction - Prcess end of an instruction.
+  virtual void endInstruction(const MachineInstr *MI) = 0;
+};
+} // End of namespace llvm
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 72b2f0c..7068211 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -13,6 +13,7 @@
 
 #define DEBUG_TYPE "asm-printer"
 #include "llvm/CodeGen/AsmPrinter.h"
+#include "AsmDebug.h"
 #include "DwarfDebug.h"
 #include "DwarfException.h"
 #include "llvm/DebugInfo.h"
@@ -96,14 +97,14 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
     OutContext(Streamer.getContext()),
     OutStreamer(Streamer),
     LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
-  DD = 0; DE = 0; MMI = 0; LI = 0;
+  DI = 0; DE = 0; MMI = 0; LI = 0;
   CurrentFnSym = CurrentFnSymForSize = 0;
   GCMetadataPrinters = 0;
   VerboseAsm = Streamer.isVerboseAsm();
 }
 
 AsmPrinter::~AsmPrinter() {
-  assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized");
+  assert(DI == 0 && DE == 0 && "Debug/EH info didn't get finalized");
 
   if (GCMetadataPrinters != 0) {
     gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
@@ -184,7 +185,7 @@ bool AsmPrinter::doInitialization(Module &M) {
   }
 
   if (MAI->doesSupportDebugInformation())
-    DD = new DwarfDebug(this, &M);
+    DI = new DwarfDebug(this, &M);
 
   switch (MAI->getExceptionHandlingType()) {
   case ExceptionHandling::None:
@@ -465,9 +466,9 @@ void AsmPrinter::EmitFunctionHeader() {
     NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
     DE->BeginFunction(MF);
   }
-  if (DD) {
+  if (DI) {
     NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
-    DD->beginFunction(MF);
+    DI->beginFunction(MF);
   }
 }
 
@@ -648,7 +649,7 @@ void AsmPrinter::EmitFunctionBody() {
   // Emit target-specific gunk before the function body.
   EmitFunctionBodyStart();
 
-  bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo();
+  bool ShouldPrintDebugScopes = DI && MMI->hasDebugInfo();
 
   // Print out code for the function.
   bool HasAnyRealCode = false;
@@ -670,7 +671,7 @@ void AsmPrinter::EmitFunctionBody() {
 
       if (ShouldPrintDebugScopes) {
         NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
-        DD->beginInstruction(II);
+        DI->beginInstruction(II);
       }
 
       if (isVerbose())
@@ -710,7 +711,7 @@ void AsmPrinter::EmitFunctionBody() {
 
       if (ShouldPrintDebugScopes) {
         NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
-        DD->endInstruction(II);
+        DI->endInstruction(II);
       }
     }
   }
@@ -767,9 +768,9 @@ void AsmPrinter::EmitFunctionBody() {
   }
 
   // Emit post-function debug information.
-  if (DD) {
+  if (DI) {
     NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
-    DD->endFunction(MF);
+    DI->endFunction(MF);
   }
   if (DE) {
     NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
@@ -871,12 +872,12 @@ bool AsmPrinter::doFinalization(Module &M) {
     }
     delete DE; DE = 0;
   }
-  if (DD) {
+  if (DI) {
     {
       NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
-      DD->endModule();
+      DI->endModule();
     }
-    delete DD; DD = 0;
+    delete DI; DI = 0;
   }
 
   // If the target wants to know about weak references, print them all.
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index c4c9d3f..db285d7 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -153,7 +153,7 @@ DIType DbgVariable::getType() const {
 } // end llvm namespace
 
 DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
-  : Asm(A), MMI(Asm->MMI), FirstCU(0), FissionCU(0),
+  : AsmDebug(A), FirstCU(0), FissionCU(0),
     AbbreviationsSet(InitAbbreviationsSetSize),
     SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator),
     PrevLabel(NULL) {
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 35bddee..63ead84 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -14,6 +14,7 @@
 #ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__
 #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__
 
+#include "AsmDebug.h"
 #include "DIE.h"
 #include "llvm/DebugInfo.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -189,12 +190,7 @@ public:
 };
 
 /// \brief Collects and handles dwarf debug information.
-class DwarfDebug {
-  // Target of Dwarf emission.
-  AsmPrinter *Asm;
-
-  // Collected machine module information.
-  MachineModuleInfo *MMI;
+class DwarfDebug : public AsmDebug {
 
   // All DIEValues are allocated through this allocator.
   BumpPtrAllocator DIEValueAllocator;
-- 
1.8.0.msysgit.0

-------------- next part --------------
>From 9ed5de31dcb9f4ae1ac8091315dce83f2cbfd389 Mon Sep 17 00:00:00 2001
From: kai <kai at redstar.de>
Date: Wed, 28 Nov 2012 21:19:45 +0100
Subject: [PATCH 2/4] Add infrastructure to support other debug information
 formats then DWARF and introduce CodeView as possible
 other format.

Support of debug information formats is modelled analog to EH support. A new
enumeration DebugInformation contains values for all debug information formats.
Flag SupportsDebugInformation is replaced by enum-valued DebugInformationType.
Class AsmPrinter uses DebugInformationType to decide on the XxxDebug class to
 use (currently only DwarfDebug).
There is no functional change intended.

Patch by Kai Nacke.
---
 include/llvm/MC/MCAsmInfo.h                        | 15 +++++++++++----
 lib/CodeGen/AsmPrinter/AsmPrinter.cpp              | 12 ++++++++++--
 lib/MC/MCAsmInfo.cpp                               |  2 +-
 lib/MC/MCAsmInfoCOFF.cpp                           |  2 +-
 lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp       |  4 ++--
 lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp |  2 +-
 lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp     |  2 +-
 lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp   |  3 ++-
 lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp   |  4 ++--
 lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp   |  4 ++--
 lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp       |  4 ++--
 lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp   |  4 ++--
 12 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 97aad71..dbe190e 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -28,6 +28,10 @@ namespace llvm {
   class MCSymbol;
   class MCContext;
 
+  namespace DebugInformation {
+      enum DebugInformationType { None, Dwarf, CodeView };
+  }
+
   namespace ExceptionHandling {
     enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 };
   }
@@ -301,9 +305,9 @@ namespace llvm {
     /// HasLEB128 - True if target asm supports leb128 directives.
     bool HasLEB128;                          // Defaults to false.
 
-    /// SupportsDebugInformation - True if target supports emission of debugging
-    /// information.
-    bool SupportsDebugInformation;           // Defaults to false.
+    /// DebugInformationType - Contains type of debug information to emit.
+    /// Defaults to None.
+    DebugInformation::DebugInformationType DebugInformationType;
 
     /// SupportsExceptionHandling - True if target supports exception handling.
     ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None
@@ -521,7 +525,10 @@ namespace llvm {
       return HasLEB128;
     }
     bool doesSupportDebugInformation() const {
-      return SupportsDebugInformation;
+      return DebugInformationType != DebugInformation::None;
+    }
+    DebugInformation::DebugInformationType getDebugInformationType() const {
+        return DebugInformationType;
     }
     bool doesSupportExceptionHandling() const {
       return ExceptionsType != ExceptionHandling::None;
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 7068211..620b760 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -184,9 +184,17 @@ bool AsmPrinter::doInitialization(Module &M) {
     OutStreamer.AddBlankLine();
   }
 
-  if (MAI->doesSupportDebugInformation())
+  switch (MAI->getDebugInformationType()) {
+  case DebugInformation::None:
+    break;
+  case DebugInformation::Dwarf:
     DI = new DwarfDebug(this, &M);
-
+    break;
+  case DebugInformation::CodeView:
+    llvm_unreachable("CodeView debug support is not yet implemented.");
+    //DI = new CodeViewDebug(this, &M);
+    //break;
+  }
   switch (MAI->getExceptionHandlingType()) {
   case ExceptionHandling::None:
     return false;
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 7ea0f3b..a5b573f 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -81,7 +81,7 @@ MCAsmInfo::MCAsmInfo() {
   HiddenDeclarationVisibilityAttr = MCSA_Hidden;
   ProtectedVisibilityAttr = MCSA_Protected;
   HasLEB128 = false;
-  SupportsDebugInformation = false;
+  DebugInformationType = DebugInformation::None;
   ExceptionsType = ExceptionHandling::None;
   DwarfUsesInlineInfoSection = false;
   DwarfSectionOffsetDirective = 0;
diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
index fd79193..03ecdcc 100644
--- a/lib/MC/MCAsmInfoCOFF.cpp
+++ b/lib/MC/MCAsmInfoCOFF.cpp
@@ -35,7 +35,7 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
 
   // Set up DWARF directives
   HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
   DwarfSectionOffsetDirective = "\t.secrel32\t";
   HasMicrosoftFastStdCallMangling = true;
 }
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
index c1aab9c..d522471 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
@@ -31,7 +31,7 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() {
   Code32Directive = ".code\t32";
   UseDataRegionDirectives = true;
 
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
 
   // Exceptions handling
   ExceptionsType = ExceptionHandling::SjLj;
@@ -52,7 +52,7 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
   WeakRefDirective = "\t.weak\t";
 
   HasLEB128 = true;
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
 
   // Exceptions handling
   if (EnableARMEHABI)
diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp
index 8231f07..34460bb 100644
--- a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp
+++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp
@@ -19,7 +19,7 @@ void MBlazeMCAsmInfo::anchor() { }
 MBlazeMCAsmInfo::MBlazeMCAsmInfo() {
   IsLittleEndian              = false;
   StackGrowsUp                = false;
-  SupportsDebugInformation    = true;
+  DebugInformationType        = DebugInformation::Dwarf;
   AlignmentIsInBytes          = false;
   PrivateGlobalPrefix         = "$";
   GPRel32Directive            = "\t.gpword\t";
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index 9d67aa1..fc795fb 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -35,7 +35,7 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) {
   GPRel64Directive            = "\t.gpdword\t";
   WeakRefDirective            = "\t.weak\t";
 
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
   ExceptionsType = ExceptionHandling::DwarfCFI;
   HasLEB128 = true;
   DwarfRegNumForCFI = true;
diff --git a/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp b/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp
index 1d41665..8050d95 100644
--- a/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp
+++ b/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp
@@ -46,7 +46,8 @@ NVPTXMCAsmInfo::NVPTXMCAsmInfo(const Target &T, const StringRef &TT) {
   InlineAsmStart = " inline asm";
   InlineAsmEnd = " inline asm";
 
-  SupportsDebugInformation = CompileForDebugging;
+  DebugInformationType = CompileForDebugging ? DebugInformation::Dwarf
+                                             : DebugInformation::None;
   HasDotTypeDotSizeDirective = false;
 
   Data8bitsDirective = " .b8 ";
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
index 215aa40..c679836 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
@@ -29,7 +29,7 @@ PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) {
     Data64bitsDirective = 0;      // We can't emit a 64-bit unit in PPC32 mode.
 
   AssemblerDialect = 1;           // New-Style mnemonics.
-  SupportsDebugInformation= true; // Debug information.
+  DebugInformationType = DebugInformation::Dwarf; // Debug information.
 }
 
 void PPCLinuxMCAsmInfo::anchor() { }
@@ -51,7 +51,7 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
   UsesELFSectionDirectiveForBSS = true;  
 
   // Debug Information
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
 
   PCSymbol = ".";
 
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
index f5e10fc..10cf51d 100644
--- a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
+++ b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
@@ -30,8 +30,8 @@ SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, StringRef TT) {
   ZeroDirective = "\t.skip\t";
   CommentString = "!";
   HasLEB128 = true;
-  SupportsDebugInformation = true;
-  
+  DebugInformationType = DebugInformation::Dwarf;
+
   SunStyleELFSectionSwitchSyntax = true;
   UsesELFSectionDirectiveForBSS = true;
 
diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
index 16488eb..25ab975 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -61,7 +61,7 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T) {
   CommentString = "##";
   PCSymbol = ".";
 
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
   DwarfUsesInlineInfoSection = true;
   UseDataRegionDirectives = MarkedJTDataRegions;
 
@@ -91,7 +91,7 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) {
   HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
 
   // Debug Information
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
 
   // Exceptions handling
   ExceptionsType = ExceptionHandling::DwarfCFI;
diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp
index 1cfdbda..ccc73b8 100644
--- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp
+++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp
@@ -14,13 +14,13 @@ using namespace llvm;
 void XCoreMCAsmInfo::anchor() { }
 
 XCoreMCAsmInfo::XCoreMCAsmInfo(const Target &T, StringRef TT) {
-  SupportsDebugInformation = true;
+  DebugInformationType = DebugInformation::Dwarf;
   Data16bitsDirective = "\t.short\t";
   Data32bitsDirective = "\t.long\t";
   Data64bitsDirective = 0;
   ZeroDirective = "\t.space\t";
   CommentString = "#";
-    
+
   PrivateGlobalPrefix = ".L";
   AscizDirective = ".asciiz";
   WeakDefDirective = "\t.weak\t";
-- 
1.8.0.msysgit.0

-------------- next part --------------
>From 1ffec64e950f417e57f933514c5f363761a8a2f9 Mon Sep 17 00:00:00 2001
From: kai <kai at redstar.de>
Date: Sun, 2 Dec 2012 15:24:07 +0100
Subject: [PATCH 3/4] Add getReturnType() to DISubprogram.

Subprogram return types are encoded either as DIType or as
DICompositeType. Currently there is no way to get the return type
if it is encoded as DIType. This functionality is added here.

Patch by Kai Nacke
---
 include/llvm/DebugInfo.h | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h
index 8520eba..d1aaec2 100644
--- a/include/llvm/DebugInfo.h
+++ b/include/llvm/DebugInfo.h
@@ -477,17 +477,21 @@ namespace llvm {
     unsigned getLineNumber() const      { return getUnsignedField(7); }
     DICompositeType getType() const { return getFieldAs<DICompositeType>(8); }
 
-    /// getReturnTypeName - Subprogram return types are encoded either as
-    /// DIType or as DICompositeType.
-    StringRef getReturnTypeName() const {
+    /// \brief Subprogram return types are encoded either as DIType or
+    /// as DICompositeType.
+    DIType getReturnType() const {
       DICompositeType DCT(getFieldAs<DICompositeType>(8));
       if (DCT.Verify()) {
         DIArray A = DCT.getTypeArray();
-        DIType T(A.getElement(0));
-        return T.getName();
+        return DIType(A.getElement(0));
       }
-      DIType T(getFieldAs<DIType>(8));
-      return T.getName();
+      return DIType(getFieldAs<DIType>(8));
+    }
+
+    /// \brief Subprogram return types are encoded either as DIType or
+    /// as DICompositeType.
+    StringRef getReturnTypeName() const {
+      return getReturnType().getName();
     }
 
     /// isLocalToUnit - Return true if this subprogram is local to the current
-- 
1.8.0.msysgit.0

-------------- next part --------------
>From d83193aafdb922bcf8f351ec68420fb3b6f3cdf2 Mon Sep 17 00:00:00 2001
From: kai <kai at redstar.de>
Date: Sat, 1 Dec 2012 21:49:33 +0100
Subject: [PATCH 4/4] Add support for generation of CodeView debug
 information.

Adds the required classes to generate CodeView debug information and
changes the X86MCAsmInfoMicrosoft to use CodeView as debug information
type.

Patch by Kai Nacke
---
 include/llvm/MC/MCObjectFileInfo.h           |   4 +
 include/llvm/Support/CodeView.h              | 613 +++++++++++++++++++++++++++
 lib/CodeGen/AsmPrinter/AsmPrinter.cpp        |   6 +-
 lib/CodeGen/AsmPrinter/CMakeLists.txt        |   1 +
 lib/CodeGen/AsmPrinter/CodeViewDebug.cpp     | 549 ++++++++++++++++++++++++
 lib/CodeGen/AsmPrinter/CodeViewDebug.h       | 130 ++++++
 lib/MC/MCObjectFileInfo.cpp                  |  12 +
 lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp |   2 +
 8 files changed, 1314 insertions(+), 3 deletions(-)
 create mode 100644 include/llvm/Support/CodeView.h
 create mode 100644 lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
 create mode 100644 lib/CodeGen/AsmPrinter/CodeViewDebug.h

diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
index dcde9d9..9d4053c 100644
--- a/include/llvm/MC/MCObjectFileInfo.h
+++ b/include/llvm/MC/MCObjectFileInfo.h
@@ -174,6 +174,8 @@ protected:
   const MCSection *DrectveSection;
   const MCSection *PDataSection;
   const MCSection *XDataSection;
+  const MCSection *DebugSSection;
+  const MCSection *DebugTSection;
 
 public:
   void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM,
@@ -311,6 +313,8 @@ public:
   const MCSection *getDrectveSection() const { return DrectveSection; }
   const MCSection *getPDataSection() const { return PDataSection; }
   const MCSection *getXDataSection() const { return XDataSection; }
+  const MCSection *getDebugSSection() const { return DebugSSection; }
+  const MCSection *getDebugTSection() const { return DebugTSection; }
 
   const MCSection *getEHFrameSection() {
     if (!EHFrameSection)
diff --git a/include/llvm/Support/CodeView.h b/include/llvm/Support/CodeView.h
new file mode 100644
index 0000000..ffdc1d8
--- /dev/null
+++ b/include/llvm/Support/CodeView.h
@@ -0,0 +1,613 @@
+//===------ llvm/Support/CodeView.h --- CodeView Constants ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains constants and structures used for implementing
+/// CodeView debug information on Windows platforms. For more information, see
+/// Visual C++ 5.0 Symbolic Debug Information Specification, Revision 5.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CODEVIEW_H
+#define LLVM_SUPPORT_CODEVIEW_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+namespace CodeView {
+
+#pragma pack(push)
+#pragma pack(1)
+
+/*
+ * The .debug$S segments contains the symbol information. It starts with the
+ * CodeView version (0x0004, 4 bytes).
+ * Then follows a sequence of subsections. General layout of a subsection is:
+ *
+ * +-----------------+ 4-byte aligned
+ * | type (4 bytes)  |
+ * +-----------------+
+ * | length (4bytes) | does not include type, length and padding
+ * +-----------------+
+ * | ...             |
+ * +-----------------+
+ * | padding (0x00)  | only if required, repeated until next
+ * +-----------------+ address is 4-byte aligned
+ *
+ * Currently are 4 subsections defined.
+ *
+ * Type = 0x000f1. Contains the symbol information.
+ *   See CodeViewSymbol below.
+ *
+ * Type = 0x000f2. Line numbers for section.
+ * +-------------------------------------------------------------+
+ * | start offset in section (SECREL to section start) (4 bytes) |
+ * +-------------------------------------------------------------+
+ * | section index (SECTION to section start) (2 bytes)          |
+ * +-------------------------------------------------------------+
+ * | pad/align (0) (2 bytes)                                     |
+ * +-------------------------------------------------------------+
+ * | section length covered by line number info (4 bytes)        |
+ * +-------------------------------------------------------------+
+ * | offset of source file in source file info table (4 bytes)   |
+ * +-------------------------------------------------------------+
+ * | number of line number pairs (4 bytes)                       |
+ * +-------------------------------------------------------------+
+ * | number of bytes of line number pairs + 12 (4 bytes)         |
+ * +-------------------------------------------------------------+
+ *
+ * followed by repeated sequence of
+ *
+ * +-------------------------------------------------------------+
+ * | offset in section (4bytes)                                  |
+ * +-------------------------------------------------------------+
+ * | line number (4bytes)                                        |
+ * +-------------------------------------------------------------+
+
+    followed by pairs of:
+      4 bytes - offset in section
+      4 bytes - line number; if high bit is set,
+                end of statement/breakpointable (?) - e.g. lines containing
+          just labels should have line numbers
+
+ *
+ * Type = 0x000f3. Source filename string table.
+    1 byte - 0 (0th filename)
+    0-terminated filename strings, 1 for each source file
+ *
+ *
+ * Type = 0x000f4. Info about source files.
+    for each source file:
+        4 bytes - offset of filename in source filename string table
+  {2 bytes - checksum type/length? (0x0110)
+   16 bytes - MD5 checksum of source file} OR
+  {2 bytes - no checksum (0)}
+  2 bytes - 0 (padding?)
+ */
+
+typedef unsigned long   CV_uoff32_t;
+typedef          long   CV_off32_t;
+typedef unsigned short  CV_uoff16_t;
+typedef          short  CV_off16_t;
+typedef unsigned short  CV_typ_t;
+
+enum {
+  CV_SIGNATURE_C7 = 0x0001,
+  CV_SIGNATURE_C8 = 0x0004
+};
+
+enum {
+  Symbol_Section = 0x00f1,
+  Line_Number_Section = 0x00f2,
+  Sourcefile_Table_Section = 0x00f3,
+  Sourcefile_Info_Section = 0x00f4
+};
+
+enum CodeViewSymbolId {
+  S_COMPILE_V1 = 0x0001,     // Compile flags symbol
+  S_REGISTER_V1 = 0x0002,    // Register variable
+  S_CONSTANT_V1 = 0x0003,    // Constant symbol
+  S_UDT_V1 = 0x0004,         // User-defined Type
+  S_SSEARCH_V1 = 0x0005,     // Start search
+  S_END_V1 = 0x0006,         // End block, procedure, with, or thunk
+  S_SKIP_V1 = 0x0007,        // Skip - Reserve symbol space
+  S_CVRESERVE_V1 = 0x0008,   // Reserved for CodeView internal use
+  S_OBJNAME_V1 = 0x0009,     // Specify name of object file
+  S_ENDARG_V1 = 0x000a,      // Specify end of arguments in function symbols
+  S_COBOLUDT_V1 = 0x000b,    // Microfocus COBOL user-defined type
+  S_MANYREG_V1 = 0x000c,     // Many register symbol
+  S_RETURN_V1 = 0x000d,      // Function return description
+  S_ENTRYTHIS_V1 = 0x000e,   // Description of this pointer at entry
+
+  /* 16 bit entry omitted */
+
+  S_BPREL_V1 = 0x0200,       // BP relative 16:32
+  S_LDATA_V1 = 0x0201,       // Local data 16:32
+  S_GDATA_V1 = 0x0202,       // Global data 16:32
+  S_PUB_V1 = 0x0203,         // Public symbol 16:32
+  S_LPROC_V1 = 0x0204,       // Local procedure start 16:32
+  S_GPROC_V1 = 0x0205,       // Global procedure start 16:32
+  S_THUNK_V1 = 0x0206,       // Thunk start 16:32
+  S_BLOCK_V1 = 0x0207,       // Block start 16:32
+  S_WITH_V1 = 0x0208,        // With start 16:32
+  S_LABEL_V1 = 0x0209,       // Label 16:32
+  S_VFTPATH_V1 = 0x020b,     // Virtual function table path descriptor 16:32
+  S_REGREL_V1 = 0x020c,      // 16:32 offset relative to arbitrary register
+  S_LTHREAD_V1 = 0x020d,     // Local Thread Storage data
+  S_GTHREAD_V1 = 0x020e,     // Global Thread Storage data
+
+  S_LPROCMIPS_V1 = 0x0300,   // Local procedure start MIPS
+  S_GPROCMIPS_V1 = 0x0301,   // Global procedure start MIPS
+
+  S_PROCREF = 0x0400,        // Reference to a procedure
+  S_DATAREF = 0x0401,        // Reference to data
+  S_ALIGN = 0x0402,          // Page align symbols
+  S_LPROCREF_V1 = 0x0403,
+
+  S_REGISTER_V2 = 0x1001,    // Register variable
+  S_CONSTANT_V2 = 0x1002,    // Constant symbol
+  S_UDT_V2 = 0x1003,         // User-defined type
+  S_COBOLUDT_V2 = 0x1004,    // Microfocus COBOL user-defined type
+  S_MANYREG_V2 = 0x1005,     // Many register symbol
+  S_BPREL_V2 = 0x1006,       // BP relative 16:32
+  S_LDATA_V2 = 0x1007,       // Local data 16:32
+  S_GDATA_V2 = 0x1008,       // Global data 16:32
+  S_PUB_V2 = 0x1009,         // Public symbol 16:32
+  S_LPROC_V2 = 0x100a,       // Local procedure start 16:32
+  S_GPROC_V2 = 0x100b,       // Global procedure start 16:32
+  S_VFTTABLE_V2 = 0x100c,    // Virtual function table path descriptor 16:32
+  S_REGREL_V2 = 0x100d,      // 16:32 offset relative to arbitrary register
+  S_LTHREAD_V2 = 0x100e,     // Local Thread Storage data
+  S_GTHREAD_V2 = 0x100f,     // Global Thread Storage data
+  S_LPROCMIPS_V2 = 0x1010,   // Local procedure start MIPS
+  S_GPROCMIPS_V2 = 0x1011,   // Global procedure start MIPS
+  S_FRAMEINFO_V2 = 0x1012,
+  S_COMPILAND_V2 = 0x1013,
+
+  S_OBJNAME_V2 = 0x1101,
+  S_THUNK_V3 = 0x1102,
+  S_BLOCK_V3 = 0x1103,
+  S_LABEL_V3 = 0x1105,
+  S_REGISTER_V3 = 0x1106,
+  S_CONSTANT_V3 = 0x1107,
+  S_UDT_V3 = 0x1108,
+  S_BPREL_V3 = 0x110B,
+  S_LDATA_V3 = 0x110C,
+  S_GDATA_V3 = 0x110D,
+  S_PUB_V3 = 0x110E,
+  S_LPROC_V3 = 0x110F,
+  S_GPROC_V3 = 0x1110,
+  S_REGREL_V3 = 0x1111,
+  S_LTHREAD_V3 = 0x1112,
+  S_GTHREAD_V3 = 0x1113,
+  S_MSTOOL_V3 = 0x1116,
+  S_PUB_FUNC1_V3 = 0x1125,
+  S_PUB_FUNC2_V3 = 0x1127,
+  S_SECTINFO_V3 = 0x1136,
+  S_SUBSECTINFO_V3 = 0x1137,
+  S_ENTRYPOINT_V3 = 0x1138,
+  S_SECUCOOKIE_V3 = 0x113A,
+  S_MSTOOLINFO_V3 = 0x113C,
+  S_MSTOOLENV_V3 = 0x113D
+};
+
+union CodeViewSymbol {
+  struct {
+    uint16_t Length;
+    uint16_t SymbolId;
+  } Generic;
+  struct {
+    uint16_t Length;
+    uint16_t SymbolId; // == S_OBJNAME_V2
+    uint32_t Signature;
+    char Objname[1];
+  } Objname_V2;
+};
+
+
+/*
+struct CodeViewLineNumer {
+  uint32_t Offset;
+  uint32_t LinenumStart;
+  uint32_t DeltaLineEnd;
+  uint32_t FStatement;
+};
+
+typedef struct CodeViewColumn {
+  uint16_t offColumnStart;
+  uint16_t offColumnEnd;
+};
+*/
+
+/*
+ * The .debug$T segments contains the type information. It starts with the
+ * CodeView version (0x0004, 4 bytes). Then follows a sequence of type
+ * records. A type record has the following structure:
+ *
+ * +----------------+-------------------------------+
+ * | type (2 bytes) | type string (0 or more bytes) |
+ * +----------------+-------------------------------+
+ *
+ * A type string is a repeated sequence of leaf structures:
+ *
+ * +----------------+------------------------+
+ * | leaf (2 bytes) | data (0 or more bytes) | (possible repeated)
+ * +----------------+------------------------+
+ *
+ *
+ */
+
+enum {
+  LF_MODIFIER_V1 = 0x0001,
+  LF_POINTER_V1 = 0x0002,
+  LF_ARRAY_V1 = 0x0003,
+  LF_CLASS_V1 = 0x0004,
+  LF_STRUCTURE_V1 = 0x0005,
+  LF_UNION_V1 = 0x0006,
+  LF_ENUM_V1 = 0x0007,
+  LF_PROCEDURE_V1 = 0x0008,
+  LF_MFUNCTION_V1 = 0x0009,
+  LF_VTSHAPE_V1 = 0x000a,
+  LF_COBOL0_V1 = 0x000b,
+  LF_COBOL1_V1 = 0x000c,
+  LF_BARRAY_V1 = 0x000d,
+  LF_LABEL_V1 = 0x000e,
+  LF_NULL_V1 = 0x000f,
+  LF_NOTTRAN_V1 = 0x0010,
+  LF_DIMARRAY_V1 = 0x0011,
+  LF_VFTPATH_V1 = 0x0012,
+  LF_PRECOMP_V1 = 0x0013,
+  LF_ENDPRECOMP_V1 = 0x0014,
+  LF_OEM_V1 = 0x0015,
+  LF_TYPESERVER_V1 = 0x0016,
+
+  LF_MODIFIER_V2 = 0x1001,     /* variants with new 32-bit type indices (V2) */
+  LF_POINTER_V2 = 0x1002,
+  LF_ARRAY_V2 = 0x1003,
+  LF_CLASS_V2 = 0x1004,
+  LF_STRUCTURE_V2 = 0x1005,
+  LF_UNION_V2 = 0x1006,
+  LF_ENUM_V2 = 0x1007,
+  LF_PROCEDURE_V2 = 0x1008,
+  LF_MFUNCTION_V2 = 0x1009,
+  LF_COBOL0_V2 = 0x100a,
+  LF_BARRAY_V2 = 0x100b,
+  LF_DIMARRAY_V2 = 0x100c,
+  LF_VFTPATH_V2 = 0x100d,
+  LF_PRECOMP_V2 = 0x100e,
+  LF_OEM_V2 = 0x100f,
+
+  LF_SKIP_V1 = 0x0200,
+  LF_ARGLIST_V1 = 0x0201,
+  LF_DEFARG_V1 = 0x0202,
+  LF_LIST_V1 = 0x0203,
+  LF_FIELDLIST_V1 = 0x0204,
+  LF_DERIVED_V1 = 0x0205,
+  LF_BITFIELD_V1 = 0x0206,
+  LF_METHODLIST_V1 = 0x0207,
+  LF_DIMCONU_V1 = 0x0208,
+  LF_DIMCONLU_V1 = 0x0209,
+  LF_DIMVARU_V1 = 0x020a,
+  LF_DIMVARLU_V1 = 0x020b,
+  LF_REFSYM_V1 = 0x020c,
+
+  LF_SKIP_V2 = 0x1200,    /* variants with new 32-bit type indices (V2) */
+  LF_ARGLIST_V2 = 0x1201,
+  LF_DEFARG_V2 = 0x1202,
+  LF_FIELDLIST_V2 = 0x1203,
+  LF_DERIVED_V2 = 0x1204,
+  LF_BITFIELD_V2 = 0x1205,
+  LF_METHODLIST_V2 = 0x1206,
+  LF_DIMCONU_V2 = 0x1207,
+  LF_DIMCONLU_V2 = 0x1208,
+  LF_DIMVARU_V2 = 0x1209,
+  LF_DIMVARLU_V2 = 0x120a,
+
+  /* Field lists */
+  LF_BCLASS_V1 = 0x0400,
+  LF_VBCLASS_V1 = 0x0401,
+  LF_IVBCLASS_V1 = 0x0402,
+  LF_ENUMERATE_V1 = 0x0403,
+  LF_FRIENDFCN_V1 = 0x0404,
+  LF_INDEX_V1 = 0x0405,
+  LF_MEMBER_V1 = 0x0406,
+  LF_STMEMBER_V1 = 0x0407,
+  LF_METHOD_V1 = 0x0408,
+  LF_NESTTYPE_V1 = 0x0409,
+  LF_VFUNCTAB_V1 = 0x040a,
+  LF_FRIENDCLS_V1 = 0x040b,
+  LF_ONEMETHOD_V1 = 0x040c,
+  LF_VFUNCOFF_V1 = 0x040d,
+  LF_NESTTYPEEX_V1 = 0x040e,
+  LF_MEMBERMODIFY_V1 = 0x040f,
+
+  LF_BCLASS_V2 = 0x1400,    /* variants with new 32-bit type indices (V2) */
+  LF_VBCLASS_V2 = 0x1401,
+  LF_IVBCLASS_V2 = 0x1402,
+  LF_FRIENDFCN_V2 = 0x1403,
+  LF_INDEX_V2 = 0x1404,
+  LF_MEMBER_V2 = 0x1405,
+  LF_STMEMBER_V2 = 0x1406,
+  LF_METHOD_V2 = 0x1407,
+  LF_NESTTYPE_V2 = 0x1408,
+  LF_VFUNCTAB_V2 = 0x1409,
+  LF_FRIENDCLS_V2 = 0x140a,
+  LF_ONEMETHOD_V2 = 0x140b,
+  LF_VFUNCOFF_V2 = 0x140c,
+  LF_NESTTYPEEX_V2 = 0x140d,
+
+  LF_ENUMERATE_V3 = 0x1502,
+  LF_ARRAY_V3 = 0x1503,
+  LF_CLASS_V3 = 0x1504,
+  LF_STRUCTURE_V3 = 0x1505,
+  LF_UNION_V3 = 0x1506,
+  LF_ENUM_V3 = 0x1507,
+  LF_MEMBER_V3 = 0x150d,
+  LF_STMEMBER_V3 = 0x150e,
+  LF_METHOD_V3 = 0x150f,
+  LF_NESTTYPE_V3 = 0x1510,
+  LF_ONEMETHOD_V3 = 0x1511,
+
+  LF_NUMERIC = 0x8000,    /* numeric leaf types */
+  LF_CHAR = 0x8000,
+  LF_SHORT = 0x8001,
+  LF_USHORT = 0x8002,
+  LF_LONG = 0x8003,
+  LF_ULONG = 0x8004,
+  LF_REAL32 = 0x8005,
+  LF_REAL64 = 0x8006,
+  LF_REAL80 = 0x8007,
+  LF_REAL128 = 0x8008,
+  LF_QUADWORD = 0x8009,
+  LF_UQUADWORD = 0x800a,
+  LF_REAL48 = 0x800b,
+  LF_COMPLEX32 = 0x800c,
+  LF_COMPLEX64 = 0x800d,
+  LF_COMPLEX80 = 0x800e,
+  LF_COMPLEX128 = 0x800f,
+  LF_VARSTRING = 0x8010
+};
+
+enum {
+  CV_FIRST_NONPRIM = 0x1000
+};
+
+enum {
+  T_Size_Mask = 0x0007,
+  T_Mode_Mask = 0x0700,
+  T_ModeShift = 8,
+  T_Type_Mask = 0x00f0,
+  T_Type_Shift = 4,
+
+  // types
+  T_Special = 0x00,
+  T_Signed_integral_value = 0x01,
+  T_Unsigned_integral_value = 0x02,
+  T_Boolean = 0x03,
+  T_Real = 0x04,
+  T_Complex = 0x05,
+  T_Special2 = 0x06,
+  T_Real_int_value = 0x07,
+  // 0x08 - 0x0e Reserved
+  // 0x0f Reserved for debugger expression evaluator
+
+  // Size
+  // Type = special
+  T_No_type = 0x00,
+  T_Absolute_symbol = 0x01,
+  T_Segment = 0x02,
+  T_Void = 0x03,
+  T_Basic_8_byte_currency_value = 0x04,
+  T_Near_Basic_string = 0x05,
+  T_Far_Basic_string = 0x06,
+  T_Untranslated_type_from_previous_Microsoft_symbol_formats = 0x07,
+
+  /* bit patterns for the <mode> portion of a built-in type number */
+  T_Near_Ptr_Bits = 0x0100,
+  T_Far_Ptr_Bits = 0x0200,
+  T_Huge_Ptr_Bits = 0x0300,
+  T_Near32_Ptr_Bits = 0x0400,
+  T_Far32_Ptr_Bits = 0x0500,
+  T_Near64_Ptr_Bits = 0x0600,
+};
+
+
+enum {
+  // Values for pointer records
+  // Pointers can be one of the following types
+  CV_PTR_NEAR         = 0x00, /* near pointer */
+  CV_PTR_FAR          = 0x01, /* far pointer */
+  CV_PTR_HUGE         = 0x02, /* huge pointer */
+  CV_PTR_BASE_SEG     = 0x03, /* based on segment */
+  CV_PTR_BASE_VAL     = 0x04, /* based on value of base */
+  CV_PTR_BASE_SEGVAL  = 0x05, /* based on segment value of base */
+  CV_PTR_BASE_ADDR    = 0x06, /* based on address of base */
+  CV_PTR_BASE_SEGADDR = 0x07, /* based on segment address of base */
+  CV_PTR_BASE_TYPE    = 0x08, /* based on type */
+  CV_PTR_BASE_SELF    = 0x09, /* based on self */
+  CV_PTR_NEAR32       = 0x0a, /* 16:32 near pointer */
+  CV_PTR_FAR32        = 0x0b, /* 16:32 far pointer */
+  CV_PTR_64           = 0x0c, /* 64 bit pointer */
+  CV_PTR_UNUSEDPTR    = 0x0d, /* first unused pointer type */
+
+
+
+
+
+
+
+
+  // Values for function call type
+  CV_CALL_NEAR_C      = 0x00, // near right to left push, caller pops stack
+  CV_CALL_FAR_C       = 0x01, // far right to left push, caller pops stack
+  CV_CALL_NEAR_PASCAL = 0x02, // near left to right push, callee pops stack
+  CV_CALL_FAR_PASCAL  = 0x03, // far left to right push, callee pops stack
+  CV_CALL_NEAR_FAST   = 0x04, // near left to right push with regs, callee pops stack
+  CV_CALL_FAR_FAST    = 0x05, // far left to right push with regs, callee pops stack
+  CV_CALL_SKIPPED     = 0x06, // skipped (unused) call index
+  CV_CALL_NEAR_STD    = 0x07, // near standard call
+  CV_CALL_FAR_STD     = 0x08, // far standard call
+  CV_CALL_NEAR_SYS    = 0x09, // near sys call
+  CV_CALL_FAR_SYS     = 0x0a, // far sys call
+  CV_CALL_THISCALL    = 0x0b, // this call (this passed in register)
+  CV_CALL_MIPSCALL    = 0x0c, // Mips call
+  CV_CALL_GENERIC     = 0x0d, // Generic call sequence
+  CV_CALL_ALPHACALL   = 0x0e, // Alpha call
+  CV_CALL_PPCCALL     = 0x0f, // PPC call
+  CV_CALL_RESERVED    = 0x10, // first unused call enumeration
+
+
+};
+
+//      enumeration for LF_MODIFIER values
+
+
+struct CV_modifier_t {
+  unsigned short  MOD_const       :1;
+  unsigned short  MOD_volatile    :1;
+  unsigned short  MOD_unaligned   :1;
+  unsigned short  MOD_unused      :13;
+};
+
+
+//      bit field structure describing class/struct/union/enum properties
+
+struct CV_prop_t {
+    unsigned short  packed      :1;     // true if structure is packed
+    unsigned short  ctor        :1;     // true if constructors or destructors present
+    unsigned short  ovlops      :1;     // true if overloaded operators present
+    unsigned short  isnested    :1;     // true if this is a nested class
+    unsigned short  cnested     :1;     // true if this class contains nested types
+    unsigned short  opassign    :1;     // true if overloaded assignment (=)
+    unsigned short  opcast      :1;     // true if casting methods
+    unsigned short  fwdref      :1;     // true if forward reference (incomplete defn)
+    unsigned short  scoped      :1;     // scoped definition
+    unsigned short  reserved    :7;
+};
+
+
+
+
+//      class field attribute
+
+struct CV_fldattr_t {
+    unsigned short  access      :2;     // access protection CV_access_t
+    unsigned short  mprop       :3;     // method properties CV_methodprop_t
+    unsigned short  pseudo      :1;     // compiler generated fcn and does not exist
+    unsigned short  noinherit   :1;     // true if class cannot be inherited
+    unsigned short  noconstruct :1;     // true if class cannot be constructed
+    unsigned short  unused      :8;     // unused
+};
+
+// Argument list leaf
+struct Arglist_V2 {
+  uint16_t leaf;           // LF_ARGLIST_V2
+  uint32_t argcount;       // count of number of indices in list
+  uint32_t indices[1];     // type indices of argument types
+};
+struct Procedure_V1 {
+  uint16_t leaf;           // LF_PROCEDURE_V1
+  uint16_t rvtype;         // type index of return value
+  uint8_t  calltype;       // calling convention (CV_call_t)
+  uint8_t  reserved;       // reserved for future use
+  uint16_t parmcount;      // number of parameters
+  uint16_t arglist;        // type index of argument list
+};
+struct Procedure_V2 {
+  uint16_t leaf;           // LF_PROCEDURE_V2
+  uint32_t rvtype;         // type index of return value
+  uint8_t calltype;        // calling convention (CV_call_t)
+  uint8_t reserved;        // reserved for future use
+  uint16_t parmcount;      // number of parameters
+  uint32_t arglist;        // type index of argument list
+};
+struct Struct_v3 {
+  uint16_t leaf;           // LF_STRUCT_V3
+  uint16_t n_element;
+  uint16_t property;
+  uint16_t fieldlist;
+  uint16_t derived;
+  uint16_t vshape;
+  uint32_t structlen;  /* numeric leaf */
+  char                    name[1];
+} ;
+struct Modifier_v2
+{
+  uint16_t leaf;           // LF_MODIFIER_V2
+  uint32_t type;
+  uint16_t attribute;
+
+  bool isConst() { return attribute & 0x01; }
+  void setConst(bool b)
+    { if (b) attribute |= 0x01; else attribute &= ~0x01; }
+  bool isVolatile() { return attribute & 0x02; }
+  void setVolatile(bool b)
+    { if (b) attribute |= 0x02; else attribute &= ~0x02; }
+  bool isUnaligned() { return attribute & 0x04; }
+  void setUnaligned(bool b)
+    { if (b) attribute |= 0x04; else attribute &= ~0x04; }
+};
+
+// Pointer lead
+struct Pointer_v2
+{
+  uint16_t leaf;           // LF_POINTER_V2
+  uint32_t type;
+  uint32_t attribute;
+};
+
+// Field list leaf
+// This is the header leaf for a complex list of class and structure subfields.
+struct FieldList {
+  uint16_t leaf;           // LF_FIELDLIST
+  char data[];             // field list sub lists
+};
+
+
+// subfield record for non-static data members
+struct Member_v2 {
+  uint16_t leaf;            // LF_MEMBER_V2
+  CV_typ_t        index;      // index of type record for field
+  CV_fldattr_t    attr;       // attribute mask
+  unsigned char   offset[];   // variable length offset of field followed
+                              // by length prefixed name of field
+};
+
+
+union Leaf {
+  struct {
+    uint16_t Leaf;
+    uint8_t Data;
+  } Generic;
+  struct {
+    unsigned short  leaf;           // LF_MODIFIER
+    CV_modifier_t   attr;           // modifier attribute modifier_t
+    CV_typ_t        type;           // modified type
+  } Modifier;
+  struct {
+    unsigned short  leaf;           // LF_ENUM
+    unsigned short  count;          // count of number of elements in class
+    CV_typ_t        utype;          // underlying type of the enum
+    CV_typ_t        field;          // type index of LF_FIELD descriptor list
+    CV_prop_t       property;       // property attribute field
+    unsigned char   Name[1];        // length prefixed name of enum
+  } Enum;
+  Arglist_V2 Arglist_V2;
+  Modifier_v2 Modifier_v2;
+  Pointer_v2 Pointer_v2;
+  Procedure_V1 Procedure_V1;
+  Procedure_V2 Procedure_V2;
+};
+
+#pragma pack(pop)
+
+} // End of namespace CodeView
+} // End of namespace llvm
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 620b760..3855a77 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -14,6 +14,7 @@
 #define DEBUG_TYPE "asm-printer"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "AsmDebug.h"
+#include "CodeViewDebug.h"
 #include "DwarfDebug.h"
 #include "DwarfException.h"
 #include "llvm/DebugInfo.h"
@@ -191,9 +192,8 @@ bool AsmPrinter::doInitialization(Module &M) {
     DI = new DwarfDebug(this, &M);
     break;
   case DebugInformation::CodeView:
-    llvm_unreachable("CodeView debug support is not yet implemented.");
-    //DI = new CodeViewDebug(this, &M);
-    //break;
+    DI = new CodeViewDebug(this, &M);
+    break;
   }
   switch (MAI->getExceptionHandlingType()) {
   case ExceptionHandling::None:
diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 58fe2ed..213cd22 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_library(LLVMAsmPrinter
   AsmPrinter.cpp
   AsmPrinterDwarf.cpp
   AsmPrinterInlineAsm.cpp
+  CodeViewDebug.cpp
   DIE.cpp
   DwarfAccelTable.cpp
   DwarfCFIException.cpp
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
new file mode 100644
index 0000000..37a13dc
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -0,0 +1,549 @@
+//=== llvm/CodeGen/CodeViewDebug.cpp - CodeView Debug Framework -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains support for writing codeview debug info into
+/// asm files.
+///
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "codeviewdebug"
+#include "CodeViewDebug.h"
+#include "llvm/Constants.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/DIBuilder.h"
+#include "llvm/Module.h"
+#include "llvm/Instructions.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/DataLayout.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ValueHandle.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/Path.h"
+#include <string>
+#include <vector>
+using namespace llvm;
+
+namespace {
+  const char *CodeViewGroupName = "CodeView Emission";
+  const char *DbgTimerName = "CodeView Debug Writer";
+} // end anonymous namespace
+
+static void emit(AsmPrinter *Asm, const CodeView::Modifier_v2 &Leaf) {
+  assert(Leaf.leaf == CodeView::LF_MODIFIER_V2 && "Unexpected leaf type");
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Leaf type LF_MODIFIER_V2");
+  Asm->EmitInt16(Leaf.leaf);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Type index");
+  Asm->EmitInt32(Leaf.type);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Attribute");
+  Asm->EmitInt16(Leaf.attribute);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Padding");
+  Asm->EmitInt16(0xf1f2);
+}
+
+static void emit(AsmPrinter *Asm, const CodeView::Pointer_v2 &Leaf) {
+  assert(Leaf.leaf == CodeView::LF_POINTER_V2 && "Unexpected leaf type");
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Leaf type LF_POINTER_V2");
+  Asm->EmitInt16(Leaf.leaf);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Type index");
+  Asm->EmitInt32(Leaf.type);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Attribute");
+  Asm->EmitInt32(Leaf.attribute);
+}
+
+static void emit(AsmPrinter *Asm, const CodeView::Arglist_V2 &Leaf) {
+  assert(Leaf.leaf == CodeView::LF_ARGLIST_V2 && "Unexpected leaf type");
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Leaf type LF_ARGLIST_V2");
+  Asm->EmitInt16(Leaf.leaf);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Number of type indices");
+  Asm->EmitInt32(Leaf.argcount);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Type indices");
+  for (uint32_t I = 0, E = Leaf.argcount; I < E; ++I) {
+    Asm->EmitInt32(Leaf.indices[I]);
+  } 
+}
+
+static void emit(AsmPrinter *Asm, const CodeView::Procedure_V2 &Leaf) {
+  assert(Leaf.leaf == CodeView::LF_PROCEDURE_V2 && "Unexpected leaf type");
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Leaf type LF_PROCEDURE_V2");
+  Asm->EmitInt16(Leaf.leaf);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Type index of return value");
+  Asm->EmitInt32(Leaf.rvtype);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Calling convention");
+  Asm->EmitInt8(Leaf.calltype);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Reserved");
+  Asm->EmitInt8(Leaf.reserved);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Number of parameters");
+  Asm->EmitInt16(Leaf.parmcount);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Type index of parameter list");
+  Asm->EmitInt32(Leaf.arglist);
+}
+
+// Add a new leaf record, returns index
+uint16_t TypeStringManager::add(LeafRecord *Record) {
+  uint16_t idx = CodeView::CV_FIRST_NONPRIM + NextIndex;
+  TypesString.push_back(Record);
+  ++NextIndex;
+  return idx;
+}
+
+uint32_t TypeStringManager::size() {
+  uint64_t Size = 0;
+  for (LeafVector::const_iterator I = TypesString.cbegin(),
+                                  E =  TypesString.cend();
+                                  I != E;
+                                  ++I) {
+    LeafRecord *Rec = *I;
+    Size += (2 /*Size of Leaf Type*/ + Rec->Length);
+  }
+  assert(Size <= UINT32_MAX && "Type string is oversized");
+  return static_cast<uint32_t>(Size);
+}
+
+// Emit the records
+void TypeStringManager::emit(AsmPrinter *Asm) {
+  for (LeafVector::const_iterator I = TypesString.cbegin(),
+                                  E =  TypesString.cend();
+                                  I != E;
+                                  ++I) {
+    LeafRecord *Rec = *I;
+    if (Asm->isVerbose())
+      Asm->OutStreamer.AddComment("Length");
+    assert(Rec->Length <= UINT16_MAX);
+    Asm->EmitInt16(Rec->Length);
+    switch (Rec->Leaf.Generic.Leaf) {
+    default: llvm_unreachable("Unimplemented leaf type");
+    case CodeView::LF_ARGLIST_V2: ::emit(Asm, Rec->Leaf.Arglist_V2); break;
+    case CodeView::LF_MODIFIER_V2: ::emit(Asm, Rec->Leaf.Modifier_v2); break;
+    case CodeView::LF_POINTER_V2: ::emit(Asm, Rec->Leaf.Pointer_v2); break;
+    case CodeView::LF_PROCEDURE_V2: ::emit(Asm, Rec->Leaf.Procedure_V2); break;
+    }
+  }
+}
+
+uint16_t TypeStringManager::toReservedType(const DIBasicType &type) {
+  enum {
+    SV = CodeView::T_Signed_integral_value << CodeView::T_Type_Shift,
+    UV = CodeView::T_Unsigned_integral_value << CodeView::T_Type_Shift,
+    BV = CodeView::T_Boolean << CodeView::T_Type_Shift,
+    RV = CodeView::T_Real << CodeView::T_Type_Shift,
+    RiV = CodeView::T_Real_int_value << CodeView::T_Type_Shift,
+
+  };
+  uint16_t Res = 0U;
+  // Encode size
+  switch (type.getEncoding())
+  {
+  case dwarf::DW_ATE_boolean:
+  case dwarf::DW_ATE_signed:
+  case dwarf::DW_ATE_signed_char:
+  case dwarf::DW_ATE_unsigned:
+  case dwarf::DW_ATE_unsigned_char:
+  case dwarf::DW_ATE_UTF:
+    switch (type.getSizeInBits()) {
+    default: llvm_unreachable("wrong bit size");
+    case  8: Res |= 0; break;
+    case 16: Res |= 1; break;
+    case 32: Res |= 2; break;
+    case 64: Res |= 3; break;
+    }
+    break;
+  case dwarf::DW_ATE_float:
+  case dwarf::DW_ATE_complex_float:
+  case dwarf::DW_ATE_imaginary_float:
+    switch (type.getSizeInBits()) {
+    default: llvm_unreachable("wrong bit size");
+    case 32: Res |= 0; break;
+    case 64: Res |= 1; break;
+    case 80: Res |= 2; break;
+    case 128: Res |= 3; break;
+    case 48: Res |= 4; break;
+    }
+    break;
+  }
+  // Encode type
+  switch (type.getEncoding())
+  {
+  case dwarf::DW_ATE_address:
+    break;
+  case dwarf::DW_ATE_boolean:
+    Res |= CodeView::T_Boolean << CodeView::T_Type_Shift;
+    break;
+  case dwarf::DW_ATE_complex_float:
+    Res |= CodeView::T_Complex << CodeView::T_Type_Shift;
+    break;
+  case dwarf::DW_ATE_float:
+    Res |= CodeView::T_Real << CodeView::T_Type_Shift;
+    break;
+  case dwarf::DW_ATE_signed:
+    Res |= CodeView::T_Signed_integral_value << CodeView::T_Type_Shift;
+    break;
+  case dwarf::DW_ATE_signed_char:
+    break;
+  case dwarf::DW_ATE_unsigned:
+    Res |= CodeView::T_Unsigned_integral_value << CodeView::T_Type_Shift;
+    break;
+  case dwarf::DW_ATE_unsigned_char:
+    break;
+  case dwarf::DW_ATE_imaginary_float:
+  case dwarf::DW_ATE_packed_decimal:
+  case dwarf::DW_ATE_numeric_string:
+  case dwarf::DW_ATE_edited:
+  case dwarf::DW_ATE_signed_fixed:
+  case dwarf::DW_ATE_unsigned_fixed:
+  case dwarf::DW_ATE_decimal_float:
+  case dwarf::DW_ATE_UTF:
+  case dwarf::DW_ATE_lo_user:
+  case dwarf::DW_ATE_hi_user:
+    llvm_unreachable("Not yet implemented.");
+    break;
+  }
+  assert(Res < CodeView::CV_FIRST_NONPRIM &&
+         "Primitive type index not lower than CV_FIRST_NONPRIM");
+  return Res;
+}
+
+uint32_t TypeStringManager::toTypeIdx(const DIType &Type) {
+  outs() << "toTypeIdx: tag = " << Type.getTag() << "\n";
+  uint32_t Res = 0;
+  if (Type.isBasicType()) {
+    return toReservedType(DIBasicType(Type));
+  }
+  else if (Type.isCompositeType()) {
+    outs() << "CompositeType\n";
+    Type.print(outs()); outs() << "\n"; outs().flush();
+    DICompositeType dct(Type);
+    outs().flush();
+  }
+  else if (Type.isDerivedType()) {
+    DIDerivedType DDT(Type);
+    uint32_t BaseIdx = toTypeIdx(DDT.getTypeDerivedFrom());
+    if (BaseIdx < CodeView::CV_FIRST_NONPRIM &&
+        !(BaseIdx & CodeView::T_Mode_Mask) &&
+        DDT.getTag() == dwarf::DW_TAG_pointer_type) {
+      Res = BaseIdx | CodeView::T_Near64_Ptr_Bits; // FIXME: 32bit
+      outs() << "Modifying base type\n";
+    }
+    else if (DDT.getTag() == dwarf::DW_TAG_const_type ||
+             DDT.getTag() == dwarf::DW_TAG_volatile_type) {
+      LeafRecord *Rec = LeafRecord::create(CodeView::LF_MODIFIER_V2,
+                                       sizeof(CodeView::Modifier_v2));
+      Rec->Leaf.Modifier_v2.type = BaseIdx;
+      Rec->Leaf.Modifier_v2.attribute = 0;
+      if (DDT.getTag() == dwarf::DW_TAG_const_type)
+        Rec->Leaf.Modifier_v2.setConst(true);
+      if (DDT.getTag() == dwarf::DW_TAG_volatile_type)
+        Rec->Leaf.Modifier_v2.setVolatile(true);
+      Res = add(Rec);
+      outs() << "Adding modifier const: " << Rec->Leaf.Modifier_v2.isConst()
+              << " volatile: " << Rec->Leaf.Modifier_v2.isVolatile() << "\n";
+    }
+    else if (DDT.getTag() == dwarf::DW_TAG_pointer_type) {
+      LeafRecord *Rec = LeafRecord::create(CodeView::LF_POINTER_V2,
+                                       sizeof(CodeView::Pointer_v2));
+      Rec->Leaf.Pointer_v2.type = BaseIdx;
+      Rec->Leaf.Pointer_v2.attribute = 12; // 64 bit pointer
+      outs() << "Adding incomplete pointer type\n";
+      Res = add(Rec);
+    }
+    else {
+      outs() << "Missing support for something else\n";
+      LeafRecord *Rec = LeafRecord::create(CodeView::LF_MODIFIER_V2,
+                                           sizeof(CodeView::Modifier_v2));
+      Rec->Leaf.Modifier_v2.type = BaseIdx;
+      Rec->Leaf.Modifier_v2.attribute = 0; // FIXME
+      Res = add(Rec);
+    }
+  }
+  else {
+    outs() << "Type not implemented: "; Type.print(outs()); outs() << "\n"; outs().flush();
+    //llvm_unreachable("Not yet implemented.");
+  }
+  return Res;
+}
+
+uint32_t TypeStringManager::parameterToTypeIdx(const DIArray &Vars) {
+  LeafRecord *Rec = LeafRecord::create(CodeView::LF_ARGLIST_V2,
+                                       sizeof(CodeView::Arglist_V2)
+                                       + ((Vars.getNumElements()-1)
+                                       * sizeof(uint32_t)));
+  Rec->Leaf.Arglist_V2.argcount = Vars.getNumElements();
+  uint32_t *Data = reinterpret_cast<uint32_t *>(&Rec->Leaf.Arglist_V2.indices);
+  for (unsigned I = 0, E = Vars.getNumElements(); I != E; ++I) {
+    DIVariable DV(Vars.getElement(I));
+    *Data++ = toTypeIdx(DV.getType());
+  }
+  return add(Rec);
+}
+
+uint32_t TypeStringManager::procedureToTypeIdx(const DISubprogram &Proc) {
+  LeafRecord *Rec = LeafRecord::create(CodeView::LF_PROCEDURE_V2,
+                                       sizeof(CodeView::Procedure_V2));
+  Rec->Leaf.Procedure_V2.rvtype = toTypeIdx(DIType(Proc.getReturnType()));
+  Rec->Leaf.Procedure_V2.calltype = CodeView::CV_CALL_NEAR_PASCAL;
+  Rec->Leaf.Procedure_V2.reserved = 0;
+  Rec->Leaf.Procedure_V2.parmcount = Proc.getVariables().getNumElements();
+  Rec->Leaf.Procedure_V2.arglist = parameterToTypeIdx(Proc.getVariables());
+  return add(Rec);
+}
+
+CodeViewDebug::CodeViewDebug(AsmPrinter *A, Module *M)
+  : AsmDebug(A), TypeString(TypeStringManager()) {
+  {
+    NamedRegionTimer T(DbgTimerName, CodeViewGroupName, TimePassesIsEnabled);
+    beginModule();
+  }
+}
+
+CodeViewDebug::~CodeViewDebug() {
+}
+
+/// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such
+/// as llvm.dbg.enum and llvm.dbg.ty
+void CodeViewDebug::collectInfoFromNamedMDNodes(const Module *M) {
+  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"))
+    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+      const MDNode *N = NMD->getOperand(i);
+      //if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
+      //  constructSubprogramDIE(CU, N);
+    }
+
+  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"))
+    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+      const MDNode *N = NMD->getOperand(i);
+      //if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
+      //  CU->createGlobalVariableDIE(N);
+    }
+
+  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum"))
+    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+      DIType Ty(NMD->getOperand(i));
+      //if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
+      //  CU->getOrCreateTypeDIE(Ty);
+    }
+
+  if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty"))
+    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+      DIType Ty(NMD->getOperand(i));
+      //if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
+      //  CU->getOrCreateTypeDIE(Ty);
+    }
+}
+
+/// beginModule - Emit all Dwarf sections that should come prior to the
+/// content. Create global DIEs and emit initial debug info sections.
+/// This is invoked by the target AsmPrinter.
+void CodeViewDebug::beginModule() {
+  // Gather source modules.
+  std::vector<Sourcefile> Srcfiles;
+
+  const Module *M = MMI->getModule();
+
+  // If module has named metadata anchors then use them, otherwise scan the
+  // module using debug info finder to collect debug info.
+  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
+  if (CU_Nodes) {
+    Srcfiles.reserve(CU_Nodes->getNumOperands());
+    for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
+      DICompileUnit CUNode(CU_Nodes->getOperand(i));
+
+      // FIXME:
+      // - create the type records from the metadata (includes type indices used in symbols)
+      // - create mapping MDNode -> type record / type index
+      {
+        DIArray SPs = CUNode.getSubprograms();
+        for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
+          DISubprogram sub(SPs.getElement(i));
+          TypeString.procedureToTypeIdx(sub);
+        }
+      }
+
+      sys::Path AbsolutePath(CUNode.getDirectory());
+      AbsolutePath.appendComponent(CUNode.getFilename());
+      uint32_t ofs = 1;
+      if (!Srcfiles.empty()) {
+        Sourcefile& prev = Srcfiles[Srcfiles.size()-1];
+        ofs = prev.Offset + prev.Filename.length() + 1;
+      }
+      Srcfiles.push_back(Sourcefile(AbsolutePath.str(), ofs));
+    }
+  } //else if (!collectLegacyDebugInfo(M))
+    //return;
+
+  // Emit .debug$S section
+  Asm->OutStreamer.SwitchSection(
+    Asm->getObjFileLowering().getDebugSSection());
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("CodeView Version");
+  Asm->EmitInt32(CodeView::CV_SIGNATURE_C8);
+  // FIXME: emit S_OBJNAME_V2 symbol
+  // FIXME: emit tool info symbol
+  if (!Srcfiles.empty()) {
+    emitSourcefileTable(Srcfiles);
+    emitSourcefileInfo(Srcfiles);
+  }
+}
+
+/// endModule - Emit all type information.
+///
+void CodeViewDebug::endModule() {
+  // Emit type information for the module
+
+  // Emit .debug$T section
+  Asm->OutStreamer.SwitchSection(
+    Asm->getObjFileLowering().getDebugTSection());
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("CodeView Version");
+  Asm->EmitInt32(CodeView::CV_SIGNATURE_C8);
+  TypeString.emit(Asm);
+}
+
+/// beginInstruction - Process beginning of an instruction.
+void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
+}
+
+/// endInstruction - Process end of an instruction.
+void CodeViewDebug::endInstruction(const MachineInstr *MI) {
+}
+
+/// beginFunction - Gather pre-function debug information.  Assumes being
+/// emitted immediately after the function entry point.
+void CodeViewDebug::beginFunction(const MachineFunction *MF) {
+  MCSymbol* FunctionBeginSym = Asm->GetTempSymbol("func_begin",
+                                        Asm->getFunctionNumber());
+  // Assumes in correct section after the entry point.
+  Asm->OutStreamer.EmitLabel(FunctionBeginSym);
+
+  //MF->
+
+  // Record function type
+  // Length, leaf, data, leaf, data, ....
+  // Record symbol data
+}
+
+/// endFunction - Gather and emit post-function debug information.
+///
+void CodeViewDebug::endFunction(const MachineFunction *MF) {
+  // Emit symbol information for the function
+
+  // Emit .debug$S section
+  Asm->OutStreamer.SwitchSection(
+    Asm->getObjFileLowering().getDebugSSection());
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("CodeView Version");
+  Asm->EmitInt32(CodeView::CV_SIGNATURE_C8);
+}
+
+//===----------------------------------------------------------------------===//
+// Emit Methods
+//===----------------------------------------------------------------------===//
+
+void CodeViewDebug::emitSourcefileTable(std::vector<Sourcefile> Srcfiles) {
+  // Calculate length
+  uint32_t length = 1;
+  for (std::vector<Sourcefile>::const_iterator I = Srcfiles.begin(),
+                                               E = Srcfiles.end();
+                                               I != E; ++I) {
+    length += (*I).Filename.size() + 1;
+  }
+
+  // Emit
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Sourcefile string table");
+  Asm->EmitInt32(CodeView::Sourcefile_Table_Section);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Length of data");
+  Asm->EmitInt32(length);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("0th filename");
+  Asm->EmitInt8(0);
+
+  for (std::vector<Sourcefile>::const_iterator I = Srcfiles.begin(),
+                                               E = Srcfiles.end();
+                                               I != E; ++I) {
+    const std::string& Filename = (*I).Filename;
+    if (Asm->isVerbose())
+      Asm->OutStreamer.AddComment("Filename");
+    emitStringZ(Filename);
+  }
+  emitPadding(length);
+}
+
+void CodeViewDebug::emitSourcefileInfo(std::vector<Sourcefile> Srcfiles) {
+  // Emit
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Sourcefile information");
+  Asm->EmitInt32(CodeView::Sourcefile_Info_Section);
+  if (Asm->isVerbose())
+    Asm->OutStreamer.AddComment("Length of data");
+  Asm->EmitInt32(Srcfiles.size() * 8);
+
+  for (std::vector<Sourcefile>::const_iterator I = Srcfiles.begin(),
+                                               E = Srcfiles.end();
+                                               I != E; ++I) {
+    Sourcefile t = *I;
+    if (Asm->isVerbose())
+      Asm->OutStreamer.AddComment("Offset into Sourcefile string table");
+    Asm->EmitInt32(t.Offset);
+    if (Asm->isVerbose())
+      Asm->OutStreamer.AddComment("Checksum");
+    Asm->EmitInt16(0);
+    if (Asm->isVerbose())
+      Asm->OutStreamer.AddComment("Padding");
+    Asm->EmitInt16(0);
+  }
+}
+
+void CodeViewDebug::emitStringZ(const std::string &Str) {
+  Asm->OutStreamer.EmitBytes(StringRef(Str.c_str(), Str.size()+1),
+                             0/*addrspace*/);
+}
+
+void CodeViewDebug::emitPadding(uint32_t Length) {
+  if (Length % 4) {
+    static const char Zero[4] = { 0, 0, 0, 0 };
+
+    if (Asm->isVerbose())
+      Asm->OutStreamer.AddComment("Padding");
+    Asm->OutStreamer.EmitBytes(StringRef(Zero, 4-(Length%4)), 0/*addrspace*/);
+  }
+}
\ No newline at end of file
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/lib/CodeGen/AsmPrinter/CodeViewDebug.h
new file mode 100644
index 0000000..41d2959
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -0,0 +1,130 @@
+//=== llvm/CodeGen/CodeViewDebug.cpp - CodeView Debug Framework -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains support for writing codeview debug info into
+/// asm files.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H__
+#define CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H__
+
+#include "AsmDebug.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/CodeView.h"
+#include "llvm/Support/DebugLoc.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class MachineFrameInfo;
+class MachineModuleInfo;
+class MachineOperand;
+class MCAsmInfo;
+
+// A single type records
+struct LeafRecord {
+  static LeafRecord *create(uint16_t LeafType, uint32_t Length) {
+    void *Rec = new uint8_t[Length];
+    return new (Rec) LeafRecord(LeafType, Length);
+  }
+
+  LeafRecord(uint16_t LeafType, uint32_t Length)
+    : Length(Length)
+  {
+    Leaf.Generic.Leaf = LeafType;
+  }
+
+  uint32_t Length;   // Overall Length
+  union CodeView::Leaf Leaf;
+};
+
+class TypeStringManager {
+  typedef std::vector<LeafRecord *> LeafVector;
+
+  LeafVector TypesString;
+  uint32_t NextIndex;
+
+public:
+  TypeStringManager() : NextIndex(0), TypesString(LeafVector()) {}
+
+  // Add a new leaf record, returns index
+  uint16_t add(LeafRecord *Record);
+  uint32_t size();
+  void emit(AsmPrinter *Asm);
+  uint16_t toReservedType(const DIBasicType &Type);
+  uint32_t toTypeIdx(const DIType &Type);
+  uint32_t parameterToTypeIdx(const DIArray &Vars);
+  uint32_t procedureToTypeIdx(const DISubprogram &Proc);
+};
+
+struct Sourcefile {
+  std::string Filename;
+  uint32_t Offset;
+
+  Sourcefile(std::string FName, uint32_t Ofs)
+    : Filename(FName), Offset(Ofs)
+  {}
+};
+
+class CodeViewDebug : public AsmDebug {
+  TypeStringManager TypeString;
+
+  void emitSourcefileTable(std::vector<Sourcefile> Srcfiles);
+  void emitSourcefileInfo(std::vector<Sourcefile> Srcfiles);
+  void emitPadding(uint32_t Length);
+  void emitStringZ(const std::string &Str);
+
+public:
+  //===--------------------------------------------------------------------===//
+  // Main entry points.
+  //
+  CodeViewDebug(AsmPrinter *A, Module *M);
+  ~CodeViewDebug();
+
+  /// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such
+  /// as llvm.dbg.enum and llvm.dbg.ty
+  void collectInfoFromNamedMDNodes(const Module *M);
+
+  /// beginModule - Emit all Dwarf sections that should come prior to the
+  /// content.
+  void beginModule();
+
+  /// endModule - Emit all Dwarf sections that should come after the content.
+  ///
+  void endModule();
+
+  /// beginFunction - Gather pre-function debug information.  Assumes being
+  /// emitted immediately after the function entry point.
+  void beginFunction(const MachineFunction *MF);
+
+  /// endFunction - Gather and emit post-function debug information.
+  ///
+  void endFunction(const MachineFunction *MF);
+
+  /// beginInstruction - Process beginning of an instruction.
+  void beginInstruction(const MachineInstr *MI);
+
+  /// endInstruction - Prcess end of an instruction.
+  void endInstruction(const MachineInstr *MI);
+};
+} // End of namespace llvm
+
+#endif
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index e064911..5d6aa8c 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -563,6 +563,18 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
                         COFF::IMAGE_SCN_MEM_READ |
                         COFF::IMAGE_SCN_MEM_WRITE,
                         SectionKind::getDataRel());
+  DebugSSection =
+    Ctx->getCOFFSection(".debug$S",
+                        COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                        COFF::IMAGE_SCN_MEM_READ |
+                        COFF::IMAGE_SCN_MEM_DISCARDABLE,
+                        SectionKind::getDataRel());
+  DebugTSection =
+    Ctx->getCOFFSection(".debug$T",
+                        COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                        COFF::IMAGE_SCN_MEM_READ |
+                        COFF::IMAGE_SCN_MEM_DISCARDABLE,
+                        SectionKind::getDataRel());
 }
 
 void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm,
diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
index 25ab975..39032ec 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -131,6 +131,8 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {
   AssemblerDialect = AsmWriterFlavor;
 
   TextAlignFillValue = 0x90;
+
+  DebugInformationType = DebugInformation::CodeView;
 }
 
 void X86MCAsmInfoGNUCOFF::anchor() { }
-- 
1.8.0.msysgit.0



More information about the llvm-commits mailing list