1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

New option and #pragma --local-strings that causes string literals to be

output immediately.


git-svn-id: svn://svn.cc65.org/cc65/trunk@4504 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2009-12-08 20:35:24 +00:00
parent 2bca737f57
commit 7d94dc50a1
8 changed files with 113 additions and 35 deletions

View File

@ -84,6 +84,7 @@ Long options:
--forget-inc-paths Forget include search paths
--help Help (this text)
--include-dir dir Set an include directory search path
--local-strings Emit string literals immediately
--register-space b Set space available for register variables
--register-vars Enable register variables
--rodata-name seg Set the name of the RODATA segment
@ -192,6 +193,20 @@ Here is a description of all the command line options:
Print the short option summary shown above.
<label id="option-local-strings">
<tag><tt>--local-strings</tt></tag>
Emit string literals to the data segment when they're encountered in the
source. The default is to keep string literals until end of assembly, merge
read only literals if possible, and then output the literals into the data
or rodata segment that is active at that point. Use of this option prevents
merging of duplicate strings, but the options that change the name of one of
the data segments will work.
You can also use <tt><ref id="pragma-local-strings"
name="#pragma&nbsp;local-strings"></tt> for fine grained control.
<tag><tt>-o name</tt></tag>
Specify the name of the output file. If you don't specify a name, the
@ -868,6 +883,20 @@ parameter with the <tt/#pragma/.
</verb></tscreen>
<sect1><tt>#pragma local-strings ([push,] on|off)</tt><label id="pragma-local-strings"><p>
When "on", emit string literals to the data segment when they're encountered
in the source. The default ("off") is to keep string literals until end of
assembly, merge read only literals if possible, and then output the literals
into the data or rodata segment that is active at that point.
Using this <tt/#pragma/ it is possible to control the behaviour from within
the source. When <tt/#pragma local-strings/ is active, string literals are
output immediately, which means that they go into the currently active data
or rodata segment, but cannot be merged. When inactive, string literals are
remembered and output as a whole when translation is finished.
<sect1><tt>#pragma optimize ([push,] on|off)</tt><label id="pragma-optimize"><p>
Switch optimization on or off. If the argument is "off", optimization is

View File

@ -410,8 +410,8 @@ void FinishCompile (void)
Func = Func->NextSym;
}
/* Dump the literal pool */
DumpLiteralPool ();
/* Output the literal pool */
OutputLiteralPool ();
/* Write imported/exported symbols */
EmitExternals ();

View File

@ -51,6 +51,7 @@ unsigned RegisterSpace = 6; /* Space available for register vars */
/* Stackable options */
IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */
IntStack LocalStrings = INTSTACK(0); /* Emit string literals immediately */
IntStack InlineStdFuncs = INTSTACK(0); /* Inline some known functions */
IntStack EnableRegVars = INTSTACK(0); /* Enable register variables */
IntStack AllowRegVarAddr = INTSTACK(0); /* Allow taking addresses of register vars */
@ -62,4 +63,3 @@ IntStack Optimize = INTSTACK(0); /* Optimize flag */
IntStack CodeSizeFactor = INTSTACK(100);/* Size factor for generated code */

View File

@ -58,6 +58,7 @@ extern unsigned RegisterSpace; /* Space available for register
/* Stackable options */
extern IntStack WritableStrings; /* Literal strings are r/w */
extern IntStack LocalStrings; /* Emit string literals immediately */
extern IntStack InlineStdFuncs; /* Inline some known functions */
extern IntStack EnableRegVars; /* Enable register variables */
extern IntStack AllowRegVarAddr; /* Allow taking addresses of register vars */

View File

