From: uz Date: Tue, 16 Aug 2011 14:25:18 +0000 (+0000) Subject: Handle imports correctly. X-Git-Tag: V2.13.3~275 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=7d7667f7820e48f47233f74ea37e70850959459c;p=cc65 Handle imports correctly. git-svn-id: svn://svn.cc65.org/cc65/trunk@5187 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index be516f1b6..56dbe5990 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -129,9 +129,11 @@ typedef enum { TOK_COUNT, /* COUNT keyword */ TOK_ENUM, /* ENUM keyword */ TOK_EQUATE, /* EQUATE keyword */ + TOK_EXPORT, /* EXPORT keyword */ TOK_FILE, /* FILE keyword */ TOK_GLOBAL, /* GLOBAL keyword */ TOK_ID, /* ID keyword */ + TOK_IMPORT, /* IMPORT keyword */ TOK_INFO, /* INFO keyword */ TOK_LABEL, /* LABEL keyword */ TOK_LIBRARY, /* LIBRARY keyword */ @@ -322,6 +324,10 @@ struct SymInfo { cc65_symbol_type Type; /* Type of symbol */ long Value; /* Value of symbol */ cc65_size Size; /* Size of symbol */ + union { + unsigned Id; /* Id of export if any */ + SymInfo* Info; /* Pointer to export if any */ + } Exp; union { unsigned Id; /* Id of segment if any */ SegInfo* Info; /* Pointer to segment if any */ @@ -1158,7 +1164,7 @@ static LineInfo* NewLineInfo (void) static void FreeLineInfo (LineInfo* L) /* Free a LineInfo struct */ -{ +{ CollDone (&L->SpanInfoList); xfree (L); } @@ -1562,13 +1568,28 @@ static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count) static void CopySymInfo (cc65_symboldata* D, const SymInfo* S) /* Copy data from a SymInfo struct to a cc65_symboldata struct */ { + SegInfo* Seg; + D->symbol_id = S->Id; D->symbol_name = S->Name; D->symbol_type = S->Type; D->symbol_size = S->Size; - D->symbol_value = S->Value; - if (S->Seg.Info) { - D->segment_id = S->Seg.Info->Id; + + /* If this is an import, it doesn't have a value or segment. Use the data + * from the matching export instead. + */ + if (S->Exp.Info) { + /* This is an import, because it has a matching export */ + D->export_id = S->Exp.Info->Id; + D->symbol_value = S->Exp.Info->Value; + Seg = S->Exp.Info->Seg.Info; + } else { + D->export_id = CC65_INV_ID; + D->symbol_value = S->Value; + Seg = S->Seg.Info; + } + if (Seg) { + D->segment_id = Seg->Id; } else { D->segment_id = CC65_INV_ID; } @@ -2033,9 +2054,11 @@ static void NextToken (InputData* D) { "count", TOK_COUNT }, { "enum", TOK_ENUM }, { "equ", TOK_EQUATE }, + { "exp", TOK_EXPORT }, { "file", TOK_FILE }, { "global", TOK_GLOBAL }, { "id", TOK_ID }, + { "imp", TOK_IMPORT }, { "info", TOK_INFO }, { "lab", TOK_LABEL }, { "lib", TOK_LIBRARY }, @@ -3428,6 +3451,7 @@ static void ParseSym (InputData* D) /* Most of the following variables are initialized with a value that is * overwritten later. This is just to avoid compiler warnings. */ + unsigned ExportId = CC65_INV_ID; unsigned FileId = CC65_INV_ID; unsigned Id = CC65_INV_ID; StrBuf Name = STRBUF_INITIALIZER; @@ -3435,7 +3459,7 @@ static void ParseSym (InputData* D) unsigned ScopeId = CC65_INV_ID; unsigned SegId = CC65_INV_ID; cc65_size Size = 0; - cc65_symbol_type Type = CC65_SYM_EQUATE; + cc65_symbol_type Type = CC65_SYM_EQUATE; long Value = 0; SymInfo* S; @@ -3443,17 +3467,18 @@ static void ParseSym (InputData* D) ibNone = 0x000, ibAddrSize = 0x001, - ibFileId = 0x002, - ibId = 0x004, - ibParentId = 0x008, - ibScopeId = 0x010, - ibSegId = 0x020, - ibSize = 0x040, - ibName = 0x080, - ibType = 0x100, - ibValue = 0x200, - - ibRequired = ibAddrSize | ibId | ibName | ibType | ibValue, + ibExportId = 0x002, + ibFileId = 0x004, + ibId = 0x008, + ibParentId = 0x010, + ibScopeId = 0x020, + ibSegId = 0x040, + ibSize = 0x080, + ibName = 0x100, + ibType = 0x200, + ibValue = 0x400, + + ibRequired = ibAddrSize | ibId | ibName, } InfoBits = ibNone; /* Skip the SYM token */ @@ -3465,11 +3490,12 @@ static void ParseSym (InputData* D) Token Tok; /* Something we know? */ - if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_FILE && - D->Tok != TOK_ID && D->Tok != TOK_NAME && - D->Tok != TOK_PARENT && D->Tok != TOK_SCOPE && - D->Tok != TOK_SEGMENT && D->Tok != TOK_SIZE && - D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) { + if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_EXPORT && + D->Tok != TOK_FILE && D->Tok != TOK_ID && + D->Tok != TOK_NAME && D->Tok != TOK_PARENT && + D->Tok != TOK_SCOPE && D->Tok != TOK_SEGMENT && + D->Tok != TOK_SIZE && D->Tok != TOK_TYPE && + D->Tok != TOK_VALUE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { @@ -3496,6 +3522,15 @@ static void ParseSym (InputData* D) InfoBits |= ibAddrSize; break; + case TOK_EXPORT: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + ExportId = D->IVal; + InfoBits |= ibExportId; + NextToken (D); + break; + case TOK_FILE: if (!IntConstFollows (D)) { goto ErrorExit; @@ -3564,7 +3599,6 @@ static void ParseSym (InputData* D) switch (D->Tok) { case TOK_EQUATE: Type = CC65_SYM_EQUATE; break; case TOK_LABEL: Type = CC65_SYM_LABEL; break; - default: ParseError (D, CC65_ERROR, "Unknown value for attribute \"type\""); @@ -3622,6 +3656,7 @@ static void ParseSym (InputData* D) S->Type = Type; S->Value = Value; S->Size = Size; + S->Exp.Id = ExportId; S->Seg.Id = SegId; S->Scope.Id = ScopeId; S->Parent.Id = ParentId; @@ -4249,6 +4284,19 @@ static void ProcessSymInfo (InputData* D) /* Get the symbol info */ SymInfo* S = CollAt (&D->Info->SymInfoById, I); + /* Resolve export */ + if (S->Exp.Id == CC65_INV_ID) { + S->Exp.Info = 0; + } else if (S->Exp.Id >= CollCount (&D->Info->SymInfoById)) { + ParseError (D, + CC65_ERROR, + "Invalid export id %u for symbol with id %u", + S->Exp.Id, S->Id); + S->Exp.Info = 0; + } else { + S->Exp.Info = CollAt (&D->Info->SymInfoById, S->Exp.Id); + } + /* Resolve segment */ if (S->Seg.Id == CC65_INV_ID) { S->Seg.Info = 0; diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index 617a769e9..fe1415385 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -380,6 +380,16 @@ typedef enum { CC65_SYM_LABEL, /* Some sort of address */ } cc65_symbol_type; +/* Notes: + * - If the symbol is segment relative, the segment id gives segment + * information, otherwise it contains CC65_INV_ID. + * - If export_id is valid (not CC65_INV_ID), the symbol is an import and + * export_id allows to retrieve the corresponding export. The fields + * symbol_value and segment_id are taken from the export, since imports + * have no value or segments by itself. symbol_type and symbol_size are + * more or less unusable because they don't have a meaning for imports. + * - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID. + */ typedef struct cc65_symboldata cc65_symboldata; struct cc65_symboldata { unsigned symbol_id; /* Id of symbol */ @@ -387,10 +397,8 @@ struct cc65_symboldata { cc65_symbol_type symbol_type; /* Type of symbol */ cc65_size symbol_size; /* Size of symbol, 0 if unknown */ long symbol_value; /* Value of symbol */ - unsigned segment_id; /* If the symbol is segment relative, - * this contains the id of segment, - * otherwise CC65_INV_ID - */ + unsigned export_id; /* For imports: Matching export */ + unsigned segment_id; /* Id of segment if any */ unsigned scope_id; /* The scope this symbol is in */ unsigned parent_id; /* Parent symbol for cheap locals */ };