* src/hc08/gen.c (hc08_emitDebuggerSymbol),
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 13 May 2004 22:10:41 +0000 (22:10 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 13 May 2004 22:10:41 +0000 (22:10 +0000)
* src/hc08/main.c,
* src/mcs51/gen.c (mcs51_emitDebuggerSymbol),
* src/mcs51/main.c,
* src/ds390/gen.c (ds390_emitDebuggerSymbol),
* src/ds390/main.c,
* src/z80/gen.c (z80_emitDebuggerSymbol),
* src/z80/main.c,
* src/pic/gen.c (pic14_emitDebuggerSymbol),
* src/pic/main.c,
* src/pic16/gen.c (pic14_emitDebuggerSymbol),
* src/pic16/main.c,
* src/avr/gen.c (avr_emitDebuggerSymbol),
* src/avr/main.c,
* src/xa51/gen.c (xa51_emitDebuggerSymbol),
* src/xa51/main.c,
* src/SDCCdebug.c (emitDebuggerSymbol),
* src/SDCCdebug.h,
* src/port.h: added a debugger struct to the port struct. Added a
callback for defining debugger symbols

* src/SDCCast.c (createLabel),
* src/SDCC.y (labeled_statement): mark all compiler generated labels
with isitmp = 1
* src/SDCCicode.h,
* src/SDCCicode.c (geniCodeFunctionBody): added a link from the FUNCTION
iCode back to the ast for the function

* src/hc08/ralloc.c (hc08_assignRegisters),
* src/hc08/ralloc.h: define a regs struct for the stack pointer. Removed
unneeded fields from the regs struct.
* src/hc08/gen.c (transferRegReg, genFunction, genEndFunction): use the
pushReg() & pullReg() functions instead of emitcode()

* src/hc08/gen.c (genLabel, genhc08Code),
* src/SDCCdebug.h: Added additional debugger hooks needed for DWARF

* src/cdbFile.c (cdbWriteLabel, cdbWriteScope): Added stubs for unneeded
debugger hooks

* src/hc08/gen.c (genEndFunction, genhc08Code),
* src/hc08/gen.h,
* src/mcs51/gen.c (genEndFunction, gen51Code),
* src/mcs51/gen.h,
* src/ds390/gen.c (genEndFunction, gen390Code),
* src/ds390/gen.h,
* src/z80/gen.c (genEndFunction, genZ80Code),
* src/z80/gen.h,
* src/z80/z80.h,
* src/pic/gen.c (genEndFunction, genpic14Code),
* src/pic/gen.h,
* src/pic16/gen.c (genEndFunction, genpic16Code),
* src/pic16/gen.h,
* src/avr/gen.c (genEndFunction, genAVRCode),
* src/avr/gen.h,
* src/xa51/gen.c (genEndFunction, genXA51Code),
* src/xa51/gen.h,
* src/cdbFile.c (cdbWriteFunction, cdbWriteEndFunction): moved cdb
specific code to cdbFile.c and out of the backend code generators

* as/hc08/lkmain.c (main): removed OMF51 support from link-hc08
* as/hc08/lkarea.c (lnkarea): areas with NOLOAD attribute default
starting address is now 0

* as/hc08/asm.h,
* as/hc08/m08pst.c,
* as/hc08/asmain.c (asmbl): implemented the .sleb128 and .uleb128
assembler directive for DWARF support
* as/hc08/lkelf.c (elf): only increment address when rtflg[] set

* src/src.dsp,
* src/Makefile.in,
* src/SDCCdwarf2.c: preliminary DWARF (ver 2) debugger data generator

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3305 4a8a32a2-be11-0410-ad9d-d568d2c75423

26 files changed:
as/hc08/asm.h
as/hc08/asmain.c
as/hc08/lkarea.c
as/hc08/lkelf.c
as/hc08/lkmain.c
as/hc08/m08pst.c
src/Makefile.in
src/SDCC.y
src/SDCCast.c
src/SDCCdwarf2.c [new file with mode: 0644]
src/SDCCdwarf2.h [new file with mode: 0644]
src/SDCCicode.c
src/SDCCicode.h
src/avr/gen.h
src/cdbFile.c
src/ds390/gen.h
src/hc08/gen.h
src/hc08/ralloc.c
src/hc08/ralloc.h
src/mcs51/gen.h
src/pic/gen.h
src/pic16/gen.h
src/src.dsp
src/xa51/gen.h
src/z80/gen.h
src/z80/z80.h

index 948992a4dd61f654cdbdf29591703dc98c4d087c..c7b1b6c7a85f21738317276ce787aa93765b5ff9 100644 (file)
@@ -332,7 +332,8 @@ struct      sym
 #define        S_ASCIS         26      /* .ascis */
 #define        S_FLAT24        27  /* .flat24 */
 #define        S_OPTSDCC       28  /* .optsdcc */
-
+#define S_ULEB128      29      /* .uleb128 */
+#define S_SLEB128      30      /* .sleb128 */
 
 /*
  *     The tsym structure is a linked list of temporary
index cb987f551b2701cd40458bba93173117ea7936c2..2ed786af3ca01b1b0030f0d979ee1faa426f9147 100644 (file)
@@ -740,6 +740,37 @@ loop:
                } while ((c = getnb()) == ',');
                unget(c);
                break;
+       
+       case S_ULEB128:
+       case S_SLEB128:
+               do {
+                       Addr_T val = absexpr();
+                       int bit = sizeof(val)*8 - 1;
+                       int impliedBit;
+
+                       if (mp->m_type == S_ULEB128) {
+                               impliedBit = 0;
+                       } else {
+                               impliedBit = (val & (1 << bit)) ? 1 : 0;
+                       }
+                       while ((bit>0) && (((val & (1 << bit)) ? 1 : 0) == impliedBit)) {
+                               bit--;
+                       }
+                       if (mp->m_type == S_SLEB128) {
+                               bit++;
+                       }
+                       while (bit>=0) {
+                               if (bit<7) {
+                                       outab(val & 0x7f);
+                               } else {
+                                       outab(0x80 | (val & 0x7f));
+                               }
+                               bit -= 7;
+                               val >>= 7;
+                       }
+               } while ((c = getnb()) == ',');
+               unget(c);
+               break;
 
        case S_ASCII:
        case S_ASCIZ:
index 42cdd4c1efc6a3accd5da074f8b1034e1bd11185..5b8eaf85f87507b854254ce3c6429b1bdc14b4f2 100644 (file)
@@ -350,7 +350,12 @@ lnkarea()
                         * Relocatable sections
                         */
                        if (ap->a_type == 0) {  /* JLH */
-                               ap->a_addr = rloc[ locIndex ];
+                               if (ap->a_flag & A_NOLOAD) {
+                                       locIndex = 2;
+                                       ap->a_addr = 0;
+                               } else {
+                                       ap->a_addr = rloc[ locIndex ];
+                               }
                                ap->a_type = 1;
                        }
                        lnksect(ap);
index edaad5bce4169cf4d0713e77d35d2dfe32220e21..3cc602fd483de07718419311c0c42af01075ddd5 100644 (file)
@@ -753,7 +753,7 @@ elf (int i)
         }
 
       /* Copy the data into the image buffer */
-      for (i = 2; i < rtcnt ; i++, address++)
+      for (i = 2; i < rtcnt ; i++)
         {
           if (rtflg[i])
             {
@@ -775,6 +775,7 @@ elf (int i)
                       execStartLSBfound = 1;
                     }
                 }
+             address++;
             }
         }
     }
index 882b5ca9e6c20e61f29a739d1c3ae63167d3e301..14003b7e22d4038e334d01d953413284aec5e6a9 100644 (file)
@@ -375,7 +375,7 @@ char *argv[];
                }
        }
        //JCF:
-       CreateAOMF51();
+       //CreateAOMF51();
 
 #ifdef WIN32T
     Timer(1, "Linker execution time");
