]> git.sur5r.net Git - cc65/commitdiff
Rewrote literal handling. Literals are now saved together with other function
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 5 Dec 2009 22:39:45 +0000 (22:39 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 5 Dec 2009 22:39:45 +0000 (22:39 +0000)
data, and at the end of compilation merged if possible. Literals for unused
functions are removed together with the function.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4501 b7a2c559-68d2-44c3-8de9-860c34a00d81

19 files changed:
doc/cc65.sgml
src/cc65/asmcode.c
src/cc65/asmstmt.c
src/cc65/codegen.c
src/cc65/codegen.h
src/cc65/compile.c
src/cc65/compile.h
src/cc65/declare.c
src/cc65/expr.c
src/cc65/function.c
src/cc65/litpool.c
src/cc65/litpool.h
src/cc65/main.c
src/cc65/pragma.c
src/cc65/scanner.c
src/cc65/scanner.h
src/cc65/stdfunc.c
src/cc65/symentry.c
src/cc65/symentry.h

index fddb3793719454b25191c6933f7bfc6defd055e0..6ae45dcacb5340c12c3fd48a495f8fb1c6d3b11a 100644 (file)
@@ -244,7 +244,7 @@ Here is a description of all the command line options:
   better way is to declare characters explicitly as "signed" if needed. You
   can also use <tt><ref id="pragma-signed-chars"
   name="#pragma&nbsp;signed-chars"></tt> for better control of this option.
-                                                                        
+
 
   <label id="option--standard">
   <tag><tt>--standard std</tt></tag>
@@ -301,8 +301,8 @@ Here is a description of all the command line options:
 
   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&nbsp;writable-strings"></tt> to control this option on a
-  per function basis.
+  name="#pragma&nbsp;writable-strings"></tt> to control this option from within
+  the source file.
 
 
   <label id="option-static-locals">
@@ -979,9 +979,9 @@ parameter with the <tt/#pragma/.
 
 <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.
 
@@ -990,10 +990,6 @@ parameter with the <tt/#pragma/.
   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.
 
 
index 83ea3b2520586d2c0e3558b567add9c6cf4cc446..c70675c011f4f49522b794b18ba9cac6c600c40e 100644 (file)
@@ -38,7 +38,6 @@
 
 /* cc65 */
 #include "asmcode.h"
-#include "codeopt.h"
 #include "codeseg.h"
 #include "dataseg.h"
 #include "segments.h"
@@ -124,12 +123,8 @@ void WriteAsmOutput (void)
     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;
index b54771aa9332080baa0b851b1329ca8e379dc771..3f858c679f7a8501a6cde6f8b61c700a40db3fbd 100644 (file)
@@ -321,8 +321,7 @@ static void ParseStrArg (StrBuf* T, unsigned Arg attribute ((unused)))
 
         case TOK_SCONST:
             /* String constant */
-            SB_AppendStr (T, GetLiteral (CurTok.IVal));
-            ResetLiteralPoolOffs (CurTok.IVal);
+            SB_Append (T, GetLiteralStrBuf (CurTok.SVal));
             NextToken ();
             break;
 
@@ -347,14 +346,7 @@ static void ParseAsm (void)
 
     /* 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 ();
index 8287ca84ee1d21475e99112d404baa895b71e828..07d6597dd2c143eadc77ab25a74ab4f9039b8b4b 100644 (file)
@@ -41,9 +41,9 @@
 #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"
@@ -346,6 +346,24 @@ void g_defdatalabel (unsigned label)
 
 
 
+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                      */
 /*****************************************************************************/
index 9d17ebe69b63656cc4a1b8d7cdfc555a9c40a4f9..a3b6df128f3082ba51a81cbb8d8c34a077d0e384 100644 (file)
@@ -136,6 +136,9 @@ void g_defcodelabel (unsigned label);
 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 */
+
 
 
 /*****************************************************************************/
index 9d92b4acec504f886cf3546b53c911953c8bbb39..0fcbfdf42a8e76bf10bc4155b3784c83a5d72742 100644 (file)
@@ -46,6 +46,7 @@
 #include "asmlabel.h"
 #include "asmstmt.h"
 #include "codegen.h"
+#include "codeopt.h"
 #include "compile.h"
 #include "declare.h"
 #include "error.h"
@@ -373,35 +374,51 @@ void Compile (const char* FileName)
         /* 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 ();
 }
 
 
 
-
index e1be3ee240464623127e2fd5d4135b3d351776de..27dae0778be652e6923c9310e2d7a8e0bb1462e4 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (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       */
@@ -47,6 +47,9 @@
 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 */
index 1e0b610edb200d1eb1746e4507262effd3f2993f..2b5e5fb639cd8b14f37b9261f5667aa6a367c0b0 100644 (file)
@@ -1769,7 +1769,6 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
 
         /* 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.
@@ -1779,16 +1778,13 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
             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) {
@@ -1797,10 +1793,9 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
         }
 
         /* 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
index ee658fbb58208240b9770d6ba3fc9c6dea69e646..ff5cde4f0a83685f6878cdaf174a94c245977a7b 100644 (file)
@@ -578,6 +578,7 @@ static void Primary (ExprDesc* E)
 /* This is the lowest level of the expression parser. */
 {
     SymEntry* Sym;
+    Literal*  L;
 
     /* Initialize fields in the expression stucture */
     ED_Init (E);
@@ -748,10 +749,11 @@ static void Primary (ExprDesc* 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;
 
index dcc625a690c0d5213a7404d88ab5fcb4dbf150d0..8944d10077583c722124f0b19c75a8c5cf5f0921 100644 (file)
@@ -359,7 +359,7 @@ static void F_RestoreRegVars (Function* F)
 }
 
 
-
+    
 /*****************************************************************************/
 /*                                          code                                    */
 /*****************************************************************************/
@@ -542,9 +542,8 @@ void NewFunc (SymEntry* Func)
     /* 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 ();
index 30c605d5fb7b1afee0407d3f737fe4c1651125bb..6f345662193417c1e96184de3b60f8e9654a435f 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                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
@@ -80,6 +85,99 @@ static Collection       LPStack  = STATIC_COLLECTION_INITIALIZER;
 
 
 
+/*****************************************************************************/
+/*                              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                                    */
 /*****************************************************************************/
@@ -93,10 +191,9 @@ static LiteralPool* NewLiteralPool (struct SymEntry* Func)
     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;
@@ -107,8 +204,9 @@ static LiteralPool* NewLiteralPool (struct SymEntry* Func)
 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);
@@ -116,11 +214,21 @@ static void FreeLiteralPool (LiteralPool* 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);
 }
 
 
