]> granicus.if.org Git - re2c/commitdiff
- Add threshold control for -g style code generation
authorhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Sun, 14 May 2006 13:38:26 +0000 (13:38 +0000)
committerhelly <helly@642ea486-5414-0410-9d7f-a0204ed87703>
Sun, 14 May 2006 13:38:26 +0000 (13:38 +0000)
code.cc
dfa.h
globals.h
main.cc

diff --git a/code.cc b/code.cc
index 376d298d08396d4346c9a21dfbdac4615c6840cb..ee8bd0c54a70971d4580267ff7581f0ca8a3962d 100644 (file)
--- a/code.cc
+++ b/code.cc
@@ -539,7 +539,7 @@ void Accept::emit(std::ostream &o, uint ind, bool &readCh) const
                {
                        bUsedYYAccept = true;
 
-                       if (gFlag)
+                       if (gFlag && mapRules.size() >= cGotoThreshold)
                        {
                                o << indent(ind++) << "{\n";
                                o << indent(ind++) << "static void *yytarget[" << mapRules.size() << "] = {\n";
@@ -891,77 +891,102 @@ void Go::genBase(std::ostream &o, uint ind, const State *from, const State *next
        }
 }
 
-void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh)
+void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh) const
 {
-       if (gFlag || wFlag)
+       const char * sYych = readCh ? "(yych = *YYCURSOR)" : "yych";
+
+       readCh = false;
+       if (wFlag)
+       {
+               o << indent(ind) << "if(" << sYych <<" & 0xFF00) {\n";
+               genBase(o, ind+1, from, next, readCh, 1);
+               o << indent(ind++) << "} else {\n";
+               sYych = "yych";
+       }
+       else
        {
-               if (wSpans == ~0u)
+               o << indent(ind++) << "{\n";
+       }
+       o << indent(ind++) << "static void *yytarget[256] = {\n";
+       o << indent(ind);
+
+       uint ch = 0;
+       for (uint i = 0; i < lSpans; ++i)
+       {
+               vUsedLabels.insert(span[i].to->label);
+               for(; ch < span[i].ub; ++ch)
                {
-                       wSpans = 0;
-                       lSpans = 1;
-                       for (uint p = 0; p < nSpans; p++)
+                       o << "&&yy" << span[i].to->label;
+                       if (ch == 255)
                        {
-                               if (span[p].ub > 0xFF)
-                               {
-                                       wSpans++;
-                               }
-                               if (span[p].ub < 0x100)
-                               {
-                                       lSpans++;
-                               }
+                               o << "\n";
+                               i = lSpans;
+                               break;
+                       }
+                       else if (ch % 8 == 7)
+                       {
+                               o << ",\n" << indent(ind);
+                       }
+                       else
+                       {
+                               o << "," << space(span[i].to->label);
                        }
-               }
-               else
-               {
-                       lSpans = nSpans;
                }
        }
+       o << indent(--ind) << "};\n";
+       o << indent(ind) << "goto *yytarget[" << sYych << "];\n";
+       o << indent(--ind) << "}\n";
+}
 