index 57f44e18a0d81d901d009da9dc36411606a833ed..0da9cc9c01f414ea7bb27f6e37be5cd5f9cc0bb3 100644 (file)
@@ -33,6 +33,8 @@ struct        mne     mne[] = {
     {  NULL,   "LOAD",         S_ATYP,         0,      A_LOAD  },
     {  NULL,   "NOLOAD",       S_ATYP,         0,      A_NOLOAD },
 
+    {  NULL,   ".uleb128",     S_ULEB128,      0,      0       },
+    {  NULL,   ".sleb128",     S_SLEB128,      0,      0       },
     {  NULL,   ".byte",        S_BYTE,         0,      1       },
     {  NULL,   ".db",          S_BYTE,         0,      1       },
     {  NULL,   ".word",        S_WORD,         0,      2       },
index 26478f8bffe4baa5070eaa035a7d786714001762..8dcdf7feac9e8f02d915ebefe4eea19befc06e4d 100644 (file)
@@ -27,7 +27,7 @@ OBJECTS       = SDCCy.o SDCChasht.o SDCCmain.o \
                  SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \
                  SDCCBBlock.o SDCCloop.o SDCCcse.o SDCCcflow.o SDCCdflow.o \
                  SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o \
-                 asm.o SDCCmacro.o SDCCutil.o SDCCdebug.o cdbFile.o
+                 asm.o SDCCmacro.o SDCCutil.o SDCCdebug.o cdbFile.o SDCCdwarf2.o
 
 SPECIAL                = SDCCy.h 
 ifeq ($(USE_ALT_LEX), 1)
index 442e17e5ae1e926742ca7421c33dc72dac4d828a..77182a48ce2a822077a23e66d38bf34aecf758f3 100644 (file)
@@ -1399,7 +1399,8 @@ critical_statement
       
 labeled_statement
 //   : identifier ':' statement          {  $$ = createLabel($1,$3);  }   
-   : identifier ':'                    {  $$ = createLabel($1,NULL);  }   
+   : identifier ':'                    {  $$ = createLabel($1,NULL);
+                                         $1->isitmp = 0;  }   
    | CASE constant_expr ':'
      {
        if (STACK_EMPTY(swStk))
index f44ae1cc744590b239bde7a01f464f7c1e3c8462..a3fb39df8e7048a02e769ec735c62fcdc83885d9 100644 (file)
@@ -4446,6 +4446,7 @@ createLabel (symbol * label, ast * stmnt)
   else
     addSym (LabelTab, label, name, label->level, 0, 0);
 
+  label->isitmp = 1;
   label->islbl = 1;
   label->key = labelKey++;
   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
diff --git a/src/SDCCdwarf2.c b/src/SDCCdwarf2.c
new file mode 100644 (file)
index 0000000..5a9c22c
--- /dev/null
@@ -0,0 +1,3032 @@
+/*-------------------------------------------------------------------------
+  SDCCdwarf2.c - generate DWARF2 debug information
+
+             Written By -  Erik Petrich . epetrich@users.sourceforge.net (2004)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+
+#include "common.h"
+#include "SDCCdwarf2.h"
+
+/*************************************************************
+ *
+ *
+ *
+ *
+ *************************************************************/
+
+extern set *includeDirsSet;
+
+int dwOpenFile(char *file);
+int dwCloseFile(void);
+int dwWriteFunction(symbol *pSym, iCode *ic);
+int dwWriteEndFunction(symbol *pSym, iCode *ic, int offset);
+int dwWriteLabel(symbol *pSym, iCode *ic);
+int dwWriteScope(iCode *ic);
+int dwWriteSymbol(symbol *pSym);
+int dwWriteType(structdef *sdef, int block, int inStruct, char *tag);
+int dwWriteModule(char *name);
+int dwWriteCLine(iCode *ic);
+int dwWriteALine(char *module, int Line);
+int dwWriteFrameAddress(char *variable, struct regs *reg, int offset);
+int dwWriteBasicSymbol(symbol *sym, int isStructSym, int isFunc);
+     
+
+DEBUGFILE dwarf2DebugFile = 
+  {
+    &dwOpenFile,
+    &dwCloseFile,
+    &dwWriteModule,
+    &dwWriteFunction,
+    &dwWriteEndFunction,
+    &dwWriteLabel,
+    &dwWriteScope,
+    &dwWriteSymbol,
+    &dwWriteType,
+    &dwWriteCLine,
+    &dwWriteALine,
+    &dwWriteFrameAddress
+  };
+
+FILE *dwarf2FilePtr = NULL;
+char *dwModuleName = NULL;
+dwtag *dwRootTag = NULL;
+dwtag *dwFuncTag = NULL;
+dwtag *dwScopeTag = NULL;
+hTab * dwAbbrevTable;
+int dwAbbrevNum = 0;
+hTab * dwTypeTagTable;
+int dwRefNum = 0;
+int dwScopeBlock = 0;
+int dwScopeLevel = 0;
+int dwDebugSymbol = 0;
+//dwcfins * dwCIEins = NULL;
+dwlocregion * dwFrameLastLoc = NULL;
+dwloclist * dwRootLocList = NULL;
+dwloclist * dwFrameLocList = NULL;
+int dwLineBase = -5;
+int dwLineRange = 15;
+int dwLineOpcodeBase = 10;
+set * dwFilenameSet = NULL;
+dwline * dwLineFirst = NULL;
+dwline * dwLineLast = NULL;
+
+
+/*----------------------------------------------------------------------*/
+/* dwNewDebugSymbol - returns the name for a new debug symbol           */
+/*----------------------------------------------------------------------*/
+static char *
+dwNewDebugSymbol ()
+{
+  char debugSym[SDCC_NAME_MAX];
+        
+  sprintf (debugSym, "S%s$%s$%d", moduleName, currFunc->name, dwDebugSymbol);
+  dwDebugSymbol++;
+  return Safe_strdup (debugSym);
+}
+
+
+/*----------------------------------------------------------------------*/
+/* dwWriteByte - generate a single byte assembler constant in the form: */
+/*                                                                      */
+/*       .db label+offset  ; comment                                    */
+/*                                                                      */
+/* The label and comment parameters are optional                        */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteByte (char * label, int offset, char * comment)
+{
+  tfprintf (dwarf2FilePtr, "\t!db\t");
+  if (label)
+    {
+      if (offset)
+       fprintf (dwarf2FilePtr, "%s+%d", label, offset);
+      else
+       fprintf (dwarf2FilePtr, "%s", label);
+    }
+  else
+    fprintf (dwarf2FilePtr, "%d", offset);
+  
+  if (comment)
+    fprintf (dwarf2FilePtr, "\t;%s\n", comment);
+  else
+    fprintf (dwarf2FilePtr, "\n");
+}
+
+/*----------------------------------------------------------------------*/
+/* dwWriteHalf - generate a two byte assembler constant in the form:    */
+/*                                                                      */
+/*       .dw label+offset  ; comment                                    */
+/*                                                                      */
+/* The label and comment parameters are optional                        */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteHalf (char * label, int offset, char * comment)
+{
+  tfprintf (dwarf2FilePtr, "\t!dw\t");
+  if (label)
+    {
+      if (offset)
+       fprintf (dwarf2FilePtr, "%s+%d", label, offset);
+      else
+       fprintf (dwarf2FilePtr, "%s", label);
+    }
+  else
+    fprintf (dwarf2FilePtr, "%d", offset);
+  
+  if (comment)
+    fprintf (dwarf2FilePtr, "\t;%s\n", comment);
+  else
+    fprintf (dwarf2FilePtr, "\n");
+}
+
+/*----------------------------------------------------------------------*/
+/* dwWriteWord - generate a four byte assembler constant in the form:   */
+/*                                                                      */
+/*       .dd label+offset  ; comment                                    */
+/*                                                                      */
+/* The label and comment parameters are optional                        */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteWord (char * label, int offset, char * comment)
+{
+  /* FIXME: need to implement !dd pseudo-op in the assember. In the */
+  /* meantime, we use dw with zero padding and hope the values fit  */
+  /* in only 16 bits.                                               */
+#if 0
+  tfprintf (dwarf2FilePtr, "\t!dd\t");
+  if (label)
+    {
+      if (offset)
+       fprintf (dwarf2FilePtr, "%s+%d", label, offset);
+      else
+       fprintf (dwarf2FilePtr, "%s", label);
+    }
+  else
+    fprintf (dwarf2FilePtr, "%d", offset);
+#else
+  tfprintf (dwarf2FilePtr, "\t!dw\t");
+  if (port->little_endian)
+    {
+      if (label)
+       {
+         if (offset)
+           fprintf (dwarf2FilePtr, "(%s+%d),0", label, offset);
+         else
+           fprintf (dwarf2FilePtr, "(%s),0", label);
+       }
+      else
+       fprintf (dwarf2FilePtr, "%d,%d", offset, offset >> 16);
+    }
+  else
+    {
+      if (label)
+       {
+         if (offset)
+           fprintf (dwarf2FilePtr, "0,(%s+%d)", label, offset);
+         else
+           fprintf (dwarf2FilePtr, "0,(%s)", label);
+       }
+      else
+       fprintf (dwarf2FilePtr, "%d,%d", offset >> 16, offset);
+    }
+#endif
+  
+  if (comment)
+    fprintf (dwarf2FilePtr, "\t;%s\n", comment);
+  else
+    fprintf (dwarf2FilePtr, "\n");
+}
+
+
+/*----------------------------------------------------------------------*/
+/* dwWriteULEB128 - generate an unsigned variable length assembler      */
+/*                  constant in the form:                               */
+/*                                                                      */
+/*       .uleb128 label+offset  ; comment                               */
+/*                                                                      */
+/* The label and comment parameters are optional                        */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteULEB128 (char * label, int offset, char * comment)
+{
+  tfprintf (dwarf2FilePtr, "\t.uleb128\t");
+  if (label)
+    {
+      if (offset)
+       fprintf (dwarf2FilePtr, "%s+%d", label, offset);
+      else
+       fprintf (dwarf2FilePtr, "%s", label);
+    }
+  else
+    fprintf (dwarf2FilePtr, "%d", offset);
+  
+  if (comment)
+    fprintf (dwarf2FilePtr, "\t;%s\n", comment);
+  else
+    fprintf (dwarf2FilePtr, "\n");
+}
+
+/*----------------------------------------------------------------------*/
+/* dwWriteSLEB128 - generate a signed variable length assembler         */
+/*                  constant in the form:                               */
+/*                                                                      */
+/*       .sleb128 label+offset  ; comment                               */
+/*                                                                      */
+/* The label and comment parameters are optional                        */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteSLEB128 (char * label, int offset, char * comment)
+{
+  tfprintf (dwarf2FilePtr, "\t.sleb128\t");
+  if (label)
+    {
+      if (offset)
+       fprintf (dwarf2FilePtr, "%s+%d", label, offset);
+      else
+       fprintf (dwarf2FilePtr, "%s", label);
+    }
+  else
+    fprintf (dwarf2FilePtr, "%d", offset);
+  
+  if (comment)
+    fprintf (dwarf2FilePtr, "\t;%s\n", comment);
+  else
+    fprintf (dwarf2FilePtr, "\n");
+}
+
+
+/*----------------------------------------------------------------------*/
+/* dwSizeofULEB128 - return the size (in bytes) of an unsigned variable */
+/*                   length constant                                    */
+/*----------------------------------------------------------------------*/
+static int
+dwSizeofULEB128 (int unsigned value)
+{
+  int size = 0;
+  
+  do
+    {
+      value >>= 7;
+      size++;
+    }
+  while (value);
+  
+  return size;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwSizeofSLEB128 - return the size (in bytes) of a signed variable    */
+/*                   length constant                                    */
+/*----------------------------------------------------------------------*/
+static int
+dwSizeofSLEB128 (int value)
+{
+  int size = 0;
+  int negative = (value < 0);
+  int sign;
+  
+  while (1)
+    {
+      size++;
+      sign = value & 0x40;
+      value >>= 7;
+      if (negative)
+        value |= (0x7f << (sizeof(int)*8 - 7));
+      if ((value == 0 && !sign) || (value == -1 && sign))
+        break;
+    }
+  
+  return size;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwWriteString - generate a string constant in the form:              */
+/*                                                                      */
+/*       .ascii /string/  ; comment                                     */
+/*                                                                      */
+/* The comment parameter is optional. The string may contain any        */
+/* non-null characters                                                  */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteString (char * string, char * comment)
+{
+  /* FIXME: need to safely handle nonalphanumeric data in string */
+  
+  tfprintf (dwarf2FilePtr, "\t!ascii\n", string);
+  dwWriteByte (NULL, 0, comment);
+}
+
+
+/*----------------------------------------------------------------------*/
+/* dwWriteAddress - generate an assembler constant in the form:         */
+/*                                                                      */
+/*       .dw label+offset  ; comment                                    */
+/* or    .dd label+offset  ; comment                                    */
+/*                                                                      */
+/* depending on how the relevant ABI defines the address size (may be   */
+/* larger than the CPU's actual address size). The label and comment    */
+/* parameters are optional                                              */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteAddress (char * label, int offset, char * comment)
+{
+  switch (port->debugger.dwarf.addressSize)
+    {
+    case 2:
+      dwWriteHalf (label, offset, comment);
+      break;
+    case 4:
+      dwWriteWord (label, offset, comment);
+      break;
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "unsupported port->debugger.dwarf.addressSize");
+    }
+}
+
+
+/*----------------------------------------------------------------------*/
+/* dwWriteHalfDelta - generate a two byte assembler constant in the     */
+/*                    form:                                             */
+/*                                                                      */
+/*       .dw offset+label1-label2                                       */
+/*                                                                      */
+/* The offset parameter is optional                                     */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteHalfDelta (char * label1, char * label2, int offset)
+{
+  if (offset)
+    tfprintf (dwarf2FilePtr, "\t!dw\t%d+%s-%s\n", offset, label1, label2);
+  else
+    tfprintf (dwarf2FilePtr, "\t!dw\t%s-%s\n", label1, label2);
+}
+
+/*----------------------------------------------------------------------*/
+/* dwWriteWordDelta - generate a four byte assembler constant in the    */
+/*                    form:                                             */
+/*                                                                      */
+/*       .dd label1-label2                                              */
+/*----------------------------------------------------------------------*/
+static void 
+dwWriteWordDelta (char * label1, char * label2)
+{
+  /* FIXME: need to implement !dd pseudo-op; this hack only */
+  /* works for positive offsets of less than 64k            */
+#if 0
+  tfprintf (dwarf2FilePtr, "\t!dd\t%s-%s\n", label1,label2);
+#else
+  if (port->little_endian)
+    {
+      tfprintf (dwarf2FilePtr, "\t!dw\t%s-%s,%d\n", label1, label2, 0);
+    }
+  else
+    {
+      tfprintf (dwarf2FilePtr, "\t!dw\t%d,%s-%s\n", 0, label1, label2);
+    }
+#endif
+}
+
+
+/* disabled to eliminiate unused function warning */
+#if 0 
+/*----------------------------------------------------------------------*/
+/* dwWriteAddressDelta - generate an assembler constant in the form:    */
+/*                                                                      */
+/*       .dw label1-label2                                              */
+/* or    .dd label1-label2                                              */
+/*                                                                      */
+/* depending on how the relevant ABI defines the address size (may be   */
+/* larger than the CPU's actual address size)                           */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteAddressDelta (char * label1, char * label2)
+{
+  switch (port->debugger.dwarf.addressSize)
+    {
+    case 2:
+      dwWriteHalfDelta (label1, label2, 0);
+      break;
+    case 4:
+      dwWriteWordDelta (label1, label2);
+      break;
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "unsupported port->debugger.dwarf.addressSize");
+    }
+}
+
+/*----------------------------------------------------------------------*/
+/* dwWriteULEB128Delta - generate an unsigned variable byte assembler   */
+/*                       constant in the form:                          */
+/*                                                                      */
+/*       .uleb128 offset+label1-label2                                  */
+/*                                                                      */
+/* The offset parameter is optional                                     */
+/*----------------------------------------------------------------------*/
+static void
+dwWriteULEB128Delta (char * label1, char * label2, int offset)
+{
+  if (offset)
+    tfprintf (dwarf2FilePtr, "\t.uleb128\t%d+%s-%s\n", offset, label1, label2);
+  else
+    tfprintf (dwarf2FilePtr, "\t.uleb128\t%s-%s\n", label1, label2);
+}
+#endif
+
+/*------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/* dwNewLoc - allocates a new location expression node                  */
+/*----------------------------------------------------------------------*/
+dwloc *
+dwNewLoc (int opcode, char * label, int offset)
+{
+  dwloc * lp;
+  
+  lp = Safe_alloc (sizeof (dwloc));
+  
+  lp->opcode = opcode;
+  lp->operand.label = label;
+  lp->operand.offset = offset;
+
+  return lp;
+}
+
+/*-------------------------------------------------------------------------*/
+/* dwSizeofLoc - returns the size (in bytes) of a chain of location        */
+/*               expression nodes as they would be encoded by dwWriteLoc() */
+/*-------------------------------------------------------------------------*/
+static int
+dwSizeofLoc (dwloc * lp)
+{
+  int size = 0;
+  
+  while (lp)
+    {
+      size++;
+      switch (lp->opcode)
+        {
+       case DW_OP_addr:
+         size += port->debugger.dwarf.addressSize;
+         break;
+         
+       case DW_OP_deref_size:
+       case DW_OP_xderef_size:
+       case DW_OP_pick:
+       case DW_OP_const1u:
+       case DW_OP_const1s:
+         size += 1;
+         break;
+       
+       case DW_OP_skip:
+       case DW_OP_bra:
+       case DW_OP_const2u:
+       case DW_OP_const2s:
+         size += 2;
+         break;
+       
+       case DW_OP_const4u:
+       case DW_OP_const4s:
+         size += 4;
+         break;
+       
+       case DW_OP_const8u:
+       case DW_OP_const8s:
+         size += 8;
+         break;
+
+       case DW_OP_piece:
+       case DW_OP_regx:
+       case DW_OP_plus_uconst:
+         size += dwSizeofULEB128 (lp->operand.offset);
+         break;
+       
+       case DW_OP_breg0:
+       case DW_OP_breg1:
+       case DW_OP_breg2:
+       case DW_OP_breg3:
+       case DW_OP_breg4:
+       case DW_OP_breg5:
+       case DW_OP_breg6:
+       case DW_OP_breg7:
+       case DW_OP_breg8:
+       case DW_OP_breg9:
+       case DW_OP_breg10:
+       case DW_OP_breg11:
+       case DW_OP_breg12:
+       case DW_OP_breg13:
+       case DW_OP_breg14:
+       case DW_OP_breg15:
+       case DW_OP_breg16:
+       case DW_OP_breg17:
+       case DW_OP_breg18:
+       case DW_OP_breg19:
+       case DW_OP_breg20:
+       case DW_OP_breg21:
+       case DW_OP_breg22:
+       case DW_OP_breg23:
+       case DW_OP_breg24:
+       case DW_OP_breg25:
+       case DW_OP_breg26:
+       case DW_OP_breg27:
+       case DW_OP_breg28:
+       case DW_OP_breg29:
+       case DW_OP_breg30:
+       case DW_OP_breg31:
+       case DW_OP_fbreg:
+         size += dwSizeofSLEB128 (lp->operand.offset);
+         break;
+       }
+      
+      lp = lp->next;
+    }
+  
+  return size;
+}
+
+/*------------------------------------------------------------------------*/
+/* dwWriteLoc - writes a chain of location expression nodes               */
+/*------------------------------------------------------------------------*/
+static void
+dwWriteLoc (dwloc *lp)
+{
+  while (lp)
+    {
+      dwWriteByte (NULL, lp->opcode, NULL);
+      switch (lp->opcode)
+        {
+       case DW_OP_addr:
+         dwWriteAddress (lp->operand.label, lp->operand.offset, NULL);
+         break;
+         
+       case DW_OP_deref_size:
+       case DW_OP_xderef_size:
+       case DW_OP_pick:
+       case DW_OP_const1u:
+       case DW_OP_const1s:
+         dwWriteByte (NULL, lp->operand.offset, NULL);
+         break;
+       
+       case DW_OP_skip:
+       case DW_OP_bra:
+       case DW_OP_const2u:
+       case DW_OP_const2s:
+         dwWriteHalf (NULL, lp->operand.offset, NULL);
+         break;
+       
+       case DW_OP_const4u:
+       case DW_OP_const4s:
+         dwWriteWord (NULL, lp->operand.offset, NULL);
+         break;
+       
+       case DW_OP_piece:
+       case DW_OP_regx:
+       case DW_OP_plus_uconst:
+         dwWriteULEB128 (NULL, lp->operand.offset, NULL);
+         break;
+       
+       case DW_OP_breg0:
+       case DW_OP_breg1:
+       case DW_OP_breg2:
+       case DW_OP_breg3:
+       case DW_OP_breg4:
+       case DW_OP_breg5:
+       case DW_OP_breg6:
+       case DW_OP_breg7:
+       case DW_OP_breg8:
+       case DW_OP_breg9:
+       case DW_OP_breg10:
+       case DW_OP_breg11:
+       case DW_OP_breg12:
+       case DW_OP_breg13:
+       case DW_OP_breg14:
+       case DW_OP_breg15:
+       case DW_OP_breg16:
+       case DW_OP_breg17:
+       case DW_OP_breg18:
+       case DW_OP_breg19:
+       case DW_OP_breg20:
+       case DW_OP_breg21:
+       case DW_OP_breg22:
+       case DW_OP_breg23:
+       case DW_OP_breg24:
+       case DW_OP_breg25:
+       case DW_OP_breg26:
+       case DW_OP_breg27:
+       case DW_OP_breg28:
+       case DW_OP_breg29:
+       case DW_OP_breg30:
+       case DW_OP_breg31:
+       case DW_OP_fbreg:
+         dwWriteSLEB128 (NULL, lp->operand.offset, NULL);
+         break;
+       }
+       
+      lp = lp->next;
+    }
+}
+
+/*----------------------------------------------------------------------*/
+/* dwNewLocList - allocates a new list of location expression node      */
+/*----------------------------------------------------------------------*/
+static dwloclist *
+dwNewLocList (void)
+{
+  dwloclist * llp;
+  
+  llp = Safe_alloc (sizeof (dwloclist));
+  
+  return llp;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwSizeofLocRegion - returns the size (in bytes) of a chain of        */
+/*                     location regions (inluding their location        */
+/*                     expression nodes) as encoded by dwWriteLocLists  */
+/*----------------------------------------------------------------------*/
+static int
+dwSizeofLocRegion (dwlocregion * lrp)
+{
+  int size = 0;
+  
+  while (lrp)
+    {
+      size += 2 * port->debugger.dwarf.addressSize;
+      size += 2 + dwSizeofLoc (lrp->loc);
+      lrp = lrp->next;
+    }
+  
+  size += 2 * port->debugger.dwarf.addressSize;
+  return size;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwAssignLocListAddresses - assign the address offsets of the location */
+/*                            lists so that they can be referenced from  */
+/*                            the tag structure                          */
+/*-----------------------------------------------------------------------*/
+static void
+dwAssignLocListAddresses (void)
+{
+  dwloclist * llp;
+  int address = 0;
+
+  llp = dwRootLocList;
+  while (llp)
+    {
+      llp->baseOffset = address;
+      address += dwSizeofLocRegion (llp->region);
+
+      llp = llp->next;
+    }
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteLocLists - write all of the location lists in dwRootLocList to */
+/*                   the .debug_loc section                              */
+/*-----------------------------------------------------------------------*/
+static void
+dwWriteLocLists (void)
+{
+  dwlocregion * lrp;
+  dwloclist * llp;
+
+  tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_loc (NOLOAD)");
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_loc_start");
+
+  llp = dwRootLocList;
+  while (llp)
+    {
+      //fprintf (dwarf2FilePtr, "; baseOffset = 0x%x\n", llp->baseOffset);
+      lrp = llp->region;
+      while (lrp)
+       {
+         dwWriteAddress (lrp->startLabel, 0, NULL);
+         dwWriteAddress (lrp->endLabel, 0, NULL);
+         dwWriteHalf (NULL, dwSizeofLoc (lrp->loc), NULL);
+         dwWriteLoc (lrp->loc);
+         lrp = lrp ->next;
+       }
+
+      dwWriteAddress (NULL, 0, NULL);
+      dwWriteAddress (NULL, 0, NULL);
+
+      llp = llp->next;
+    }
+    
+}
+
+
+/*------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------*/
+/* dwNewAttr - allocate a new tag attribute node                        */
+/*----------------------------------------------------------------------*/
+static dwattr *
+dwNewAttr (int attr)
+{
+  dwattr * ap;
+  
+  ap = Safe_alloc ( sizeof (dwattr));
+  ap->attr = attr;
+  
+  return ap;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwFreeAttr - deallocate a tag attribute node                         */
+/*----------------------------------------------------------------------*/
+static void
+dwFreeAttr (dwattr * ap)
+{
+  Safe_free (ap);
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/* dwNewAttrString - allocate a new tag attribute node with a string value */
+/*-------------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrString (int attr, char * string)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_string;
+  ap->val.string = string;
+  return ap;
+}
+
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrConst - allocate a new tag attribute node with an unsigned */
+/*                  numeric constant value                             */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrConst (int attr, unsigned int data)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  if (data <= 0xffu)
+    ap->form = DW_FORM_data1;
+  else if (data <= 0xffffu)
+    ap->form = DW_FORM_data2;
+  else
+    ap->form = DW_FORM_data4;
+  
+  ap->val.data = data;
+  return ap;
+}
+
+/* disabled to eliminiate unused function warning */
+#if 0
+/*---------------------------------------------------------------------*/
+/* dwNewAttrSignedConst - allocate a new tag attribute node with a     */
+/*                        signed numeric constant value                */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrSignedConst (int attr, int data)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  if (data <= 0x7f && data >= -0x80)
+    ap->form = DW_FORM_data1;
+  else if (data <= 0xffff && data >= -0x8000)
+    ap->form = DW_FORM_data2;
+  else
+    ap->form = DW_FORM_data4;
+  
+  ap->val.data = data;
+  return ap;
+}
+#endif
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrFlag - allocate a new tag attribute node with a boolean    */
+/*                 flag value (zero/non-zero)                          */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrFlag (int attr, int data)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_flag;
+  
+  ap->val.data = data;
+  return ap;
+}
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrAddrSymbol - allocate a new tag attribute node with the    */
+/*                       address of a C symbol plus an offset          */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrAddrSymbol (int attr, symbol * sym, int offset)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_addr;
+  
+  ap->val.symaddr.label = sym->rname;
+  ap->val.symaddr.offset = offset;
+  return ap;
+}
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrAddrLabel - allocate a new tag attribute node with the     */
+/*                      address of an assembler label plus an offset   */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrAddrLabel (int attr, char * label, int offset)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_addr;
+  
+  ap->val.symaddr.label = label;
+  ap->val.symaddr.offset = offset;
+  return ap;
+}
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrTagRef - allocate a new tag attribute node that references */
+/*                   a tag node                                        */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrTagRef (int attr, dwtag * tp)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_ref4;
+  
+  ap->val.ref = tp;
+  return ap;
+}
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrLocRef - allocate a new tag attribute node that references */
+/*                   a location list                                   */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrLocRef (int attr, dwloclist * llp)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_data4;
+  
+  ap->val.loclist = llp;
+  return ap;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwNewAttrLabelRef - allocate a new tag attribute node that references */
+/*                     the address of an assembler label plus an offset  */
+/*-----------------------------------------------------------------------*/
+static dwattr *
+dwNewAttrLabelRef (int attr, char * label, int offset)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_data4;
+  
+  ap->val.symaddr.label = label;
+  ap->val.symaddr.offset = offset;
+  return ap;
+}
+
+/*---------------------------------------------------------------------*/
+/* dwNewAttrLoc - allocate a new tag attribute node for a chain of     */
+/*                location expression nodes                            */
+/*---------------------------------------------------------------------*/
+dwattr *
+dwNewAttrLoc (int attr, dwloc * lp)
+{
+  dwattr * ap;
+  
+  ap = dwNewAttr (attr);
+  ap->form = DW_FORM_block1;
+  ap->val.loc = lp;
+  
+  return ap;
+}
+
+/*---------------------------------------------------------------------*/
+/* dwWriteAttr - write a tag attribute node                            */
+/*---------------------------------------------------------------------*/
+static void
+dwWriteAttr (dwattr * ap)
+{
+  
+  switch (ap->form)
+    {
+      case DW_FORM_addr:
+       dwWriteAddress (ap->val.symaddr.label, ap->val.symaddr.offset, NULL);
+       break;
+      
+      case DW_FORM_block:
+        dwWriteULEB128 (NULL, dwSizeofLoc (ap->val.loc), NULL);
+       dwWriteLoc (ap->val.loc);
+       break;
+      
+      case DW_FORM_block1:
+        dwWriteByte (NULL, dwSizeofLoc (ap->val.loc), NULL);
+       dwWriteLoc (ap->val.loc);
+       break;
+      
+      case DW_FORM_block2:
+        dwWriteHalf (NULL, dwSizeofLoc (ap->val.loc), NULL);
+       dwWriteLoc (ap->val.loc);
+       break;
+      
+      case DW_FORM_block4:
+        dwWriteWord (NULL, dwSizeofLoc (ap->val.loc), NULL);
+       dwWriteLoc (ap->val.loc);
+       break;
+      
+      case DW_FORM_data1:
+      case DW_FORM_flag:
+        dwWriteByte (NULL, ap->val.data, NULL);
+       break;
+      
+      case DW_FORM_data2:
+        dwWriteHalf (NULL, ap->val.data, NULL);
+       break;
+      
+      case DW_FORM_data4:
+        switch (ap->attr)
+         {
+         case DW_AT_stmt_list:
+           dwWriteWord (ap->val.symaddr.label, ap->val.symaddr.offset, NULL);
+           break;
+         case DW_AT_location:
+         case DW_AT_frame_base:
+           dwWriteWord (NULL, ap->val.loclist->baseOffset, NULL);
+           break;
+         default:
+           dwWriteWord (NULL, ap->val.data, NULL);
+         }
+       break;
+      
+      case DW_FORM_udata:
+        dwWriteULEB128 (NULL, ap->val.data, NULL);
+       break;
+      
+      case DW_FORM_sdata:
+        dwWriteSLEB128 (NULL, ap->val.data, NULL);
+       break;
+
+      case DW_FORM_string:
+        dwWriteString (ap->val.string, NULL);
+       break;
+      
+      case DW_FORM_ref1:
+       dwWriteByte (NULL, ap->val.ref->baseOffset, NULL);
+       break;
+      
+      case DW_FORM_ref2:
+       dwWriteHalf (NULL, ap->val.ref->baseOffset, NULL);
+       break;
+      
+      case DW_FORM_ref4:
+       dwWriteWord (NULL, ap->val.ref->baseOffset, NULL);
+       break;
+       
+      default:
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+               "unsupported DWARF form");
+       exit (1);
+    }
+}
+
+/*---------------------------------------------------------------------*/
+/* dwSizeofAttr - returns the size (in bytes) of a tag attribute node  */
+/*                as encoded by dwWriteAttr                            */
+/*---------------------------------------------------------------------*/
+static int
+dwSizeofAttr (dwattr * ap)
+{
+  int size;
+  
+  switch (ap->form)
+    {
+      case DW_FORM_addr:
+        return port->debugger.dwarf.addressSize;
+      
+      case DW_FORM_block:
+        size = dwSizeofLoc (ap->val.loc);
+        return size + dwSizeofULEB128 (size);
+      
+      case DW_FORM_block1:
+        size = dwSizeofLoc (ap->val.loc);
+        return size + 1;
+      
+      case DW_FORM_block2:
+        size = dwSizeofLoc (ap->val.loc);
+        return size + 2;
+      
+      case DW_FORM_block4:
+        size = dwSizeofLoc (ap->val.loc);
+        return size + 4;
+      
+      case DW_FORM_data1:
+      case DW_FORM_flag:
+        return 1;
+      
+      case DW_FORM_data2:
+        return 2;
+      
+      case DW_FORM_data4:
+        return 4;
+      
+      case DW_FORM_udata:
+        return dwSizeofULEB128 (ap->val.data);
+      
+      case DW_FORM_sdata:
+        return dwSizeofSLEB128 (ap->val.data);
+
+      case DW_FORM_string:
+        return 1 + strlen (ap->val.string);
+      
+      case DW_FORM_ref1:
+        return 1;
+      
+      case DW_FORM_ref2:
+        return 2;
+      
+      case DW_FORM_ref4:
+        return 4;
+       
+      default:
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+               "unsupported DWARF form");
+       exit (1);
+    }
+    
+}
+
+
+/*---------------------------------------------------------------------*/
+/* dwFindAttr - for a tag node, return a pointer to a particular       */
+/*              attribute node, or NULL if not found                   */
+/*---------------------------------------------------------------------*/
+static dwattr *
+dwFindAttr (dwtag * tp, int attr)
+{
+  dwattr * ap;
+  
+  ap = tp->attribs;
+  while (ap)
+    {
+      if (ap->attr == attr)
+        return ap;
+      ap = ap->next;
+    }
+  
+  return NULL;
+}
+
+
+
+/*------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------*/
+/* dwNewTag - allocate a new tag node                                   */
+/*----------------------------------------------------------------------*/
+static dwtag *
+dwNewTag (int tag)
+{
+  dwtag * tp;
+  
+  tp = Safe_alloc ( sizeof (dwtag));
+  tp->tag = tag;
+  
+  return tp;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwAddTagAttr - add an attribute to a tag                             */
+/*----------------------------------------------------------------------*/
+static void
+dwAddTagAttr (dwtag * tp, dwattr * ap)
+{
+  dwattr * curap;
+  
+  if (!tp->attribs)
+    tp->attribs = ap;
+  else if (ap->attr < tp->attribs->attr)
+    {
+      ap->next = tp->attribs;
+      tp->attribs = ap;
+    }
+  else
+    {
+      curap = tp->attribs;
+      while (curap->next && curap->next->attr < ap->attr)
+        curap = curap->next;
+      ap->next = curap->next;
+      curap->next = ap;
+    }
+}
+
+/*----------------------------------------------------------------------*/
+/* dwSetTagAttr - repleace an existing attribute of a tag with a new    */
+/*                attribute or add if non-existent                      */
+/*----------------------------------------------------------------------*/
+static void
+dwSetTagAttr (dwtag *tp, dwattr * ap)
+{
+  dwattr * curap;
+  
+  curap = dwFindAttr (tp, ap->attr);
+  if (curap)
+    {
+      ap->next = curap->next;
+      *curap = *ap;
+      dwFreeAttr (ap);
+    }
+  else
+    dwAddTagAttr (tp, ap);
+}
+
+
+/*----------------------------------------------------------------------*/
+/* dwAddTagChild - add a tag as a child of another tag                  */
+/*----------------------------------------------------------------------*/
+static dwtag *
+dwAddTagChild (dwtag * parent, dwtag * child)
+{
+  child->parent = parent;
+  if (parent->lastChild)
+    {
+      parent->lastChild->siblings = child;
+      parent->lastChild = child;
+    }
+  else
+    {
+      parent->firstChild = child;
+      parent->lastChild = child;
+    }
+  return parent;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwMatchTagAttr - returns true if two tags are equal in value,        */
+/*                  attributes, and offspring status (the child tags    */
+/*                  need not match, but they must both have children or */
+/*                  both not have children)                             */
+/*----------------------------------------------------------------------*/
+static int
+dwMatchTagAttr (const void * tp1v, const void * tp2v)
+{
+  const dwtag * tp1 = tp1v;
+  const dwtag * tp2 = tp2v;
+  dwattr * ap1 = tp1->attribs;
+  dwattr * ap2 = tp2->attribs;
+
+  if (!tp1 || !tp2)
+    return 0;
+    
+  if (tp1->tag != tp2->tag)
+    return 0;
+  
+  if (tp1->firstChild && !tp2->lastChild)
+    return 0;
+  if (!tp1->firstChild && tp2->lastChild)
+    return 0;
+    
+  while (ap1 && ap2)
+    {
+      if (ap1->attr != ap2->attr)
+        return 0;
+      if (ap1->form != ap2->form)
+        return 0;
+
+      ap1 = ap1->next;
+      ap2 = ap2->next;
+    }
+  
+  return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwHashTag - return a hash code for a tag based on its value and      */
+/*             attributes                                               */
+/*----------------------------------------------------------------------*/
+static int
+dwHashTag (dwtag * tp)
+{
+  dwattr * ap = tp->attribs;
+  int hash = tp->tag;
+
+  while (ap)
+    {
+      hash = (hash << 6) ^ ((hash >> 11) & 0xff);
+      hash ^= (ap->attr) | (ap->form << 8);
+      
+      ap = ap->next;
+    }  
+  if (hash<0)
+    return -hash;
+  else
+    return hash;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwTraverseTag - perform a depth-first preorder traversal of a tag    */
+/*                 tree, calling the user function at each node. The    */
+/*                 user function is also called with a NULL tag pointer */
+/*                 after the last sibling of each immediate family is   */
+/*                 processed.                                           */
+/*----------------------------------------------------------------------*/
+static int
+dwTraverseTag (dwtag *tp, int (*somefunc)(dwtag *tp, void * info), void * info)
+{
+  int rvalue = 0;
+  
+  while (tp)
+    {
+      rvalue += (*somefunc)(tp, info);
+      if (tp->firstChild)
+        rvalue += dwTraverseTag (tp->firstChild, somefunc, info);
+      tp = tp->siblings;
+    }
+  rvalue += (*somefunc)(NULL, info);
+  
+  return rvalue;
+}
+
+/*----------------------------------------------------------------------*/
+/* dwAssignAbbrev - find a matching abbreviation for a tag or create a  */
+/*                  a new one and assign it                             */
+/*----------------------------------------------------------------------*/
+static int
+dwAssignAbbrev (dwtag *tp, void *info)
+{
+  dwtag * oldtp;
+  int * anp = info;    /* pointer to current abbreviation number */
+  int key;
+  
+  if (!tp)
+    return 0;
+
+  key = dwHashTag (tp) % dwAbbrevTable->size;
+  oldtp = hTabFindByKey (dwAbbrevTable, key, tp, dwMatchTagAttr);
+  if (oldtp)
+    {
+      tp->abbrev = oldtp->abbrev;
+      return 0;
+    }
+  else
+    {
+      tp->abbrev = ++(*anp);
+      hTabAddItemLong (&dwAbbrevTable, key, tp, tp);
+      return 1;
+    }
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteAbbrevs - write the abbreviations to the .debug_abbrev section */
+/*-----------------------------------------------------------------------*/
+static void
+dwWriteAbbrevs (void)
+{
+  dwtag * tp;
+  dwattr * ap;
+  int key;
+  
+  tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_abbrev (NOLOAD)");
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_abbrev");
+
+  tp = hTabFirstItem (dwAbbrevTable, &key);
+  for (; tp; tp = hTabNextItem (dwAbbrevTable, &key))
+    {
+      dwWriteULEB128 (NULL, tp->abbrev, NULL);
+      dwWriteULEB128 (NULL, tp->tag, NULL);
+      dwWriteByte (NULL, tp->firstChild ? DW_CHILDREN_yes : DW_CHILDREN_no,
+                  NULL);
+      ap = tp->attribs;
+      while (ap)
+        {
+         dwWriteULEB128 (NULL, ap->attr, NULL);
+         dwWriteULEB128 (NULL, ap->form, NULL);
+         ap = ap->next;
+       }
+      dwWriteULEB128 (NULL, 0, NULL);
+      dwWriteULEB128 (NULL, 0, NULL);
+      
+    }
+  dwWriteULEB128 (NULL, 0, NULL);
+  
+  hTabDeleteAll (dwAbbrevTable);
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteTag - write the encoded tag information                        */
+/*-----------------------------------------------------------------------*/
+static int
+dwWriteTag (dwtag *tp, void *info)
+{
+  dwattr * ap;
+
+  if (!tp)
+    {
+      /* mark the end of this series of siblings */
+      dwWriteULEB128 (NULL, 0, NULL);
+      return 0;
+    }
+
+  //fprintf (dwarf2FilePtr, "; baseOffset = 0x%x\n", tp->baseOffset);
+  
+  /* write the tag abbreviation */
+  dwWriteULEB128 (NULL, tp->abbrev, NULL);
+  
+  /* write the values of the attributes */
+  ap = tp->attribs;
+  while (ap)
+    {
+      dwWriteAttr (ap);
+      ap = ap->next;
+    }
+    
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteTags - write all the tags to the .debug_info section           */
+/*-----------------------------------------------------------------------*/
+static void
+dwWriteTags (void)
+{  
+  tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_info (NOLOAD)");
+  
+  dwWriteWordDelta ("Ldebug_info_end", "Ldebug_info_start");
+  
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_info_start");
+  
+  dwWriteHalf (NULL, 2, NULL); /* DWARF version */
+  
+  dwWriteWord ("Ldebug_abbrev", 0, NULL);
+    
+  dwWriteByte (NULL, port->debugger.dwarf.addressSize, NULL);
+    
+  dwTraverseTag (dwRootTag, dwWriteTag, NULL);
+  
+  dwWriteULEB128 (NULL, 0, NULL);
+  
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_info_end");
+
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwAssignTagAddress - assign the current address to the current tag.   */
+/*                      Compute the next address based on the tag size   */
+/*-----------------------------------------------------------------------*/
+static int
+dwAssignTagAddress (dwtag *tp, void *info)
+{
+  int * tap = info;
+  dwattr * ap;
+
+  if (!tp)
+    {
+      *tap += 1;
+      return 0;
+    }
+      
+  tp->baseOffset = *tap;
+
+  *tap += dwSizeofULEB128 (tp->abbrev);
+  
+  ap = tp->attribs;
+  while (ap)
+    {
+      *tap += dwSizeofAttr (ap);
+      ap = ap->next;
+    }
+    
+  return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwAddSibAttr - if a tag has children and a sibling, add a sibling     */
+/*                attribute (it allows debuggers to jump to the sibling  */
+/*                and skip the child data)                               */
+/*-----------------------------------------------------------------------*/
+static int
+dwAddSibAttr (dwtag *tp, void *info)
+{
+  if (!tp)
+    return 0;
+  if (tp == dwRootTag)
+    return 0;
+  
+  if (tp->firstChild && tp->siblings)
+    dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_sibling, tp->siblings));
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwDeleteTagAttr - given a pointer to an attribute type, delete any    */
+/*                   matching attribute                                  */
+/*-----------------------------------------------------------------------*/
+static int
+dwDeleteTagAttr (dwtag *tp, void *info)
+{
+  int attr = *((int *) info);
+  dwattr * ap;
+  
+  if (!tp)
+    return 0;
+
+  ap = tp->attribs;
+  if (ap && ap->attr == attr)
+    {
+      tp->attribs = ap->next;
+      return 1;
+    }
+  
+  while (ap)
+    {
+      if (ap->next && ap->next->attr == attr)
+        {
+         ap->next = ap->next->next;
+         return 1;
+       }
+      ap = ap->next;
+    }
+  
+  return 0;
+}
+
+
+/*------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------*/
+/* dwWritePubnames - write all the public names to the .debug_pubnames   */
+/*                   section. Externally visible functions and variables */
+/*                   are considered to have public names.                */
+/*-----------------------------------------------------------------------*/
+static void
+dwWritePubnames (void)
+{
+  dwtag * tp;
+  dwattr * ap1;
+  dwattr * ap2;
+  
+  tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_pubnames (NOLOAD)");
+  
+  dwWriteWordDelta ("Ldebug_pubnames_end", "Ldebug_pubnames_start");
+  
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_pubnames_start");
+  
+  dwWriteHalf (NULL, 2, NULL); /* DWARF version */
+  
+  dwWriteWord ("Ldebug_info_start-4", 0, NULL);
+  dwWriteWordDelta ("4+Ldebug_info_end", "Ldebug_info_start");
+
+  if (dwRootTag && dwRootTag->firstChild)
+    {
+      tp = dwRootTag->firstChild;
+      while (tp)
+       {
+         if (tp->tag == DW_TAG_variable || tp->tag == DW_TAG_subprogram)
+           {
+             /* If it has a name and is externally visible, it's a pubname */
+             ap1 = dwFindAttr (tp, DW_AT_external);
+             ap2 = dwFindAttr (tp, DW_AT_name);
+             if (ap1 && ap1->val.data && ap2)
+               {
+                 dwWriteWord (NULL, tp->baseOffset, NULL);
+                 dwWriteString (ap2->val.string, NULL);
+               }
+           }
+       
+         tp = tp->siblings;
+       }
+    }  
+  dwWriteWord (NULL, 0, NULL);
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_pubnames_end");
+}
+
+/*------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------*/
+/* dwFindFileIndex - find the index of a filename in dwFilenameSet; if   */
+/*                   it does not exist, it is added                      */
+/*-----------------------------------------------------------------------*/
+static int
+dwFindFileIndex (char * filename)
+{
+  char * includeDir;
+  dwfile * srcfile;
+  int fileIndex = 1;
+  int dirIndex = 1;
+
+  /* Just do a linear search for the file. There should be hardly */
+  /* a penalty since 1) most calls search for the first file, and */
+  /* 2) the file set is usually small (often just 1 item)         */
+  for (srcfile = setFirstItem (dwFilenameSet);
+       srcfile;
+       srcfile = setNextItem(dwFilenameSet), fileIndex++ )
+    {
+      if (!strcmp (srcfile->name, filename))
+        return fileIndex;
+    }
+
+  for (includeDir = setFirstItem (includeDirsSet);
+       includeDir;
+       includeDir = setNextItem(includeDirsSet), dirIndex++ )
+    {
+      if (!strncmp (includeDir, filename, strlen (includeDir))
+          && strlen (filename) > strlen (includeDir))
+        {
+         if (*(filename+strlen (includeDir)) == DIR_SEPARATOR_CHAR)
+           break;
+       }
+    }
+  if (!includeDir)
+    dirIndex = 0;
+
+  srcfile = Safe_alloc (sizeof (dwfile));
+  srcfile->name = filename;
+  srcfile->dirIndex = dirIndex;
+  srcfile->timestamp = 0;
+  srcfile->length = 0;
+
+  addSet (&dwFilenameSet, srcfile);
+  return fileIndex;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteLineNumber - write line number (and related position info) to  */
+/*                     address corespondence data for a single node      */
+/*-----------------------------------------------------------------------*/
+static void
+dwWriteLineNumber (dwline * lp)
+{
+  static int curFileIndex = 1;
+  static int curLine = 1;
+  static char * curLabel = NULL;
+  static int curOffset = 0;
+  int deltaLine = lp->line - curLine;
+  int deltaAddr = lp->offset - curOffset;
+  int deltaAddrValid = curLabel && lp->label && !strcmp (lp->label, curLabel);
+
+  //fprintf (dwarf2FilePtr, "; line %d\n", lp->line);
+  if (lp->begin_sequence)
+    {
+      curFileIndex = 1;
+      curLine = 1;
+      curLabel = NULL;
+      curOffset = 0;
+      
+      if (lp->end_sequence)
+        return;
+    }
+  
+  if (lp->fileIndex != curFileIndex)
+    {
+      dwWriteByte (NULL, DW_LNS_set_file, NULL);
+      dwWriteULEB128 (NULL, lp->fileIndex, NULL);
+      curFileIndex = lp->fileIndex;
+    }
+  
+  if (lp->basic_block)
+    {
+      dwWriteByte (NULL, DW_LNS_set_basic_block, NULL);
+    }
+  
+  if (lp->begin_sequence)
+    {
+      dwWriteByte (NULL, 0, NULL);
+      dwWriteULEB128 (NULL, 1+port->debugger.dwarf.addressSize, NULL);
+      dwWriteByte (NULL, DW_LNE_set_address, NULL);
+      dwWriteAddress (lp->label, lp->offset, NULL);
+      curLabel = lp->label;
+      curOffset = lp->offset;
+
+      dwWriteByte (NULL, DW_LNS_advance_line, NULL);
+      dwWriteULEB128 (NULL, lp->line - 1, NULL);
+      curLine = lp->line;
+
+      dwWriteByte (NULL, DW_LNS_copy, NULL);
+    }
+  else if (lp->end_sequence)
+    {
+      if (deltaAddrValid)
+       {
+         dwWriteByte (NULL, DW_LNS_advance_pc, NULL);
+         dwWriteULEB128 (NULL, deltaAddr, NULL);
+       }
+      else
+        {
+         dwWriteByte (NULL, DW_LNS_fixed_advance_pc, NULL);
+         dwWriteHalfDelta (lp->label, curLabel, lp->offset-curOffset);
+         curLabel = lp->label;
+         curOffset = lp->offset;
+       }
+      
+      dwWriteByte (NULL, 0, NULL);
+      dwWriteULEB128 (NULL, 1, NULL);
+      dwWriteByte (NULL, DW_LNE_end_sequence, NULL);
+    }
+  else
+    {
+      int usedSpecial = 0;
+      
+      /* Metrowerks CW08 V3.0 gets confused by this. Just use the long */
+      /* encoding until we can find a more compatible phrasing.        */
+      #if 0
+      if (deltaLine >= dwLineBase && deltaLine < (dwLineBase+dwLineRange))
+        {
+         int opcode;
+         
+         /* try to build a "special" opcode */
+         opcode = dwLineOpcodeBase + (deltaLine - dwLineBase);
+         if (deltaAddrValid)
+           opcode += deltaAddr*dwLineRange;
+         
+         if (opcode >= dwLineOpcodeBase && opcode <= 255)
+           {
+             /* ok, we can use a "special" opcode */
+             
+             /* If the deltaAddr value was symbolic, it can't be part */
+             /* of the "special" opcode, so encode it seperately      */
+             if (!deltaAddrValid)
+               {
+                 dwWriteByte (NULL, DW_LNS_advance_pc, NULL);
+                 dwWriteULEB128Delta (lp->label, curLabel, lp->offset-curOffset);
+                 curLabel = lp->label;
+                 curOffset = lp->offset;
+               }
+
+             /* Write the "special" opcode */        
+             dwWriteByte (NULL, opcode, NULL);
+             curLine = lp->line;
+             usedSpecial = 1;
+           }
+       }
+      #endif
+      
+      /* If we couldn't use the "special" opcode, we will have to */
+      /* encode this the long way.                                */
+      if (!usedSpecial)
+        {
+         dwWriteByte (NULL, DW_LNS_fixed_advance_pc, NULL);
+         dwWriteHalfDelta (lp->label, curLabel, lp->offset-curOffset);
+         curLabel = lp->label;
+         curOffset = lp->offset;
+       
+         dwWriteByte (NULL, DW_LNS_advance_line, NULL);
+         dwWriteULEB128 (NULL, deltaLine, NULL);
+         curLine = lp->line;
+         
+         dwWriteByte (NULL, DW_LNS_copy, NULL);
+       }
+       
+    }
+    
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteLineNumbers - write all the source line number position data   */
+/*                      to the .debug_line section                       */
+/*-----------------------------------------------------------------------*/
+static void
+dwWriteLineNumbers (void)
+{
+  char * includeDir;
+  dwfile * srcfile;
+  dwline * lp;
+  
+  tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_line (NOLOAD)");
+  
+  dwWriteWordDelta ("Ldebug_line_end", "Ldebug_line_start");
+  
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_line_start");
+  
+  dwWriteHalf (NULL, 2, NULL); /* DWARF version */
+
+  dwWriteWordDelta ("Ldebug_line_stmt-6", "Ldebug_line_start");
+
+  dwWriteByte (NULL, 1, NULL); /* we track everything in 1 byte increments */
+  
+  dwWriteByte (NULL, 1, NULL); /* assume every line is a new statement */
+
+  dwWriteByte (NULL, dwLineBase, NULL);
+  dwWriteByte (NULL, dwLineRange, NULL);
+  
+  dwWriteByte (NULL, 9+1, NULL);  /* there are 9 standard opcodes */
+  
+  dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_copy arguments */
+  dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_advance_pc arguments */
+  dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_advance_line arguments */
+  dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_set_file arguments */
+  dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_set_column arguments */
+  dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_negate_stmt arguments */
+  dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_set_basic_block arguments */
+  dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_const_add_pc arguments */
+  dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_fixed_advance_pc arguments */
+
+  /* Write the list of source directories searched */
+  for (includeDir = setFirstItem (includeDirsSet);
+       includeDir;
+       includeDir = setNextItem(includeDirsSet) )
+    dwWriteString (includeDir, NULL);
+  dwWriteByte (NULL, 0, NULL);
+  
+  /* Write the list of source files used */
+  for (srcfile = setFirstItem (dwFilenameSet);
+       srcfile;
+       srcfile = setNextItem(dwFilenameSet) )
+    {
+      dwWriteString (srcfile->name, NULL);
+      dwWriteULEB128 (NULL, srcfile->dirIndex, NULL);
+      dwWriteULEB128 (NULL, srcfile->timestamp, NULL);
+      dwWriteULEB128 (NULL, srcfile->length, NULL);
+    }
+  dwWriteByte (NULL, 0, NULL);
+  
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_line_stmt");
+
+  lp = dwLineFirst;
+  if (lp)
+    lp->begin_sequence = 1;
+  while (lp)
+    {
+      dwWriteLineNumber (lp);
+      if (lp->end_sequence && lp->next)
+        lp->next->begin_sequence = 1;
+      lp = lp->next;
+    }
+    
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_line_end");
+}
+
+/*------------------------------------------------------------------------*/
+
+
+/* I have disabled all of this canonical frame address related code */
+/* until I better understand this part of the DWARF2 spec. -- EEP   */
+#if 0
+static void
+dwWriteCFAinstructions (dwcfins *ip)
+{
+  dwcfop * op = ip->first;
+  
+  while (op)
+    {
+      dwWriteByte (NULL, op->opcode, NULL);
+      switch (op->opcode >> 6)
+        {
+       case 0:
+         switch (op->opcode)
+           {
+           case DW_CFA_set_loc:
+             dwWriteAddress (NULL, op->label, op->operand1);
+             break;
+           
+           case DW_CFA_advance_loc1:
+             dwWriteByte (NULL, op->operand1, NULL);
+             break;
+           
+           case DW_CFA_advance_loc2:
+             dwWriteHalf (NULL, op->operand1, NULL);
+             break;
+           
+           case DW_CFA_advance_loc4:
+             dwWriteWord (NULL, op->operand1, NULL);
+             break;
+           
+           case DW_CFA_def_cfa:
+           case DW_CFA_register:
+           case DW_CFA_offset_extended:
+             dwWriteULEB128 (NULL, op->operand1, NULL);
+             dwWriteULEB128 (NULL, op->operand2, NULL);
+             break;
+           
+           case DW_CFA_undefined:
+           case DW_CFA_same_value:
+           case DW_CFA_def_cfa_register:
+           case DW_CFA_def_cfa_offset:
+           case DW_CFA_restore_extended:
+             dwWriteULEB128 (NULL, op->operand1, NULL);
+             break;
+           }
+         break;
+       
+       case DW_CFA_restore >> 6:
+       case DW_CFA_advance_loc >> 6:
+         break;
+       
+       case DW_CFA_offset >> 6:
+         dwWriteULEB128 (NULL, op->operand1, NULL);
+         break;
+       }
+      op = op->next;
+    }
+}
+
+static int
+dwSizeofCFAinstructions (dwcfins *ip)
+{
+  int size = 0;
+  dwcfop * op = ip->first;
+  
+  while (op)
+    {
+      size++;
+      switch (op->opcode >> 6)
+        {
+       case 0:
+         switch (op->opcode)
+           {
+           case DW_CFA_set_loc:
+             size += port->debugger.dwarf.addressSize;
+             break;
+           
+           case DW_CFA_advance_loc1:
+             size += 1;
+             break;
+           
+           case DW_CFA_advance_loc2:
+             size += 2;
+             break;
+           
+           case DW_CFA_advance_loc4:
+             size += 4;
+             break;
+           
+           case DW_CFA_def_cfa:
+           case DW_CFA_register:
+           case DW_CFA_offset_extended:
+             size += dwSizeofULEB128 (op->operand1);
+             size += dwSizeofULEB128 (op->operand2);
+             break;
+           
+           case DW_CFA_undefined:
+           case DW_CFA_same_value:
+           case DW_CFA_def_cfa_register:
+           case DW_CFA_def_cfa_offset:
+           case DW_CFA_restore_extended:
+             size += dwSizeofULEB128 (op->operand1);
+             break;
+           }
+         break;
+       
+       case DW_CFA_restore >> 6:
+       case DW_CFA_advance_loc >> 6:
+         break;
+       
+       case DW_CFA_offset >> 6:
+         size += dwSizeofULEB128 (op->operand1);
+         break;
+       }
+      op = op->next;
+    }
+  return size;
+}
+
+static dwcfop *
+dwNewCFop (int opcode)
+{
+  dwcfop * op;
+  
+  op = Safe_alloc (sizeof (dwcfop));
+  op->opcode = opcode;
+  
+  return op;
+}
+
+static dwcfins *
+dwNewCFins (void)
+{
+  return (dwcfins *) Safe_alloc (sizeof (dwcfins));
+}
+
+static void
+dwAddCFinsOp (dwcfins * ip, dwcfop *op)
+{
+  if (ip->last)
+    ip->last->next = op;
+  else
+    ip->first = op;
+  ip->last = op;
+}
+
+static dwcfins *
+dwGenCFIins (void)
+{
+  dwcfins * ip;
+  dwcfop * op;
+  int i;
+  
+  ip = dwNewCFins ();
+  
+  /* Define the CFA as the top of the stack at function start. */
+  /* The return address is then at cfa+0                       */
+  op = dwNewCFop (DW_CFA_def_cfa);
+  op->operand1 = port->debugger.dwarf.regNumSP;
+  op->operand2 = port->debugger.dwarf.offsetSP;
+  dwAddCFinsOp (ip, op);
+
+  op = dwNewCFop (DW_CFA_offset + port->debugger.dwarf.regNumRet);
+  op->operand1 = 0;
+  dwAddCFinsOp (ip, op);
+
+  if (port->debugger.dwarf.cfiUndef)
+    for (i=0; i < port->debugger.dwarf.cfiUndef->size; i++)
+      {
+       if (bitVectBitValue (port->debugger.dwarf.cfiUndef, i))
+         {
+           op = dwNewCFop (DW_CFA_undefined);
+           dwAddCFinsOp (ip, op);
+         }
+    }
+  
+  if (port->debugger.dwarf.cfiSame)
+    for (i=0; i < port->debugger.dwarf.cfiSame->size; i++)
+      {
+       if (bitVectBitValue (port->debugger.dwarf.cfiSame, i))
+         {
+           op = dwNewCFop (DW_CFA_undefined);
+           dwAddCFinsOp (ip, op);
+         }
+      }
+
+  return ip;
+}
+
+
+static void
+dwWriteFDE (dwfde * fp)
+{
+  dwWriteWord (NULL, dwSizeofCFAinstructions(fp->ins) + 4
+               + port->debugger.dwarf.addressSize * 2, NULL);
+  
+  dwWriteWord ("Ldebug_CIE_start-4", 0, NULL);
+  
+  dwWriteAddressDelta (fp->endLabel, fp->startLabel);
+  
+  dwWriteCFAinstructions (fp->ins);
+  
+}
+
+static void
+dwWriteFrames (void)
+{  
+  tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_frame (NOLOAD)");
+
+  /* FIXME: these two dw should be combined into a dd */
+  tfprintf (dwarf2FilePtr, "\t!dw\t0\n");
+  tfprintf (dwarf2FilePtr, "\t!dw\t%s\n", "Ldebug_CIE_end-Ldebug_CIE_start");
+
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_CIE_start");
+  
+  tfprintf (dwarf2FilePtr, "\t!dw\t0xffff\n");
+  tfprintf (dwarf2FilePtr, "\t!dw\t0xffff\n"); /* CIE_id */
+
+  tfprintf (dwarf2FilePtr, "\t!db\t%d\n",1);   /* CIE version number */
+
+  tfprintf (dwarf2FilePtr, "\t!db\t%d\n",0);   /* augmentation (none) */
+
+  dwWriteULEB128 (NULL, 1, NULL);      /* code alignment factor */
+  
+  dwWriteSLEB128 (NULL, (port->stack.direction > 0) ? -1 : 1, NULL); /* data alignment factor */
+  
+  dwWriteByte (NULL, port->debugger.dwarf.regNumRet, NULL);
+  
+  if (!dwCIEins)
+    {
+      #if 0
+      if (port->debugger.dwarf.genCFIins)
+        dwCIEins = port->debugger.dwarf.genCFIins ();
+      else
+      #endif
+        dwCIEins = dwGenCFIins ();
+    }
+  dwWriteCFAinstructions (dwCIEins);
+  
+  tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_CIE_end");
+}
+#endif
+
+
+
+
+/*------------------------------------------------------------------------*/
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* dwHashType - return a hash code for a type chain                      */
+/*-----------------------------------------------------------------------*/
+static int
+dwHashType (sym_link * type)
+{
+  int hash = 0;
+
+  while (type)
+    {
+      hash = (hash << 5) ^ ((hash >> 8) & 0xff);
+      if (IS_DECL (type))
+       {
+          hash ^= DCL_TYPE (type);
+       }
+      else
+        {
+          hash ^= SPEC_NOUN (type)
+              | (SPEC_CONST (type) << 4)
+              | (SPEC_VOLATILE (type) << 5)
+              | (SPEC_LONG (type) << 6);
+       }
+      
+      type = type->next;
+    }  
+
+  if (hash<0)
+    return -hash;
+  else
+    return hash;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwMatchType - returns true if two types match exactly (including type */
+/*               qualifiers)                                             */
+/*-----------------------------------------------------------------------*/
+static int
+dwMatchTypes (const void * type1v, const void * type2v)
+{
+  sym_link * type1 = (sym_link *)type1v;
+  sym_link * type2 = (sym_link *)type2v;
+  
+  if (!type1 || !type2)
+    return 0;
+  
+  while (type1 && type2)
+    {
+      if (IS_SPEC(type1))
+        {
+         if (IS_SPEC (type2))
+           {
+             if (SPEC_NOUN (type1) != SPEC_NOUN (type2))
+               return 0;
+             if (SPEC_CONST (type1) != SPEC_CONST (type2))
+               return 0;
+             if (SPEC_VOLATILE (type1) != SPEC_VOLATILE (type2))
+               return 0;
+             if (SPEC_SHORT (type1) != SPEC_SHORT (type2))
+               return 0;
+             if (SPEC_LONG (type1) != SPEC_LONG (type2))
+               return 0;
+             if (SPEC_USIGN (type1) != SPEC_USIGN (type2))
+               return 0;
+           }
+         else
+           return 0;
+       }
+      else
+        {
+         if (IS_DECL (type2))
+           {
+             if (DCL_TYPE (type1) != DCL_TYPE (type2))
+               return 0;
+             if (DCL_PTR_CONST (type1) != DCL_PTR_CONST (type2))
+               return 0;
+             if (DCL_PTR_VOLATILE (type1) != DCL_PTR_VOLATILE (type2))
+               return 0;
+             if (DCL_TYPE (type1) == ARRAY
+                 && DCL_ELEM (type1) != DCL_ELEM (type2))
+               return 0;
+             /* FIXME: need to match function pointer parameters */
+           }
+         else
+           return 0;
+       }
+      
+      type1 = type1->next;
+      type2 = type2->next;
+    }
+
+  if (!type1 && !type2)
+    return 1;
+  else
+    return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwTagFromType - returns the tag describing a type. If new tags need   */
+/*                 to be created, they will be added under the specified */
+/*                 parent tag                                            */
+/*-----------------------------------------------------------------------*/
+static dwtag *
+dwTagFromType (sym_link * type, dwtag * parent)
+{
+  dwtag * oldtp;
+  dwtag * tp = NULL;
+  dwtag * modtp;
+  dwtag * subtp;
+  int key;
+  
+  key = dwHashType (type) % dwTypeTagTable->size;
+  oldtp = hTabFindByKey (dwTypeTagTable, key, type, dwMatchTypes);
+  if (oldtp)
+    return oldtp;
+  else
+    {
+      if (IS_DECL (type))
+        {
+         switch (DCL_TYPE (type))
+           {
+           case POINTER:
+           case FPOINTER:
+           case CPOINTER:
+           case GPOINTER:
+           case PPOINTER:
+           case IPOINTER:
+           case EEPPOINTER:
+           case UPOINTER:
+             tp = dwNewTag (DW_TAG_pointer_type);
+             if (type->next && !IS_VOID (type->next))
+               {
+                 subtp = dwTagFromType (type->next, parent);
+                 dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp));
+               }
+             dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size,
+                                               getSize (type)));
+             dwAddTagChild (parent, tp);
+             if (DCL_PTR_VOLATILE (type))
+               {
+                 modtp = dwNewTag (DW_TAG_volatile_type);
+                 dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp));
+                 dwAddTagChild (parent, modtp);
+                 tp = modtp;
+               }
+             if (DCL_PTR_CONST (type))
+               {
+                 modtp = dwNewTag (DW_TAG_const_type);
+                 dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp));
+                 dwAddTagChild (parent, modtp);
+                 tp = modtp;
+               }
+             break;
+             
+           case ARRAY:
+             tp = dwNewTag (DW_TAG_array_type);
+             subtp = dwTagFromType (type->next, parent);
+             dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp));
+             if (!subtp->parent)
+               dwAddTagChild (tp, subtp);
+             if (DCL_ELEM (type))
+               {
+                 dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size,
+                                                   getSize (type)));
+                 subtp = dwNewTag (DW_TAG_subrange_type);
+                 dwAddTagAttr (subtp, dwNewAttrConst (DW_AT_upper_bound,
+                                                      DCL_ELEM (type)-1));
+                 dwAddTagChild (tp, subtp);
+               }
+
+             break;
+           
+           case FUNCTION:
+             tp = dwNewTag (DW_TAG_subroutine_type);
+             if (type->next && !IS_VOID (type->next))
+               {
+                 subtp = dwTagFromType (type->next, parent);
+                 dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp));
+               }
+             /* FIXME: need to handle function parameters */
+             break;
+             
+           default:
+             werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                     "unknown DCL_TYPE");
+             exit (1);
+           }
+       }
+      else
+        {
+         if (IS_STRUCT (type))
+           {
+             struct structdef * sdp = SPEC_STRUCT (type);
+             symbol * field;
+             
+             tp = dwNewTag (sdp->type == STRUCT ? DW_TAG_structure_type
+                                                : DW_TAG_union_type);
+             if (*(sdp->tag))
+               dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, sdp->tag));
+             
+             /* FIXME: should only specify the size if we know this */
+             /* is a complete type */
+             dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size,
+                                               getSize (type)));
+             field = sdp->fields;
+             while (field)
+               {
+                 dwtag * memtp;
+                 dwloc * lp;
+                 
+                 memtp = dwNewTag (DW_TAG_member);
+                 if (*(field->name))
+                   dwAddTagAttr (memtp, dwNewAttrString (DW_AT_name,
+                                                         field->name));
+                 subtp = dwTagFromType (field->type, tp);
+                 dwAddTagAttr (memtp, dwNewAttrTagRef (DW_AT_type, subtp));
+                 if (!subtp->parent)
+                   dwAddTagChild (parent, subtp);
+
+                 lp = dwNewLoc (DW_OP_plus_uconst, NULL, field->offset);
+                 dwAddTagAttr (memtp,
+                               dwNewAttrLoc (DW_AT_data_member_location, lp));
+
+                 dwAddTagChild (tp, memtp);
+                 
+                 field = field->next;
+               }
+           }
+         else if (SPEC_VOLATILE (type) || SPEC_CONST (type))
+           {
+             sym_link temptype = *type;
+             
+             SPEC_VOLATILE (&temptype) = 0;
+             SPEC_CONST (&temptype) = 0;
+             tp = dwTagFromType (&temptype, parent);
+             if (SPEC_VOLATILE (type))
+               {
+                 modtp = dwNewTag (DW_TAG_volatile_type);
+                 dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp));
+                 dwAddTagChild (parent, modtp);
+                 tp = modtp;
+               }
+             if (SPEC_CONST (type))
+               {
+                 modtp = dwNewTag (DW_TAG_const_type);
+                 dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp));
+                 dwAddTagChild (parent, modtp);
+                 tp = modtp;
+               }
+           }
+         else
+           {
+             switch (SPEC_NOUN (type))
+               {
+               case V_INT:
+                 tp = dwNewTag (DW_TAG_base_type);
+                 if (SPEC_USIGN (type))
+                   {
+                     dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding,
+                                                       DW_ATE_unsigned));
+                     if (SPEC_LONG (type))
+                       dwAddTagAttr (tp, dwNewAttrString (DW_AT_name,
+                                                          "unsigned long"));
+                     else
+                       dwAddTagAttr (tp, dwNewAttrString (DW_AT_name,
+                                                          "unsigned int"));
+                   }
+                 else
+                   {
+                     dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding,
+                                                       DW_ATE_signed));
+                     if (SPEC_LONG (type))
+                       dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "long"));
+                     else
+                       dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "int"));
+                   }
+                 dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size,
+                                                   getSize (type)));
+                 dwAddTagChild (dwRootTag, tp);
+                 break;
+                 
+               case V_FLOAT:
+                 tp = dwNewTag (DW_TAG_base_type);
+                 dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding,
+                                                   DW_ATE_float));
+                 dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "float"));
+                 dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size,
+                                                   getSize (type)));
+                 dwAddTagChild (dwRootTag, tp);
+                 break;
+               
+               case V_CHAR:
+                 tp = dwNewTag (DW_TAG_base_type);
+                 if (SPEC_USIGN (type))
+                   {
+                     dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding,
+                                                       DW_ATE_unsigned_char));
+                     dwAddTagAttr (tp, dwNewAttrString (DW_AT_name,
+                                                        "unsigned char"));
+                   }
+                 else
+                   {
+                     dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding,
+                                                       DW_ATE_signed));
+                     dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "char"));
+                   }
+                 dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size,
+                                                   getSize (type)));
+                 dwAddTagChild (dwRootTag, tp);
+                 break;
+               
+               case V_VOID:
+               case V_BIT:
+               case V_BITFIELD:
+               case V_SBIT:
+               case V_DOUBLE:
+               default:
+                 
+                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                     "unhandled base type");
+                 printTypeChain (type, NULL);
+                 exit (1);
+  
+               }
+           }
+       }
+    }
+  
+  hTabAddItemLong (&dwTypeTagTable, key, type, tp);
+  return tp;
+}
+/*------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* dwOpenFile - opens a temporary file for debugging information         */
+/*-----------------------------------------------------------------------*/
+int dwOpenFile(char *file)
+{
+  dwarf2FilePtr = tempfile();
+  if(!dwarf2FilePtr) return 0;
+  
+  dwTypeTagTable = newHashTable (128);
+  
+  return 1;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwCloseFile - close (and deletes) the temporary file for debugging    */
+/*               information                                             */
+/*-----------------------------------------------------------------------*/
+int dwCloseFile(void)
+{
+  if(!dwarf2FilePtr) return 0;
+  
+  fclose(dwarf2FilePtr);
+  
+  return 1;
+}
+  
+
+/*-----------------------------------------------------------------------*/
+/* dwGenerateScopes - recursively traverse an ast, generating lexical    */
+/*                    block tags for block scopes found                  */
+/*-----------------------------------------------------------------------*/
+static void  
+dwGenerateScopes (dwtag *tp, ast * tree)
+{
+  dwtag *subtp;
+
+  if (!tree)
+    return;
+  
+  if (!IS_AST_OP (tree))
+    return;
+      
+  if (tree->opval.op == BLOCK)
+    {
+      subtp = dwNewTag (DW_TAG_lexical_block);
+      if (tree->right)
+        {
+          dwAddTagAttr (subtp, dwNewAttrConst (DW_AT_user_block, tree->right->block));
+         dwAddTagAttr (subtp, dwNewAttrConst (DW_AT_user_level, tree->right->level));
+      
+          dwAddTagChild (tp, subtp);
+       }
+      dwGenerateScopes (subtp, tree->right);
+    }
+  else
+    {
+      dwGenerateScopes (tp, tree->left);
+      dwGenerateScopes (tp, tree->right);
+    }
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwFindScope - return the lexical block tag for a particular block     */
+/*               scope, or NULL if not found                             */
+/*-----------------------------------------------------------------------*/
+static dwtag *
+dwFindScope (dwtag * tp, int block)
+{
+  dwtag * rettp;
+  dwattr * ap;
+  
+  if (!tp)
+    return NULL;
+  
+  while (tp)
+    {
+      if (tp->tag == DW_TAG_lexical_block)
+        {
+         ap = tp->attribs;
+         while (ap)
+           {
+             if (ap->attr == DW_AT_user_block)
+               {
+                 if (ap->val.data == block)
+                   return tp;
+               }
+             ap = ap->next;
+           }
+           
+         rettp = dwFindScope (tp->firstChild, block);
+         if (rettp)
+           return rettp;
+       }
+      tp = tp->siblings;
+    }
+  
+  return NULL;  
+}
+
+/*------------------------------------------------------------------------*/
+/* dwWriteSymbolInternal - create tag information for a variable or       */
+/*                         parameter and place it in the correct position */
+/*                         within the tag tree                            */
+/*------------------------------------------------------------------------*/
+static int
+dwWriteSymbolInternal (symbol *sym)
+{
+  dwtag * tp;
+  dwtag * subtp;
+  dwloc * lp;
+  dwtag * scopetp;
+  symbol * symloc;
+  dwtag * functp;
+  dwattr * funcap;
+  int inregs = 0;
+
+  if (!sym->level)
+    scopetp = dwRootTag;
+  else
+    {
+      assert(sym->localof);
+      if (!sym->localof)
+        return 0;
+       
+      /* Find the tag for the function this symbol is defined in */
+      functp = dwRootTag->firstChild;
+      while (functp)
+        {
+         if (functp->tag == DW_TAG_subprogram)
+           {
+             funcap = dwFindAttr (functp, DW_AT_name);
+             if (funcap && !strcmp (funcap->val.string, sym->localof->name))
+               break;
+           }
+         functp = functp->siblings;
+       }
+      assert (functp);
+      if (!functp)
+        return 0;
+       
+      /* Find the correct scope within this function */
+      scopetp = dwFindScope (functp->firstChild, sym->block);
+      if (!scopetp)
+        scopetp = functp;
+    }
+  
+  tp = dwNewTag (sym->_isparm ? DW_TAG_formal_parameter : DW_TAG_variable);
+  
+  dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, sym->name));
+  
+  /* Find the ultimate symbol holding the value. */
+  /* Might be:                                   */
+  /*   a) original symbol,                       */
+  /*   b) register equivalent,                   */
+  /*   c) spill location                         */
+  symloc = sym;
+  if (!sym->allocreq && sym->reqv)
+    {
+      symloc = OP_SYMBOL (symloc->reqv);
+      if (symloc->isspilt && !symloc->remat)
+       symloc = symloc->usl.spillLoc;
+      else
+        inregs = 1;
+    }
+  
+  lp = NULL;
+  if (inregs && symloc->regs[0])
+    {
+      dwloc * reglp;
+      dwloc * lastlp = NULL;
+      int regNum;
+      int i;
+      
+      /* register allocation */
+      for (i = (port->little_endian ? 0 : symloc->nRegs-1);
+           (port->little_endian ? (i < symloc->nRegs) : (i >= 0));
+          (port->little_endian ? i++ : i--))
+       {
+         regNum = port->debugger.dwarf.regNum (symloc->regs[i]);
+         if (regNum >= 0 && regNum <= 31)
+           reglp = dwNewLoc (DW_OP_reg0 + regNum, NULL, 0);
+         else if (regNum >= 0)
+           reglp = dwNewLoc (DW_OP_regx, NULL, regNum);
+         else
+           {
+             /* We are forced to give up if the ABI for this port */
+             /* does not define a number for this register        */
+             lp = NULL;
+             break;
+           }
+         
+         if (lastlp)
+           lastlp->next = reglp;
+         else
+           lp = reglp;
+         lastlp = reglp;
+         
+         if (symloc->nRegs != 1)
+           {
+             reglp = dwNewLoc (DW_OP_piece, NULL, 1);
+             lastlp->next = reglp;
+             lastlp = reglp;
+           }
+       }
+    }
+  else if (symloc->onStack)
+    {
+      /* stack allocation */
+      lp = dwNewLoc (DW_OP_fbreg, NULL, sym->stack);
+    }
+  else
+    {
+      /* global allocation */
+      lp = dwNewLoc (DW_OP_addr, sym->rname, 0);
+    }
+
+  /* Only create the DW_AT_location if a known location exists.   */
+  /* It might not exist if the variable has been optimized away   */
+  /* or if the compiler has lost track of it (not good, but still */
+  /* happens sometimes -- need to improve induction)              */
+  if (lp)
+    dwAddTagAttr (tp, dwNewAttrLoc (DW_AT_location, lp));
+  
+  if (!IS_STATIC (sym->etype) && !sym->level)
+    dwAddTagAttr (tp, dwNewAttrFlag (DW_AT_external, 1));
+  if (IS_EXTERN (sym->etype))
+    dwAddTagAttr (tp, dwNewAttrFlag (DW_AT_declaration, 1));
+  
+  subtp = dwTagFromType (sym->type, scopetp);
+  dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp));
+  if (!subtp->parent)
+    dwAddTagChild (scopetp, subtp);
+  
+  dwAddTagChild (scopetp, tp);
+  return 1;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteFunction - generate a tag for a function.                      */
+/*-----------------------------------------------------------------------*/
+int dwWriteFunction(symbol *sym, iCode *ic)
+{
+  dwtag * tp;
+  value * args;
+    
+  if(!dwarf2FilePtr) return 0;
+  
+  dwFuncTag = tp = dwNewTag (DW_TAG_subprogram);
+  
+  dwAddTagAttr (dwFuncTag, dwNewAttrString (DW_AT_name, sym->name));
+  
+  dwAddTagAttr (dwFuncTag, dwNewAttrAddrSymbol (DW_AT_low_pc, sym, 0));
+  
+  if (FUNC_ISISR (sym->type))
+    dwAddTagAttr (dwFuncTag, dwNewAttrConst (DW_AT_calling_convention,
+                                             DW_CC_nocall));
+  
+  dwAddTagAttr (dwFuncTag, dwNewAttrFlag (DW_AT_external, 
+                                          !IS_STATIC (sym->etype)));
+
+  if (sym->type->next && !IS_VOID (sym->type->next))
+    {
+      dwtag * subtp;
+
+      subtp = dwTagFromType (sym->type->next, dwRootTag);
+      dwAddTagAttr (dwFuncTag, dwNewAttrTagRef (DW_AT_type, subtp));
+    }
+  dwAddTagChild (dwRootTag, dwFuncTag);
+  
+  args = FUNC_ARGS(sym->type);
+  while (args)
+    {
+      dwWriteSymbolInternal (args->sym);
+      args = args->next;
+    }
+  if (FUNC_HASVARARGS (sym->type))
+    {
+      dwAddTagChild (dwFuncTag, dwNewTag (DW_TAG_unspecified_parameters));
+    }
+  
+  while (ic && ic->op != FUNCTION)
+    ic = ic->next;
+  if (ic && ic->op == FUNCTION && ic->tree && ic->tree->right)
+    {
+      dwGenerateScopes (dwFuncTag, ic->tree->right->left);
+      dwGenerateScopes (dwFuncTag, ic->tree->right->right);
+    }
+  
+  dwScopeTag = NULL;
+  dwScopeLevel = 0;
+  
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteEndFunction - write attributes to the current function tag     */
+/*                      that are only known after code generation is     */
+/*                      complete                                         */
+/*-----------------------------------------------------------------------*/
+int dwWriteEndFunction(symbol *sym, iCode *ic, int offset)
+{
+  char debugSym[SDCC_NAME_MAX];
+  
+  if (ic)
+    {
+      dwWriteCLine (ic);
+      dwLineLast->offset += offset;
+      dwLineLast->end_sequence = 1;
+    }
+
+  if (IS_STATIC (sym->etype))
+    sprintf (debugSym, "XF%s$%s$0$0", moduleName, sym->name);
+  else
+    sprintf (debugSym, "XG$%s$0$0", sym->name);
+  emitDebuggerSymbol (debugSym);
+      
+  dwAddTagAttr (dwFuncTag, dwNewAttrAddrLabel (DW_AT_high_pc,
+                                              Safe_strdup(debugSym),
+                                              offset));
+  
+  if (dwFrameLocList)
+    {
+      dwAddTagAttr (dwFuncTag, dwNewAttrLocRef (DW_AT_frame_base,
+                                               dwFrameLocList));
+      
+      dwFrameLocList->next = dwRootLocList;
+      dwRootLocList = dwFrameLocList;
+      dwFrameLocList = NULL;
+    }
+    
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteLabel - generate a tag for a source level label                */
+/*-----------------------------------------------------------------------*/
+int dwWriteLabel(symbol *sym, iCode *ic)
+{
+  char debugSym[SDCC_NAME_MAX];
+  dwtag * tp;
+  
+  /* ignore the compiler generated labels */
+  if (sym->isitmp)
+    return 1;
+
+  sprintf (debugSym, "L%s$%s$%s", moduleName, currFunc->name, sym->name);
+  emitDebuggerSymbol (debugSym);
+
+  tp = dwNewTag (DW_TAG_label);
+  dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, sym->name));
+  dwAddTagAttr (tp, dwNewAttrAddrLabel (DW_AT_low_pc,
+                                       Safe_strdup (debugSym), 0));
+
+  dwAddTagChild (dwFuncTag, tp);
+  
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteScope - add the starting and ending address attributes to a    */
+/*                a lexical block tag (created during dwWriteFunction)   */
+/*-----------------------------------------------------------------------*/
+int dwWriteScope(iCode *ic)
+{
+  char * debugSym = NULL;
+  dwtag * scopetp;
+  dwattr * ap;
+  
+  scopetp = dwFindScope (dwFuncTag->firstChild, ic->block);
+  
+  if (dwScopeTag && ic->level <= dwScopeLevel)
+    {
+      debugSym = dwNewDebugSymbol ();
+      emitDebuggerSymbol (debugSym);
+      dwSetTagAttr (dwScopeTag, dwNewAttrAddrLabel (DW_AT_high_pc, debugSym, 0));
+                                                   
+      dwScopeTag = scopetp;
+      dwScopeLevel = ic->level;
+    }
+  if (scopetp)
+    {
+      ap = dwFindAttr (scopetp, DW_AT_low_pc);
+      if (ap)
+        return 1;
+      
+      if (!debugSym)
+        debugSym = dwNewDebugSymbol ();
+      emitDebuggerSymbol (debugSym);
+      dwAddTagAttr (scopetp, dwNewAttrAddrLabel (DW_AT_low_pc, debugSym, 0));
+                                                
+      dwScopeTag = scopetp;
+      dwScopeLevel = ic->level;
+    }
+  
+  return 1;
+}
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteSymbol - generate tags for global variables. This is actually  */
+/*                 called for all variables and parameters, but we       */
+/*                 process the non-global variables elsewhere.           */
+/*-----------------------------------------------------------------------*/
+int dwWriteSymbol(symbol *sym)
+{
+  if (IS_FUNC (sym->type))
+    return 1;
+
+  /* If it is an iTemp, then it is not a C source symbol; ignore it */
+  if (sym->isitmp)
+    return 1;
+
+  /* Ignore parameters; they must be handled specially so that they will */
+  /* appear in the correct order */
+  if (sym->_isparm)
+    return 1;
+    
+  return dwWriteSymbolInternal (sym);
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteType                                                           */
+/*-----------------------------------------------------------------------*/
+int dwWriteType(structdef *sdef, int block, int inStruct, char *tag)
+{
+  /* FIXME: needs implementation */
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteModule - generates the root tag for this compilation unit      */
+/*-----------------------------------------------------------------------*/
+int dwWriteModule(char *name)
+{
+  dwtag * tp;
+  
+  if(!dwarf2FilePtr) return 0;
+  
+  tp = dwNewTag (DW_TAG_compile_unit);
+  dwAddTagAttr (tp, dwNewAttrString (DW_AT_producer, "SDCC version "
+                                            SDCC_VERSION_STR));
+  dwAddTagAttr (tp, dwNewAttrConst (DW_AT_language, DW_LANG_C89));
+
+  dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, fullSrcFileName));
+
+  dwAddTagAttr (tp, dwNewAttrLabelRef (DW_AT_stmt_list,
+                                      "Ldebug_line_start", -4));
+
+  dwRootTag = tp;
+  
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteCLine - generates a line number/position to address record for */
+/*                C source                                               */
+/*-----------------------------------------------------------------------*/
+int dwWriteCLine(iCode *ic)
+{
+  dwline * lp;
+  char * debugSym;
+  
+  if(!dwarf2FilePtr) return 0;
+
+  lp = Safe_alloc (sizeof (dwline));
+
+  lp->line = ic->lineno;
+  
+  debugSym = dwNewDebugSymbol ();
+  emitDebuggerSymbol (debugSym);
+  lp->label = debugSym;
+  lp->offset = 0;
+
+  lp->fileIndex = dwFindFileIndex (ic->filename);
+
+  if (!dwLineFirst)
+    dwLineFirst = lp;
+  else
+    dwLineLast->next = lp;
+  dwLineLast = lp;
+  
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteFrameAddress - note the current position of the frame pointer  */
+/*                       address. The base address can be specified by   */
+/*                       either a register or pointer variable, leaving  */
+/*                       the other as NULL. If both are NULL, there is   */
+/*                       no current frame pointer address defined.       */
+/*-----------------------------------------------------------------------*/
+int
+dwWriteFrameAddress(char *variable, struct regs *reg, int offset)
+{
+  char * debugSym = NULL;
+  dwlocregion * lrp;
+  dwloc * lp;
+  int regNum;
+    
+  if(!dwarf2FilePtr) return 0;
+
+  /* If there was a region open, close it */
+  if (dwFrameLastLoc)
+    {
+      debugSym = dwNewDebugSymbol ();
+      emitDebuggerSymbol (debugSym);
+      
+      dwFrameLastLoc->endLabel = debugSym;
+      dwFrameLastLoc = NULL;
+    }
+
+  if (!variable && !reg)
+    return 1;
+
+  /* Create a new debugger symbol for the start of the region if */
+  /* we can't recycle the symbol at the end of the previous      */
+  if (!debugSym)
+    {
+      debugSym = dwNewDebugSymbol ();
+      emitDebuggerSymbol (debugSym);
+    }
+
+  lrp = Safe_alloc (sizeof (dwlocregion));
+  lrp->startLabel = debugSym;
+
+  if (variable)                /* frame pointer based from a global variable */
+    {
+      dwloc * lp;
+
+      lrp->loc = dwNewLoc (DW_OP_addr, variable, 0);
+      lrp->loc->next = lp = dwNewLoc (DW_OP_deref_size, NULL, PTRSIZE);
+      if (offset)
+        {
+         lp->next = dwNewLoc (DW_OP_consts, NULL, offset);
+         lp->next->next = dwNewLoc (DW_OP_plus, NULL, 0);
+       }
+    }
+  else if (reg)                /* frame pointer based from a register */
+    {
+      regNum = port->debugger.dwarf.regNum (reg);
+      assert (regNum>=0);
+      
+      if (regNum>=0 && regNum<=31)
+       {
+         if (offset)
+           lrp->loc = dwNewLoc (DW_OP_breg0 + regNum, NULL, offset);
+         else
+           lrp->loc = dwNewLoc (DW_OP_reg0 + regNum, NULL, 0);
+       }
+      else
+        {
+          lrp->loc = lp = dwNewLoc (DW_OP_regx, NULL, regNum);
+         if (offset)
+           {
+             lp->next = dwNewLoc (DW_OP_consts, NULL, offset);
+             lp->next->next = dwNewLoc (DW_OP_plus, NULL, 0);
+           }
+       }
+    }
+  dwFrameLastLoc = lrp;
+  
+  if (!dwFrameLocList)
+    dwFrameLocList = dwNewLocList();
+  lrp->next = dwFrameLocList->region;
+  dwFrameLocList->region = lrp;
+  
+  return 1;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* dwWriteALine - generates a line number/position to address record for */
+/*                assembly source                                        */
+/*-----------------------------------------------------------------------*/
+int dwWriteALine(char *module, int Line)
+{
+  if(!dwarf2FilePtr) return 0;
+  
+  return 1;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* dwarf2FinalizeFile - write all of the DWARF debugging data to the     */
+/*                      debug file                                       */
+/*-----------------------------------------------------------------------*/
+int
+dwarf2FinalizeFile(void)
+{
+  int tagAddress = 11;
+  int abbrevNum = 0;
+  int attr;
+  
+  if(!dwarf2FilePtr) return 1;
+
+  /* Write the .debug_line section */
+  dwWriteLineNumbers ();
+  /* Assign the location list addresses (for cross references) */
+  dwAssignLocListAddresses ();
+  
+  /* Write the .debug_loc section */
+  dwWriteLocLists ();
+
+  /* Delete our scope related user attributes; they were only needed to help */
+  /* build the tag tree and have no meaning to (and may confuse) debuggers   */
+  attr = DW_AT_user_block;
+  dwTraverseTag (dwRootTag, dwDeleteTagAttr, &attr);
+  attr = DW_AT_user_level;
+  dwTraverseTag (dwRootTag, dwDeleteTagAttr, &attr);
+  
+  /* Add a DW_AT_sibling attribute to all tags with children and siblings */
+  dwTraverseTag (dwRootTag, dwAddSibAttr, NULL);
+
+  /* Assign the tag abbreviations. The tags, attributes, and forms must   */
+  /* not change after this point. The attribute values may change as long */
+  /* as the size of the value does not.                                   */
+  dwAbbrevTable = newHashTable (128);
+  dwTraverseTag (dwRootTag, dwAssignAbbrev, &abbrevNum);
+  
+  /* Assign the tag addresses (for cross references) */
+  dwTraverseTag (dwRootTag, dwAssignTagAddress, &tagAddress);
+  
+  /* Write the .debug_abbrev section */
+  dwWriteAbbrevs ();  
+  
+  /* Write the .debug_info section */
+  dwWriteTags ();
+
+  /* Write the .debug_pubnames section */
+  dwWritePubnames ();
+  
+  return 1;
+}
diff --git a/src/SDCCdwarf2.h b/src/SDCCdwarf2.h
new file mode 100644 (file)
index 0000000..814912f
--- /dev/null
@@ -0,0 +1,425 @@
+/*-------------------------------------------------------------------------
+  SDCCdwarf2.h - DWARF2 debugging constants
+
+             Written By -  Erik Petrich . epetrich@users.sourceforge.net (2004)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#ifndef SDCCDWARF2_H
+#define SDCCDWARF2_H
+
+#define DW_TAG_array_type 0x01
+#define DW_TAG_class_type 0x02
+#define DW_TAG_entry_point 0x03
+#define DW_TAG_enumeration_type 0x04
+#define DW_TAG_formal_parameter 0x05
+#define DW_TAG_imported_declaration 0x08
+#define DW_TAG_label 0x0a
+#define DW_TAG_lexical_block 0x0b
+#define DW_TAG_member 0x0d
+#define DW_TAG_pointer_type 0x0f
+#define DW_TAG_reference_type 0x10
+#define DW_TAG_compile_unit 0x11
+#define DW_TAG_string_type 0x12
+#define DW_TAG_structure_type 0x13
+#define DW_TAG_subroutine_type 0x15
+#define DW_TAG_typedef 0x16
+#define DW_TAG_union_type 0x17
+#define DW_TAG_unspecified_parameters 0x18
+#define DW_TAG_variant 0x19
+#define DW_TAG_common_block 0x1a
+#define DW_TAG_common_inclusion 0x1b
+#define DW_TAG_inheritance 0x1c
+#define DW_TAG_inlined_subroutine 01x1d
+#define DW_TAG_module 0x1e
+#define DW_TAG_ptr_to_member_type 0x1f
+#define DW_TAG_set_type 0x20
+#define DW_TAG_subrange_type 0x21
+#define DW_TAG_with_stmt 0x22
+#define DW_TAG_access_declaration 0x23
+#define DW_TAG_base_type 0x24
+#define DW_TAG_catch_block 0x25
+#define DW_TAG_const_type 0x26
+#define DW_TAG_constant 0x27
+#define DW_TAG_enumerator 0x28
+#define DW_TAG_file_type 0x29
+#define DW_TAG_friend 0x2a
+#define DW_TAG_namelist 0x2b
+#define DW_TAG_namelist_item 0x2c
+#define DW_TAG_packed_type 0x2d
+#define DW_TAG_subprogram 0x2e
+#define DW_TAG_template_type_param 0x2f
+#define DW_TAG_template_value_param 0x30
+#define DW_TAG_thrown_type 0x31
+#define DW_TAG_try_block 0x32
+#define DW_TAG_variant_part 0x33
+#define DW_TAG_variable 0x34
+#define DW_TAG_volatile_type 0x35
+
+#define DW_CHILDREN_no 0
+#define DW_CHILDREN_yes 1
+
+#define DW_LANG_C89 0x0001
+
+#define DW_AT_sibling 0x01
+#define DW_AT_location 0x02
+#define DW_AT_name 0x03
+#define DW_AT_ordering 0x09
+#define DW_AT_byte_size 0x0b
+#define DW_AT_bit_offset 0x0c
+#define DW_AT_bit_size 0x0d
+#define DW_AT_stmt_list 0x10
+#define DW_AT_low_pc 0x11
+#define DW_AT_high_pc 0x12
+#define DW_AT_language 0x13
+#define DW_AT_discr 0x15
+#define DW_AT_discr_value 0x16
+#define DW_AT_visibility 0x17
+#define DW_AT_import 0x18
+#define DW_AT_string_length 0x19
+#define DW_AT_common_reference 0x1a
+#define DW_AT_comp_dir 0x1b
+#define DW_AT_const_value 0x1c
+#define DW_AT_containing_type 0x1d
+#define DW_AT_default_value 0x1e
+#define DW_AT_inline 0x20
+#define DW_AT_is_optional 0x21
+#define DW_AT_lower_bound 0x22
+#define DW_AT_producer 0x25
+#define DW_AT_prototyped 0x27
+#define DW_AT_return_addr 0x2a
+#define DW_AT_start_scope 0x2c
+#define DW_AT_stride_size 0x2e
+#define DW_AT_upper_bound 0x2f
+#define DW_AT_abstract_origin 0x31
+#define DW_AT_accessibility 0x32
+#define DW_AT_address_class 0x33
+#define DW_AT_artificial 0x34
+#define DW_AT_base_types 0x35
+#define DW_AT_calling_convention 0x36
+#define DW_AT_count 0x37
+#define DW_AT_data_member_location 0x38
+#define DW_AT_decl_column 0x39
+#define DW_AT_decl_file 0x3a
+#define DW_AT_decl_line 0x3b
+#define DW_AT_declaration 0x3c
+#define DW_AT_discr_list 0x3d
+#define DW_AT_encoding 0x3e
+#define DW_AT_external 0x3f
+#define DW_AT_frame_base 0x40
+#define DW_AT_friend 0x41
+#define DW_AT_identifier_case 0x42
+#define DW_AT_macro_info 0x43
+#define DW_AT_namelist_item 0x44
+#define DW_AT_priority 0x45
+#define DW_AT_segment 0x46
+#define DW_AT_specification 0x47
+#define DW_AT_static_link 0x48
+#define DW_AT_type 0x49
+#define DW_AT_use_location 0x4a
+#define DW_AT_variable_parameter 0x4b
+#define DW_AT_virtuality 0x4c
+#define DW_AT_vtable_elem_location 0x4d
+#define DW_AT_lo_user 0x2000
+#define DW_AT_hi_user 0x3fff
+
+#define DW_AT_user_block 0x2650
+#define DW_AT_user_level 0x2651
+
+#define DW_FORM_addr 0x01
+#define DW_FORM_block2 0x03
+#define DW_FORM_block4 0x04
+#define DW_FORM_data2 0x05
+#define DW_FORM_data4 0x06
+#define DW_FORM_data8 0x07
+#define DW_FORM_string 0x08
+#define DW_FORM_block 0x09
+#define DW_FORM_block1 0x0a
+#define DW_FORM_data1 0x0b
+#define DW_FORM_flag 0x0c
+#define DW_FORM_sdata 0x0d
+#define DW_FORM_strp 0x0e
+#define DW_FORM_udata 0x0f
+#define DW_FORM_ref_addr 0x10
+#define DW_FORM_ref1 0x11
+#define DW_FORM_ref2 0x12
+#define DW_FORM_ref4 0x13
+#define DW_FORM_ref_udata 0x15
+#define DW_FORM_indirect 0x16
+
+#define DW_OP_addr 0x03
+#define DW_OP_deref 0x06
+#define DW_OP_const1u 0x08
+#define DW_OP_const1s 0x09
+#define DW_OP_const2u 0x0a
+#define DW_OP_const2s 0x0b
+#define DW_OP_const4u 0x0c
+#define DW_OP_const4s 0x0d
+#define DW_OP_const8u 0x0e
+#define DW_OP_const8s 0x0f
+#define DW_OP_constu 0x10
+#define DW_OP_consts 0x11
+#define DW_OP_dup 0x12
+#define DW_OP_drop 0x13
+#define DW_OP_over 0x14
+#define DW_OP_pick 0x15
+#define DW_OP_swap 0x16
+#define DW_OP_rot 0x17
+#define DW_OP_xderef 0x18
+#define DW_OP_abs 0x19
+#define DW_OP_and 0x1a
+#define DW_OP_div 0x1b
+#define DW_OP_minus 0x1c
+#define DW_OP_mod 0x1d
+#define DW_OP_mul 0x1e
+#define DW_OP_neg 0x1f
+#define DW_OP_not 0x20
+#define DW_OP_or 0x21
+#define DW_OP_plus 0x22
+#define DW_OP_plus_uconst 0x23
+#define DW_OP_shl 0x24
+#define DW_OP_shr 0x25
+#define DW_OP_shra 0x26
+#define DW_OP_xor 0x27
+#define DW_OP_skip 0x2f
+#define DW_OP_bra 0x28
+#define DW_OP_eq 0x29
+#define DW_OP_ge 0x2a
+#define DW_OP_gt 0x2b
+#define DW_OP_le 0x2c
+#define DW_OP_lt 0x2d
+#define DW_OP_ne 0x2e
+#define DW_OP_lit0 0x30
+#define DW_OP_reg0 0x50
+#define DW_OP_breg0 0x70
+#define DW_OP_breg1 0x71
+#define DW_OP_breg2 0x72
+#define DW_OP_breg3 0x73
+#define DW_OP_breg4 0x74
+#define DW_OP_breg5 0x75
+#define DW_OP_breg6 0x76
+#define DW_OP_breg7 0x77
+#define DW_OP_breg8 0x78
+#define DW_OP_breg9 0x79
+#define DW_OP_breg10 0x7a
+#define DW_OP_breg11 0x7b
+#define DW_OP_breg12 0x7c
+#define DW_OP_breg13 0x7d
+#define DW_OP_breg14 0x7e
+#define DW_OP_breg15 0x7f
+#define DW_OP_breg16 0x80
+#define DW_OP_breg17 0x81
+#define DW_OP_breg18 0x82
+#define DW_OP_breg19 0x83
+#define DW_OP_breg20 0x84
+#define DW_OP_breg21 0x85
+#define DW_OP_breg22 0x86
+#define DW_OP_breg23 0x87
+#define DW_OP_breg24 0x88
+#define DW_OP_breg25 0x89
+#define DW_OP_breg26 0x8a
+#define DW_OP_breg27 0x8b
+#define DW_OP_breg28 0x8c
+#define DW_OP_breg29 0x8d
+#define DW_OP_breg30 0x8e
+#define DW_OP_breg31 0x8f
+#define DW_OP_regx 0x90
+#define DW_OP_fbreg 0x91
+#define DW_OP_bregx 0x92
+#define DW_OP_piece 0x93
+#define DW_OP_deref_size 0x94
+#define DW_OP_xderef_size 0x95
+#define DW_OP_nop 0x96
+
+#define DW_ATE_address 0x1
+#define DW_ATE_boolean 0x2
+#define DW_ATE_complex_float 0x3
+#define DW_ATE_float 0x4
+#define DW_ATE_signed 0x5
+#define DW_ATE_signed_char 0x6
+#define DW_ATE_unsigned 0x7
+#define DW_ATE_unsigned_char 0x8
+
+#define DW_CC_normal 0x1
+#define DW_CC_program 0x2
+#define DW_CC_nocall 0x3
+
+#define DW_LNS_copy 1
+#define DW_LNS_advance_pc 2
+#define DW_LNS_advance_line 3
+#define DW_LNS_set_file 4
+#define DW_LNS_set_column 5
+#define DW_LNS_negate_stmt 6
+#define DW_LNS_set_basic_block 7
+#define DW_LNS_const_add_pc 8
+#define DW_LNS_fixed_advance_pc 9
+
+#define DW_LNE_end_sequence 1
+#define DW_LNE_set_address 2
+#define DW_LNE_define_file 3
+
+#define DW_MACINFO_define 1
+#define DW_MACINFO_undef 2
+#define DW_MACINFO_start_file 3
+#define DW_MACINFO_end_file 4
+#define DW_MACINFO_vendor_ext 255
+
+#define DW_CFA_advance_loc (1 << 6)
+#define DW_CFA_offset (2 << 6)
+#define DW_CFA_restore (3 << 6)
+#define DW_CFA_set_loc 0x01
+#define DW_CFA_advance_loc1 0x02
+#define DW_CFA_advance_loc2 0x03
+#define DW_CFA_advance_loc4 0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended 0x06
+#define DW_CFA_undefined 0x07
+#define DW_CFA_same_value 0x08
+#define DW_CFA_register 0x09
+#define DW_CFA_remember_state 0x0a
+#define DW_CFA_restore_state 0x0b
+#define DW_CFA_def_cfa 0x0c
+#define DW_CFA_def_cfa_register 0x0d
+#define DW_CFA_def_cfa_offset 0x0e
+#define DW_CFA_nop 0x0f
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_hi_user 0x3f
+
+
+typedef struct dwloc
+{
+  int opcode;
+  struct
+  {
+    symbol * sym;
+    char * label;
+    int offset;
+  } operand;
+  struct dwloc * next;
+} dwloc;
+
+typedef struct dwlocregion
+{
+  char * startLabel;
+  char * endLabel;
+  dwloc * loc;
+  struct dwlocregion * next;
+} dwlocregion;
+
+typedef struct dwloclist
+{
+  int baseOffset;
+  dwlocregion * region;
+  struct dwloclist * next;
+} dwloclist;
+
+struct dwtag;
+
+typedef struct dwattr
+{
+  int attr;
+  int form;
+  union
+  {
+    struct
+    {
+      char * label;
+      int offset;
+    } symaddr;
+    struct
+    {
+      unsigned char * data;
+      int length;
+    } block;
+    int data;
+    char * string;
+    struct dwtag * ref;
+    struct dwloc * loc;
+    struct dwloclist * loclist;
+  } val;
+  struct dwattr * next;
+} dwattr;
+
+typedef struct dwtag
+{
+  int tag;
+  int abbrev;
+  int baseOffset;
+  struct dwattr * attribs;
+  struct dwtag * parent;
+  struct dwtag * firstChild;
+  struct dwtag * lastChild;
+  struct dwtag * siblings;
+} dwtag;
+
+typedef struct dwfile
+{
+  char * name;
+  int dirIndex;
+  int timestamp;
+  int length;
+} dwfile;
+
+typedef struct dwline
+{
+  char * label;
+  int offset;
+  int fileIndex;
+  int line;
+  unsigned is_stmt:1;
+  unsigned basic_block:1;
+  unsigned end_sequence:1;
+  unsigned begin_sequence:1;
+  struct dwline * next;
+} dwline;
+
+#if 0
+typedef struct dwblock
+{
+  unsigned char * data;
+  int length;
+  int alloc;
+} dwblock;
+
+typedef struct dwcfop
+{
+  int opcode;
+  char * label;
+  int operand1;
+  int operand2;
+  struct dwcfop * next;
+} dwcfop;
+
+typedef struct dwcfins
+{
+  dwcfop * first;
+  dwcfop * last;
+} dwcfins;
+
+typedef struct dwfde
+{
+  char * startLabel;
+  char * endLabel;
+  dwcfins * ins;
+} dwfde;
+#endif
+
+
+#endif
index a704cbc46d6f4a56db079e8cf678a0943cbd7cde..fdc278044186d9e437ab8ebad1a51941928d0a66 100644 (file)
@@ -3363,6 +3363,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
   /* create a proc icode */
   ic = newiCode (FUNCTION, func, NULL);
   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
+  ic->tree = tree;
 
   ADDTOCHAIN (ic);
 
@@ -3378,6 +3379,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
 
   /* now generate the end proc */
   ic = newiCode (ENDFUNCTION, func, NULL);
+  ic->tree = tree;
   ADDTOCHAIN (ic);
   return;
 }
index 3dc90c7a480bdc409b3316527f0af475b1546272..3069ff1004c71c08e00e7854887f091f324f9780 100644 (file)
@@ -191,6 +191,7 @@ typedef struct iCode
     int argreg;                        /* argument regno for SEND/RECEIVE */
     int eBBlockNum;             /* belongs to which eBBlock */
     char riu;                  /* after ralloc, the registers in use */
+    struct ast * tree;         /* ast node for this iCode (if not NULL) */
   }
 iCode;
 
index 57158ceebf3f22ab9b84b6fe481005d9fc6e2e01..89ca931dbced0add7cfd3ab6aeb2da1e8de5a14d 100644 (file)
@@ -73,7 +73,8 @@ typedef struct asmop
   }
 asmop;
 
-void gen51Code (iCode *);
+void genAVRCode (iCode *);
+void avr_emitDebuggerSymbol (char *);
 
 extern char *fReturn8051[];
 extern char *fReturn390[];
index ea9e55598254bcbafff8af7439165dbc8a7fa81b..1e8e277bde8380d4182156cf46acf5bd9a427cc6 100644 (file)
 
 int cdbOpenFile(char *file);
 int cdbCloseFile(void);
-int cdbWriteFunction(symbol *pSym);
+int cdbWriteFunction(symbol *pSym, iCode *ic);
+int cdbWriteEndFunction(symbol *pSym, iCode *ic, int offset);
+int cdbWriteLabel(symbol *pSym, iCode *ic);
+int cdbWriteScope(iCode *ic);
 int cdbWriteSymbol(symbol *pSym);
 int cdbWriteType(structdef *sdef, int block, int inStruct, char *tag);
 int cdbWriteModule(char *name);
-int cdbWriteCLine(char *module, int Line, int Level, int Block);
+int cdbWriteCLine(iCode *ic);
 int cdbWriteALine(char *module, int Line);
+int cdbWriteFrameAddress(char *variable, struct regs *reg, int offset);
 int cdbWriteBasicSymbol(symbol *sym, int isStructSym, int isFunc);
 void cdbTypeInfo (sym_link * type);
      
@@ -28,10 +32,14 @@ DEBUGFILE cdbDebugFile =
     &cdbCloseFile,
     &cdbWriteModule,
     &cdbWriteFunction,
+    &cdbWriteEndFunction,
+    &cdbWriteLabel,
+    &cdbWriteScope,
     &cdbWriteSymbol,
     &cdbWriteType,
     &cdbWriteCLine,
-    &cdbWriteALine
+    &cdbWriteALine,
+    &cdbWriteFrameAddress
   };
 
 FILE *cdbFilePtr = NULL;
@@ -79,17 +87,92 @@ int cdbCloseFile(void)
  *
  *****************************************************************/
 
-int cdbWriteFunction(symbol *pSym)
+int cdbWriteFunction(symbol *pSym, iCode *ic)
 {
+  char debugSym[INITIAL_INLINEASM];
+  
   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
     fprintf (stderr, "cdbFile.c:cdbWriteFunction()\n");
 
 
   if(!cdbFilePtr) return 0;
 
+  if (IS_STATIC (pSym->etype))
+    sprintf (debugSym, "F%s$%s$0$0", moduleName, pSym->name);
+  else
+    sprintf (debugSym, "G$%s$0$0", pSym->name);
+  emitDebuggerSymbol (debugSym);
+    
   return cdbWriteBasicSymbol(pSym, FALSE, TRUE);
 }
 
+/******************************************************************
+ *
+ *
+ *
+ *
+ *****************************************************************/
+
+int cdbWriteEndFunction(symbol *pSym, iCode *ic, int offset)
+{
+  char debugSym[INITIAL_INLINEASM];
+  
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "cdbFile.c:cdbWriteEndFunction()\n");
+
+  if(!cdbFilePtr) return 0;
+         
+  if (ic)
+    {
+      sprintf (debugSym, "C$%s$%d$%d$%d",
+              FileBaseName (ic->filename), pSym->lastLine,
+              ic->level, ic->block);
+      emitDebuggerSymbol (debugSym);
+    }
+
+  if (IS_STATIC (pSym->etype))
+    sprintf (debugSym, "XF%s$%s$0$0", moduleName, pSym->name);
+  else
+    sprintf (debugSym, "XG$%s$0$0", pSym->name);
+  emitDebuggerSymbol (debugSym);
+    
+  return 1;
+}
+
+/******************************************************************
+ *
+ *
+ *
+ *
+ *****************************************************************/
+
+int cdbWriteLabel(symbol *pSym, iCode *ic)
+{
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "cdbFile.c:cdbWriteLabel()\n");
+
+  if(!cdbFilePtr) return 0;
+         
+  return 1;
+}
+
+/******************************************************************
+ *
+ *
+ *
+ *
+ *****************************************************************/
+
+int cdbWriteScope(iCode *ic)
+{
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "cdbFile.c:cdbWriteScope()\n");
+
+  if(!cdbFilePtr) return 0;
+         
+  return 1;
+}
+
 /******************************************************************
  *
  *
@@ -171,9 +254,16 @@ int cdbWriteModule(char *name)
  *
  *
  *****************************************************************/
