From 8e35a82c91c002f62befbfd29e637d9b1d8b0b0f Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Tue, 21 Mar 2017 22:35:25 +0100 Subject: [PATCH] Fix regression of #pragma bss-name Closes #409 --- cfg/sim6502.cfg | 2 +- cfg/sim65c02.cfg | 2 +- src/cc65/compile.c | 28 +++++++++++++++++++--------- src/cc65/symentry.c | 1 + src/cc65/symentry.h | 2 ++ test/err/bss-name-conflict.c | 20 ++++++++++++++++++++ test/val/bss-name-decl.c | 22 ++++++++++++++++++++++ test/val/bss-name.c | 21 +++++++++++++++++++++ 8 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 test/err/bss-name-conflict.c create mode 100644 test/val/bss-name-decl.c create mode 100644 test/val/bss-name.c diff --git a/cfg/sim6502.cfg b/cfg/sim6502.cfg index b4f7738f5..530787489 100644 --- a/cfg/sim6502.cfg +++ b/cfg/sim6502.cfg @@ -3,7 +3,7 @@ SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { - ZP: file = "", start = $0000, size = $001A; + ZP: file = "", start = $0000, size = $001B; HEADER: file = %O, start = $0000, size = $0001; MAIN: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__; } diff --git a/cfg/sim65c02.cfg b/cfg/sim65c02.cfg index b4f7738f5..530787489 100644 --- a/cfg/sim65c02.cfg +++ b/cfg/sim65c02.cfg @@ -3,7 +3,7 @@ SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { - ZP: file = "", start = $0000, size = $001A; + ZP: file = "", start = $0000, size = $001B; HEADER: file = %O, start = $0000, size = $0001; MAIN: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__; } diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 48a5c29d3..4425b6aad 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -242,16 +242,24 @@ static void Parse (void) Error ("Variable `%s' has unknown size", Decl.Ident); } Entry->Flags &= ~(SC_STORAGE | SC_DEF); + } 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 these will be generated in FinishCompile. + ** For now, just save the BSS segment name + ** (can be set with #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", + Entry->Name, Entry->V.BssName); + } + Entry->V.BssName = xstrdup (bssName); } - - /* 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. - */ } } @@ -418,6 +426,8 @@ void FinishCompile (void) } else if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) { /* Tentative definition of uninitialized global variable */ 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 */ diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index 980ee27f2..d6e68d1bb 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -71,6 +71,7 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags) E->Type = 0; E->Attr = 0; E->AsmName = 0; + E->V.BssName = 0; memcpy (E->Name, Name, Len+1); /* Return the new entry */ diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 4fa84255b..ff136702f 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -153,6 +153,8 @@ struct SymEntry { struct LiteralPool* LitPool; /* Literal pool for this function */ } F; + /* Segment name for tentantive global definitions */ + const char* BssName; } V; char Name[1]; /* Name, dynamically allocated */ }; diff --git a/test/err/bss-name-conflict.c b/test/err/bss-name-conflict.c new file mode 100644 index 000000000..1d6cd5066 --- /dev/null +++ b/test/err/bss-name-conflict.c @@ -0,0 +1,20 @@ +/* + !!DESCRIPTION!! conflicting bss-name pragmas + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Piotr Fusik +*/ + +/* + see: https://github.com/cc65/cc65/issues/409 +*/ + +char oam_off; +#pragma bss-name (push,"ZEROPAGE") +char oam_off; +#pragma bss-name (pop) + +int main(void) +{ + return 0; +} diff --git a/test/val/bss-name-decl.c b/test/val/bss-name-decl.c new file mode 100644 index 000000000..9a535844e --- /dev/null +++ b/test/val/bss-name-decl.c @@ -0,0 +1,22 @@ +/* + !!DESCRIPTION!! bss-name pragma not affecting declarations + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Piotr Fusik +*/ + +/* + see: https://github.com/cc65/cc65/issues/409 +*/ + +#pragma bss-name (push,"ZEROPAGE") + +char n; /* only a declaration because followed by definition */ +char n = 1; /* not BSS */ + +#pragma bss-name (pop) + +int main(void) +{ + return (unsigned) &n >= 0x100 ? 0 : 1; +} diff --git a/test/val/bss-name.c b/test/val/bss-name.c new file mode 100644 index 000000000..f0ad7111e --- /dev/null +++ b/test/val/bss-name.c @@ -0,0 +1,21 @@ +/* + !!DESCRIPTION!! bss-name pragma + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Piotr Fusik +*/ + +/* + see: https://github.com/cc65/cc65/issues/409 +*/ + +#pragma bss-name (push,"ZEROPAGE") + +char zp_var; + +#pragma bss-name (pop) + +int main(void) +{ + return (unsigned) &zp_var < 0x100 ? 0 : 1; +}