} else {
/* Static variable */
char Buf [16];
- xsprintf (Buf, sizeof (Buf), "L%04X", Sym->V.Label);
+ xsprintf (Buf, sizeof (Buf), "L%04X", Sym->V.L.Label);
SB_AppendStr (T, Buf);
}
}
SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF);
/* Append the label name to the buffer */
- SB_AppendStr (T, LocalLabelName (Entry->V.Label));
+ SB_AppendStr (T, LocalLabelName (Entry->V.L.Label));
/* Eat the label name */
NextToken ();
E->Name = (uintptr_t) Sym->Name;
} else {
E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
- E->Name = Sym->V.Label;
+ E->Name = Sym->V.L.Label;
}
} else {
/* Local static variable */
/*****************************************************************************/
-
-/* Enumeration for function flags */
-typedef enum {
- FF_NONE = 0x0000,
- FF_HAS_RETURN = 0x0001, /* Function has a return statement */
- FF_IS_MAIN = 0x0002, /* This is the main function */
- FF_VOID_RETURN = 0x0004, /* Function returning void */
-} funcflags_t;
-
-/* Structure that holds all data needed for function activation */
-struct Function {
- struct SymEntry* FuncEntry; /* Symbol table entry */
- Type* ReturnType; /* Function return type */
- FuncDesc* Desc; /* Function descriptor */
- int Reserved; /* Reserved local space */
- unsigned RetLab; /* Return code label */
- int TopLevelSP; /* SP at function top level */
- unsigned RegOffs; /* Register variable space offset */
- funcflags_t Flags; /* Function flags */
-};
-
/* Pointer to current function */
Function* CurrentFunc = 0;
Function* F = (Function*) xmalloc (sizeof (Function));
/* Initialize the fields */
- F->FuncEntry = Sym;
- F->ReturnType = GetFuncReturn (Sym->Type);
- F->Desc = GetFuncDesc (Sym->Type);
- F->Reserved = 0;
- F->RetLab = GetLocalLabel ();
- F->TopLevelSP = 0;
- F->RegOffs = RegisterSpace;
- F->Flags = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE;
+ F->FuncEntry = Sym;
+ F->ReturnType = GetFuncReturn (Sym->Type);
+ F->Desc = GetFuncDesc (Sym->Type);
+ F->Reserved = 0;
+ F->RetLab = GetLocalLabel ();
+ F->TopLevelSP = 0;
+ F->RegOffs = RegisterSpace;
+ F->Flags = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE;
+ F->LocalsBlockCount = 0;
+
+ InitCollection (&F->LocalsBlockStack);
/* Return the new structure */
return F;
static void FreeFunction (Function* F)
/* Free a function activation structure */
{
+ DoneCollection (&F->LocalsBlockStack);
xfree (F);
}
#ifndef FUNCTION_H
#define FUNCTION_H
-
+#include "coll.h"
/*****************************************************************************/
-/* data */
+/* Data */
/*****************************************************************************/
+/* Enumeration for function flags */
+typedef enum {
+ FF_NONE = 0x0000,
+ FF_HAS_RETURN = 0x0001, /* Function has a return statement */
+ FF_IS_MAIN = 0x0002, /* This is the main function */
+ FF_VOID_RETURN = 0x0004, /* Function returning void */
+} funcflags_t;
+
+/* Structure that holds all data needed for function activation */
+struct Function {
+ struct SymEntry* FuncEntry; /* Symbol table entry */
+ Type* ReturnType; /* Function return type */
+ FuncDesc* Desc; /* Function descriptor */
+ int Reserved; /* Reserved local space */
+ unsigned RetLab; /* Return code label */
+ int TopLevelSP; /* SP at function top level */
+ unsigned RegOffs; /* Register variable space offset */
+ funcflags_t Flags; /* Function flags */
+ long LocalsBlockCount; /* Number of blocks with local vars */
+ Collection LocalsBlockStack; /* Stack of blocks with local vars */
+};
+
+
/* Structure that holds all data needed for function activation */
typedef struct Function Function;
SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF);
/* Jump to the label */
- g_jump (Entry->V.Label);
+ g_jump (Entry->V.L.Label);
}
/* Eat the label name */
SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_DEF);
/* Emit the jump label */
- g_defcodelabel (Entry->V.Label);
+ g_defcodelabel (Entry->V.L.Label);
/* Eat the ident and colon */
NextToken ();
/* Be sure to allocate any reserved space for locals */
F_AllocLocalSpace (CurrentFunc);
+ if (InitialStack != StackPtr)
+ {
+ ++CurrentFunc->LocalsBlockCount;
+ /* Is it ok to abuse Collection in this way? */
+ CollAppend (&CurrentFunc->LocalsBlockStack, (void *)CurrentFunc->LocalsBlockCount);
+ }
+
/* In case we've allocated local variables in this block, emit a call to
** the stack checking routine if stack checks are enabled.
*/
if (!GotBreak) {
g_space (StackPtr - OldStack);
}
+
+ if (OldStack != StackPtr)
+ CollPop (&CurrentFunc->LocalsBlockStack);
+
StackPtr = OldStack;
/* Emit references to imports/exports for this block */
void FreeSymEntry (SymEntry* E)
/* Free a symbol entry */
{
+ unsigned i;
+
TypeFree (E->Type);
xfree (E->AsmName);
+
+ if (E->Flags & SC_LABEL)
+ {
+ for (i = 0; i < CollCount (E->V.L.DefsOrRefs); i++)
+ {
+ xfree (CollAt(E->V.L.DefsOrRefs, i));
+ }
+
+ DoneCollection (E->V.L.DefsOrRefs);
+ }
+
xfree (E);
}
/* Symbol table entry */
+
+typedef struct DefOrRef DefOrRef;
+
+struct DefOrRef {
+ unsigned Line;
+ long LocalsBlockNum;
+ unsigned Flags;
+};
+
typedef struct SymEntry SymEntry;
+
struct SymEntry {
SymEntry* NextHash; /* Next entry in hash list */
SymEntry* PrevSym; /* Previous symbol in dl list */
int Offs;
/* Label name for static symbols */
- unsigned Label;
+ struct {
+ unsigned Label;
+ Collection *DefsOrRefs;
+ } L;
/* Register bank offset and offset of the saved copy on stack for
** register variables.
#include "symentry.h"
#include "typecmp.h"
#include "symtab.h"
+#include "function.h"
+#include "input.h"
}
+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->Flags = Flags;
+
+ return DOR;
+}
+
SymEntry* AddLabelSym (const char* Name, unsigned Flags)
/* Add a goto label to the label table */
{
+ unsigned i;
+ DefOrRef *DOR;
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
if (Entry) {
/* Trying to define the label more than once */
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. */
+ 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);
+
Entry->Flags |= Flags;
} else {
Entry = NewSymEntry (Name, SC_LABEL | Flags);
/* Set a new label number */
- Entry->V.Label = GetLocalLabel ();
+ Entry->V.L.Label = GetLocalLabel ();
+
+ /* Create Collection for label definition and references */
+ Entry->V.L.DefsOrRefs = NewCollection ();
+ AddDefOrRef (Entry, Flags);
/* Generate the assembler name of the label */
- Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
+ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
/* Add the entry to the label table */
AddSymEntry (LabelTab, Entry);
Entry->V.R.RegOffs = Offs;
Entry->V.R.SaveOffs = StackPtr;
} else if ((Flags & SC_EXTERN) == SC_EXTERN) {
- Entry->V.Label = Offs;
+ Entry->V.L.Label = Offs;
SymSetAsmName (Entry);
} else if ((Flags & SC_STATIC) == SC_STATIC) {
/* Generate the assembler name from the label number */
- Entry->V.Label = Offs;
- Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
+ Entry->V.L.Label = Offs;
+ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
} else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
Entry->V.Offs = Offs;
} else {