-int cdbWriteCLine(char *module, int Line, int Level, int Block)
+int cdbWriteCLine(iCode *ic)
 {
+  char debugSym[INITIAL_INLINEASM];
+  
   if(!cdbFilePtr) return 0;
+             
+  sprintf (debugSym, "C$%s$%d$%d$%d", 
+          FileBaseName (ic->filename), ic->lineno,
+          ic->level, ic->block);
+  emitDebuggerSymbol (debugSym);
 
   return 1;
 }
@@ -192,6 +282,23 @@ int cdbWriteALine(char *module, int Line)
   return 1;
 }
 
+/******************************************************************
+ *
+ *
+ *
+ *
+ *****************************************************************/
+
+int cdbWriteFrameAddress(char *variable, struct regs *reg, int offset)
+{
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "cdbFile.c:cdbWriteFrameAddress()\n");
+
+  if(!cdbFilePtr) return 0;
+         
+  return 1;
+}
+
 /******************************************************************
  *
  *
index 8f33d7122a5f97918ba6e6bf6b90bfb1f0a1b874..731847d1137e0237db5b11488b9fd9d9f317a1b0 100644 (file)
@@ -81,6 +81,7 @@ typedef struct asmop
 asmop;
 
 void gen390Code (iCode *);
+void ds390_emitDebuggerSymbol (char *);
 
 extern unsigned fReturnSizeDS390;
 
index f1463a58f24338ed8d50d0b0671c82b37fd83069..b8b09b6a93d3cb255f990b47f940f7750a39edc4 100644 (file)
@@ -88,6 +88,7 @@ typedef struct asmop
 asmop;
 
 void genhc08Code (iCode *);
+void hc08_emitDebuggerSymbol (char *);
 
 //extern char *fReturn8051[];
 extern unsigned fReturnSizeHC08;
index cec247d7b7a602ddb416e71028bf76c4a87dd213..4669e852cc04def5a22e83efd51c9edae947ccc0 100644 (file)
@@ -61,21 +61,23 @@ int hc08_ptrRegReq;         /* one byte pointer register required */
 regs regshc08[] =
 {
 
-  {REG_GPR, A_IDX, REG_GPR, "a", "a", "0", 1, NULL, 0, 1},
-  {REG_GPR, X_IDX, REG_GPR, "x", "x", "0", 2, NULL, 0, 1},
-  {REG_GPR, H_IDX, REG_GPR, "h", "h", "0", 4, NULL, 0, 1},
-  {REG_PTR, HX_IDX, REG_PTR, "hx", "hx", "0", 6, NULL, 0, 1},
-  {REG_GPR, XA_IDX, REG_GPR, "xa", "xa", "0", 3, NULL, 0, 1},
-
-  {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, NULL, 0, 1},
+  {REG_GPR, A_IDX,   "a",  1, NULL, 0, 1},
+  {REG_GPR, X_IDX,   "x",  2, NULL, 0, 1},
+  {REG_GPR, H_IDX,   "h",  4, NULL, 0, 1},
+  {REG_PTR, HX_IDX,  "hx", 6, NULL, 0, 1},
+  {REG_GPR, XA_IDX,  "xa", 3, NULL, 0, 1},
+
+  {REG_CND, CND_IDX, "C",  0, NULL, 0, 1},
+  {0,       SP_IDX,  "sp", 0, NULL, 0, 1},
 };
