Sort out mangled names for globals
[oota-llvm.git] / lib / CodeGen / DwarfWriter.cpp
index 3aadd97f2a13494e8174816ce72619807c20d1de..0921cc5c6478971da21fe7a64a1ab920d9235967 100644 (file)
@@ -23,6 +23,7 @@
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Mangler.h"
+#include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
@@ -35,7 +36,7 @@ using namespace llvm::dwarf;
 
 static cl::opt<bool>
 DwarfVerbose("dwarf-verbose", cl::Hidden,
-                                cl::desc("Add comments to Dwarf directives."));
+                              cl::desc("Add comments to Dwarf directives."));
 
 namespace llvm {
 
@@ -573,24 +574,24 @@ void DIEAbbrev::Emit(const DwarfWriter &DW) const {
 }
 
 #ifndef NDEBUG
-  void DIEAbbrev::print(std::ostream &O) {
-    O << "Abbreviation @"
-      << std::hex << (intptr_t)this << std::dec
+void DIEAbbrev::print(std::ostream &O) {
+  O << "Abbreviation @"
+    << std::hex << (intptr_t)this << std::dec
+    << "  "
+    << TagString(Tag)
+    << " "
+    << ChildrenString(ChildrenFlag)
+    << "\n";
+  
+  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
+    O << "  "
+      << AttributeString(Data[i].getAttribute())
       << "  "
-      << TagString(Tag)
-      << " "
-      << ChildrenString(ChildrenFlag)
+      << FormEncodingString(Data[i].getForm())
       << "\n";
-    
-    for (unsigned i = 0, N = Data.size(); i < N; ++i) {
-      O << "  "
-        << AttributeString(Data[i].getAttribute())
-        << "  "
-        << FormEncodingString(Data[i].getForm())
-        << "\n";
-    }
   }
-  void DIEAbbrev::dump() { print(std::cerr); }
+}
+void DIEAbbrev::dump() { print(std::cerr); }
 #endif
 
 //===----------------------------------------------------------------------===//
@@ -674,7 +675,7 @@ void DIEDwarfLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
 /// SizeOf - Determine size of label value in bytes.
 ///
 unsigned DIEDwarfLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
-  return DW.getAddressSize();
+  return DW.getTargetAsmInfo()->getAddressSize();
 }
     
 //===----------------------------------------------------------------------===//
@@ -688,7 +689,7 @@ void DIEObjectLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
 /// SizeOf - Determine size of label value in bytes.
 ///
 unsigned DIEObjectLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
-  return DW.getAddressSize();
+  return DW.getTargetAsmInfo()->getAddressSize();
 }
     
 //===----------------------------------------------------------------------===//