@@ -140,143 +248,224 @@ void PushLiteralPool (struct SymEntry* Func)
 
 
 
-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));
 }
 
 
index 26f602ca32cbb8910c4938a15733fb8435edee1b..f89ffda8b625a4e1682ffd0947c149dc7ff3adda 100644 (file)
 /* 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. */
 
 
 
index 3785716dfafc1bdaa7e543757df16ec88f24cbfd..a0f570d215a5a01907fee569541747845bd093c8 100644 (file)
@@ -938,10 +938,13 @@ int main (int argc, char* argv[])
     /* 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);
 
index 37ae1bbb140991cbab8a7c3741c3024e533d8f2a..9ca49313771548f1745660d02577e2f4c6d857e0 100644 (file)
@@ -652,14 +652,7 @@ static void ParsePragma (void)
 
     /* 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 ();
index 2bf684268b124a8912f3a94e24be77ea2c432239..3dee4239f0acd3807fd95e0cd54bf9fce8c7c95f 100644 (file)
@@ -454,7 +454,7 @@ static void StringConst (void)
     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);
@@ -760,7 +760,7 @@ void NextToken (void)
        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) {
@@ -771,7 +771,7 @@ void NextToken (void)
                    } 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;
                }
index 6c3db2ed21423da04df1e849fe55e59e960f9c5b..f186e83437f6972e459145dfe27acd581537dc4d 100644 (file)
@@ -186,20 +186,24 @@ typedef enum token_t {
 
 
 /*****************************************************************************/
-/*                                  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 */
@@ -208,7 +212,7 @@ extern Token NextTok;               /* The next token */
 
 
 /*****************************************************************************/
-/*                                  code                                    */
+/*                                  Code                                    */
 /*****************************************************************************/
 
 
index 4f48c4fc4d3c5626397f23790c1f3ced7227c318..0c3e2779da38e0897f8e19a3453a561b6f63309a 100644 (file)
@@ -933,7 +933,8 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
 
     /* 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
@@ -942,14 +943,15 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
     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 */
index aedf2652e0899fe744d387f30c24bdee05bb2053..e42c8bbaa52a45be4bcd537515a2f0deb1212045 100644 (file)
@@ -153,6 +153,19 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
 
 
 
+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 */
 {
index d83113809533ef587ec041db5355badda1f045fa..900d2ee5fbc8b1f18e52aa8bc4e833e19262cb59 100644 (file)
@@ -57,6 +57,7 @@
 
 
 struct Segments;
+struct LiteralPool;
 
 
 
@@ -147,6 +148,7 @@ struct SymEntry {
        struct {
            struct FuncDesc*    Func;     /* Function descriptor */
                    struct Segments*    Seg;      /* Segments for this function */
+            struct LiteralPool* LitPool;  /* Literal pool for this function */
                } F;
 
     } V;
@@ -221,6 +223,9 @@ INLINE int SymIsRegVar (const SymEntry* Sym)
 #  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!) */
@@ -238,7 +243,7 @@ const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType);
 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)