-int hc08_nRegs = 6;
+int hc08_nRegs = 7;
 
 regs *hc08_reg_a;
 regs *hc08_reg_x;
 regs *hc08_reg_h;
 regs *hc08_reg_hx;
 regs *hc08_reg_xa;
+regs *hc08_reg_sp;
 
 static void spillThis (symbol *);
 static void freeAllRegs ();
@@ -3020,12 +3022,14 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void *) &_G.regAssigned);
   setToNull ((void *) &_G.totRegAssigned);
   hc08_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
-  hc08_nRegs = 5;
+  hc08_nRegs = 7;
   hc08_reg_a = hc08_regWithIdx(A_IDX);
   hc08_reg_x = hc08_regWithIdx(X_IDX);
   hc08_reg_h = hc08_regWithIdx(H_IDX);
   hc08_reg_hx = hc08_regWithIdx(HX_IDX);
   hc08_reg_xa = hc08_regWithIdx(XA_IDX);
+  hc08_reg_sp = hc08_regWithIdx(SP_IDX);
+  hc08_nRegs = 5;
 
   /* change assignments this will remove some
      live ranges reducing some register pressure */
index 878c9aac62c9c6eddfc4b04ef4eccf5bc5fe65aa..ce77cbaedc9ba784db466e6b36192829e3436774 100644 (file)
@@ -34,23 +34,22 @@ enum
     X_IDX,
     HX_IDX,
     XA_IDX,
