static SymTable* TagTab0 = 0;
static SymTable* TagTab = 0;
static SymTable* LabelTab = 0;
-
+static SymTable* SPAdjustTab = 0;
/*****************************************************************************/
/* Create and assign the tag table */
TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
+
+ SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
}
-static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
+SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
/* Search for an entry in one table */
{
/* Get the start of the hash chain */
}
-DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
+DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags)
/* Add definition or reference to the SymEntry and preserve its attributes */
{
DefOrRef *DOR;
DOR = xmalloc (sizeof (DefOrRef));
CollAppend (E->V.L.DefsOrRefs, DOR);
DOR->Line = GetCurrentLine ();
- DOR->LocalsBlockNum = (long)CollLast (&CurrentFunc->LocalsBlockStack);
+ DOR->LocalsBlockId = (long)CollLast (&CurrentFunc->LocalsBlockStack);
DOR->Flags = Flags;
+ DOR->StackPtr = StackPtr;
+ DOR->Depth = CollCount (&CurrentFunc->LocalsBlockStack);
+ DOR->LateSP_Label = GetLocalLabel ();
return DOR;
}
+unsigned short FindSPAdjustment (const char* Name)
+{
+ SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name));
+
+ if (Entry) {
+ printf("L: %s sa: %d\n", Name, Entry->V.G.SPAdjustment);
+ return Entry->V.G.SPAdjustment;
+ }
+
+ Fatal("ICE: No label entry found");
+
+ return 0;
+}
SymEntry* AddLabelSym (const char* Name, unsigned Flags)
/* Add a goto label to the label table */
{
unsigned i;
- DefOrRef *DOR;
+ DefOrRef *DOR, *NewDOR;
+ /* We juggle it so much that a shortcut will help with clarity */
+ Collection *AIC = &CurrentFunc->LocalsBlockStack;
+
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
if (Entry) {
Error ("Label `%s' is defined more than once", Name);
}
- /* Walk through all occurrences of the label so far and check
- if any of them is in a region that would be risky to jump from/to
- from the place where we are right now. */
+ NewDOR = AddDefOrRef (Entry, Flags);
+
+ /* Walk through all occurrences of the label so far and evaluate
+ ** their relationship with the one passed to the function.
+ */
for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) {
DOR = CollAt (Entry->V.L.DefsOrRefs, i);
- /* We are only interested in label occurences of type opposite to
- the one currently being added, i.e. if we are processing the
- definition, we will only check the gotos; if we are processing
- a goto statement, we will only look for the label definition. */
- if (((DOR->Flags & SC_DEF) != (Flags & SC_DEF)) &&
- (DOR->LocalsBlockNum != (long)CollLast (&CurrentFunc->LocalsBlockStack)))
- Warning ("Goto from line %d to label \'%s\' can result in a "
- "trashed stack", Flags & SC_DEF ? DOR->Line : GetCurrentLine (), Name);
- }
- AddDefOrRef (Entry, Flags);
+ if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & SC_GOTO)) {
+ /* We're processing a goto and here is its destination label.
+ ** This means the difference between SP values is already known,
+ ** so we simply emit the SP adjustment code.
+ */
+ if (StackPtr != DOR->StackPtr) {
+ g_space (StackPtr - DOR->StackPtr);
+ }
+
+ /* Are we jumping into a block with initalization of an object that
+ ** has automatic storage duration? Let's emit a warning.
+ */
+ if ((long)CollLast (AIC) != DOR->LocalsBlockId &&
+ (CollCount (AIC) < DOR->Depth ||
+ (long)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) {
+ Warning ("Goto at line %d to label %s jumps into a block with "
+ "initialization of an object that has automatic storage duration",
+ GetCurrentLine (), Name);
+ }
+ }
+
+
+ if ((DOR->Flags & SC_REF) && (DOR->Flags & SC_GOTO) && (Flags & SC_DEF)) {
+ /* We're processing a label, let's update all gotos encountered
+ ** so far
+ */
+ SymEntry *E;
+ g_userodata();
+ g_defdatalabel (DOR->LateSP_Label);
+ g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
+ E = NewSymEntry (LocalLabelName(DOR->LateSP_Label), SC_SPADJUSTMENT);
+ E->V.G.SPAdjustment = StackPtr - DOR->StackPtr;
+ AddSymEntry (SPAdjustTab, E);
+
+
+ /* Are we jumping into a block with initalization of an object that
+ ** has automatic storage duration? Let's emit a warning.
+ */
+ if ((long)CollLast (AIC) != DOR->LocalsBlockId &&
+ (CollCount (AIC) >= DOR->Depth ||
+ (long)CollLast (AIC) >= (long)DOR->Line))
+ Warning ("Goto at line %d to label %s jumps into a block with "
+ "initialization of an object that has automatic storage duration",
+ DOR->Line, Name);
+ }
+
+ }
Entry->Flags |= Flags;
/* Create Collection for label definition and references */
Entry->V.L.DefsOrRefs = NewCollection ();
- AddDefOrRef (Entry, Flags);
+ NewDOR = AddDefOrRef (Entry, Flags);
/* Generate the assembler name of the label */
Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
}
+ /* We are processing a goto, but the label has not yet been defined */
+ if (!SymIsDef (Entry) && (Flags & SC_REF) && (Flags & SC_GOTO)) {
+ g_lateadjustSP (NewDOR->LateSP_Label);
+ }
+
/* Return the entry */
return Entry;
}
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
if (Entry) {
-
Type* EType;
+ /* If the existing symbol is an enumerated constant,
+ ** then avoid a compiler crash. See GitHub issue #728.
+ */
+ if (Entry->Flags & SC_ENUM) {
+ Fatal ("Can't redeclare enum constant `%s' as global variable", Name);
+ }
+
/* We have a symbol with this name already */
if (Entry->Flags & SC_TYPE) {
Error ("Multiple definition for `%s'", Name);