1 /*****************************************************************************/
5 /* Symbol table entry forward for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
53 /*****************************************************************************/
55 /*****************************************************************************/
59 /* List of all symbol table entries */
60 SymEntry* SymList = 0;
62 /* Pointer to last defined symbol */
63 SymEntry* SymLast = 0;
67 /*****************************************************************************/
69 /*****************************************************************************/
73 int IsLocalName (const char* Name)
74 /* Return true if Name is the name of a local symbol */
76 return (*Name == LocalStart);
81 int IsLocalNameId (unsigned Name)
82 /* Return true if Name is the name of a local symbol */
84 return (*GetString (Name) == LocalStart);
89 static unsigned SymAddrSize (const SymEntry* S)
90 /* Get the default address size for a symbol. */
92 /* Local symbols are always near (is this ok?) */
93 if (IsLocalNameId (S->Name)) {
97 /* Return the address size of the enclosing scope */
98 return S->SymTab->AddrSize;
103 SymEntry* NewSymEntry (const char* Name)
104 /* Allocate a symbol table entry, initialize and return it */
106 /* Allocate memory */
107 SymEntry* S = xmalloc (sizeof (SymEntry));
109 /* Initialize the entry */
117 S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
118 S->ExportSize = ADDR_SIZE_DEFAULT;
119 S->AddrSize = ADDR_SIZE_DEFAULT;
120 memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
121 S->Name = GetStringId (Name);
123 /* Insert it into the list of all entries */
127 /* Return the initialized entry */
133 void SymRef (SymEntry* S)
134 /* Mark the given symbol as referenced */
136 /* Mark the symbol as referenced */
137 S->Flags |= SF_REFERENCED;
142 void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
143 /* Define a new symbol */
145 if (S->Flags & SF_IMPORT) {
146 /* Defined symbol is marked as imported external symbol */
147 Error ("Symbol `%s' is already an import", GetSymName (S));
150 if (S->Flags & SF_DEFINED) {
151 /* Multiple definition */
152 Error ("Symbol `%s' is already defined", GetSymName (S));
153 S->Flags |= SF_MULTDEF;
157 /* Map a default address size to a real value */
158 if (AddrSize == ADDR_SIZE_DEFAULT) {
159 AddrSize = SymAddrSize (S);
162 /* Set the symbol value */
165 /* If the symbol is marked as global, export it */
166 if (S->Flags & SF_GLOBAL) {
167 S->ExportSize = S->AddrSize;
168 S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
171 /* Mark the symbol as defined and use the given address size */
172 S->Flags |= (SF_DEFINED | Flags);
173 S->AddrSize = AddrSize;
175 /* If the symbol is exported, check the address sizes */
176 if (S->Flags & SF_EXPORT) {
177 if (S->ExportSize == ADDR_SIZE_DEFAULT) {
178 /* Use the real size of the symbol */
179 S->ExportSize = S->AddrSize;
180 } else if (S->AddrSize > S->ExportSize) {
181 Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
185 /* If the symbol is a ZP symbol, check if the value is in correct range */
186 if (S->AddrSize == ADDR_SIZE_ZP) {
187 /* Already marked as ZP symbol by some means */
188 if (!IsByteExpr (Expr)) {
189 Error ("Range error");
193 /* If this is not a local symbol, remember it as the last global one */
194 if (!IsLocalNameId (S->Name)) {
201 void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
202 /* Mark the given symbol as an imported symbol */
204 /* Don't accept local symbols */
205 if (IsLocalNameId (S->Name)) {
206 Error ("Illegal use of a local symbol");
210 if (S->Flags & SF_DEFINED) {
211 Error ("Symbol `%s' is already defined", GetSymName (S));
212 S->Flags |= SF_MULTDEF;
215 if (S->Flags & SF_EXPORT) {
216 /* The symbol is already marked as exported symbol */
217 Error ("Cannot import exported symbol `%s'", GetSymName (S));
221 /* Map a default address size to a real value */
222 if (AddrSize == ADDR_SIZE_DEFAULT) {
223 AddrSize = SymAddrSize (S);
226 /* If the symbol is marked as import or global, check the symbol flags,
227 * then do silently remove the global flag
229 if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
230 if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
231 AddrSize != S->AddrSize) {
232 Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
234 S->Flags &= ~SF_GLOBAL;
237 /* Set the symbol data */
238 S->Flags |= (SF_IMPORT | Flags);
239 S->AddrSize = AddrSize;
244 void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
245 /* Mark the given symbol as an exported symbol */
247 /* Don't accept local symbols */
248 if (IsLocalNameId (S->Name)) {
249 Error ("Illegal use of a local symbol");
253 /* Check if it's ok to export the symbol */
254 if (S->Flags & SF_IMPORT) {
255 /* The symbol is already marked as imported external symbol */
256 Error ("Symbol `%s' is already an import", GetSymName (S));
260 /* If the symbol was already marked as an export or global, check if
261 * this was done specifiying the same address size. In case of a global
262 * declaration, silently remove the global flag.
264 if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
265 if (S->ExportSize != AddrSize) {
266 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
268 S->Flags &= ~SF_GLOBAL;
270 S->ExportSize = AddrSize;
272 /* If the symbol is already defined, check symbol size against the
275 if (S->Flags & SF_DEFINED) {
276 if (S->ExportSize == ADDR_SIZE_DEFAULT) {
277 /* Use the real size of the symbol */
278 S->ExportSize = S->AddrSize;
279 } else if (S->AddrSize > S->ExportSize) {
280 Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
284 /* Set the symbol data */
285 S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
290 void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
291 /* Mark the given symbol as a global symbol, that is, as a symbol that is
292 * either imported or exported.
295 /* Don't accept local symbols */
296 if (IsLocalNameId (S->Name)) {
297 Error ("Illegal use of a local symbol");
301 /* Map a default address size to a real value */
302 if (AddrSize == ADDR_SIZE_DEFAULT) {
303 AddrSize = SymAddrSize (S);
306 /* If the symbol is already marked as import or export, check the
307 * size of the definition, then bail out.
309 if (S->Flags & SF_IMPORT) {
310 if (AddrSize != S->AddrSize) {
311 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
315 if (S->Flags & SF_EXPORT) {
316 if (AddrSize != S->ExportSize) {
317 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
322 /* If the symbol is already defined, export it. Otherwise mark it as
325 if (S->Flags & SF_DEFINED) {
326 /* The symbol is defined, export it */
327 if (S->ExportSize != AddrSize) {
328 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
330 S->Flags |= (SF_EXPORT | Flags);
331 S->ExportSize = AddrSize;
333 S->Flags |= (SF_GLOBAL | Flags);
334 S->AddrSize = AddrSize;
340 int SymIsDef (const SymEntry* S)
341 /* Return true if the given symbol is already defined */
343 return (S->Flags & SF_DEFINED) != 0;
348 int SymIsRef (const SymEntry* S)
349 /* Return true if the given symbol has been referenced */
351 return (S->Flags & SF_REFERENCED) != 0;
356 int SymIsImport (const SymEntry* S)
357 /* Return true if the given symbol is marked as import */
359 /* Resolve trampoline entries */
360 if (S->Flags & SF_TRAMPOLINE) {
364 /* Check the import flag */
365 return (S->Flags & SF_IMPORT) != 0;
370 int SymIsConst (SymEntry* S, long* Val)
371 /* Return true if the given symbol has a constant value. If Val is not NULL
372 * and the symbol has a constant value, store it's value there.
375 /* Resolve trampoline entries */
376 if (S->Flags & SF_TRAMPOLINE) {
380 /* Check for constness */
381 return (SymHasExpr (S) && IsConstExpr (S->V.Expr, Val));
386 int SymHasExpr (const SymEntry* S)
387 /* Return true if the given symbol has an associated expression */
389 /* Resolve trampoline entries */
390 if (S->Flags & SF_TRAMPOLINE) {
394 /* Check the expression */
395 return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED);
400 void SymMarkUser (SymEntry* S)
401 /* Set a user mark on the specified symbol */
403 /* Resolve trampoline entries */
404 if (S->Flags & SF_TRAMPOLINE) {
414 void SymUnmarkUser (SymEntry* S)
415 /* Remove a user mark from the specified symbol */
417 /* Resolve trampoline entries */
418 if (S->Flags & SF_TRAMPOLINE) {
423 S->Flags &= ~SF_USER;
428 int SymHasUserMark (SymEntry* S)
429 /* Return the state of the user mark for the specified symbol */
431 /* Resolve trampoline entries */
432 if (S->Flags & SF_TRAMPOLINE) {
437 return (S->Flags & SF_USER) != 0;
442 struct ExprNode* GetSymExpr (SymEntry* S)
443 /* Get the expression for a non-const symbol */
445 /* Resolve trampoline entries */
446 if (S->Flags & SF_TRAMPOLINE) {
450 PRECONDITION (S != 0 && SymHasExpr (S));
456 const struct ExprNode* SymResolve (const SymEntry* S)
457 /* Helper function for DumpExpr. Resolves a symbol into an expression or return
458 * NULL. Do not call in other contexts!
461 /* Resolve trampoline entries */
462 if (S->Flags & SF_TRAMPOLINE) {
466 return SymHasExpr (S)? S->V.Expr : 0;
471 const char* GetSymName (SymEntry* S)
472 /* Return the name of the symbol */
474 /* Resolve trampoline entries */
475 if (S->Flags & SF_TRAMPOLINE) {
478 return GetString (S->Name);
483 unsigned GetSymIndex (SymEntry* S)
484 /* Return the symbol index for the given symbol */
486 /* Resolve trampoline entries */
487 if (S->Flags & SF_TRAMPOLINE) {
490 PRECONDITION (S != 0 && (S->Flags & SF_INDEXED) != 0);
496 const FilePos* GetSymPos (SymEntry* S)
497 /* Return the position of first occurence in the source for the given symbol */
499 /* Resolve trampoline entries */
500 if (S->Flags & SF_TRAMPOLINE) {
503 PRECONDITION (S != 0);