-    CND_IDX
+    CND_IDX,
+    SP_IDX
   };
 
 
 #define REG_PTR 0x01
 #define REG_GPR 0x02
 #define REG_CND 0x04
+
 /* definition for the registers */
 typedef struct regs
   {
     short type;                        /* can have value 
                                   REG_GPR, REG_PTR or REG_CND */
     short rIdx;                        /* index into register table */
-    short otype;
     char *name;                        /* name */
-    char *dname;               /* name when direct access needed */
-    char *base;                        /* base address */
     short mask;                        /* bitmask for pair allocation */
     struct asmop *aop;         /* last operand */
     int aopofs;                        /* last operand offset */
@@ -63,6 +62,7 @@ extern regs *hc08_reg_x;
 extern regs *hc08_reg_h;
 extern regs *hc08_reg_hx;
 extern regs *hc08_reg_xa;
+extern regs *hc08_reg_sp;
 
 regs *hc08_regWithIdx (int);
 void hc08_useReg (regs * reg);
index ada89d6acdd75b0ff18645416437d2c452c852e0..9988061d68beb57ffb7220ed14be74af24996ac6 100644 (file)
@@ -79,6 +79,7 @@ typedef struct asmop
 asmop;
 
 void gen51Code (iCode *);
+void mcs51_emitDebuggerSymbol (char *);
 
 //extern char *fReturn8051[];
 extern unsigned fReturnSizeMCS51;
index 4083c1ae6ac3efc606c42d99dd61092e904e02d4..6c1e5e7ffea0dab3444c298c3ba08031995d284f 100644 (file)
@@ -139,6 +139,7 @@ void emitpcode(PIC_OPCODE poc, pCodeOp *pcop);
 void emitpLabel(int key);
 void pic14_emitcode (char *inst,char *fmt, ...);
 void DEBUGpic14_emitcode (char *inst,char *fmt, ...);
+void pic14_emitDebuggerSymbol (char *);
 asmop *newAsmop (short type);
 bool pic14_sameRegs (asmop *aop1, asmop *aop2 );
 char *aopGet (asmop *aop, int offset, bool bit16, bool dname);
index e942384ddc66886948a90ae04d880985df218255..9c8c7e053805edf74e12046a77ed20e7f9f6a319 100644 (file)
@@ -151,6 +151,7 @@ void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop);
 void pic16_emitpLabel(int key);
 void pic16_emitcode (char *inst,char *fmt, ...);
 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