@ -62,6 +62,7 @@
struct Literal {
unsigned Label; /* Asm label for this literal */
int RefCount; /* Reference count */
int Output; /* True if output has been generated */
StrBuf Data; /* Literal data */
};
@ -100,6 +101,7 @@ static Literal* NewLiteral (const void* Buf, unsigned Len)
/* Initialize the fields */
L->Label = GetLocalLabel ();
L->RefCount = 0;
L->Output = 0;
SB_Init (&L->Data);
SB_AppendBuf (&L->Data, Buf, Len);
@ -121,10 +123,43 @@ static void FreeLiteral (Literal* L)
static void OutputLiteral (Literal* L)
/* Output one literal to the currently active data segment */
{
/* Translate the literal into the target charset */
TranslateLiteral (L);
/* Define the label for the literal */
g_defdatalabel (L->Label);
/* Output the literal data */
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
/* Mark the literal as output */
L->Output = 1;
}
Literal* UseLiteral (Literal* L)
/* Increase the reference counter for the literal and return it */
{
/* Increase the reference count */
++L->RefCount;
/* If --local-strings was given, immediately output the literal */
if (IS_Get (&LocalStrings)) {
/* Switch to the proper data segment */
if (IS_Get (&WritableStrings)) {
g_usedata ();
} else {
g_userodata ();
}
/* Output the literal */
OutputLiteral (L);
}
/* Return the literal */
return L;
}
@ -133,7 +168,8 @@ Literal* UseLiteral (Literal* L)
void ReleaseLiteral (Literal* L)
/* Decrement the reference counter for the literal */
{
CHECK (--L->RefCount >= 0);
--L->RefCount;
CHECK (L->RefCount >= 0 && (L->RefCount > 0 || !L->Output));
}
@ -276,8 +312,10 @@ static void MoveLiterals (Collection* Source, Collection* Target)
/* Get the literal */
Literal* L = CollAt (Source, I);
/* If it is referenced, add it to the Target pool, otherwise free it */
if (L->RefCount) {
/* If it is referenced and not output, add it to the Target pool,
* otherwise free it
*/
if (L->RefCount && !L->Output) {
CollAppend (Target, L);
} else {
FreeLiteral (L);
@ -302,8 +340,8 @@ void MoveLiteralPool (LiteralPool* LocalPool)
static void DumpWritableLiterals (Collection* Literals)
/* Dump the given writable literals */
static void OutputWritableLiterals (Collection* Literals)
/* Output the given writable literals */
{
unsigned I;
@ -318,30 +356,21 @@ static void DumpWritableLiterals (Collection* Literals)
/* Emit all literals that have a reference */
for (I = 0; I < CollCount (Literals); ++I) {
/* Get the next literal */
Literal* L = CollAt (Literals, I);
/* Get a pointer to the literal */
Literal* L = CollAtUnchecked (Literals, I);
/* Ignore it, if it doesn't have references */
if (L->RefCount == 0) {
continue;
/* Output this one, if it has references and wasn't already output */
if (L->RefCount > 0 && !L->Output) {
OutputLiteral (L);
}
/* Translate the literal into the target charset */
TranslateLiteral (L);
/* Define the label for the literal */
g_defdatalabel (L->Label);
/* Output the literal data */
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
}
}
static void DumpReadOnlyLiterals (Collection* Literals)
/* Dump the given readonly literals merging (even partial) duplicates */
static void OutputReadOnlyLiterals (Collection* Literals)
/* Output the given readonly literals merging (even partial) duplicates */
{
unsigned I;
@ -365,8 +394,8 @@ static void DumpReadOnlyLiterals (Collection* Literals)
/* Get the next literal */
Literal* L = CollAt (Literals, I);
/* Ignore it, if it doesn't have references */
if (L->RefCount == 0) {
/* Ignore it, if it doesn't have references or was already output */
if (L->RefCount == 0 || L->Output) {
continue;
}
@ -408,7 +437,6 @@ static void DumpReadOnlyLiterals (Collection* Literals)
/* This literal is part of a longer literal, merge them */
g_aliasdatalabel (L->Label, C->Label, GetLiteralSize (C) - GetLiteralSize (L));
} else {
/* Define the label for the literal */
@ -418,17 +446,20 @@ static void DumpReadOnlyLiterals (Collection* Literals)
g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
}
/* Mark the literal */
L->Output = 1;
}
}
void DumpLiteralPool (void)
/* Dump the global literal pool */
void OutputLiteralPool (void)
/* Output the global literal pool */
{
/* Dump both sorts of literals */
DumpWritableLiterals (&GlobalPool->WritableLiterals);
DumpReadOnlyLiterals (&GlobalPool->ReadOnlyLiterals);
/* Output both sorts of literals */
OutputWritableLiterals (&GlobalPool->WritableLiterals);
OutputReadOnlyLiterals (&GlobalPool->ReadOnlyLiterals);
}

View File

@ -113,8 +113,8 @@ void MoveLiteralPool (LiteralPool* LocalPool);
* function will free LocalPool after moving the used string literals.
*/
void DumpLiteralPool (void);
/* Dump the literal pool */
void OutputLiteralPool (void);
/* Output the literal pool */
Literal* AddLiteral (const char* S);
/* Add a literal string to the literal pool. Return the literal. */

View File

@ -121,7 +121,8 @@ static void Usage (void)
" --help\t\tHelp (this text)\n"
" --include-dir dir\tSet an include directory search path\n"
" --list-opt-steps\tList all optimizer steps and exit\n"
" --memory-model model\tSet the memory model\n"
" --local-strings\tEmit string literals immediately\n"
" --memory-model model\tSet the memory model\n"
" --register-space b\tSet space available for register variables\n"
" --register-vars\tEnable register variables\n"
" --rodata-name seg\tSet the name of the RODATA segment\n"
@ -556,6 +557,15 @@ static void OptListOptSteps (const char* Opt attribute ((unused)),
static void OptLocalStrings (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Emit string literals immediately */
{
IS_Set (&LocalStrings, 1);
}
static void OptMemoryModel (const char* Opt, const char* Arg)
/* Set the memory model */
{
@ -751,6 +761,7 @@ int main (int argc, char* argv[])
{ "--help", 0, OptHelp },
{ "--include-dir", 1, OptIncludeDir },
{ "--list-opt-steps", 0, OptListOptSteps },
{ "--local-strings", 0, OptLocalStrings },
{ "--memory-model", 1, OptMemoryModel },
{ "--register-space", 1, OptRegisterSpace },
{ "--register-vars", 0, OptRegisterVars },

View File

@ -73,6 +73,7 @@ typedef enum {
PRAGMA_CODESIZE,
PRAGMA_DATA_NAME,
PRAGMA_DATASEG, /* obsolete */
PRAGMA_LOCAL_STRINGS,
PRAGMA_OPTIMIZE,
PRAGMA_REGVARADDR,
PRAGMA_REGISTER_VARS,
@ -104,6 +105,7 @@ static const struct Pragma {
{ "codesize", PRAGMA_CODESIZE },
{ "data-name", PRAGMA_DATA_NAME },
{ "dataseg", PRAGMA_DATASEG }, /* obsolete */
{ "local-strings", PRAGMA_LOCAL_STRINGS },
{ "optimize", PRAGMA_OPTIMIZE },
{ "register-vars", PRAGMA_REGISTER_VARS },
{ "regvaraddr", PRAGMA_REGVARADDR },
@ -727,6 +729,10 @@ static void ParsePragma (void)
SegNamePragma (&B, SEG_DATA);
break;
case PRAGMA_LOCAL_STRINGS:
FlagPragma (&B, &LocalStrings);
break;
case PRAGMA_OPTIMIZE:
FlagPragma (&B, &Optimize);
break;