Collection TypeInfoById; /* Type infos sorted by id */
/* Collections with other sort criteria */
+ Collection CSymFuncByName; /* C functions sorted by name */
Collection FileInfoByName; /* File infos sorted by name */
Collection ModInfoByName; /* Module info sorted by name */
Collection ScopeInfoByName;/* Scope infos sorted by name */
unsigned Id; /* Id of scope */
ScopeInfo* Info; /* Pointer to scope */
} Scope;
+ Collection* LocalsByName; /* Locals if this is a function */
char Name[1]; /* Name of file with full path */
};
LibInfo* Info; /* Pointer to library info */
} Lib;
ScopeInfo* MainScope; /* Pointer to main scope */
+ Collection CSymFuncByName; /* C functions by name */
Collection FileInfoByName; /* Files for this module */
Collection ScopeInfoByName;/* Scopes for this module */
char Name[1]; /* Name of module with path */
unsigned Id; /* Id of label symbol */
SymInfo* Info; /* Pointer to label symbol */
} Label;
+ CSymInfo* CSymFunc; /* C function for this scope */
Collection SpanInfoList; /* List of spans for this scope */
Collection SymInfoByName; /* Symbols in this scope */
+ Collection* CSymInfoByName; /* C symbols for this scope */
Collection* ChildScopeList; /* Child scopes of this scope */
char Name[1]; /* Name of scope */
};
unsigned Id; /* Parent symbol if any */
SymInfo* Info; /* Pointer to parent symbol if any */
} Parent;
+ CSymInfo* CSym; /* Corresponding C symbol */
Collection* ImportList; /* List of imports if this is an export */
Collection* CheapLocals; /* List of cheap local symbols */
Collection DefLineInfoList;/* Line info of symbol definition */
CSymInfo* S = xmalloc (sizeof (CSymInfo) + SB_GetLen (Name));
/* Initialize it */
+ S->LocalsByName = 0;
memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
/* Return it */
static void FreeCSymInfo (CSymInfo* S)
/* Free a CSymInfo struct */
{
+ /* Free collections */
+ CollFree (S->LocalsByName);
+
/* Free the structure itself */
xfree (S);
}
static int CompareCSymInfoByName (const void* L, const void* R)
/* Helper function to sort c symbol infos in a collection by name */
{
- /* Sort by symbol name */
- return strcmp (((const CSymInfo*) L)->Name,
- ((const CSymInfo*) R)->Name);
+ /* Sort by symbol name, then by id */
+ int Res = strcmp (((const CSymInfo*) L)->Name, ((const CSymInfo*) R)->Name);
+ if (Res == 0) {
+ Res = (int)((const CSymInfo*) L)->Id - (int)((const CSymInfo*) R)->Id;
+ }
+ return Res;
}
/* Initialize it */
M->MainScope = 0;
+ CollInit (&M->CSymFuncByName);
CollInit (&M->FileInfoByName);
CollInit (&M->ScopeInfoByName);
memcpy (M->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
/* Free a ModInfo struct */
{
/* Free the collections */
+ CollDone (&M->CSymFuncByName);
CollDone (&M->FileInfoByName);
CollDone (&M->ScopeInfoByName);
ScopeInfo* S = xmalloc (sizeof (ScopeInfo) + SB_GetLen (Name));
/* Initialize the fields as necessary */
+ S->CSymFunc = 0;
CollInit (&S->SpanInfoList);
CollInit (&S->SymInfoByName);
+ S->CSymInfoByName = 0;
S->ChildScopeList = 0;
memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
{
CollDone (&S->SpanInfoList);
CollDone (&S->SymInfoByName);
+ CollFree (S->CSymInfoByName);
CollFree (S->ChildScopeList);
xfree (S);
}
SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name));
/* Initialize it as necessary */
- S->ImportList = 0;
+ S->CSym = 0;
+ S->ImportList = 0;
S->CheapLocals = 0;
CollInit (&S->DefLineInfoList);
CollInit (&S->RefLineInfoList);
CollInit (&Info->SymInfoById);
CollInit (&Info->TypeInfoById);
+ CollInit (&Info->CSymFuncByName);
CollInit (&Info->FileInfoByName);
CollInit (&Info->ModInfoByName);
CollInit (&Info->ScopeInfoByName);
CollDone (&Info->TypeInfoById);
/* Free the memory used by the other collections */
+ CollDone (&Info->CSymFuncByName);
CollDone (&Info->FileInfoByName);
CollDone (&Info->ModInfoByName);
CollDone (&Info->ScopeInfoByName);
+static void ProcessCSymInfo (InputData* D)
+/* Postprocess c symbol infos */
+{
+ unsigned I;
+
+ /* Walk over all c symbols. Resolve the ids and add the c symbols to the
+ * corresponding asm symbols.
+ */
+ for (I = 0; I < CollCount (&D->Info->CSymInfoById); ++I) {
+
+ /* Get this c symbol info */
+ CSymInfo* S = CollAt (&D->Info->CSymInfoById, I);
+
+ /* Resolve the asm symbol */
+ if (S->Sym.Id == CC65_INV_ID) {
+ S->Sym.Info = 0;
+ } else if (S->Sym.Id >= CollCount (&D->Info->SymInfoById)) {
+ ParseError (D,
+ CC65_ERROR,
+ "Invalid symbol id %u for c symbol with id %u",
+ S->Sym.Id, S->Id);
+ S->Sym.Info = 0;
+ } else {
+ S->Sym.Info = CollAt (&D->Info->SymInfoById, S->Sym.Id);
+
+ /* For normal (=static) symbols, add a backlink to the symbol but
+ * check that there is not more than one.
+ */
+ if (S->SC != CC65_CSYM_AUTO && S->SC != CC65_CSYM_REG) {
+ if (S->Sym.Info->CSym) {
+ ParseError (D,
+ CC65_ERROR,
+ "Asm symbol id %u has more than one C symbol attached",
+ S->Sym.Info->Id);
+ S->Sym.Info = 0;
+ } else {
+ S->Sym.Info->CSym = S;
+ }
+ }
+ }
+
+ /* Resolve the type */
+ if (S->Type.Id >= CollCount (&D->Info->TypeInfoById)) {
+ ParseError (D,
+ CC65_ERROR,
+ "Invalid type id %u for c symbol with id %u",
+ S->Type.Id, S->Id);
+ S->Type.Info = 0;
+ } else {
+ S->Type.Info = CollAt (&D->Info->TypeInfoById, S->Type.Id);
+ }
+
+ /* Resolve the scope */
+ if (S->Scope.Id >= CollCount (&D->Info->ScopeInfoById)) {
+ ParseError (D,
+ CC65_ERROR,
+ "Invalid scope id %u for c symbol with id %u",
+ S->Scope.Id, S->Id);
+ S->Scope.Info = 0;
+ } else {
+ S->Scope.Info = CollAt (&D->Info->ScopeInfoById, S->Scope.Id);
+
+ /* Add the c symbol to the list of all c symbols for this scope */
+ if (S->Scope.Info->CSymInfoByName == 0) {
+ S->Scope.Info->CSymInfoByName = CollNew ();
+ }
+ CollAppend (S->Scope.Info->CSymInfoByName, S);
+
+ /* If the scope has an owner symbol, it's a .PROC scope. If this
+ * symbol is identical to the one attached to the C symbol, this
+ * is actuallay a C function and the scope is the matching scope.
+ * Remember the C symbol in the scope in this case.
+ * Beware: Scopes haven't been postprocessed, so we don't have a
+ * pointer but just an id.
+ */
+ if (S->Sym.Info && S->Scope.Info->Label.Id == S->Sym.Info->Id) {
+ /* This scope is our function scope */
+ S->Scope.Info->CSymFunc = S;
+ /* Add it to the list of all c functions */
+ CollAppend (&D->Info->CSymFuncByName, S);
+ }
+
+ }
+ }
+
+ /* Walk over all scopes and sort the c symbols by name */
+ for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) {
+
+ /* Get this scope */
+ ScopeInfo* S = CollAt (&D->Info->ScopeInfoById, I);
+
+ /* Ignore scopes without C symbols */
+ if (S->CSymInfoByName && CollCount (S->CSymInfoByName) > 1) {
+ /* Sort the c symbols for this scope by name */
+ CollSort (S->CSymInfoByName, CompareCSymInfoByName);
+ }
+ }
+
+ /* Sort the main list of all C functions by name */
+ CollSort (&D->Info->CSymFuncByName, CompareCSymInfoByName);
+}
+
+
+
static void ProcessFileInfo (InputData* D)
/* Postprocess file infos */
{
/* No parent means main scope */
S->Mod.Info->MainScope = S;
}
+
+ /* If this is the scope that implements a C function, add the
+ * function to the list of all functions in this module.
+ */
+ if (S->CSymFunc) {
+ CollAppend (&S->Mod.Info->CSymFuncByName, S->CSymFunc);
+ }
}
/* Resolve the parent scope */
/* Walk over all modules. If a module doesn't have scopes, it wasn't
* compiled with debug info which is ok. If it has debug info, it must
- * also have a main scope. If there are scopes, sort them by name.
+ * also have a main scope. If there are scopes, sort them by name. Do
+ * also sort C functions in this module by name.
*/
for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) {
/* Sort the scopes for this module by name */
CollSort (&M->ScopeInfoByName, CompareScopeInfoByName);
+
+ /* Sort the C functions in this module by name */
+ CollSort (&M->CSymFuncByName, CompareCSymInfoByName);
}
/* Sort the scope infos */
}
/* We do now have all the information from the input file. Do
- * postprocessing.
+ * postprocessing. Beware: Some of the following postprocessing
+ * depends on the order of the calls.
*/
+ ProcessCSymInfo (&D);
ProcessFileInfo (&D);
ProcessLineInfo (&D);
ProcessModInfo (&D);