@@ -702,7 +703,7 @@ void DIEDelta::EmitValue(const DwarfWriter &DW, unsigned Form) const {
 /// SizeOf - Determine size of delta value in bytes.
 ///
 unsigned DIEDelta::SizeOf(const DwarfWriter &DW, unsigned Form) const {
-  return DW.getAddressSize();
+  return DW.getTargetAsmInfo()->getAddressSize();
 }
 
 //===----------------------------------------------------------------------===//
@@ -942,7 +943,7 @@ void DIE::AddChild(DIE *Child) {
 
 //===----------------------------------------------------------------------===//
 
-/// DWContext
+/// DwarfWriter
 
 //===----------------------------------------------------------------------===//
 
@@ -957,7 +958,7 @@ void DwarfWriter::PrintHex(int Value) const {
 void DwarfWriter::EOL(const std::string &Comment) const {
   if (DwarfVerbose && !Comment.empty()) {
     O << "\t"
-      << Asm->CommentString
+      << TAI->getCommentString()
       << " "
       << Comment;
   }
@@ -967,17 +968,17 @@ void DwarfWriter::EOL(const std::string &Comment) const {
 /// EmitAlign - Print a align directive.
 ///
 void DwarfWriter::EmitAlign(unsigned Alignment) const {
-  O << Asm->AlignDirective << Alignment << "\n";
+  O << TAI->getAlignDirective() << Alignment << "\n";
 }
 
 /// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
 /// unsigned leb128 value.
 void DwarfWriter::EmitULEB128Bytes(unsigned Value) const {
-  if (hasLEB128) {
+  if (TAI->hasLEB128()) {
     O << "\t.uleb128\t"
       << Value;
   } else {
-    O << Asm->Data8bitsDirective;
+    O << TAI->getData8bitsDirective();
     PrintULEB128(Value);
   }
 }
@@ -985,11 +986,11 @@ void DwarfWriter::EmitULEB128Bytes(unsigned Value) const {
 /// EmitSLEB128Bytes - Emit an assembler byte data directive to compose a
 /// signed leb128 value.
 void DwarfWriter::EmitSLEB128Bytes(int Value) const {
-  if (hasLEB128) {
+  if (TAI->hasLEB128()) {
     O << "\t.sleb128\t"
       << Value;
   } else {
-    O << Asm->Data8bitsDirective;
+    O << TAI->getData8bitsDirective();
     PrintSLEB128(Value);
   }
 }
@@ -1052,29 +1053,29 @@ unsigned DwarfWriter::SizeSLEB128(int Value) {
 /// EmitInt8 - Emit a byte directive and value.
 ///
 void DwarfWriter::EmitInt8(int Value) const {
-  O << Asm->Data8bitsDirective;
+  O << TAI->getData8bitsDirective();
   PrintHex(Value & 0xFF);
 }
 
 /// EmitInt16 - Emit a short directive and value.
 ///
 void DwarfWriter::EmitInt16(int Value) const {
-  O << Asm->Data16bitsDirective;
+  O << TAI->getData16bitsDirective();
   PrintHex(Value & 0xFFFF);
 }
 
 /// EmitInt32 - Emit a long directive and value.
 ///
 void DwarfWriter::EmitInt32(int Value) const {
-  O << Asm->Data32bitsDirective;
+  O << TAI->getData32bitsDirective();
   PrintHex(Value);
 }
 
 /// EmitInt64 - Emit a long long directive and value.
 ///
 void DwarfWriter::EmitInt64(uint64_t Value) const {
-  if (Asm->Data64bitsDirective) {
-    O << Asm->Data64bitsDirective << "0x" << std::hex << Value << std::dec;
+  if (TAI->getData64bitsDirective()) {
+    O << TAI->getData64bitsDirective() << "0x" << std::hex << Value << std::dec;
   } else {
     if (TD->isBigEndian()) {
       EmitInt32(unsigned(Value >> 32)); O << "\n";
@@ -1089,7 +1090,7 @@ void DwarfWriter::EmitInt64(uint64_t Value) const {
 /// EmitString - Emit a string with quotes and a null terminator.
 /// Special characters are emitted properly. (Eg. '\t')
 void DwarfWriter::EmitString(const std::string &String) const {
-  O << Asm->AsciiDirective
+  O << TAI->getAsciiDirective()
     << "\"";
   for (unsigned i = 0, N = String.size(); i < N; ++i) {
     unsigned char C = String[i];
@@ -1103,9 +1104,9 @@ void DwarfWriter::EmitString(const std::string &String) const {
       case '\t': O << "\\t"; break;
       default:
         O << '\\';
-        O << char('0' + (C >> 6));
-        O << char('0' + (C >> 3));
-        O << char('0' + (C >> 0));
+        O << char('0' + ((C >> 6) & 7));
+        O << char('0' + ((C >> 3) & 7));
+        O << char('0' + ((C >> 0) & 7));
         break;
       }
     } else if (C == '\"') {
@@ -1122,7 +1123,7 @@ void DwarfWriter::EmitString(const std::string &String) const {
 /// PrintLabelName - Print label name in form used by Dwarf writer.
 ///
 void DwarfWriter::PrintLabelName(const char *Tag, unsigned Number) const {
-  O << Asm->PrivateGlobalPrefix
+  O << TAI->getPrivateGlobalPrefix()
     << "debug_"
     << Tag;
   if (Number) O << Number;
@@ -1138,18 +1139,18 @@ void DwarfWriter::EmitLabel(const char *Tag, unsigned Number) const {
 /// EmitReference - Emit a reference to a label.
 ///
 void DwarfWriter::EmitReference(const char *Tag, unsigned Number) const {
-  if (AddressSize == 4)
-    O << Asm->Data32bitsDirective;
+  if (TAI->getAddressSize() == 4)
+    O << TAI->getData32bitsDirective();
   else
-    O << Asm->Data64bitsDirective;
+    O << TAI->getData64bitsDirective();
     
   PrintLabelName(Tag, Number);
 }
 void DwarfWriter::EmitReference(const std::string &Name) const {
-  if (AddressSize == 4)
-    O << Asm->Data32bitsDirective;
+  if (TAI->getAddressSize() == 4)
+    O << TAI->getData32bitsDirective();
   else
-    O << Asm->Data64bitsDirective;
+    O << TAI->getData64bitsDirective();
     
   O << Name;
 }
@@ -1159,7 +1160,7 @@ void DwarfWriter::EmitReference(const std::string &Name) const {
 /// is an option (needsSet) to use an intermediary 'set' expression.
 void DwarfWriter::EmitDifference(const char *TagHi, unsigned NumberHi,
                                  const char *TagLo, unsigned NumberLo) const {
-  if (needsSet) {
+  if (TAI->needsSet()) {
     static unsigned SetCounter = 0;
     
     O << "\t.set\t";
@@ -1170,19 +1171,19 @@ void DwarfWriter::EmitDifference(const char *TagHi, unsigned NumberHi,
     PrintLabelName(TagLo, NumberLo);
     O << "\n";
     
-    if (AddressSize == sizeof(int32_t))
-      O << Asm->Data32bitsDirective;
+    if (TAI->getAddressSize() == sizeof(int32_t))
+      O << TAI->getData32bitsDirective();
     else
-      O << Asm->Data64bitsDirective;
+      O << TAI->getData64bitsDirective();
       
     PrintLabelName("set", SetCounter);
     
     ++SetCounter;
   } else {
-    if (AddressSize == sizeof(int32_t))
-      O << Asm->Data32bitsDirective;
+    if (TAI->getAddressSize() == sizeof(int32_t))
+      O << TAI->getData32bitsDirective();
     else
-      O << Asm->Data64bitsDirective;
+      O << TAI->getData64bitsDirective();
       
     PrintLabelName(TagHi, NumberHi);
     O << "-";
@@ -1205,7 +1206,7 @@ DWLabel DwarfWriter::NewString(const std::string &String) {
 
 /// AddSourceLine - Add location information to specified debug information
 /// entry.
-void DwarfWriter::AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line) {
+void DwarfWriter::AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line){
   if (File && Line) {
     CompileUnit *FileUnit = FindCompileUnit(File);
     unsigned FileID = FileUnit->getID();
@@ -1219,12 +1220,22 @@ void DwarfWriter::AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line)
 void DwarfWriter::AddAddress(DIE *Die, unsigned Attribute,
                              const MachineLocation &Location) {
   DIEBlock *Block = new DIEBlock();
+  unsigned Reg = RI->getDwarfRegNum(Location.getRegister());
+  
   if (Location.isRegister()) {
-    Block->AddUInt(DW_FORM_data1,
-                   DW_OP_reg0 + RI->getDwarfRegNum(Location.getRegister()));
+    if (Reg < 32) {
+      Block->AddUInt(DW_FORM_data1, DW_OP_reg0 + Reg);
+    } else {
+      Block->AddUInt(DW_FORM_data1, DW_OP_regx);
+      Block->AddUInt(DW_FORM_udata, Reg);
+    }
   } else {
-    Block->AddUInt(DW_FORM_data1,
-                   DW_OP_breg0 + RI->getDwarfRegNum(Location.getRegister()));
+    if (Reg < 32) {
+      Block->AddUInt(DW_FORM_data1, DW_OP_breg0 + Reg);
+    } else {
+      Block->AddUInt(DW_FORM_data1, DW_OP_bregx);
+      Block->AddUInt(DW_FORM_udata, Reg);
+    }
     Block->AddUInt(DW_FORM_sdata, Location.getOffset());
   }
   Block->ComputeSize(*this);
@@ -1236,7 +1247,7 @@ void DwarfWriter::AddAddress(DIE *Die, unsigned Attribute,
 DIE *&DwarfWriter::getDieMapSlotFor(DebugInfoDesc *DD) {
   return DescToDieMap[DD];
 }
-                                 
+
 /// NewType - Create a new type DIE.
 ///
 DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
@@ -1249,8 +1260,6 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
     return Die;
   }
   
-  // FIXME - Should handle other contexts that compile units.
-
   // Check for pre-existence.
   DIE *&Slot = Unit->getDieMapSlotFor(TyDesc);
   if (Slot) return Slot;
@@ -1265,7 +1274,7 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
     // Fundamental types like int, float, bool
     Slot = Ty = new DIE(DW_TAG_base_type);
     unsigned Encoding = BasicTy->getEncoding();
-    Ty->AddUInt  (DW_AT_encoding,  DW_FORM_data1, Encoding);
+    Ty->AddUInt(DW_AT_encoding,  DW_FORM_data1, Encoding);
   } else if (DerivedTypeDesc *DerivedTy = dyn_cast<DerivedTypeDesc>(TyDesc)) {
     // Create specific DIE.
     Slot = Ty = new DIE(DerivedTy->getTag());
@@ -1276,17 +1285,25 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
                      NewType(Context, FromTy, Unit));
     }
   } else if (CompositeTypeDesc *CompTy = dyn_cast<CompositeTypeDesc>(TyDesc)) {
+    // Fetch tag
+    unsigned Tag = CompTy->getTag();
+    
     // Create specific DIE.
-    Slot = Ty = new DIE(CompTy->getTag());
+    Slot = Ty = Tag == DW_TAG_vector_type ? new DIE(DW_TAG_array_type) :
+                                            new DIE(Tag);
+    
     std::vector<DebugInfoDesc *> &Elements = CompTy->getElements();
     
-    switch (CompTy->getTag()) {
+    switch (Tag) {
+    case DW_TAG_vector_type: Ty->AddUInt(DW_AT_GNU_vector, DW_FORM_flag, 1);
+      // Fall thru
     case DW_TAG_array_type: {
       // Add element type.
       if (TypeDesc *FromTy = CompTy->getFromType()) {
         Ty->AddDIEntry(DW_AT_type, DW_FORM_ref4,
                        NewType(Context, FromTy, Unit));
       }
+      
       // Don't emit size attribute.
       Size = 0;
       
@@ -1318,65 +1335,161 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
     }
     case DW_TAG_structure_type:
     case DW_TAG_union_type: {
-      // FIXME - this is just the basics.
       // Add elements to structure type.
       for(unsigned i = 0, N = Elements.size(); i < N; ++i) {
-        DerivedTypeDesc *MemberDesc = cast<DerivedTypeDesc>(Elements[i]);
-        
-        // Extract the basic information.
-        const std::string &Name = MemberDesc->getName();
-        TypeDesc *MemTy = MemberDesc->getFromType();
-        uint64_t Size = MemberDesc->getSize();
-        uint64_t Align = MemberDesc->getAlign();
-        uint64_t Offset = MemberDesc->getOffset();
-   
-        // Construct member debug information entry.
-        DIE *Member = new DIE(DW_TAG_member);
-        
-        // Add name if not "".
-        if (!Name.empty()) Member->AddString(DW_AT_name, DW_FORM_string, Name);
-        // Add location if available.
-        AddSourceLine(Member, MemberDesc->getFile(), MemberDesc->getLine());
+        DebugInfoDesc *Element = Elements[i];
         
-        // Most of the time the field info is the same as the members.
-        uint64_t FieldSize = Size;
-        uint64_t FieldAlign = Align;
-        uint64_t FieldOffset = Offset;
-        
-        if (TypeDesc *FromTy = MemberDesc->getFromType()) {
-          Member->AddDIEntry(DW_AT_type, DW_FORM_ref4,
-                             NewType(Context, FromTy, Unit));
-          FieldSize = FromTy->getSize();
-          FieldAlign = FromTy->getSize();
-        }
+        if (DerivedTypeDesc *MemberDesc = dyn_cast<DerivedTypeDesc>(Element)) {
+          // Add field or base class.
+          
+          unsigned Tag = MemberDesc->getTag();
         
-        // Unless we have a bit field.
-        if (FieldSize != Size) {
-          // Construct the alignment mask.
-          uint64_t AlignMask = ~(FieldAlign - 1);
-          // Determine the high bit + 1 of the declared size.
-          uint64_t HiMark = (Offset + FieldSize) & AlignMask;
-          // Work backwards to determine the base offset of the field.
-          FieldOffset = HiMark - FieldSize;
-          // Now normalize offset to the field.
-          Offset -= FieldOffset;
+          // Extract the basic information.
+          const std::string &Name = MemberDesc->getName();
+          TypeDesc *MemTy = MemberDesc->getFromType();
+          uint64_t Size = MemberDesc->getSize();
+          uint64_t Align = MemberDesc->getAlign();
+          uint64_t Offset = MemberDesc->getOffset();
+     
+          // Construct member debug information entry.
+          DIE *Member = new DIE(Tag);
+          
+          // Add name if not "".
+          if (!Name.empty())Member->AddString(DW_AT_name, DW_FORM_string, Name);
+          // Add location if available.
+          AddSourceLine(Member, MemberDesc->getFile(), MemberDesc->getLine());
+          
+          // Most of the time the field info is the same as the members.
+          uint64_t FieldSize = Size;
+          uint64_t FieldAlign = Align;
+          uint64_t FieldOffset = Offset;
           
-          // Maybe we need to work from the other end.
-          if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
+          if (TypeDesc *FromTy = MemberDesc->getFromType()) {
+            Member->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+                               NewType(Context, FromTy, Unit));
+            FieldSize = FromTy->getSize();
+            FieldAlign = FromTy->getSize();
+          }
           
-          Member->AddUInt(DW_AT_byte_size, 0, FieldSize >> 3);
-          Member->AddUInt(DW_AT_bit_size, 0, Size);
-          Member->AddUInt(DW_AT_bit_offset, 0, Offset);
+          // Unless we have a bit field.
+          if (Tag == DW_TAG_member && FieldSize != Size) {
+            // Construct the alignment mask.
+            uint64_t AlignMask = ~(FieldAlign - 1);
+            // Determine the high bit + 1 of the declared size.
+            uint64_t HiMark = (Offset + FieldSize) & AlignMask;
+            // Work backwards to determine the base offset of the field.
+            FieldOffset = HiMark - FieldSize;
+            // Now normalize offset to the field.
+            Offset -= FieldOffset;
+            
+            // Maybe we need to work from the other end.
+            if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
+            
+            // Add size and offset.
+            Member->AddUInt(DW_AT_byte_size, 0, FieldSize >> 3);
+            Member->AddUInt(DW_AT_bit_size, 0, Size);
+            Member->AddUInt(DW_AT_bit_offset, 0, Offset);
+          }
+          
+          // Add computation for offset.
+          DIEBlock *Block = new DIEBlock();
+          Block->AddUInt(DW_FORM_data1, DW_OP_plus_uconst);
+          Block->AddUInt(DW_FORM_udata, FieldOffset >> 3);
+          Block->ComputeSize(*this);
+          Member->AddBlock(DW_AT_data_member_location, 0, Block);
+
+          // Add accessibility (public default unless is base class.
+          if (MemberDesc->isProtected()) {
+            Member->AddUInt(DW_AT_accessibility, 0, DW_ACCESS_protected);
+          } else if (MemberDesc->isPrivate()) {
+            Member->AddUInt(DW_AT_accessibility, 0, DW_ACCESS_private);
+          } else if (Tag == DW_TAG_inheritance) {
+            Member->AddUInt(DW_AT_accessibility, 0, DW_ACCESS_public);
+          }
+          
+          Ty->AddChild(Member);
+        } else if (GlobalVariableDesc *StaticDesc =
+                                        dyn_cast<GlobalVariableDesc>(Element)) {
+          // Add static member.
+          
+          // Construct member debug information entry.
+          DIE *Static = new DIE(DW_TAG_variable);
+          
+          // Add name and mangled name.
+          const std::string &Name = StaticDesc->getDisplayName();
+          const std::string &MangledName = StaticDesc->getName();
+          Static->AddString(DW_AT_name, DW_FORM_string, Name);
+          Static->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+                            MangledName);
+          
+          // Add location.
+          AddSourceLine(Static, StaticDesc->getFile(), StaticDesc->getLine());
+         
+          // Add type.
+          if (TypeDesc *StaticTy = StaticDesc->getType()) {
+            Static->AddDIEntry(DW_AT_type, DW_FORM_ref4, 
+                               NewType(Context, StaticTy, Unit));
+          }
+          
+          // Add flags.
+          Static->AddUInt(DW_AT_external, DW_FORM_flag, 1);
+          Static->AddUInt(DW_AT_declaration, DW_FORM_flag, 1);
+          
+          Ty->AddChild(Static);
+        } else if (SubprogramDesc *MethodDesc =
+                                            dyn_cast<SubprogramDesc>(Element)) {
+          // Add member function.
+          
+          // Construct member debug information entry.
+          DIE *Method = new DIE(DW_TAG_subprogram);
+         
+          // Add name and mangled name.
+          const std::string &Name = MethodDesc->getDisplayName();
+          const std::string &MangledName = MethodDesc->getName();
+          bool IsCTor = false;
+          
+          if (Name.empty()) {
+            Method->AddString(DW_AT_name, DW_FORM_string, MangledName);            
+            IsCTor = TyDesc->getName() == MangledName;
+          } else {
+            Method->AddString(DW_AT_name, DW_FORM_string, Name);            
+            Method->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+                              MangledName);
+          }
+          
+          // Add location.
+          AddSourceLine(Method, MethodDesc->getFile(), MethodDesc->getLine());
+         
+          // Add type.
+          if (CompositeTypeDesc *MethodTy =
+                   dyn_cast_or_null<CompositeTypeDesc>(MethodDesc->getType())) {
+            // Get argument information.
+            std::vector<DebugInfoDesc *> &Args = MethodTy->getElements();
+           
+            // If not a ctor.
+            if (!IsCTor) {
+              // Add return type.
+              Method->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+                                 NewType(Context, dyn_cast<TypeDesc>(Args[0]),
+                                 Unit));
+            }
+            
+            // Add arguments.
+            for(unsigned i = 1, N = Args.size(); i < N; ++i) {
+              DIE *Arg = new DIE(DW_TAG_formal_parameter);
+              Arg->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+                              NewType(Context, cast<TypeDesc>(Args[i]), Unit));
+              Arg->AddUInt(DW_AT_artificial, DW_FORM_flag, 1);
+              Method->AddChild(Arg);
+            }
+          }
+
+          // Add flags.
+          Method->AddUInt(DW_AT_external, DW_FORM_flag, 1);
+          Method->AddUInt(DW_AT_declaration, DW_FORM_flag, 1);
+            
+          Ty->AddChild(Method);
         }
-        
-        // Add computation for offset.
-        DIEBlock *Block = new DIEBlock();
-        Block->AddUInt(DW_FORM_data1, DW_OP_plus_uconst);
-        Block->AddUInt(DW_FORM_udata, FieldOffset >> 3);
-        Block->ComputeSize(*this);
-        Member->AddBlock(DW_AT_data_member_location, 0, Block);
-        
-        Ty->AddChild(Member);
       }
       break;
     }
@@ -1394,6 +1507,23 @@ DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
 
       break;
     }
+    case DW_TAG_subroutine_type: {
+      // Add prototype flag.
+      Ty->AddUInt(DW_AT_prototyped, DW_FORM_flag, 1);
+      // Add return type.
+      Ty->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+                     NewType(Context, dyn_cast<TypeDesc>(Elements[0]), Unit));
+      
+      // Add arguments.
+      for(unsigned i = 1, N = Elements.size(); i < N; ++i) {
+        DIE *Arg = new DIE(DW_TAG_formal_parameter);
+        Arg->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+                        NewType(Context, cast<TypeDesc>(Elements[i]), Unit));
+        Ty->AddChild(Arg);
+      }
+      
+      break;
+    }
     default: break;
     }
   }
@@ -1419,9 +1549,10 @@ CompileUnit *DwarfWriter::NewCompileUnit(CompileUnitDesc *UnitDesc,
                                          unsigned ID) {
   // Construct debug information entry.
   DIE *Die = new DIE(DW_TAG_compile_unit);
-  Die->AddLabel (DW_AT_stmt_list, DW_FORM_data4,  DWLabel("line", 0));
-  Die->AddLabel (DW_AT_high_pc,   DW_FORM_addr,   DWLabel("text_end", 0));
-  Die->AddLabel (DW_AT_low_pc,    DW_FORM_addr,   DWLabel("text_begin", 0));
+  Die->AddDelta (DW_AT_stmt_list, DW_FORM_data4,  DWLabel("line", 0),
+                                                  DWLabel("section_line", 0));
+//  Die->AddLabel (DW_AT_high_pc,   DW_FORM_addr,   DWLabel("text_end", 0));
+//  Die->AddLabel (DW_AT_low_pc,    DW_FORM_addr,   DWLabel("text_begin", 0));
   Die->AddString(DW_AT_producer,  DW_FORM_string, UnitDesc->getProducer());
   Die->AddUInt  (DW_AT_language,  DW_FORM_data1,  UnitDesc->getLanguage());
   Die->AddString(DW_AT_name,      DW_FORM_string, UnitDesc->getFileName());
@@ -1461,20 +1592,23 @@ DIE *DwarfWriter::NewGlobalVariable(GlobalVariableDesc *GVD) {
   
   // Get the global variable itself.
   GlobalVariable *GV = GVD->getGlobalVariable();
-  // Generate the mangled name.
-  std::string MangledName = Asm->Mang->getValueName(GV);
 
-  // Gather the details (simplify add attribute code.)
-  const std::string &Name = GVD->getName();
-  
+  const std::string &Name = GVD->hasMangledName() ? GVD->getDisplayName()
+                                                  : GVD->getName();
+  const std::string &MangledName = GVD->hasMangledName() ? GVD->getName()
+                                                         : "";
   // Get the global's type.
   DIE *Type = NewType(Unit->getDie(), GVD->getType(), Unit); 
 
   // Create the globale variable DIE.
   DIE *VariableDie = new DIE(DW_TAG_variable);
-  VariableDie->AddString     (DW_AT_name,      DW_FORM_string, Name);
-  VariableDie->AddDIEntry    (DW_AT_type,      DW_FORM_ref4,   Type);
-  VariableDie->AddUInt       (DW_AT_external,  DW_FORM_flag,   1);
+  VariableDie->AddString(DW_AT_name, DW_FORM_string, Name);
+  if (!MangledName.empty()) {
+    VariableDie->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+                           MangledName);
+  }
+  VariableDie->AddDIEntry(DW_AT_type, DW_FORM_ref4, Type);
+  VariableDie->AddUInt(DW_AT_external, DW_FORM_flag, 1);
   
   // Add source line info if available.
   AddSourceLine(VariableDie, UnitDesc, GVD->getLine());
@@ -1511,17 +1645,24 @@ DIE *DwarfWriter::NewSubprogram(SubprogramDesc *SPD) {
   if (Slot) return Slot;
   
   // Gather the details (simplify add attribute code.)
-  const std::string &Name = SPD->getName();
+  const std::string &Name = SPD->hasMangledName() ? SPD->getDisplayName()
+                                                  : SPD->getName();
+  const std::string &MangledName = SPD->hasMangledName() ? SPD->getName()
+                                                         : "";
   DIE *Type = NewType(Unit->getDie(), SPD->getType(), Unit); 
   unsigned IsExternal = SPD->isStatic() ? 0 : 1;
                                     
   DIE *SubprogramDie = new DIE(DW_TAG_subprogram);
-  SubprogramDie->AddString     (DW_AT_name,      DW_FORM_string, Name);
+  SubprogramDie->AddString(DW_AT_name, DW_FORM_string, Name);
+  if (!MangledName.empty()) {
+    SubprogramDie->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+                             MangledName);
+  }
   if (Type) {
-    SubprogramDie->AddDIEntry    (DW_AT_type,      DW_FORM_ref4,   Type);
+    SubprogramDie->AddDIEntry(DW_AT_type, DW_FORM_ref4, Type);
   }
-  SubprogramDie->AddUInt       (DW_AT_external,    DW_FORM_flag,   IsExternal);
-  SubprogramDie->AddUInt       (DW_AT_prototyped,  DW_FORM_flag,   1);
+  SubprogramDie->AddUInt(DW_AT_external, DW_FORM_flag, IsExternal);
+  SubprogramDie->AddUInt(DW_AT_prototyped, DW_FORM_flag, 1);
   
   // Add source line info if available.
   AddSourceLine(SubprogramDie, UnitDesc, SPD->getLine());
@@ -1589,7 +1730,7 @@ void DwarfWriter::ConstructScope(DebugScope *ParentScope,
     // Define the Scope debug information entry.
     DebugScope *Scope = Scopes[j];
     // FIXME - Ignore inlined functions for the time being.
-    if (Scope->getParent()) continue;
+    if (!Scope->getParent()) continue;
     
     DIE *ScopeDie = new DIE(DW_TAG_lexical_block);
     
@@ -1652,35 +1793,35 @@ void DwarfWriter::EmitInitial() {
   didInitial = true;
   
   // Dwarf sections base addresses.
-  Asm->SwitchToDataSection(DwarfFrameSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfFrameSection(), 0);
   EmitLabel("section_frame", 0);
-  Asm->SwitchToDataSection(DwarfInfoSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfInfoSection(), 0);
   EmitLabel("section_info", 0);
   EmitLabel("info", 0);
-  Asm->SwitchToDataSection(DwarfAbbrevSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection(), 0);
   EmitLabel("section_abbrev", 0);
   EmitLabel("abbrev", 0);
-  Asm->SwitchToDataSection(DwarfARangesSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfARangesSection(), 0);
   EmitLabel("section_aranges", 0);
-  Asm->SwitchToDataSection(DwarfMacInfoSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection(), 0);
   EmitLabel("section_macinfo", 0);
-  Asm->SwitchToDataSection(DwarfLineSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfLineSection(), 0);
   EmitLabel("section_line", 0);
   EmitLabel("line", 0);
-  Asm->SwitchToDataSection(DwarfLocSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfLocSection(), 0);
   EmitLabel("section_loc", 0);
-  Asm->SwitchToDataSection(DwarfPubNamesSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection(), 0);
   EmitLabel("section_pubnames", 0);
-  Asm->SwitchToDataSection(DwarfStrSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfStrSection(), 0);
   EmitLabel("section_str", 0);
-  Asm->SwitchToDataSection(DwarfRangesSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfRangesSection(), 0);
   EmitLabel("section_ranges", 0);
 
-  Asm->SwitchToDataSection(TextSection, 0);
+  Asm->SwitchToTextSection(TAI->getTextSection(), 0);
   EmitLabel("text_begin", 0);
-  Asm->SwitchToDataSection(DataSection, 0);
+  Asm->SwitchToDataSection(TAI->getDataSection(), 0);
   EmitLabel("data_begin", 0);
-  
+
   // Emit common frame information.
   EmitInitialDebugFrame();
 }
@@ -1816,7 +1957,7 @@ void DwarfWriter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
     
     // Advance row if new location.
     if (BaseLabel && LabelID && BaseLabelID != LabelID) {
-      EmitULEB128Bytes(DW_CFA_advance_loc4);
+      EmitInt8(DW_CFA_advance_loc4);
       EOL("DW_CFA_advance_loc4");
       EmitDifference("loc", LabelID, BaseLabel, BaseLabelID);
       EOL("");
@@ -1825,30 +1966,56 @@ void DwarfWriter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
       BaseLabel = "loc";
     }
     
+    int stackGrowth =
+        Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
+          TargetFrameInfo::StackGrowsUp ?
+            TAI->getAddressSize() : -TAI->getAddressSize();
+
     // If advancing cfa.
     if (Dst.isRegister() && Dst.getRegister() == MachineLocation::VirtualFP) {
       if (!Src.isRegister()) {
         if (Src.getRegister() == MachineLocation::VirtualFP) {
-          EmitULEB128Bytes(DW_CFA_def_cfa_offset);
+          EmitInt8(DW_CFA_def_cfa_offset);
           EOL("DW_CFA_def_cfa_offset");
         } else {
-          EmitULEB128Bytes(DW_CFA_def_cfa);
+          EmitInt8(DW_CFA_def_cfa);
           EOL("DW_CFA_def_cfa");
           
           EmitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister()));
           EOL("Register");
         }
         
-        int stackGrowth =
-            Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
-              TargetFrameInfo::StackGrowsUp ?
-            AddressSize : -AddressSize;
+        int Offset = Src.getOffset() / stackGrowth;
         
-        EmitULEB128Bytes(Src.getOffset() / stackGrowth);
+        EmitULEB128Bytes(Offset);
         EOL("Offset");
       } else {
+        assert(0 && "Machine move no supported yet.");
       }
     } else {
+      unsigned Reg = RI->getDwarfRegNum(Src.getRegister());
+      int Offset = Dst.getOffset() / stackGrowth;
+      
+      if (Offset < 0) {
+        EmitInt8(DW_CFA_offset_extended_sf);
+        EOL("DW_CFA_offset_extended_sf");
+        EmitULEB128Bytes(Reg);
+        EOL("Reg");
+        EmitSLEB128Bytes(Offset);
+        EOL("Offset");
+      } else if (Reg < 64) {
+        EmitInt8(DW_CFA_offset + Reg);
+        EOL("DW_CFA_offset + Reg");
+        EmitULEB128Bytes(Offset);
+        EOL("Offset");
+      } else {
+        EmitInt8(DW_CFA_offset_extended);
+        EOL("DW_CFA_offset_extended");
+        EmitULEB128Bytes(Reg);
+        EOL("Reg");
+        EmitULEB128Bytes(Offset);
+        EOL("Offset");
+      }
     }
   }
 }
@@ -1857,7 +2024,7 @@ void DwarfWriter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
 ///
 void DwarfWriter::EmitDebugInfo() const {
   // Start debug info section.
-  Asm->SwitchToDataSection(DwarfInfoSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfInfoSection(), 0);
   
   // Process each compile unit.
   for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
@@ -1875,8 +2042,9 @@ void DwarfWriter::EmitDebugInfo() const {
                              
       EmitInt32(ContentSize);  EOL("Length of Compilation Unit Info");
       EmitInt16(DWARF_VERSION); EOL("DWARF version number");
-      EmitReference("abbrev_begin", 0); EOL("Offset Into Abbrev. Section");
-      EmitInt8(AddressSize); EOL("Address Size (in bytes)");
+      EmitDifference("abbrev_begin", 0, "section_abbrev", 0);
+      EOL("Offset Into Abbrev. Section");
+      EmitInt8(TAI->getAddressSize()); EOL("Address Size (in bytes)");
     
       EmitDIE(Die);
       EmitLabel("info_end", Unit->getID());
@@ -1892,7 +2060,7 @@ void DwarfWriter::EmitAbbreviations() const {
   // Check to see if it is worth the effort.
   if (!Abbreviations.empty()) {
     // Start the debug abbrev section.
-    Asm->SwitchToDataSection(DwarfAbbrevSection, 0);
+    Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection(), 0);
     
     EmitLabel("abbrev_begin", 0);
     
@@ -1926,7 +2094,7 @@ void DwarfWriter::EmitDebugLines() const {
   const int MaxLineDelta = 255 + MinLineDelta;
 
   // Start the dwarf line section.
-  Asm->SwitchToDataSection(DwarfLineSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfLineSection(), 0);
   
   // Construct the section header.
   
@@ -1984,76 +2152,86 @@ void DwarfWriter::EmitDebugLines() const {
   
   EmitLabel("line_prolog_end", 0);
   
-  // Emit line information
-  const std::vector<SourceLineInfo *> &LineInfos = DebugInfo->getSourceLines();
-  
-  // Dwarf assumes we start with first line of first source file.
-  unsigned Source = 1;
-  unsigned Line = 1;
-  
-  // Construct rows of the address, source, line, column matrix.
-  for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
-    SourceLineInfo *LineInfo = LineInfos[i];
+  // A sequence for each text section.
+  for (unsigned j = 0, M = SectionSourceLines.size(); j < M; ++j) {
+    // Isolate current sections line info.
+    const std::vector<SourceLineInfo *> &LineInfos = SectionSourceLines[j];
     
     if (DwarfVerbose) {
-      unsigned SourceID = LineInfo->getSourceID();
-      const SourceFileInfo &SourceFile = SourceFiles[SourceID];
-      unsigned DirectoryID = SourceFile.getDirectoryID();
       O << "\t"
-        << Asm->CommentString << " "
-        << Directories[DirectoryID]
-        << SourceFile.getName() << ":"
-        << LineInfo->getLine() << "\n"; 
+        << TAI->getCommentString() << " "
+        << "Section "
+        << SectionMap[j + 1].c_str() << "\n";
     }
 
-    // Define the line address.
-    EmitInt8(0); EOL("Extended Op");
-    EmitInt8(4 + 1); EOL("Op size");
-    EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
-    EmitReference("loc",  LineInfo->getLabelID()); EOL("Location label");
-    
-    // If change of source, then switch to the new source.
-    if (Source != LineInfo->getSourceID()) {
-      Source = LineInfo->getSourceID();
-      EmitInt8(DW_LNS_set_file); EOL("DW_LNS_set_file");
-      EmitULEB128Bytes(Source); EOL("New Source");
-    }
+    // Dwarf assumes we start with first line of first source file.
+    unsigned Source = 1;
+    unsigned Line = 1;
     
-    // If change of line.
-    if (Line != LineInfo->getLine()) {
-      // Determine offset.
-      int Offset = LineInfo->getLine() - Line;
-      int Delta = Offset - MinLineDelta;
+    // Construct rows of the address, source, line, column matrix.
+    for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
+      SourceLineInfo *LineInfo = LineInfos[i];
       
-      // Update line.
-      Line = LineInfo->getLine();
+      if (DwarfVerbose) {
+        unsigned SourceID = LineInfo->getSourceID();
+        const SourceFileInfo &SourceFile = SourceFiles[SourceID];
+        unsigned DirectoryID = SourceFile.getDirectoryID();
+        O << "\t"
+          << TAI->getCommentString() << " "
+          << Directories[DirectoryID]
+          << SourceFile.getName() << ":"
+          << LineInfo->getLine() << "\n"; 
+      }
+
+      // Define the line address.
+      EmitInt8(0); EOL("Extended Op");
+      EmitInt8(4 + 1); EOL("Op size");
+      EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
+      EmitReference("loc",  LineInfo->getLabelID()); EOL("Location label");
       
-      // If delta is small enough and in range...
-      if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
-        // ... then use fast opcode.
-        EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
+      // If change of source, then switch to the new source.
+      if (Source != LineInfo->getSourceID()) {
+        Source = LineInfo->getSourceID();
+        EmitInt8(DW_LNS_set_file); EOL("DW_LNS_set_file");
+        EmitULEB128Bytes(Source); EOL("New Source");
+      }
+      
+      // If change of line.
+      if (Line != LineInfo->getLine()) {
+        // Determine offset.
+        int Offset = LineInfo->getLine() - Line;
+        int Delta = Offset - MinLineDelta;
+        
+        // Update line.
+        Line = LineInfo->getLine();
+        
+        // If delta is small enough and in range...
+        if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
+          // ... then use fast opcode.
+          EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
+        } else {
+          // ... otherwise use long hand.
+          EmitInt8(DW_LNS_advance_line); EOL("DW_LNS_advance_line");
+          EmitSLEB128Bytes(Offset); EOL("Line Offset");
+          EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
+        }
       } else {
-        // ... otherwise use long hand.
-        EmitInt8(DW_LNS_advance_line); EOL("DW_LNS_advance_line");
-        EmitSLEB128Bytes(Offset); EOL("Line Offset");
+        // Copy the previous row (different address or source)
         EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
       }
-    } else {
-      // Copy the previous row (different address or source)
-      EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
     }
-  }
 
-  // Define last address.
-  EmitInt8(0); EOL("Extended Op");
-  EmitInt8(4 + 1); EOL("Op size");
-  EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
-  EmitReference("text_end", 0); EOL("Location label");
+    // Define last address of section.
+    EmitInt8(0); EOL("Extended Op");
+    EmitInt8(4 + 1); EOL("Op size");
+    EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
+    EmitReference("section_end", j + 1); EOL("Section end label");
 
-  // Mark end of matrix.
-  EmitInt8(0); EOL("DW_LNE_end_sequence");
-  EmitULEB128Bytes(1);  O << "\n";
-  EmitInt8(1); O << "\n";
+    // Mark end of matrix.
+    EmitInt8(0); EOL("DW_LNE_end_sequence");
+    EmitULEB128Bytes(1);  O << "\n";
+    EmitInt8(1); O << "\n";
+  }
   
   EmitLabel("line_end", 0);
   
@@ -2066,11 +2244,12 @@ void DwarfWriter::EmitInitialDebugFrame() {
   int stackGrowth =
       Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
         TargetFrameInfo::StackGrowsUp ?
-      AddressSize : -AddressSize;
+      TAI->getAddressSize() : -TAI->getAddressSize();
 
   // Start the dwarf frame section.
-  Asm->SwitchToDataSection(DwarfFrameSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfFrameSection(), 0);
 
+  EmitLabel("frame_common", 0);
   EmitDifference("frame_common_end", 0,
                  "frame_common_begin", 0);
   EOL("Length of Common Information Entry");
@@ -2098,7 +2277,7 @@ void DwarfWriter::EmitInitialDebugFrame() {
 /// section.
 void DwarfWriter::EmitFunctionDebugFrame() {
   // Start the dwarf frame section.
-  Asm->SwitchToDataSection(DwarfFrameSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfFrameSection(), 0);
   
   EmitDifference("frame_end", SubprogramCount,
                  "frame_begin", SubprogramCount);
@@ -2106,7 +2285,8 @@ void DwarfWriter::EmitFunctionDebugFrame() {
   
   EmitLabel("frame_begin", SubprogramCount);
   
-  EmitReference("section_frame", 0); EOL("FDE CIE offset");
+  EmitDifference("frame_common", 0, "section_frame", 0);
+  EOL("FDE CIE offset");
 
   EmitReference("func_begin", SubprogramCount); EOL("FDE initial location");
   EmitDifference("func_end", SubprogramCount,
@@ -2127,7 +2307,7 @@ void DwarfWriter::EmitFunctionDebugFrame() {
 ///
 void DwarfWriter::EmitDebugPubNames() {
   // Start the dwarf pubnames section.
-  Asm->SwitchToDataSection(DwarfPubNamesSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection(), 0);
     
   // Process each compile unit.
   for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
@@ -2142,7 +2322,7 @@ void DwarfWriter::EmitDebugPubNames() {
       
       EmitInt16(DWARF_VERSION); EOL("DWARF Version");
       
-      EmitReference("info_begin", Unit->getID());
+      EmitDifference("info_begin", Unit->getID(), "section_info", 0);
       EOL("Offset of Compilation Unit Info");
 
       EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID());
@@ -2174,7 +2354,7 @@ void DwarfWriter::EmitDebugStr() {
   // Check to see if it is worth the effort.
   if (!StringPool.empty()) {
     // Start the dwarf str section.
-    Asm->SwitchToDataSection(DwarfStrSection, 0);
+    Asm->SwitchToDataSection(TAI->getDwarfStrSection(), 0);
     
     // For each of strings in the string pool.
     for (unsigned StringID = 1, N = StringPool.size();
@@ -2194,7 +2374,7 @@ void DwarfWriter::EmitDebugStr() {
 ///
 void DwarfWriter::EmitDebugLoc() {
   // Start the dwarf loc section.
-  Asm->SwitchToDataSection(DwarfLocSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfLocSection(), 0);
   
   O << "\n";
 }
@@ -2203,7 +2383,7 @@ void DwarfWriter::EmitDebugLoc() {
 ///
 void DwarfWriter::EmitDebugARanges() {
   // Start the dwarf aranges section.
-  Asm->SwitchToDataSection(DwarfARangesSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfARangesSection(), 0);
   
   // FIXME - Mock up
 #if 0
@@ -2220,7 +2400,7 @@ void DwarfWriter::EmitDebugARanges() {
       EmitReference("info_begin", Unit->getID());
       EOL("Offset of Compilation Unit Info");
 
-      EmitInt8(AddressSize); EOL("Size of Address");
+      EmitInt8(TAI->getAddressSize()); EOL("Size of Address");
 
       EmitInt8(0); EOL("Size of Segment Descriptor");
 
@@ -2244,7 +2424,7 @@ void DwarfWriter::EmitDebugARanges() {
 ///
 void DwarfWriter::EmitDebugRanges() {
   // Start the dwarf ranges section.
-  Asm->SwitchToDataSection(DwarfRangesSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfRangesSection(), 0);
   
   O << "\n";
 }
@@ -2253,7 +2433,7 @@ void DwarfWriter::EmitDebugRanges() {
 ///
 void DwarfWriter::EmitDebugMacInfo() {
   // Start the dwarf macinfo section.
-  Asm->SwitchToDataSection(DwarfMacInfoSection, 0);
+  Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection(), 0);
   
   O << "\n";
 }
@@ -2297,9 +2477,11 @@ void DwarfWriter::ConstructSubprogramDIEs() {
 // Main entry points.
 //
   
-DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A)
+DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A,
+  const TargetAsmInfo *T)
 : O(OS)
 , Asm(A)
+, TAI(T)
 , TD(Asm->TM.getTargetData())
 , RI(Asm->TM.getRegisterInfo())
 , M(NULL)
@@ -2307,32 +2489,14 @@ DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A)
 , DebugInfo(NULL)
 , didInitial(false)
 , shouldEmit(false)
-, IsNormalText(false)
 , SubprogramCount(0)
 , CompileUnits()
 , Abbreviations()
 , StringPool()
 , DescToUnitMap()
 , DescToDieMap()
-, TypeToDieMap()
-, AddressSize(sizeof(int32_t))
-, hasLEB128(false)
-, hasDotLoc(false)
-, hasDotFile(false)
-, needsSet(false)
-, DwarfAbbrevSection(".debug_abbrev")
-, DwarfInfoSection(".debug_info")
-, DwarfLineSection(".debug_line")
-, DwarfFrameSection(".debug_frame")
-, DwarfPubNamesSection(".debug_pubnames")
-, DwarfPubTypesSection(".debug_pubtypes")
-, DwarfStrSection(".debug_str")
-, DwarfLocSection(".debug_loc")
-, DwarfARangesSection(".debug_aranges")
-, DwarfRangesSection(".debug_ranges")
-, DwarfMacInfoSection(".debug_macinfo")
-, TextSection(".text")
-, DataSection(".data")
+, SectionMap()
+, SectionSourceLines()
 {}
 DwarfWriter::~DwarfWriter() {
   for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
@@ -2359,6 +2523,9 @@ void DwarfWriter::SetDebugInfo(MachineDebugInfo *DI) {
 
     // Create DIEs for each of the externally visible subprograms.
     ConstructSubprogramDIEs();
+    
+    // Prime section data.
+    SectionMap.insert(std::string("\t") + TAI->getTextSection());
   }
 }
 
@@ -2378,11 +2545,17 @@ void DwarfWriter::EndModule() {
   EOL("Dwarf End Module");
   
   // Standard sections final addresses.
-  Asm->SwitchToTextSection(TextSection, 0);
+  Asm->SwitchToTextSection(TAI->getTextSection(), 0);
   EmitLabel("text_end", 0);
-  Asm->SwitchToDataSection(DataSection, 0);
+  Asm->SwitchToDataSection(TAI->getDataSection(), 0);
   EmitLabel("data_end", 0);
   
+  // End text sections.
+  for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
+    Asm->SwitchToTextSection(SectionMap[i].c_str(), 0);
+    EmitLabel("section_end", i);
+  }
+  
   // Compute DIE offsets and sizes.
   SizeAndOffsets();
   
@@ -2416,24 +2589,17 @@ void DwarfWriter::EndModule() {
 
 /// BeginFunction - Gather pre-function debug information.  Assumes being 
 /// emitted immediately after the function entry point.
-void DwarfWriter::BeginFunction(MachineFunction *MF, bool IsNormalText) {
+void DwarfWriter::BeginFunction(MachineFunction *MF) {
   this->MF = MF;
-  // FIXME - should be able to debug coalesced functions.
-  this->IsNormalText = IsNormalText;
   
-  // FIXME - should be able to debug coalesced functions.
-  if (IsNormalText) {
-    // Begin accumulating function debug information.
-    DebugInfo->BeginFunction(MF);
-    
-    if (!ShouldEmitDwarf()) return;
-    EOL("Dwarf Begin Function");
+  if (!ShouldEmitDwarf()) return;
+  EOL("Dwarf Begin Function");
+
+  // Begin accumulating function debug information.
+  DebugInfo->BeginFunction(MF);
   
-    // Assumes in correct section after the entry point.
-    EmitLabel("func_begin", ++SubprogramCount);
-  } else {
-    ShouldEmitDwarf();
-  }
+  // Assumes in correct section after the entry point.
+  EmitLabel("func_begin", ++SubprogramCount);
 }
 
 /// EndFunction - Gather and emit post-function debug information.
@@ -2442,18 +2608,31 @@ void DwarfWriter::EndFunction() {
   if (!ShouldEmitDwarf()) return;
   EOL("Dwarf End Function");
   
-  // FIXME - should be able to debug coalesced functions.
-  if (IsNormalText) {
-    // Define end label for subprogram.
-    EmitLabel("func_end", SubprogramCount);
-  
-    // Construct scopes for subprogram.
-    ConstructRootScope(DebugInfo->getRootScope());
+  // Define end label for subprogram.
+  EmitLabel("func_end", SubprogramCount);
     
-    // Emit function frame information.
-    EmitFunctionDebugFrame();
+  // Get function line info.
+  std::vector<SourceLineInfo *> &LineInfos = DebugInfo->getSourceLines();
+
+  if (!LineInfos.empty()) {
+    // Get section line info.
+    unsigned ID = SectionMap.insert(Asm->CurrentSection);
+    if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
+    std::vector<SourceLineInfo *> &SectionLineInfos =SectionSourceLines[ID-1];
+    // Append the function info to section info.
+    SectionLineInfos.insert(SectionLineInfos.end(),
+                            LineInfos.begin(), LineInfos.end());
   }
   
+  // Construct scopes for subprogram.
+  ConstructRootScope(DebugInfo->getRootScope());
+  
+  // Emit function frame information.
+  EmitFunctionDebugFrame();
+  
+  // Reset the line numbers for the next function.
+  LineInfos.clear();
+
   // Clear function debug information.
   DebugInfo->EndFunction();
 }