Merge pull request #1560 from empathicqubit/master
Add --debug-tables <filename> option and output struct fields
This commit is contained in:
commit
58de94edd4
5 changed files with 260 additions and 13 deletions
183
doc/cc65.sgml
183
doc/cc65.sgml
|
@ -198,6 +198,189 @@ Here is a description of all the command line options:
|
||||||
Enables debug mode, for debugging the behavior of cc65.
|
Enables debug mode, for debugging the behavior of cc65.
|
||||||
|
|
||||||
|
|
||||||
|
<tag><tt>--debug-tables name</tt></tag>
|
||||||
|
|
||||||
|
Writes symbol table information to a file, which includes details on structs, unions
|
||||||
|
functions, and global variables. For example, given the following code:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
struct l {
|
||||||
|
unsigned char m;
|
||||||
|
unsigned char n;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hello {
|
||||||
|
unsigned char j;
|
||||||
|
unsigned char k;
|
||||||
|
struct l l;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sub {
|
||||||
|
unsigned char x;
|
||||||
|
unsigned char y;
|
||||||
|
};
|
||||||
|
|
||||||
|
union xy {
|
||||||
|
struct sub xy;
|
||||||
|
unsigned int mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct hello thingy;
|
||||||
|
|
||||||
|
unsigned char single;
|
||||||
|
|
||||||
|
unsigned char test_local_vars_main(void) {
|
||||||
|
static unsigned char wahoo;
|
||||||
|
static unsigned char bonanza = 0x42;
|
||||||
|
unsigned char i;
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int *random;
|
||||||
|
unsigned char *lol;
|
||||||
|
signed char whoa;
|
||||||
|
struct hello wow;
|
||||||
|
thingy *cool;
|
||||||
|
union xy xy;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
The following output would be produced:
|
||||||
|
|
||||||
|
<tscreen><verb>
|
||||||
|
SC_FUNC: _test_local_vars_main: Symbol table
|
||||||
|
============================================
|
||||||
|
__fixargs__:
|
||||||
|
Flags: SC_CONST SC_DEF
|
||||||
|
Type: unsigned int
|
||||||
|
__argsize__:
|
||||||
|
Flags: SC_CONST SC_DEF
|
||||||
|
Type: unsigned char
|
||||||
|
wahoo:
|
||||||
|
AsmName: M0001
|
||||||
|
Flags: SC_STATIC SC_DEF SC_REF
|
||||||
|
Type: unsigned char
|
||||||
|
bonanza:
|
||||||
|
AsmName: M0002
|
||||||
|
Flags: SC_STATIC SC_DEF SC_REF
|
||||||
|
Type: unsigned char
|
||||||
|
i:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: unsigned char
|
||||||
|
j:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: unsigned int
|
||||||
|
random:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: unsigned int *
|
||||||
|
lol:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: unsigned char *
|
||||||
|
whoa:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: signed char
|
||||||
|
wow:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: struct hello
|
||||||
|
cool:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: struct hello *
|
||||||
|
xy:
|
||||||
|
Flags: SC_AUTO SC_DEF SC_REF
|
||||||
|
Type: union xy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Global symbol table
|
||||||
|
===================
|
||||||
|
thingy:
|
||||||
|
AsmName: _thingy
|
||||||
|
Flags: SC_TYPEDEF 0x100000
|
||||||
|
Type: struct hello
|
||||||
|
single:
|
||||||
|
AsmName: _single
|
||||||
|
Flags: SC_STATIC SC_EXTERN SC_STORAGE SC_DEF SC_REF 0x100000
|
||||||
|
Type: unsigned char
|
||||||
|
test_local_vars_main:
|
||||||
|
AsmName: _test_local_vars_main
|
||||||
|
Flags: SC_FUNC SC_STATIC SC_EXTERN SC_DEF 0x100000
|
||||||
|
Type: unsigned char (void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Global tag table
|
||||||
|
================
|
||||||
|
l:
|
||||||
|
Flags: SC_STRUCT SC_DEF
|
||||||
|
Type: (none)
|
||||||
|
hello:
|
||||||
|
Flags: SC_STRUCT SC_DEF
|
||||||
|
Type: (none)
|
||||||
|
sub:
|
||||||
|
Flags: SC_STRUCT SC_DEF
|
||||||
|
Type: (none)
|
||||||
|
xy:
|
||||||
|
Flags: SC_UNION SC_DEF
|
||||||
|
Type: (none)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Global struct and union definitions
|
||||||
|
=========================
|
||||||
|
|
||||||
|
SC_STRUCT: l
|
||||||
|
============
|
||||||
|
m:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned char
|
||||||
|
n:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned char
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SC_STRUCT: hello
|
||||||
|
================
|
||||||
|
j:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned char
|
||||||
|
k:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned char
|
||||||
|
l:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: struct l
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SC_STRUCT: sub
|
||||||
|
==============
|
||||||
|
x:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned char
|
||||||
|
y:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned char
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SC_UNION: xy
|
||||||
|
============
|
||||||
|
xy:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: struct sub
|
||||||
|
mem:
|
||||||
|
Flags: SC_STRUCTFIELD
|
||||||
|
Type: unsigned int
|
||||||
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
<tag><tt>--debug-opt name</tt></tag>
|
<tag><tt>--debug-opt name</tt></tag>
|
||||||
|
|
||||||
The named file contains a list of specific optimization steps to enable or disable.
|
The named file contains a list of specific optimization steps to enable or disable.
|
||||||
|
|
|
@ -66,6 +66,7 @@ IntStack CodeSizeFactor = INTSTACK(100);/* Size factor for generated code */
|
||||||
IntStack DataAlignment = INTSTACK(1); /* Alignment for data */
|
IntStack DataAlignment = INTSTACK(1); /* Alignment for data */
|
||||||
|
|
||||||
/* File names */
|
/* File names */
|
||||||
StrBuf DepName = STATIC_STRBUF_INITIALIZER; /* Name of dependencies file */
|
StrBuf DepName = STATIC_STRBUF_INITIALIZER; /* Name of dependencies file */
|
||||||
StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Name of full dependencies file */
|
StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Name of full dependencies file */
|
||||||
StrBuf DepTarget = STATIC_STRBUF_INITIALIZER; /* Name of dependency target */
|
StrBuf DepTarget = STATIC_STRBUF_INITIALIZER; /* Name of dependency target */
|
||||||
|
StrBuf DebugTableName = STATIC_STRBUF_INITIALIZER; /* Name of debug table dump file */
|
||||||
|
|
|
@ -77,6 +77,7 @@ extern IntStack DataAlignment; /* Alignment for data */
|
||||||
extern StrBuf DepName; /* Name of dependencies file */
|
extern StrBuf DepName; /* Name of dependencies file */
|
||||||
extern StrBuf FullDepName; /* Name of full dependencies file */
|
extern StrBuf FullDepName; /* Name of full dependencies file */
|
||||||
extern StrBuf DepTarget; /* Name of dependency target */
|
extern StrBuf DepTarget; /* Name of dependency target */
|
||||||
|
extern StrBuf DebugTableName; /* Name of debug table dump file */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ static void Usage (void)
|
||||||
" --create-full-dep name\tCreate a full make dependency file\n"
|
" --create-full-dep name\tCreate a full make dependency file\n"
|
||||||
" --data-name seg\t\tSet the name of the DATA segment\n"
|
" --data-name seg\t\tSet the name of the DATA segment\n"
|
||||||
" --debug\t\t\tDebug mode\n"
|
" --debug\t\t\tDebug mode\n"
|
||||||
|
" --debug-tables name\t\tWrite symbol table debug info to a file\n"
|
||||||
" --debug-info\t\t\tAdd debug info to object file\n"
|
" --debug-info\t\t\tAdd debug info to object file\n"
|
||||||
" --debug-opt name\t\tDebug optimization steps\n"
|
" --debug-opt name\t\tDebug optimization steps\n"
|
||||||
" --debug-opt-output\t\tDebug output of each optimization step\n"
|
" --debug-opt-output\t\tDebug output of each optimization step\n"
|
||||||
|
@ -494,7 +495,11 @@ static void OptDebug (const char* Opt attribute ((unused)),
|
||||||
++Debug;
|
++Debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void OptDebugTables (const char* Opt, const char* Arg)
|
||||||
|
/* Dump tables to file */
|
||||||
|
{
|
||||||
|
FileNameOption (Opt, Arg, &DebugTableName);
|
||||||
|
}
|
||||||
|
|
||||||
static void OptDebugInfo (const char* Opt attribute ((unused)),
|
static void OptDebugInfo (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
|
@ -865,6 +870,7 @@ int main (int argc, char* argv[])
|
||||||
{ "--create-full-dep", 1, OptCreateFullDep },
|
{ "--create-full-dep", 1, OptCreateFullDep },
|
||||||
{ "--data-name", 1, OptDataName },
|
{ "--data-name", 1, OptDataName },
|
||||||
{ "--debug", 0, OptDebug },
|
{ "--debug", 0, OptDebug },
|
||||||
|
{ "--debug-tables", 1, OptDebugTables },
|
||||||
{ "--debug-info", 0, OptDebugInfo },
|
{ "--debug-info", 0, OptDebugInfo },
|
||||||
{ "--debug-opt", 1, OptDebugOpt },
|
{ "--debug-opt", 1, OptDebugOpt },
|
||||||
{ "--debug-opt-output", 0, OptDebugOptOutput },
|
{ "--debug-opt-output", 0, OptDebugOptOutput },
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
@ -68,8 +69,6 @@
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* An empty symbol table */
|
/* An empty symbol table */
|
||||||
SymTable EmptySymTab = {
|
SymTable EmptySymTab = {
|
||||||
0, /* PrevTab */
|
0, /* PrevTab */
|
||||||
|
@ -99,6 +98,7 @@ static SymTable* LabelTab = 0;
|
||||||
static SymTable* SPAdjustTab = 0;
|
static SymTable* SPAdjustTab = 0;
|
||||||
static SymTable* FailSafeTab = 0; /* For errors */
|
static SymTable* FailSafeTab = 0; /* For errors */
|
||||||
|
|
||||||
|
static FILE* DebugTableFile = 0;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* struct SymTable */
|
/* struct SymTable */
|
||||||
|
@ -256,11 +256,25 @@ void PopLexicalLevel (void)
|
||||||
--LexLevelDepth;
|
--LexLevelDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void EnterGlobalLevel (void)
|
void EnterGlobalLevel (void)
|
||||||
/* Enter the program global lexical level */
|
/* Enter the program global lexical level */
|
||||||
{
|
{
|
||||||
|
const char* OutName = NULL;
|
||||||
|
if (!SB_IsEmpty (&DebugTableName)) {
|
||||||
|
OutName = SB_GetConstBuf (&DebugTableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OutName) {
|
||||||
|
/* Open the table file */
|
||||||
|
DebugTableFile = fopen (OutName, "w");
|
||||||
|
if (DebugTableFile == 0) {
|
||||||
|
Error ("Cannot create table dump file '%s': %s", OutName, strerror (errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Debug) {
|
||||||
|
DebugTableFile = stdout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Safety */
|
/* Safety */
|
||||||
PRECONDITION (GetLexicalLevel () == LEX_LEVEL_NONE);
|
PRECONDITION (GetLexicalLevel () == LEX_LEVEL_NONE);
|
||||||
|
|
||||||
|
@ -280,8 +294,6 @@ void EnterGlobalLevel (void)
|
||||||
FailSafeTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
|
FailSafeTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LeaveGlobalLevel (void)
|
void LeaveGlobalLevel (void)
|
||||||
/* Leave the program global lexical level */
|
/* Leave the program global lexical level */
|
||||||
{
|
{
|
||||||
|
@ -292,9 +304,41 @@ void LeaveGlobalLevel (void)
|
||||||
CheckSymTable (SymTab0);
|
CheckSymTable (SymTab0);
|
||||||
|
|
||||||
/* Dump the tables if requested */
|
/* Dump the tables if requested */
|
||||||
if (Debug) {
|
if (DebugTableFile) {
|
||||||
PrintSymTable (SymTab0, stdout, "Global symbol table");
|
SymEntry* Entry;
|
||||||
PrintSymTable (TagTab0, stdout, "Global tag table");
|
StrBuf* Header;
|
||||||
|
|
||||||
|
PrintSymTable (SymTab0, DebugTableFile, "Global symbol table");
|
||||||
|
PrintSymTable (TagTab0, DebugTableFile, "Global tag table");
|
||||||
|
|
||||||
|
Entry = TagTab0->SymHead;
|
||||||
|
if (Entry) {
|
||||||
|
fputs ("\nGlobal struct and union definitions", DebugTableFile);
|
||||||
|
fputs ("\n=========================\n", DebugTableFile);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!((Entry->Flags & SC_STRUCT) || (Entry->Flags & SC_UNION)) || !Entry->V.S.SymTab) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Header = NewStrBuf();
|
||||||
|
if(Entry->Flags & SC_STRUCT) {
|
||||||
|
SB_AppendStr (Header, "SC_STRUCT: ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SB_AppendStr (Header, "SC_UNION: ");
|
||||||
|
}
|
||||||
|
SB_AppendStr (Header, Entry->Name);
|
||||||
|
SB_Terminate (Header);
|
||||||
|
|
||||||
|
PrintSymTable (Entry->V.S.SymTab, DebugTableFile, SB_GetConstBuf (Header));
|
||||||
|
} while ((Entry = Entry->NextSym));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the file */
|
||||||
|
if (DebugTableFile != stdout && fclose (DebugTableFile) != 0) {
|
||||||
|
Error ("Error closing table dump file '%s': %s", SB_GetConstBuf(&DebugTableName), strerror (errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't delete the symbol and struct tables! */
|
/* Don't delete the symbol and struct tables! */
|
||||||
|
@ -386,6 +430,18 @@ void LeaveFunctionLevel (void)
|
||||||
CheckSymTable (SymTab);
|
CheckSymTable (SymTab);
|
||||||
CheckSymTable (LabelTab);
|
CheckSymTable (LabelTab);
|
||||||
|
|
||||||
|
/* Dump the tables if requested */
|
||||||
|
if (DebugTableFile) {
|
||||||
|
StrBuf* SymbolHeader = NewStrBuf();
|
||||||
|
|
||||||
|
SB_AppendStr (SymbolHeader, "SC_FUNC: ");
|
||||||
|
SB_AppendStr (SymbolHeader, CurrentFunc->FuncEntry->AsmName);
|
||||||
|
SB_AppendStr (SymbolHeader, ": Symbol table");
|
||||||
|
SB_Terminate (SymbolHeader);
|
||||||
|
|
||||||
|
PrintSymTable (SymTab, DebugTableFile, SB_GetConstBuf(SymbolHeader));
|
||||||
|
}
|
||||||
|
|
||||||
/* Drop the label table if it is empty */
|
/* Drop the label table if it is empty */
|
||||||
if (LabelTab->SymCount == 0) {
|
if (LabelTab->SymCount == 0) {
|
||||||
FreeSymTable (LabelTab);
|
FreeSymTable (LabelTab);
|
||||||
|
|
Loading…
Add table
Reference in a new issue