From d3ccc289c1a09d290e77935c13ac94972b18ca4c Mon Sep 17 00:00:00 2001 From: Greg King Date: Fri, 16 Jun 2017 21:53:50 -0400 Subject: [PATCH] Stopped cc65 from putting redundant .segment directives into its Assembly output. --- src/cc65/compile.c | 25 +++++++++++++++---------- src/cc65/pragma.c | 20 ++++++++++++++++---- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 3c1042154..d79ef350b 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -243,19 +243,20 @@ static void Parse (void) } Entry->Flags &= ~(SC_STORAGE | SC_DEF); } else { - /* A global (including static) uninitialized variable - ** is only a tentative definition. For example, this is valid: + /* 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 these will be generated in FinishCompile. + ** Code for them will be generated by FinishCompile(). ** For now, just save the BSS segment name - ** (can be set with #pragma bss-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' has already been defined in `%s' segment", + Error ("Global variable `%s' already was defined in the `%s' segment.", Entry->Name, Entry->V.BssName); } Entry->V.BssName = xstrdup (bssName); @@ -419,7 +420,7 @@ void FinishCompile (void) SymEntry* Entry; /* Walk over all global symbols: - ** - for functions do cleanup, optimizations ... + ** - for functions, do clean-up and optimizations ** - generate code for uninitialized global variables */ for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) { @@ -429,13 +430,17 @@ void FinishCompile (void) 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)) { - /* Tentative definition of uninitialized global variable */ + /* 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 (); - SetSegName (SEG_BSS, Entry->V.BssName); - g_segname (SEG_BSS); /* TODO: skip if same as before */ g_defgloblabel (Entry->Name); g_res (SizeOf (Entry->Type)); - /* Mark as defined, so that it will be exported not imported */ + /* Mark as defined; so that it will be exported, not imported */ Entry->Flags |= SC_DEF; } } diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index 3dfc62668..de1979c12 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -386,11 +386,11 @@ static void StringPragma (StrBuf* B, void (*Func) (const char*)) static void SegNamePragma (StrBuf* B, segment_t Seg) /* Handle a pragma that expects a segment name parameter */ { - StrBuf S = AUTO_STRBUF_INITIALIZER; const char* Name; + StrBuf S = AUTO_STRBUF_INITIALIZER; + int Push = 0; /* Check for the "push" or "pop" keywords */ - int Push = 0; switch (ParsePushPop (B)) { case PP_NONE: @@ -403,7 +403,13 @@ static void SegNamePragma (StrBuf* B, segment_t Seg) case PP_POP: /* Pop the old value and output it */ PopSegName (Seg); - g_segname (Seg); + + /* BSS variables are output at the end of the compilation. Don't + ** bother to change their segment, now. + */ + if (Seg != SEG_BSS) { + g_segname (Seg); + } /* Done */ goto ExitPoint; @@ -434,7 +440,13 @@ static void SegNamePragma (StrBuf* B, segment_t Seg) } else { SetSegName (Seg, Name); } - g_segname (Seg); + + /* BSS variables are output at the end of the compilation. Don't + ** bother to change their segment, now. + */ + if (Seg != SEG_BSS) { + g_segname (Seg); + } } else {