+void pic16_emitDebuggerSymbol (char *);
 bool pic16_sameRegs (asmop *aop1, asmop *aop2 );
 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname);
 
index 2341e114c7d8efb5ceebf11dffce0d598ca8ad02..7c2e898ee724e96bc8a8cf2879fd2736b11d12e4 100644 (file)
@@ -243,6 +243,10 @@ SOURCE=.\SDCCval.c
 
 SOURCE=.\sdccy.c
 # End Source File
+# Begin Source File
+
+SOURCE=.\SDCCdwarf2.c
+# End Source File
 # End Group
 # Begin Group "Header Files"
 
@@ -367,6 +371,10 @@ SOURCE=.\sdccy.h
 
 SOURCE=.\spawn.h
 # End Source File
+# Begin Source File
+
+SOURCE=.\SDCCdwarf2.h
+# End Source File
 # End Group
 # Begin Group "Regression Test"
 
index 85f6e6bfb20e419758ddda70faafa1e16775f04c..fec9e0c3c0c598f8b5c8dd4fdd33e5f789b0d0ad 100755 (executable)
@@ -64,4 +64,6 @@ typedef struct asmop {
 #define AOP_SIZE(x) x->aop->size
 #define AOP_NAME(x) x->aop->name
 
+void xa51_emitDebuggerSymbol (char *);
+
 #endif
index 40ccd0c940c7945a5aa78e89173a581753cdc4b5..2512bd65e2c517c8b85a867db349493e97440b5b 100644 (file)
@@ -92,6 +92,7 @@ typedef struct asmop
 asmop;
 
 void genZ80Code (iCode *);
+void z80_emitDebuggerSymbol (char *);
 
 
 #endif
index 043025f9f3dea39ea99104051e194e0ae3488ac6..dd6cda26d6c94e93cbbb5a0fa690096e76631dd4 100644 (file)
@@ -3,6 +3,7 @@
 */
 #include "common.h"
 #include "ralloc.h"
+#include "gen.h"
 #include "support.h"
 
 typedef enum