-       if (gFlag && lSpans >= 16)
+void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh)
+{
+       if ((gFlag || wFlag) && wSpans == ~0u)
        {
-               const char * sYych = readCh ? "(yych = *YYCURSOR)" : "yych";
-
-               readCh = false;
-               if (wFlag)
-               {
-                       o << indent(ind) << "if(" << sYych <<" & 0xFF00) {\n";
-                       genBase(o, ind+1, from, next, readCh, 1);
-                       o << indent(ind++) << "} else {\n";
-                       sYych = "yych";
-               }
-               else
-               {
-                       o << indent(ind++) << "{\n";
-               }
-               o << indent(ind++) << "static void *yytarget[256] = {\n";
-               o << indent(ind);
-
-               uint ch = 0;
-               for (uint i = 0; i < lSpans; ++i)
+               uint nBitmaps = 0;
+               std::set<uint> vTargets;
+               wSpans = 0;
+               lSpans = 1;
+               dSpans = 0;
+               for (uint i = 0; i < nSpans; ++i)
                {
-                       vUsedLabels.insert(span[i].to->label);
-                       for(; ch < span[i].ub; ++ch)
+                       if (span[i].ub > 0xFF)
                        {
-                               o << "&&yy" << span[i].to->label;
-                               if (ch == 255)
-                               {
-                                       o << "\n";
-                                       i = lSpans;
-                                       break;
-                               }
-                               else if (ch % 8 == 7)
+                               wSpans++;
+                       }
+                       if (span[i].ub < 0x100 || !wFlag)
+                       {
+                               lSpans++;
+
+                               State *to = span[i].to;
+       
+                               if (to && to->isBase)
                                {
-                                       o << ",\n" << indent(ind);
+                                       const BitMap *b = BitMap::find(to);
+                                       const char * sYych;
+       
+                                       if (b && matches(b->go, b->on, this, to))
+                                       {
+                                               nBitmaps++;
+                                       }
+                                       else
+                                       {
+                                               dSpans++;
+                                               vTargets.insert(to->label);
+                                       }
                                }
                                else
                                {
-                                       o << "," << space(span[i].to->label);
+                                       dSpans++;
+                                       vTargets.insert(to->label);
                                }
                        }
                }
-               o << indent(--ind) << "};\n";
-               o << indent(ind) << "goto *yytarget[" << sYych << "];\n";
-               o << indent(--ind) << "}\n";
+               lTargets = vTargets.size() >> nBitmaps;
+       }
+
+       if (gFlag && (lTargets >= cGotoThreshold || dSpans >= cGotoThreshold))
+       {
+               genCpGoto(o, ind, from, next, readCh);
                return;
        }
        else if (bFlag)
@@ -1649,6 +1674,10 @@ void Scanner::config(const Str& cfg, int num)
        {
                bUseYYFill = num != 0;
        }
+       else if (cfg.to_string() == "cgoto:threshold")
+       {
+               cGotoThreshold = num;
+       }
        else
        {
                fatal("unrecognized configuration name or illegal integer value");
diff --git a/dfa.h b/dfa.h
index 626f3e2a8c94f583809a70328dca571b7bdc7017..42563f30d6eaf225ca55e2bba8e9b10e76024988 100644 (file)
--- a/dfa.h
+++ b/dfa.h
@@ -175,14 +175,18 @@ public:
                : nSpans(0)
                , wSpans(~0u)
                , lSpans(~0u)
+               , dSpans(~0u)
+               , lTargets(~0u)
                , span(NULL)
        {
        }
 
 public:
-       uint    nSpans;
-       uint    wSpans;
-       uint    lSpans;
+       uint    nSpans; // number of spans
+       uint    wSpans; // number of spans in wide mode
+       uint    lSpans; // number of low (non wide) spans
+       uint    dSpans; // number of decision spans (decide between g and b mode)
+       uint    lTargets;
        Span    *span;
 
 public:
@@ -191,6 +195,7 @@ public:
        void genLinear(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
        void genBinary(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
        void genSwitch(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
+       void genCpGoto(std::ostream&, uint ind, const State *from, const State *next, bool &readCh) const;
        void compact();
        void unmap(Go*, const State*);
 };
index 610d4097397edd2b3ef49d79ad6f63ab74311a41..b8645c425df519acd57013bc49889f864de80e8d 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -34,6 +34,7 @@ extern bool bUseStartLabel;
 extern std::string startLabelName;
 extern uint maxFill;
 extern uint next_label;
+extern uint cGotoThreshold;
 
 /* configurations */
 extern uint topIndent;
diff --git a/main.cc b/main.cc
index 4106015feb5ff0744c239bdf9b35fba4f4c7c28a..9435c029b75ffbe4dffae1f7d962d3abdde60195 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -44,6 +44,7 @@ bool bUseYYFill    = true;
 std::string startLabelName;
 uint maxFill = 1;
 uint next_label = 0;
+uint cGotoThreshold = 9;
 
 uint topIndent = 0;
 std::string indString("\t");
@@ -83,7 +84,7 @@ static const mbo_opt_struct OPTIONS[] =
 
 static void usage()
 {
-       cerr << "usage: re2c [-bdefhisvVw1] [-o file] file\n"
+       cerr << "usage: re2c [-bdefghisvVw1] [-o file] file\n"
        "\n"
        "-? -h  --help           Display this info.\n"
        "\n"
@@ -101,7 +102,7 @@ static void usage()
        "\n"
        "-f     --storable-state Generate a scanner that supports storable states.\n"
        "\n"
-       "-g     --computed-gotos Implies -b. Generate computed goto code (only useable \n"
+       "-g     --computed-gotos Implies -b. Generate computed goto code (only useable\n"
        "                        with gcc).\n"
        "\n"
        "-i     --no-debug-info  Do not generate '#line' info (usefull for versioning).\n"
@@ -118,8 +119,9 @@ static void usage()
        "-w     --wide-chars     Create a parser that supports wide chars (UCS-2). This\n"
        "                        implies -s and cannot be used together with -e switch.\n"
        "\n"
-       "-1     --single-pass    Force two pass generation, allows YYMAXFILL generation\n"
-       "                        prior to last re2c block.\n"
+       "-1     --single-pass    Force single pass generation, this cannot be combined\n"
+       "                        with -f and disables YYMAXFILL generation prior to last\n"
+       "                        re2c block.\n"
        ;
 }