CurTok.Tok == TOK_ASSIGN))) {
/* We will allocate storage */
- Decl.StorageClass |= SC_STORAGE | SC_DEF;
+ Decl.StorageClass |= SC_STORAGE;
}
/* If this is a function declarator that is not followed by a comma
/* Allow initialization */
if (CurTok.Tok == TOK_ASSIGN) {
+ /* This is a definition */
+ if (SymIsDef (Entry)) {
+ Error ("Global variable `%s' has already been defined",
+ Entry->Name);
+ }
+ Entry->Flags |= SC_DEF;
+
/* We cannot initialize types of unknown size, or
** void types in ISO modes.
*/
Error ("Variable `%s' has unknown size", Decl.Ident);
}
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
- }
-
- /* Allocate storage if it is still needed */
- if (Entry->Flags & SC_STORAGE) {
-
- /* Switch to the BSS segment */
- g_usebss ();
-
- /* Define a label */
- g_defgloblabel (Entry->Name);
-
- /* Allocate space for uninitialized variable */
- g_res (Size);
+ } else {
+ /* A global (including static) uninitialized variable is
+ ** only a tentative definition. For example, this is valid:
+ ** int i;
+ ** int i;
+ ** static int j;
+ ** static int j = 42;
+ ** Code for them will be generated by FinishCompile().
+ ** For now, just save the BSS segment name
+ ** (can be set by #pragma bss-name).
+ */
+ const char* bssName = GetSegName (SEG_BSS);
+
+ if (Entry->V.BssName && strcmp (Entry->V.BssName, bssName) != 0) {
+ Error ("Global variable `%s' already was defined in the `%s' segment.",
+ Entry->Name, Entry->V.BssName);
+ }
+ Entry->V.BssName = xstrdup (bssName);
}
}
struct tm* TM;
/* Since strftime is locale dependent, we need the abbreviated month names
- ** in english.
+ ** in English.
*/
static const char MonthNames[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
** changes using #pragma later.
*/
if (IS_Get (&Optimize)) {
- long CodeSize = IS_Get (&CodeSizeFactor);
DefineNumericMacro ("__OPT__", 1);
+ }
+ {
+ long CodeSize = IS_Get (&CodeSizeFactor);
if (CodeSize > 100) {
DefineNumericMacro ("__OPT_i__", CodeSize);
}
- if (IS_Get (&EnableRegVars)) {
- DefineNumericMacro ("__OPT_r__", 1);
- }
- if (IS_Get (&InlineStdFuncs)) {
- DefineNumericMacro ("__OPT_s__", 1);
- }
+ }
+ if (IS_Get (&EnableRegVars)) {
+ DefineNumericMacro ("__OPT_r__", 1);
+ }
+ if (IS_Get (&InlineStdFuncs)) {
+ DefineNumericMacro ("__OPT_s__", 1);
+ }
+ if (IS_Get (&EagerlyInlineFuncs)) {
+ DefineNumericMacro ("__EAGERLY_INLINE_FUNCS__", 1);
}
/* __TIME__ and __DATE__ macros */
void FinishCompile (void)
/* Emit literals, externals, debug info, do cleanup and optimizations */
{
- SymTable* SymTab;
- SymEntry* Func;
-
- /* Walk over all functions, doing cleanup, optimizations ... */
- SymTab = GetGlobalSymTab ();
- Func = SymTab->SymHead;
- while (Func) {
- if (SymIsOutputFunc (Func)) {
+ SymEntry* Entry;
+
+ /* Walk over all global symbols:
+ ** - for functions, do clean-up and optimizations
+ ** - generate code for uninitialized global variables
+ */
+ for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
+ if (SymIsOutputFunc (Entry)) {
/* Function which is defined and referenced or extern */
- MoveLiteralPool (Func->V.F.LitPool);
- CS_MergeLabels (Func->V.F.Seg->Code);
- RunOpt (Func->V.F.Seg->Code);
+ MoveLiteralPool (Entry->V.F.LitPool);
+ CS_MergeLabels (Entry->V.F.Seg->Code);
+ RunOpt (Entry->V.F.Seg->Code);
+ } else if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
+ /* Assembly definition of uninitialized global variable */
+
+ /* Set the segment name only when it changes */
+ if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
+ SetSegName (SEG_BSS, Entry->V.BssName);
+ g_segname (SEG_BSS);
+ }
+ g_usebss ();
+ g_defgloblabel (Entry->Name);
+ g_res (SizeOf (Entry->Type));
+ /* Mark as defined; so that it will be exported, not imported */
+ Entry->Flags |= SC_DEF;
}
- Func = Func->NextSym;
}
/* Output the literal pool */