better way is to declare characters explicitly as "signed" if needed. You
can also use <tt><ref id="pragma-signed-chars"
name="#pragma signed-chars"></tt> for better control of this option.
-
+
<label id="option--standard">
<tag><tt>--standard std</tt></tag>
Make string literals writable by placing them into the data segment instead
of the rodata segment. You can also use <tt><ref id="pragma-writable-strings"
- name="#pragma writable-strings"></tt> to control this option on a
- per function basis.
+ name="#pragma writable-strings"></tt> to control this option from within
+ the source file.
<label id="option-static-locals">
<sect1><tt>#pragma writable-strings ([push,] on|off)</tt><label id="pragma-writable-strings"><p>
- Changes the storage location of string literals. For historical reasons,
- the C standard defines that string literals are of type "char[]", but
- writing to such a literal causes undefined behaviour. Most compilers
+ Changes the storage location of string literals. For historical reasons,
+ the C standard defines that string literals are of type "char[]", but
+ writing to such a literal causes undefined behaviour. Most compilers
(including cc65) place string literals in the read-only data segment, which
may cause problems with old C code that writes to string literals.
literals to be placed in the data segment so they can be written to without
worry.
- Please note that the value of this flag that is in effect when a function
- is encountered, determines where the literals are stored. Changing the
- <tt/#pragma/ within a function doesn't have an effect for this function.
-
The <tt/#pragma/ understands the push and pop parameters as explained above.
/* cc65 */
#include "asmcode.h"
-#include "codeopt.h"
#include "codeseg.h"
#include "dataseg.h"
#include "segments.h"
SymTab = GetGlobalSymTab ();
Entry = SymTab->SymHead;
while (Entry) {
- if (IsTypeFunc (Entry->Type) &&
- SymIsDef (Entry) &&
- (Entry->Flags & (SC_REF | SC_EXTERN)) != 0) {
- /* Function which is defined and referenced or extern */
- CS_MergeLabels (Entry->V.F.Seg->Code);
- RunOpt (Entry->V.F.Seg->Code);
+ if (SymIsOutputFunc (Entry)) {
+ /* Function which is defined and referenced or extern */
OutputSegments (Entry->V.F.Seg);
}
Entry = Entry->NextSym;
case TOK_SCONST:
/* String constant */
- SB_AppendStr (T, GetLiteral (CurTok.IVal));
- ResetLiteralPoolOffs (CurTok.IVal);
+ SB_Append (T, GetLiteralStrBuf (CurTok.SVal));
NextToken ();
break;
/* Create a string buffer from the string literal */
StrBuf S = AUTO_STRBUF_INITIALIZER;
- GetLiteralStrBuf (&S, CurTok.IVal);
-
- /* Reset the string pointer, effectivly clearing the string from the
- * string table. Since we're working with one token lookahead, this
- * will fail if the next token is also a string token, but that's a
- * syntax error anyway, because we expect a right paren.
- */
- ResetLiteralPoolOffs (CurTok.IVal);
+ SB_Append (&S, GetLiteralStrBuf (CurTok.SVal));
/* Skip the string token */
NextToken ();
#include "check.h"
#include "cpu.h"
#include "strbuf.h"
-#include "version.h"
#include "xmalloc.h"
#include "xsprintf.h"
+#include "version.h"
/* cc65 */
#include "asmcode.h"
+void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs)
+/* Define label as a local alias for baselabel+offs */
+{
+ /* We need an intermediate buffer here since LocalLabelName uses a
+ * static buffer which changes with each call.
+ */
+ StrBuf L = AUTO_STRBUF_INITIALIZER;
+ SB_AppendStr (&L, LocalLabelName (label));
+ SB_Terminate (&L);
+ AddDataLine ("%s\t:=\t%s+%ld",
+ SB_GetConstBuf (&L),
+ LocalLabelName (baselabel),
+ offs);
+ SB_Done (&L);
+}
+
+
+
/*****************************************************************************/
/* Functions handling global labels */
/*****************************************************************************/
void g_defdatalabel (unsigned label);
/* Define a local data label */
+void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs);
+/* Define label as a local alias for baselabel+offs */
+
/*****************************************************************************/
#include "asmlabel.h"
#include "asmstmt.h"
#include "codegen.h"
+#include "codeopt.h"
#include "compile.h"
#include "declare.h"
#include "error.h"
/* Close the output file */
CloseOutputFile ();
- if (Debug) {
- PrintMacroStats (stdout);
- }
-
} else {
/* Ok, start the ball rolling... */
Parse ();
- /* Dump the literal pool. */
- DumpLiteralPool ();
+ }
- /* Write imported/exported symbols */
- EmitExternals ();
+ if (Debug) {
+ PrintMacroStats (stdout);
+ }
+
+ /* Print an error report */
+ ErrorReport ();
+}
- if (Debug) {
- PrintLiteralPoolStats (stdout);
- PrintMacroStats (stdout);
- }
+
+void FinishCompile (void)
+/* Emit literals, externals, 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)) {
+ /* 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);
+ }
+ Func = Func->NextSym;
}
+ /* Dump the literal pool */
+ DumpLiteralPool ();
+
+ /* Write imported/exported symbols */
+ EmitExternals ();
+
/* Leave the main lexical level */
LeaveGlobalLevel ();
-
- /* Print an error report */
- ErrorReport ();
}
-
/* */
/* */
/* */
-/* (C) 2000-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2009, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
void Compile (const char* FileName);
/* Top level compile routine. Will setup things and call the parser. */
+void FinishCompile (void);
+/* Emit literals, externals, do cleanup and optimizations */
+
/* End of compile.h */
/* Char array initialized by string constant */
int NeedParen;
- const char* Str;
/* If we initializer is enclosed in brackets, remember this fact and
* skip the opening bracket.
NextToken ();
}
- /* Get the initializer string and its size */
- Str = GetLiteral (CurTok.IVal);
- Count = GetLiteralPoolOffs () - CurTok.IVal;
-
/* Translate into target charset */
- TranslateLiteralPool (CurTok.IVal);
+ TranslateLiteral (CurTok.SVal);
/* If the array is one too small for the string literal, omit the
* trailing zero.
*/
+ Count = GetLiteralSize (CurTok.SVal);
if (ElementCount != UNSPECIFIED &&
ElementCount != FLEXIBLE &&
Count == ElementCount + 1) {
}
/* Output the data */
- g_defbytes (Str, Count);
+ g_defbytes (GetLiteralStr (CurTok.SVal), Count);
- /* Remove string from pool */
- ResetLiteralPoolOffs (CurTok.IVal);
+ /* Skip the string */
NextToken ();
/* If the initializer was enclosed in curly braces, we need a closing
/* This is the lowest level of the expression parser. */
{
SymEntry* Sym;
+ Literal* L;
/* Initialize fields in the expression stucture */
ED_Init (E);
case TOK_SCONST:
case TOK_WCSCONST:
/* String literal */
- E->Type = GetCharArrayType (GetLiteralPoolOffs () - CurTok.IVal);
+ L = UseLiteral (CurTok.SVal);
+ E->Type = GetCharArrayType (GetLiteralSize (CurTok.SVal));
E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL;
- E->IVal = CurTok.IVal;
- E->Name = GetLiteralPoolLabel ();
+ E->IVal = 0;
+ E->Name = GetLiteralLabel (CurTok.SVal);
NextToken ();
break;
}
-
+
/*****************************************************************************/
/* code */
/*****************************************************************************/
/* Eat the closing brace */
ConsumeRCurly ();
- /* Dump the literal pool, the restore the old one */
- DumpLiteralPool ();
- PopLiteralPool ();
+ /* Restore the old literal pool, remembering the one for the function */
+ Func->V.F.LitPool = PopLiteralPool ();
/* Switch back to the old segments */
PopSegments ();
/*****************************************************************************/
/* */
-/* litpool.c */
+/* litpool.c */
/* */
/* Literal string handling for the cc65 C compiler */
/* */
#include <stdio.h>
+#include <string.h>
/* common */
+#include "attrib.h"
#include "check.h"
#include "coll.h"
#include "tgttrans.h"
-/* Forward for struct SymEntry */
-struct SymEntry;
+/* Definition of a literal */
+struct Literal {
+ unsigned Label; /* Asm label for this literal */
+ int RefCount; /* Reference count */
+ StrBuf Data; /* Literal data */
+};
/* Definition of the literal pool */
-typedef struct LiteralPool LiteralPool;
struct LiteralPool {
- int Writable; /* True if strings are writable */
- unsigned Label; /* Pool asm label */
- struct SymEntry* Func; /* Function that contains the pool */
- StrBuf Pool; /* The pool itself */
+ struct SymEntry* Func; /* Function that owns the pool */
+ Collection WritableLiterals; /* Writable literals in the pool */
+ Collection ReadOnlyLiterals; /* Readonly literals in the pool */
};
-/* The current literal pool */
-static LiteralPool* LP = 0;
+/* The global and current literal pool */
+static LiteralPool* GlobalPool = 0;
+static LiteralPool* LP = 0;
/* Stack that contains the nested literal pools. Since TOS is in LiteralPool
* and functions aren't nested in C, the maximum depth is 1. I'm using a
+/*****************************************************************************/
+/* struct Literal */
+/*****************************************************************************/
+
+
+
+static Literal* NewLiteral (const void* Buf, unsigned Len)
+/* Create a new literal and return it */
+{
+ /* Allocate memory */
+ Literal* L = xmalloc (sizeof (*L));
+
+ /* Initialize the fields */
+ L->Label = GetLocalLabel ();
+ L->RefCount = 0;
+ SB_Init (&L->Data);
+ SB_AppendBuf (&L->Data, Buf, Len);
+
+ /* Return the new literal */
+ return L;
+}
+
+
+
+static void FreeLiteral (Literal* L)
+/* Free a literal */
+{
+ /* Free the literal data */
+ SB_Done (&L->Data);
+
+ /* Free the structure itself */
+ xfree (L);
+}
+
+
+
+Literal* UseLiteral (Literal* L)
+/* Increase the reference counter for the literal and return it */
+{
+ ++L->RefCount;
+ return L;
+}
+
+
+
+void ReleaseLiteral (Literal* L)
+/* Decrement the reference counter for the literal */
+{
+ CHECK (--L->RefCount >= 0);
+}
+
+
+
+void TranslateLiteral (Literal* L)
+/* Translate a literal into the target charset. */
+{
+ TgtTranslateBuf (SB_GetBuf (&L->Data), SB_GetLen (&L->Data));
+}
+
+
+
+unsigned GetLiteralLabel (const Literal* L)
+/* Return the asm label for a literal */
+{
+ return L->Label;
+}
+
+
+
+const char* GetLiteralStr (const Literal* L)
+/* Return the data for a literal as pointer to char */
+{
+ return SB_GetConstBuf (&L->Data);
+}
+
+
+
+const StrBuf* GetLiteralStrBuf (const Literal* L)
+/* Return the data for a literal as pointer to the string buffer */
+{
+ return &L->Data;
+}
+
+
+
+unsigned GetLiteralSize (const Literal* L)
+/* Get the size of a literal string */
+{
+ return SB_GetLen (&L->Data);
+}
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
LiteralPool* LP = xmalloc (sizeof (*LP));
/* Initialize the fields */
- LP->Writable = IS_Get (&WritableStrings);
- LP->Label = GetLocalLabel ();
LP->Func = Func;
- SB_Init (&LP->Pool);
+ InitCollection (&LP->WritableLiterals);
+ InitCollection (&LP->ReadOnlyLiterals);
/* Return the new pool */
return LP;
static void FreeLiteralPool (LiteralPool* LP)
/* Free a LiteralPool structure */
{
- /* Free the string buffer contained within the struct */
- SB_Done (&LP->Pool);
+ /* Free the collections contained within the struct */
+ DoneCollection (&LP->WritableLiterals);
+ DoneCollection (&LP->ReadOnlyLiterals);
/* Free the struct itself */
xfree (LP);
+static int Compare (void* Data attribute ((unused)),
+ const void* Left, const void* Right)
+/* Compare function used when sorting the literal pool */
+{
+ /* Larger strings are considered "smaller" */
+ return (int) GetLiteralSize (Right) - (int) GetLiteralSize (Left);
+}
+
+
+
void InitLiteralPool (void)
/* Initialize the literal pool */
{
- /* Create a new pool */
- LP = NewLiteralPool (0);
+ /* Create the global literal pool */
+ GlobalPool = LP = NewLiteralPool (0);
}
-void PopLiteralPool (void)
-/* Free the current literal pool and restore the one from TOS */
+LiteralPool* PopLiteralPool (void)
+/* Pop the last literal pool from TOS and activate it. Return the old
+ * literal pool.
+ */
{
- /* Free the current literal pool */
- FreeLiteralPool (LP);
+ /* Remember the current literal pool */
+ LiteralPool* Old = LP;
/* Pop one from stack */
LP = CollPop (&LPStack);
+
+ /* Return the old one */
+ return Old;
}
-void TranslateLiteralPool (unsigned Offs)
-/* Translate the literals starting from the given offset into the target
- * charset.
+static void MoveLiterals (Collection* Source, Collection* Target)
+/* Move referenced literals from Source to Target, delete unreferenced ones */
+{
+ unsigned I;
+
+ /* Move referenced literals, remove unreferenced ones */
+ for (I = 0; I < CollCount (Source); ++I) {
+
+ /* Get the literal */
+ Literal* L = CollAt (Source, I);
+
+ /* If it is referenced, add it to the Target pool, otherwise free it */
+ if (L->RefCount) {
+ CollAppend (Target, L);
+ } else {
+ FreeLiteral (L);
+ }
+ }
+}
+
+
+
+void MoveLiteralPool (LiteralPool* LocalPool)
+/* Move all referenced literals in LocalPool to the global literal pool. This
+ * function will free LocalPool after moving the used string literals.
*/
{
- TgtTranslateBuf (SB_GetBuf (&LP->Pool) + Offs, SB_GetLen (&LP->Pool) - Offs);
+ /* Move the literals */
+ MoveLiterals (&LocalPool->WritableLiterals, &GlobalPool->WritableLiterals);
+ MoveLiterals (&LocalPool->ReadOnlyLiterals, &GlobalPool->ReadOnlyLiterals);
+
+ /* Free the local literal pool */
+ FreeLiteralPool (LocalPool);
}
-void DumpLiteralPool (void)
-/* Dump the literal pool */
+static void DumpWritableLiterals (Collection* Literals)
+/* Dump the given writable literals */
{
+ unsigned I;
+
/* If nothing there, exit... */
- if (SB_GetLen (&LP->Pool) == 0) {
- return;
+ if (CollCount (Literals) == 0) {
+ return;
}
/* Switch to the correct segment */
- if (LP->Writable) {
- g_usedata ();
- } else {
- g_userodata ();
- }
+ g_usedata ();
- /* Define the label */
- g_defdatalabel (LP->Label);
+ /* Emit all literals that have a reference */
+ for (I = 0; I < CollCount (Literals); ++I) {
- /* Translate the buffer contents into the target charset */
- TranslateLiteralPool (0);
+ /* Get the next literal */
+ Literal* L = CollAt (Literals, I);
- /* Output the buffer data */
- g_defbytes (SB_GetConstBuf (&LP->Pool), SB_GetLen (&LP->Pool));
-}
+ /* Ignore it, if it doesn't have references */
+ if (L->RefCount == 0) {
+ continue;
+ }
+ /* Translate the literal into the target charset */
+ TranslateLiteral (L);
+ /* Define the label for the literal */
+ g_defdatalabel (L->Label);
-unsigned GetLiteralPoolLabel (void)
-/* Return the asm label for the current literal pool */
-{
- return LP->Label;
+ /* Output the literal data */
+ g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
+
+ }
}
-unsigned GetLiteralPoolOffs (void)
-/* Return the current offset into the literal pool */
+static void DumpReadOnlyLiterals (Collection* Literals)
+/* Dump the given readonly literals merging (even partial) duplicates */
{
- return SB_GetLen (&LP->Pool);
-}
+ unsigned I;
+ /* If nothing there, exit... */
+ if (CollCount (Literals) == 0) {
+ return;
+ }
+ /* Switch to the correct segment */
+ g_userodata ();
-void ResetLiteralPoolOffs (unsigned Offs)
-/* Reset the offset into the literal pool to some earlier value, effectively
- * removing values from the pool.
- */
-{
- CHECK (Offs <= SB_GetLen (&LP->Pool));
- SB_Cut (&LP->Pool, Offs);
-}
+ /* Sort the literal pool by literal size. Larger strings go first */
+ CollSort (Literals, Compare, 0);
+ /* Emit all literals that have a reference */
+ for (I = 0; I < CollCount (Literals); ++I) {
+ unsigned J;
+ Literal* C;
-unsigned AddLiteral (const char* S)
-/* Add a literal string to the literal pool. Return the starting offset into
- * the pool
- */
-{
- return AddLiteralBuf (S, strlen (S) + 1);
-}
+ /* Get the next literal */
+ Literal* L = CollAt (Literals, I);
+ /* Ignore it, if it doesn't have references */
+ if (L->RefCount == 0) {
+ continue;
+ }
+ /* Translate the literal into the target charset */
+ TranslateLiteral (L);
-unsigned AddLiteralBuf (const void* Buf, unsigned Len)
-/* Add a buffer containing a literal string to the literal pool. Return the
- * starting offset into the pool for this string.
- */
-{
- /* Remember the starting offset */
- unsigned Start = SB_GetLen (&LP->Pool);
+ /* Check if this literal is part of another one. Since the literals
+ * are sorted by size (larger ones first), it can only be part of a
+ * literal with a smaller index.
+ * Beware: Only check literals that have actually been referenced.
+ */
+ C = 0;
+ for (J = 0; J < I; ++J) {
+
+ const void* D;
+
+ /* Get a pointer to the compare literal */
+ Literal* L2 = CollAt (Literals, J);
+
+ /* Ignore literals that have no reference */
+ if (L2->RefCount == 0) {
+ continue;
+ }
+
+ /* Get a pointer to the data */
+ D = SB_GetConstBuf (&L2->Data) + SB_GetLen (&L2->Data) - SB_GetLen (&L->Data);
+
+ /* Compare the data */
+ if (memcmp (D, SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data)) == 0) {
+ /* Remember the literal and terminate the loop */
+ C = L2;
+ break;
+ }
+ }
+
+ /* Check if we found a match */
+ if (C != 0) {
+
+ /* This literal is part of a longer literal, merge them */
+ g_aliasdatalabel (L->Label, C->Label, GetLiteralSize (C) - GetLiteralSize (L));
- /* Append the buffer */
- SB_AppendBuf (&LP->Pool, Buf, Len);
- /* Return the starting offset */
- return Start;
+ } else {
+
+ /* Define the label for the literal */
+ g_defdatalabel (L->Label);
+
+ /* Output the literal data */
+ g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data));
+
+ }
+ }
}
-unsigned AddLiteralStr (const StrBuf* S)
-/* Add a literal string to the literal pool. Return the starting offset into
- * the pool for this string.
- */
+void DumpLiteralPool (void)
+/* Dump the global literal pool */
{
- return AddLiteralBuf (SB_GetConstBuf (S), SB_GetLen (S));
+ /* Dump both sorts of literals */
+ DumpWritableLiterals (&GlobalPool->WritableLiterals);
+ DumpReadOnlyLiterals (&GlobalPool->ReadOnlyLiterals);
}
-const char* GetLiteral (unsigned Offs)
-/* Get a pointer to the literal with the given offset in the pool */
+Literal* AddLiteral (const char* S)
+/* Add a literal string to the literal pool. Return the literal. */
{
- CHECK (Offs < SB_GetLen (&LP->Pool));
- return SB_GetConstBuf (&LP->Pool) + Offs;
+ return AddLiteralBuf (S, strlen (S) + 1);
}
-void GetLiteralStrBuf (StrBuf* Target, unsigned Offs)
-/* Copy the string starting at Offs and lasting to the end of the buffer
- * into Target.
+Literal* AddLiteralBuf (const void* Buf, unsigned Len)
+/* Add a buffer containing a literal string to the literal pool. Return the
+ * literal.
*/
{
- CHECK (Offs <= SB_GetLen (&LP->Pool));
- SB_Slice (Target, &LP->Pool, Offs, SB_GetLen (&LP->Pool) - Offs);
+ /* Create a new literal */
+ Literal* L = NewLiteral (Buf, Len);
+
+ /* Add the literal to the correct pool */
+ if (IS_Get (&WritableStrings)) {
+ CollAppend (&LP->WritableLiterals, L);
+ } else {
+ CollAppend (&LP->ReadOnlyLiterals, L);
+ }
+
+ /* Return the new literal */
+ return L;
}
-void PrintLiteralPoolStats (FILE* F)
-/* Print statistics about the literal space used */
+Literal* AddLiteralStr (const StrBuf* S)
+/* Add a literal string to the literal pool. Return the literal. */
{
- fprintf (F, "Literal space used: %u bytes\n", SB_GetLen (&LP->Pool));
+ return AddLiteralBuf (SB_GetConstBuf (S), SB_GetLen (S));
}
/* Forward for struct SymEntry */
struct SymEntry;
+/* Forward for a literal */
+typedef struct Literal Literal;
+
+/* Forward for a literal pool */
+typedef struct LiteralPool LiteralPool;
+
/*****************************************************************************/
-/* Code */
+/* struct Literal */
/*****************************************************************************/
-void InitLiteralPool (void);
-/* Initialize the literal pool */
+Literal* UseLiteral (Literal* L);
+/* Increase the reference counter for the literal and return it */
-void PushLiteralPool (struct SymEntry* Func);
-/* Push the current literal pool onto the stack and create a new one */
+void ReleaseLiteral (Literal* L);
+/* Decrement the reference counter for the literal */
-void PopLiteralPool (void);
-/* Free the current literal pool and restore the one from TOS */
+void TranslateLiteral (Literal* L);
+/* Translate a literal into the target charset. */
-void TranslateLiteralPool (unsigned Offs);
-/* Translate the literals starting from the given offset into the target
- * charset.
- */
+unsigned GetLiteralLabel (const Literal* L);
+/* Return the asm label for a literal */
-void DumpLiteralPool (void);
-/* Dump the literal pool */
+const char* GetLiteralStr (const Literal* L);
+/* Return the data for a literal as pointer to char */
-unsigned GetLiteralPoolLabel (void);
-/* Return the asm label for the current literal pool */
+const StrBuf* GetLiteralStrBuf (const Literal* L);
+/* Return the data for a literal as pointer to the string buffer */
-unsigned GetLiteralPoolOffs (void);
-/* Return the current offset into the literal pool */
+unsigned GetLiteralSize (const Literal* L);
+/* Get the size of a literal string */
-void ResetLiteralPoolOffs (unsigned Offs);
-/* Reset the offset into the literal pool to some earlier value, effectively
- * removing values from the pool.
- */
-unsigned AddLiteral (const char* S);
-/* Add a literal string to the literal pool. Return the starting offset into
- * the pool for this string.
- */
-unsigned AddLiteralBuf (const void* Buf, unsigned Len);
-/* Add a buffer containing a literal string to the literal pool. Return the
- * starting offset into the pool for this string.
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void InitLiteralPool (void);
+/* Initialize the literal pool */
+
+void PushLiteralPool (struct SymEntry* Func);
+/* Push the current literal pool onto the stack and create a new one */
+
+LiteralPool* PopLiteralPool (void);
+/* Pop the last literal pool from TOS and activate it. Return the old
+ * literal pool.
*/
-unsigned AddLiteralStr (const StrBuf* S);
-/* Add a literal string to the literal pool. Return the starting offset into
- * the pool for this string.
+void MoveLiteralPool (LiteralPool* LocalPool);
+/* Move all referenced literals in LocalPool to the global literal pool. This
+ * function will free LocalPool after moving the used string literals.
*/
-const char* GetLiteral (unsigned Offs);
-/* Get a pointer to the literal with the given offset in the pool */
+void DumpLiteralPool (void);
+/* Dump the literal pool */
+
+Literal* AddLiteral (const char* S);
+/* Add a literal string to the literal pool. Return the literal. */
-void GetLiteralStrBuf (StrBuf* Target, unsigned Offs);
-/* Copy the string starting at Offs and lasting to the end of the buffer
- * into Target.
+Literal* AddLiteralBuf (const void* Buf, unsigned Len);
+/* Add a buffer containing a literal string to the literal pool. Return the
+ * literal.
*/
-void PrintLiteralPoolStats (FILE* F);
-/* Print statistics about the literal space used */
+Literal* AddLiteralStr (const StrBuf* S);
+/* Add a literal string to the literal pool. Return the literal. */
/* Create the output file if we didn't had any errors */
if (PreprocessOnly == 0 && (ErrorCount == 0 || Debug)) {
- /* Open the file */
+ /* Emit literals, externals, do cleanup and optimizations */
+ FinishCompile ();
+
+ /* Open the file */
OpenOutputFile ();
- /* Write the output to the file */
+ /* Write the output to the file */
WriteAsmOutput ();
Print (stdout, 1, "Wrote output to `%s'\n", OutputFilename);
/* Create a string buffer from the string literal */
StrBuf B = AUTO_STRBUF_INITIALIZER;
- GetLiteralStrBuf (&B, CurTok.IVal);
-
- /* Reset the string pointer, effectivly clearing the string from the
- * string table. Since we're working with one token lookahead, this
- * will fail if the next token is also a string token, but that's a
- * syntax error anyway, because we expect a right paren.
- */
- ResetLiteralPoolOffs (CurTok.IVal);
+ SB_Append (&B, GetLiteralStrBuf (CurTok.SVal));
/* Skip the string token */
NextToken ();
SB_AppendChar (&S, '\0');
/* Add the whole string to the literal pool */
- NextTok.IVal = AddLiteralStr (&S);
+ NextTok.SVal = AddLiteralStr (&S);
/* Free the buffer */
SB_Done (&S);
if (token[0] == '_' && token[1] == '_') {
/* Special symbols */
if (strcmp (token+2, "FILE__") == 0) {
- NextTok.IVal = AddLiteral (GetCurrentFile());
+ NextTok.SVal = AddLiteral (GetCurrentFile());
NextTok.Tok = TOK_SCONST;
return;
} else if (strcmp (token+2, "LINE__") == 0) {
} else if (strcmp (token+2, "func__") == 0) {
/* __func__ is only defined in functions */
if (CurrentFunc) {
- NextTok.IVal = AddLiteral (F_GetFuncName (CurrentFunc));
+ NextTok.SVal = AddLiteral (F_GetFuncName (CurrentFunc));
NextTok.Tok = TOK_SCONST;
return;
}
/*****************************************************************************/
-/* data */
+/* Data */
/*****************************************************************************/
-/* Token stuff */
+/* Forward for struct Literal */
+struct Literal;
+
+/* Token stuff */
typedef struct Token Token;
struct Token {
- token_t Tok; /* The token itself */
- long IVal; /* The integer attribute */
- Double FVal; /* The float attribute */
- ident Ident; /* Identifier if IDENT */
- LineInfo* LI; /* Source line where the token comes from */
- Type* Type; /* Type if integer or float constant */
+ token_t Tok; /* The token itself */
+ long IVal; /* The integer attribute */
+ Double FVal; /* The float attribute */
+ struct Literal* SVal; /* String literal is any */
+ ident Ident; /* Identifier if IDENT */
+ LineInfo* LI; /* Source line where the token comes from */
+ Type* Type; /* Type if integer or float constant */
};
extern Token CurTok; /* The current token */
/*****************************************************************************/
-/* code */
+/* Code */
/*****************************************************************************/
/* Do type conversion */
TypeConversion (&Arg, ArgType);
-
+
+#if 0
/* If the expression is a literal, and if string literals are read
* only, we can calculate the length of the string and remove it
* from the literal pool. Otherwise we have to calculate the length
if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
/* Constant string literal */
- ED_MakeConstAbs (Expr, strlen (GetLiteral (Arg.IVal)), type_size_t);
- ResetLiteralPoolOffs (Arg.IVal);
+ ED_MakeConstAbs (Expr, GetLiteralSize (GetLiteral (Arg.IVal)), type_size_t);
/* We will inline strlen for arrays with constant addresses, if either the
* inlining was forced on the command line, or the array is smaller than
* 256, so the inlining is considered safe.
*/
- } else if (ED_IsLocConst (&Arg) && IsArray &&
+ } else
+#endif
+ if (ED_IsLocConst (&Arg) && IsArray &&
(IS_Get (&InlineStdFuncs) || IsByteIndex)) {
/* Generate the strlen code */
+int SymIsOutputFunc (const SymEntry* Sym)
+/* Return true if this is a function that must be output */
+{
+ /* Symbol must be a function which is defined and either extern or
+ * static and referenced.
+ */
+ return IsTypeFunc (Sym->Type) &&
+ SymIsDef (Sym) &&
+ (Sym->Flags & (SC_REF | SC_EXTERN));
+}
+
+
+
const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType)
/* Return an attribute for this symbol or NULL if the attribute does not exist */
{
struct Segments;
+struct LiteralPool;
struct {
struct FuncDesc* Func; /* Function descriptor */
struct Segments* Seg; /* Segments for this function */
+ struct LiteralPool* LitPool; /* Literal pool for this function */
} F;
} V;
# define SymIsRegVar(Sym) (((Sym)->Flags & (SC_REGISTER|SC_TYPE)) == SC_REGISTER)
#endif
+int SymIsOutputFunc (const SymEntry* Sym);
+/* Return true if this is a function that must be output */
+
#if defined(HAVE_INLINE)
INLINE const char* SymGetAsmName (const SymEntry* Sym)
/* Return the assembler label name for the symbol (beware: may be NULL!) */
INLINE int SymHasAttr (const SymEntry* Sym, DeclAttrType A)
/* Return true if the symbol has the given attribute */
{
- return (SymGetAttr (Sym, A) != 0);
+ return (SymGetAttr (Sym, A) != 0);
}
#else
# define SymHasAttr(Sym, A) (SymGetAttr (Sym, A) != 0)