void CheckAssertions (void) /* Check all assertions and evaluate the ones we can evaluate here. */ { unsigned I; /* Get the number of assertions */ unsigned Count = CollCount (&Assertions); /* Check the assertions */ for (I = 0; I < Count; ++I) { long Val; /* Get the next assertion */ Assertion* A = CollAtUnchecked (&Assertions, I); /* Ignore it, if it should only be evaluated by the linker */ if (!AssertAtAsmTime (A->Action)) { continue; } /* Can we evaluate the expression? */ if (IsConstExpr (A->Expr, &Val) && Val == 0) { /* Apply the action */ const char* Msg = GetString (A->Msg); switch (A->Action) { case ASSERT_ACT_WARN: LIWarning (&A->LI, 0, "%s", Msg); break; case ASSERT_ACT_ERROR: LIError (&A->LI, "%s", Msg); break; default: Internal ("Illegal assert action specifier"); break; } } } }
void ULabDone (void) /* Run through all unnamed labels, check for anomalies and errors and do * necessary cleanups. */ { /* Check if there are undefined labels */ unsigned I = ULabDefCount; while (I < CollCount (&ULabList)) { ULabel* L = CollAtUnchecked (&ULabList, I); LIError (&L->LineInfos, "Undefined label"); ++I; } /* Walk over all labels and emit a warning if any unreferenced ones * are found. Remove line infos because they're no longer needed. */ for (I = 0; I < CollCount (&ULabList); ++I) { ULabel* L = CollAtUnchecked (&ULabList, I); if (L->Ref == 0) { LIWarning (&L->LineInfos, 1, "No reference to unnamed label"); } ReleaseFullLineInfo (&L->LineInfos); } }
void SymCheck (void) /* Run through all symbols and check for anomalies and errors */ { SymEntry* S; /* Check for open scopes */ if (CurrentScope->Parent != 0) { Error ("Local scope was not closed"); } /* First pass: Walk through all symbols, checking for undefined's and ** changing them to trampoline symbols or make them imports. */ S = SymList; while (S) { /* If the symbol is marked as global, mark it as export, if it is ** already defined, otherwise mark it as import. */ if (S->Flags & SF_GLOBAL) { if (S->Flags & SF_DEFINED) { SymExportFromGlobal (S); } else { SymImportFromGlobal (S); } } /* Handle undefined symbols */ if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) { /* This is an undefined symbol. Handle it. */ SymCheckUndefined (S); } /* Next symbol */ S = S->List; } /* Second pass: Walk again through the symbols. Count exports and imports ** and set address sizes where this has not happened before. Ignore ** undefined's, since we handled them in the last pass, and ignore unused ** symbols, since we handled them in the last pass, too. */ S = SymList; while (S) { if ((S->Flags & SF_UNUSED) == 0 && (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) { /* Check for defined symbols that were never referenced */ if (IsSizeOfSymbol (S)) { /* Remove line infos, we don't need them any longer */ ReleaseFullLineInfo (&S->DefLines); ReleaseFullLineInfo (&S->RefLines); } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) { LIWarning (&S->DefLines, 2, "Symbol `%m%p' is defined but never used", GetSymName (S)); } /* Assign an index to all imports */ if (S->Flags & SF_IMPORT) { if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) { /* Imported symbol is not referenced */ LIWarning (&S->DefLines, 2, "Symbol `%m%p' is imported but never used", GetSymName (S)); } else { /* Give the import an id, count imports */ S->ImportId = ImportCount++; } } /* Count exports, assign the export ID */ if (S->Flags & SF_EXPORT) { S->ExportId = ExportCount++; } /* If the symbol is defined but has an unknown address size, ** recalculate it. */ if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) { ExprDesc ED; ED_Init (&ED); StudyExpr (S->Expr, &ED); S->AddrSize = ED.AddrSize; if (SymIsExport (S)) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real export size */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ LIWarning (&S->DefLines, 1, "Symbol `%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } ED_Done (&ED); } /* If the address size of the symbol was guessed, check the guess ** against the actual address size and print a warning if the two ** differ. */ if (S->AddrSize != ADDR_SIZE_DEFAULT) { /* Do we have data for this address size? */ if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) { /* Get the file position where the symbol was used */ const FilePos* P = S->GuessedUse[S->AddrSize - 1]; if (P) { PWarning (P, 0, "Didn't use %s addressing for `%m%p'", AddrSizeToStr (S->AddrSize), GetSymName (S)); } } } } /* Next symbol */ S = S->List; } }
static void SymCheckUndefined (SymEntry* S) /* Handle an undefined symbol */ { /* Undefined symbol. It may be... ** ** - An undefined symbol in a nested lexical level. If the symbol is not ** fixed to this level, search for the symbol in the higher levels and ** make the entry a trampoline entry if we find one. ** ** - If the symbol is not found, it is a real undefined symbol. If the ** AutoImport flag is set, make it an import. If the AutoImport flag is ** not set, it's an error. */ SymEntry* Sym = 0; if ((S->Flags & SF_FIXED) == 0) { SymTable* Tab = GetSymParentScope (S); while (Tab) { Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY); if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) { /* We've found a symbol in a higher level that is ** either defined in the source, or an import. */ break; } /* No matching symbol found in this level. Look further */ Tab = Tab->Parent; } } if (Sym) { /* We found the symbol in a higher level. Transfer the flags and ** address size from the local symbol to that in the higher level ** and check for problems. */ if (S->Flags & SF_EXPORT) { if (Sym->Flags & SF_IMPORT) { /* The symbol is already marked as import */ LIError (&S->RefLines, "Symbol `%s' is already an import", GetString (Sym->Name)); } if ((Sym->Flags & SF_EXPORT) == 0) { /* Mark the symbol as an export */ Sym->Flags |= SF_EXPORT; Sym->ExportSize = S->ExportSize; if (Sym->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the actual size of the symbol */ Sym->ExportSize = Sym->AddrSize; } if (Sym->AddrSize > Sym->ExportSize) { /* We're exporting a symbol smaller than it actually is */ LIWarning (&Sym->DefLines, 1, "Symbol `%m%p' is %s but exported %s", GetSymName (Sym), AddrSizeToStr (Sym->AddrSize), AddrSizeToStr (Sym->ExportSize)); } } } if (S->Flags & SF_REFERENCED) { /* Mark as referenced and move the line info */ Sym->Flags |= SF_REFERENCED; CollTransfer (&Sym->RefLines, &S->RefLines); CollDeleteAll (&S->RefLines); } /* Transfer all expression references */ SymTransferExprRefs (S, Sym); /* Mark the symbol as unused removing all other flags */ S->Flags = SF_UNUSED; } else { /* The symbol is definitely undefined */ if (S->Flags & SF_EXPORT) { /* We will not auto-import an export */ LIError (&S->RefLines, "Exported symbol `%m%p' was never defined", GetSymName (S)); } else { if (AutoImport) { /* Mark as import, will be indexed later */ S->Flags |= SF_IMPORT; /* Use the address size for code */ S->AddrSize = CodeAddrSize; /* Mark point of import */ GetFullLineInfo (&S->DefLines); } else { /* Error */ LIError (&S->RefLines, "Symbol `%m%p' is undefined", GetSymName (S)); } } } }