+void DbgInfoFunc (void)
+/* Parse and handle func subcommand of the .dbg pseudo instruction */
+{
+ static const char* StorageKeys[] = {
+ "EXTERN",
+ "STATIC",
+ };
+
+ StrBuf Name = STATIC_STRBUF_INITIALIZER;
+ StrBuf AsmName = STATIC_STRBUF_INITIALIZER;
+ int StorageClass;
+
+
+ /* Parameters are separated by a comma */
+ ConsumeComma ();
+
+ /* Name */
+ if (CurTok.Tok != TOK_STRCON) {
+ ErrorSkip ("String constant expected");
+ return;
+ }
+ SB_Copy (&Name, &CurTok.SVal);
+ NextTok ();
+
+ /* Comma expected */
+ ConsumeComma ();
+
+ /* The storage class follows */
+ if (CurTok.Tok != TOK_IDENT) {
+ ErrorSkip ("Storage class specifier expected");
+ return;
+ }
+ StorageClass = GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]));
+ if (StorageClass < 0) {
+ ErrorSkip ("Storage class specifier expected");
+ return;
+ }
+ NextTok ();
+
+ /* Comma expected */
+ ConsumeComma ();
+
+ /* Assembler name follows */
+ if (CurTok.Tok != TOK_STRCON) {
+ ErrorSkip ("String constant expected");
+ return;
+ }
+ SB_Copy (&AsmName, &CurTok.SVal);
+ NextTok ();
+
+ /* Free memory used for the strings */
+ SB_Done (&AsmName);
+ SB_Done (&Name);
+}
+
+
+
void DbgInfoLine (void)
/* Parse and handle LINE subcommand of the .dbg pseudo instruction */
{
void DbgInfoSym (void)
/* Parse and handle SYM subcommand of the .dbg pseudo instruction */
{
- ErrorSkip ("Not implemented");
+ static const char* StorageKeys[] = {
+ "AUTO",
+ "EXTERN",
+ "REGISTER",
+ "STATIC",
+ };
+
+ StrBuf Name = STATIC_STRBUF_INITIALIZER;
+ StrBuf AsmName = STATIC_STRBUF_INITIALIZER;
+ int StorageClass;
+ int Offs;
+
+
+ /* Parameters are separated by a comma */
+ ConsumeComma ();
+
+ /* Name */
+ if (CurTok.Tok != TOK_STRCON) {
+ ErrorSkip ("String constant expected");
+ return;
+ }
+ SB_Copy (&Name, &CurTok.SVal);
+ NextTok ();
+
+ /* Comma expected */
+ ConsumeComma ();
+
+ /* The storage class follows */
+ if (CurTok.Tok != TOK_IDENT) {
+ ErrorSkip ("Storage class specifier expected");
+ return;
+ }
+ StorageClass = GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]));
+ if (StorageClass < 0) {
+ ErrorSkip ("Storage class specifier expected");
+ return;
+ }
+
+ /* Skip the storage class token and the following comma */
+ NextTok ();
+ ConsumeComma ();
+
+ /* The next tokens depend on the storage class */
+ if (StorageClass == 0) {
+ /* Auto: Stack offset follows */
+ Offs = ConstExpression ();
+ } else if (StorageClass == 2) {
+ /* Register: Register bank offset follows */
+ Offs = ConstExpression ();
+ } else {
+ /* Extern or static: Assembler name follows */
+ if (CurTok.Tok != TOK_STRCON) {
+ ErrorSkip ("String constant expected");
+ return;
+ }
+ SB_Copy (&AsmName, &CurTok.SVal);
+ NextTok ();
+ }
+
+ /* Free memory used for the strings */
+ SB_Done (&AsmName);
+ SB_Done (&Name);
}
void DbgInfoFile (void);
/* Parse and handle FILE subcommand of the .dbg pseudo instruction */
+void DbgInfoFunc (void);
+/* Parse and handle FUNC subcommand of the .dbg pseudo instruction */
+
void DbgInfoLine (void);
/* Parse and handle LINE subcommand of the .dbg pseudo instruction */
{
static const char* Keys[] = {
"FILE",
+ "FUNC",
"LINE",
"SYM",
};
/* Check the key and dispatch to a handler */
switch (Key) {
case 0: DbgInfoFile (); break;
- case 1: DbgInfoLine (); break;
- case 2: DbgInfoSym (); break;
+ case 1: DbgInfoFunc (); break;
+ case 2: DbgInfoLine (); break;
+ case 3: DbgInfoSym (); break;
default: ErrorSkip ("Syntax error"); break;
}
}
/* */
/* */
/* */
-/* (C) 2000-2009, Ullrich von Bassewitz */
+/* (C) 2000-2011, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "litpool.h"
#include "locals.h"
#include "scanner.h"
-#include "segments.h"
#include "stackptr.h"
#include "standard.h"
#include "stmt.h"
struct Function {
struct SymEntry* FuncEntry; /* Symbol table entry */
Type* ReturnType; /* Function return type */
- struct FuncDesc* Desc; /* Function descriptor */
+ FuncDesc* Desc; /* Function descriptor */
int Reserved; /* Reserved local space */
unsigned RetLab; /* Return code label */
int TopLevelSP; /* SP at function top level */
+static void EmitDebugInfo (void)
+/* Emit debug infos for the current function */
+{
+ /* Fetch stuff for the current fuction */
+ const SymEntry* Sym = CurrentFunc->FuncEntry;
+ const FuncDesc* Desc = CurrentFunc->Desc;
+ const SymTable* Tab = Desc->SymTab;
+
+ /* Output info for the function itself */
+ AddTextLine ("\t.dbg\tfunc, \"%s\", %s, \"%s\"",
+ Sym->Name,
+ (Sym->Flags & SC_EXTERN)? "extern" : "static",
+ Sym->AsmName);
+
+ /* Output info for locals */
+ Sym = Tab->SymHead;
+ while (Sym) {
+ if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) {
+ if (Sym->Flags & SC_AUTO) {
+ AddTextLine ("\t.dbg\tsym, \"%s\", auto, %d",
+ Sym->Name, Sym->V.Offs);
+ } else if (Sym->Flags & SC_REGISTER) {
+ AddTextLine ("\t.dbg\tsym, \"%s\", register, %d",
+ Sym->Name, Sym->V.R.RegOffs);
+
+ } else {
+ AddTextLine ("\t.dbg\tsym, \"%s\", %s, \"%s\"",
+ Sym->Name,
+ (Sym->Flags & SC_EXTERN)? "extern" : "static",
+ Sym->AsmName);
+ }
+ }
+ Sym = Sym->NextSym;
+ }
+}
+
+
+
/*****************************************************************************/
-/* code */
+/* code */
/*****************************************************************************/
/* Emit references to imports/exports */
EmitExternals ();
+ /* Emit function debug info */
+ EmitDebugInfo ();
+
/* Leave the lexical level */
LeaveFunctionLevel ();