1 /*****************************************************************************/
5 /* Symbol table entry forward for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
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 /*****************************************************************************/
52 /*****************************************************************************/
54 /*****************************************************************************/
58 /* List of all symbol table entries */
59 SymEntry* SymList = 0;
61 /* Pointer to last defined symbol */
62 SymEntry* SymLast = 0;
66 /*****************************************************************************/
68 /*****************************************************************************/
72 int IsLocalName (const char* Name)
73 /* Return true if Name is the name of a local symbol */
75 return (*Name == LocalStart);
80 int IsLocalNameId (unsigned Name)
81 /* Return true if Name is the name of a local symbol */
83 return (*GetString (Name) == LocalStart);
88 static unsigned SymAddrSize (const SymEntry* S)
89 /* Get the default address size for a symbol. */
91 /* Local symbols are always near (is this ok?) */
92 if (IsLocalNameId (S->Name)) {
96 /* Return the address size of the enclosing scope */
97 return S->SymTab->AddrSize;
102 SymEntry* NewSymEntry (const char* Name)
103 /* Allocate a symbol table entry, initialize and return it */
105 /* Allocate memory */
106 SymEntry* S = xmalloc (sizeof (SymEntry));
108 /* Initialize the entry */
116 S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
117 S->ExportSize = ADDR_SIZE_DEFAULT;
118 S->AddrSize = ADDR_SIZE_DEFAULT;
119 memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
120 S->Name = GetStringId (Name);
122 /* Insert it into the list of all entries */
126 /* Return the initialized entry */
132 void SymRef (SymEntry* S)
133 /* Mark the given symbol as referenced */
135 /* Mark the symbol as referenced */
136 S->Flags |= SF_REFERENCED;
141 void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
142 /* Define a new symbol */
144 if (S->Flags & SF_IMPORT) {
145 /* Defined symbol is marked as imported external symbol */
146 Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S));
149 if (S->Flags & SF_DEFINED) {
150 /* Multiple definition */
151 Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S));
152 S->Flags |= SF_MULTDEF;
156 /* Map a default address size to a real value */
157 if (AddrSize == ADDR_SIZE_DEFAULT) {
158 AddrSize = SymAddrSize (S);
161 /* Set the symbol value */
162 if (IsConstExpr (Expr)) {
163 /* Expression is const, store the value */
164 S->Flags |= SF_CONST;
165 S->V.Val = GetExprVal (Expr);
168 /* Not const, store the expression */
172 /* If the symbol is marked as global, export it */
173 if (S->Flags & SF_GLOBAL) {
174 S->ExportSize = S->AddrSize;
175 S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
178 /* Mark the symbol as defined and use the given address size */
179 S->Flags |= (SF_DEFINED | Flags);
180 S->AddrSize = AddrSize;
182 /* If the symbol is exported, check the address sizes */
183 if (S->Flags & SF_EXPORT) {
184 if (S->AddrSize > S->ExportSize) {
185 Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S));
189 /* If the symbol is a ZP symbol, check if the value is in correct range */
190 if (S->AddrSize == ADDR_SIZE_ZP) {
191 /* Already marked as ZP symbol by some means */
192 if (!IsByteExpr (Expr)) {
197 /* If this is not a local symbol, remember it as the last global one */
198 if (!IsLocalNameId (S->Name)) {
205 void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
206 /* Mark the given symbol as an imported symbol */
208 /* Don't accept local symbols */
209 if (IsLocalNameId (S->Name)) {
210 Error (ERR_ILLEGAL_LOCAL_USE);
214 if (S->Flags & SF_DEFINED) {
215 Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S));
216 S->Flags |= SF_MULTDEF;
219 if (S->Flags & SF_EXPORT) {
220 /* The symbol is already marked as exported symbol */
221 Error (ERR_SYM_ALREADY_EXPORT, GetSymName (S));
225 /* Map a default address size to a real value */
226 if (AddrSize == ADDR_SIZE_DEFAULT) {
227 AddrSize = SymAddrSize (S);
230 /* If the symbol is marked as import or global, check the symbol flags,
231 * then do silently remove the global flag
233 if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
234 if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
235 AddrSize != S->AddrSize) {
236 Error (ERR_SYM_REDECL_MISMATCH, GetSymName (S));
238 S->Flags &= ~SF_GLOBAL;
241 /* Set the symbol data */
242 S->Flags |= (SF_IMPORT | Flags);
243 S->AddrSize = AddrSize;
248 void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
249 /* Mark the given symbol as an exported symbol */
251 /* Don't accept local symbols */
252 if (IsLocalNameId (S->Name)) {
253 Error (ERR_ILLEGAL_LOCAL_USE);
257 /* Check if it's ok to export the symbol */
258 if (S->Flags & SF_IMPORT) {
259 /* The symbol is already marked as imported external symbol */
260 Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S));
264 /* Map a default address size to a real value */
265 if (AddrSize == ADDR_SIZE_DEFAULT) {
266 AddrSize = SymAddrSize (S);
269 /* If the symbol was already marked as an export or global, check if
270 * this was done specifiying the same address size. In case of a global
271 * declaration, silently remove the global flag.
273 if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
274 if (S->ExportSize != AddrSize) {
275 Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
277 S->Flags &= ~SF_GLOBAL;
279 S->ExportSize = AddrSize;
281 /* If the symbol is already defined, check symbol size against the
284 if (S->Flags & SF_DEFINED) {
285 if (S->AddrSize > S->ExportSize) {
286 Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S));
290 /* Set the symbol data */
291 S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
296 void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
297 /* Mark the given symbol as a global symbol, that is, as a symbol that is
298 * either imported or exported.
301 /* Don't accept local symbols */
302 if (IsLocalNameId (S->Name)) {
303 Error (ERR_ILLEGAL_LOCAL_USE);
307 /* Map a default address size to a real value */
308 if (AddrSize == ADDR_SIZE_DEFAULT) {
309 AddrSize = SymAddrSize (S);
312 /* If the symbol is already marked as import or export, check the
313 * size of the definition, then bail out.
315 if (S->Flags & SF_IMPORT) {
316 if (AddrSize != S->AddrSize) {
317 Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
321 if (S->Flags & SF_EXPORT) {
322 if (AddrSize != S->ExportSize) {
323 Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
328 /* If the symbol is already defined, export it. Otherwise mark it as
331 if (S->Flags & SF_DEFINED) {
332 /* The symbol is defined, export it */
333 if (S->ExportSize != AddrSize) {
334 Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
336 S->Flags |= (SF_EXPORT | Flags);
337 S->ExportSize = AddrSize;
339 S->Flags |= (SF_GLOBAL | Flags);
340 S->AddrSize = AddrSize;
346 int SymIsDef (const SymEntry* S)
347 /* Return true if the given symbol is already defined */
349 return (S->Flags & SF_DEFINED) != 0;
354 int SymIsRef (const SymEntry* S)
355 /* Return true if the given symbol has been referenced */
357 return (S->Flags & SF_REFERENCED) != 0;
362 int SymIsImport (const SymEntry* S)
363 /* Return true if the given symbol is marked as import */
365 /* Resolve trampoline entries */
366 if (S->Flags & SF_TRAMPOLINE) {
370 /* Check the import flag */
371 return (S->Flags & SF_IMPORT) != 0;
376 int SymHasExpr (const SymEntry* S)
377 /* Return true if the given symbol has an associated expression */
379 /* Resolve trampoline entries */
380 if (S->Flags & SF_TRAMPOLINE) {
384 /* Check the expression */
385 return ((S->Flags & SF_DEFINED) != 0 &&
386 (S->Flags & SF_IMPORT) == 0 &&
387 (S->Flags & SF_CONST) == 0);
392 void SymFinalize (SymEntry* S)
393 /* Finalize a symbol expression if there is one */
395 /* Resolve trampoline entries */
396 if (S->Flags & SF_TRAMPOLINE) {
400 /* Check if we have an expression */
401 if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
402 S->V.Expr = FinalizeExpr (S->V.Expr);
403 S->Flags |= SF_FINALIZED;
409 void SymMarkUser (SymEntry* S)
410 /* Set a user mark on the specified symbol */
412 /* Resolve trampoline entries */
413 if (S->Flags & SF_TRAMPOLINE) {
423 void SymUnmarkUser (SymEntry* S)
424 /* Remove a user mark from the specified symbol */
426 /* Resolve trampoline entries */
427 if (S->Flags & SF_TRAMPOLINE) {
432 S->Flags &= ~SF_USER;
437 int SymHasUserMark (SymEntry* S)
438 /* Return the state of the user mark for the specified symbol */
440 /* Resolve trampoline entries */
441 if (S->Flags & SF_TRAMPOLINE) {
446 return (S->Flags & SF_USER) != 0;
451 long GetSymVal (SymEntry* S)
452 /* Return the symbol value */
454 /* Resolve trampoline entries */
455 if (S->Flags & SF_TRAMPOLINE) {
459 PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
465 struct ExprNode* GetSymExpr (SymEntry* S)
466 /* Get the expression for a non-const symbol */
468 /* Resolve trampoline entries */
469 if (S->Flags & SF_TRAMPOLINE) {
473 PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0);
479 const char* GetSymName (SymEntry* S)
480 /* Return the name of the symbol */
482 /* Resolve trampoline entries */
483 if (S->Flags & SF_TRAMPOLINE) {
486 return GetString (S->Name);
491 unsigned GetSymIndex (SymEntry* S)
492 /* Return the symbol index for the given symbol */
494 /* Resolve trampoline entries */
495 if (S->Flags & SF_TRAMPOLINE) {
498 PRECONDITION (S != 0 && (S->Flags & SF_INDEXED));
504 const FilePos* GetSymPos (SymEntry* S)
505 /* Return the position of first occurence in the source for the given symbol */
507 /* Resolve trampoline entries */
508 if (S->Flags & SF_TRAMPOLINE) {
511 PRECONDITION (S != 0);