src
go_construct.cc
Go to the documentation of this file.
1 #include <stddef.h>
2 #include "src/util/c99_stdint.h"
3 #include <string>
4 #include <utility>
5 #include <vector>
6 
7 #include "src/codegen/bitmap.h"
8 #include "src/codegen/go.h"
9 #include "src/conf/opt.h"
10 #include "src/globals.h"
11 #include "src/ir/adfa/adfa.h"
12 #include "src/util/allocate.h"
13 
14 namespace re2c
15 {
16 
17 static uint32_t unmap (Span * new_span, const Span * old_span, uint32_t old_nspans, const State * x);
18 
19 Cases::Cases (const Span * span, uint32_t span_size)
20  : def (span_size == 0 ? NULL : span[span_size - 1].to)
21  , cases (new Case[span_size])
22  , cases_size (0)
23 {
24  for (uint32_t i = 0, lb = 0; i < span_size; ++ i)
25  {
26  add (lb, span[i].ub, span[i].to);
27  lb = span[i].ub;
28  }
29 }
30 
31 void Cases::add (uint32_t lb, uint32_t ub, State * to)
32 {
33  for (uint32_t i = 0; i < cases_size; ++i)
34  {
35  if (cases[i].to == to)
36  {
37  cases[i].ranges.push_back (std::make_pair (lb, ub));
38  return;
39  }
40  }
41  cases[cases_size].ranges.push_back (std::make_pair (lb, ub));
42  cases[cases_size].to = to;
43  ++cases_size;
44 }
45 
46 Cond::Cond (const std::string & cmp, uint32_t val)
47  : compare (cmp)
48  , value (val)
49 {}
50 
51 Binary::Binary (const Span * s, uint32_t n, const State * next)
52  : cond (NULL)
53  , thn (NULL)
54  , els (NULL)
55 {
56  const uint32_t l = n / 2;
57  const uint32_t h = n - l;
58  cond = new Cond ("<=", s[l - 1].ub - 1);
59  thn = new If (l > 4 ? If::BINARY : If::LINEAR, &s[0], l, next);
60  els = new If (h > 4 ? If::BINARY : If::LINEAR, &s[l], h, next);
61 }
62 
63 Linear::Linear (const Span * s, uint32_t n, const State * next)
64  : branches ()
65 {
66  for (;;)
67  {
68  const State *bg = s[0].to;
69  while (n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1)
70  {
71  if (s[1].to == next && n == 3)
72  {
73  branches.push_back (std::make_pair (new Cond ("!=", s[0].ub), bg));
74  return ;
75  }
76  else
77  {
78  branches.push_back (std::make_pair (new Cond ("==", s[0].ub), s[1].to));
79  }
80  n -= 2;
81  s += 2;
82  }
83  if (n == 1)
84  {
85  if (next == NULL || s[0].to != next)
86  {
87  branches.push_back (std::make_pair (static_cast<const Cond *> (NULL), s[0].to));
88  }
89  return;
90  }
91  else if (n == 2 && bg == next)
92  {
93  branches.push_back (std::make_pair (new Cond (">=", s[0].ub), s[1].to));
94  return;
95  }
96  else
97  {
98  branches.push_back (std::make_pair (new Cond ("<=", s[0].ub - 1), bg));
99  n -= 1;
100  s += 1;
101  }
102  }
103 }
104 
105 If::If (type_t t, const Span * sp, uint32_t nsp, const State * next)
106  : type (t)
107  , info ()
108 {
109  switch (type)
110  {
111  case BINARY:
112  info.binary = new Binary (sp, nsp, next);
113  break;
114  case LINEAR:
115  info.linear = new Linear (sp, nsp, next);
116  break;
117  }
118 }
119 
120 SwitchIf::SwitchIf (const Span * sp, uint32_t nsp, const State * next)
121  : type (IF)
122  , info ()
123 {
124  if ((!opts->sFlag && nsp > 2) || (nsp > 8 && (sp[nsp - 2].ub - sp[0].ub <= 3 * (nsp - 2))))
125  {
126  type = SWITCH;
127  info.cases = new Cases (sp, nsp);
128  }
129  else if (nsp > 5)
130  {
131  info.ifs = new If (If::BINARY, sp, nsp, next);
132  }
133  else
134  {
135  info.ifs = new If (If::LINEAR, sp, nsp, next);
136  }
137 }
138 
139 GoBitmap::GoBitmap (const Span * span, uint32_t nSpans, const Span * hspan, uint32_t hSpans, const BitMap * bm, const State * bm_state, const State * next)
140  : bitmap (bm)
141  , bitmap_state (bm_state)
142  , hgo (NULL)
143  , lgo (NULL)
144 {
145  Span * bspan = allocate<Span> (nSpans);
146  uint32_t bSpans = unmap (bspan, span, nSpans, bm_state);
147  lgo = bSpans == 0
148  ? NULL
149  : new SwitchIf (bspan, bSpans, next);
150  // if there are any low spans, then next state for high spans
151  // must be NULL to trigger explicit goto generation in linear 'if'
152  hgo = hSpans == 0
153  ? NULL
154  : new SwitchIf (hspan, hSpans, lgo ? NULL : next);
155  operator delete (bspan);
156 }
157 
158 const uint32_t CpgotoTable::TABLE_SIZE = 0x100;
159 
160 CpgotoTable::CpgotoTable (const Span * span, uint32_t nSpans)
161  : table (new const State * [TABLE_SIZE])
162 {
163  uint32_t c = 0;
164  for (uint32_t i = 0; i < nSpans; ++i)
165  {
166  for(; c < span[i].ub && c < TABLE_SIZE; ++c)
167  {
168  table[c] = span[i].to;
169  }
170  }
171 }
172 
173 Cpgoto::Cpgoto (const Span * span, uint32_t nSpans, const Span * hspan, uint32_t hSpans, const State * next)
174  : hgo (hSpans == 0 ? NULL : new SwitchIf (hspan, hSpans, next))
175  , table (new CpgotoTable (span, nSpans))
176 {}
177 
178 Dot::Dot (const Span * sp, uint32_t nsp, const State * s)
179  : from (s)
180  , cases (new Cases (sp, nsp))
181 {}
182 
184  : nSpans (0)
185  , span (NULL)
186  , type (EMPTY)
187  , info ()
188 {}
189 
190 void Go::init (const State * from)
191 {
192  if (nSpans == 0)
193  {
194  return;
195  }
196 
197  // initialize high (wide) spans
198  uint32_t hSpans = 0;
199  const Span * hspan = NULL;
200  for (uint32_t i = 0; i < nSpans; ++i)
201  {
202  if (span[i].ub > 0x100)
203  {
204  hspan = &span[i];
205  hSpans = nSpans - i;
206  break;
207  }
208  }
209 
210  // initialize bitmaps
211  uint32_t nBitmaps = 0;
212  const BitMap * bitmap = NULL;
213  const State * bitmap_state = NULL;
214  for (uint32_t i = 0; i < nSpans; ++i)
215  {
216  if (span[i].to->isBase)
217  {
218  const BitMap *b = BitMap::find (span[i].to);
219  if (b && matches(b->go->span, b->go->nSpans, b->on, span, nSpans, span[i].to))
220  {
221  if (bitmap == NULL)
222  {
223  bitmap = b;
224  bitmap_state = span[i].to;
225  }
226  nBitmaps++;
227  }
228  }
229  }
230 
231  const uint32_t dSpans = nSpans - hSpans - nBitmaps;
232  if (opts->target == opt_t::DOT)
233  {
234  type = DOT;
235  info.dot = new Dot (span, nSpans, from);
236  }
237  else if (opts->gFlag && (dSpans >= opts->cGotoThreshold))
238  {
239  type = CPGOTO;
240  info.cpgoto = new Cpgoto (span, nSpans, hspan, hSpans, from->next);
241  }
242  else if (opts->bFlag && (nBitmaps > 0))
243  {
244  type = BITMAP;
245  info.bitmap = new GoBitmap (span, nSpans, hspan, hSpans, bitmap, bitmap_state, from->next);
246  bUsedYYBitmap = true;
247  }
248  else
249  {
250  type = SWITCH_IF;
251  info.switchif = new SwitchIf (span, nSpans, from->next);
252  }
253 }
254 
255 /*
256  * Find all spans, that map to the given state. For each of them,
257  * find upper adjacent span, that maps to another state (if such
258  * span exists, otherwize try lower one).
259  * If input contains single span that maps to the given state,
260  * then output contains 0 spans.
261  */
262 uint32_t unmap (Span * new_span, const Span * old_span, uint32_t old_nspans, const State * x)
263 {
264  uint32_t new_nspans = 0;
265  for (uint32_t i = 0; i < old_nspans; ++i)
266  {
267  if (old_span[i].to != x)
268  {
269  if (new_nspans > 0 && new_span[new_nspans - 1].to == old_span[i].to)
270  new_span[new_nspans - 1].ub = old_span[i].ub;
271  else
272  {
273  new_span[new_nspans].to = old_span[i].to;
274  new_span[new_nspans].ub = old_span[i].ub;
275  ++new_nspans;
276  }
277  }
278  }
279  if (new_nspans > 0)
280  new_span[new_nspans - 1].ub = old_span[old_nspans - 1].ub;
281  return new_nspans;
282 }
283 
284 } // namespace re2c
Cond(const std::string &cmp, uint32_t val)
Definition: go_construct.cc:46
bool bFlag
Definition: opt.h:118
const State * on
Definition: bitmap.h:22
If * thn
Definition: go.h:65
static const uint32_t TABLE_SIZE
Definition: go.h:136
SwitchIf * hgo
Definition: go.h:124
enum re2c::Go::@3 type
uint32_t nSpans
Definition: go.h:174
void init(const State *from)
Cpgoto(const Span *span, uint32_t nSpans, const Span *hspan, uint32_t hSpans, const State *next)
uint32_t ub
Definition: go.h:21
Definition: go.h:84
enum re2c::SwitchIf::@1 type
State * to
Definition: go.h:22
Dot(const Span *sp, uint32_t nsp, const State *from)
bool bUsedYYBitmap
Definition: main.cc:16
const State ** table
Definition: go.h:137
bool sFlag
Definition: opt.h:118
uint32_t cases_size
Definition: go.h:45
Definition: go.h:55
uint32_t cGotoThreshold
Definition: opt.h:118
GoBitmap(const Span *span, uint32_t nSpans, const Span *hspan, uint32_t hSpans, const BitMap *bm, const State *bm_state, const State *next)
opt_t::target_t target
Definition: opt.h:118
Linear(const Span *s, uint32_t n, const State *next)
Definition: go_construct.cc:63
bool gFlag
Definition: opt.h:118
Case * cases
Definition: go.h:44
SwitchIf(const Span *sp, uint32_t nsp, const State *next)
Cond * cond
Definition: go.h:64
SwitchIf * lgo
Definition: go.h:125
void add(uint32_t lb, uint32_t ub, State *to)
Definition: go_construct.cc:31
Definition: go.h:41
static uint32_t unmap(Span *new_span, const Span *old_span, uint32_t old_nspans, const State *x)
Definition: go.h:27
const State * to
Definition: go.h:30
const Go * go
Definition: bitmap.h:21
If(type_t t, const Span *sp, uint32_t nsp, const State *next)
std::vector< std::pair< const Cond *, const State * > > branches
Definition: go.h:77
Opt opts
Definition: opt.cc:7
CpgotoTable(const Span *span, uint32_t nSpans)
GoBitmap * bitmap
Definition: go.h:187
static const BitMap * find(const Go *, const State *)
Definition: bitmap.cc:30
union re2c::If::@0 info
Cases(const Span *s, uint32_t n)
Definition: go_construct.cc:19
union re2c::SwitchIf::@2 info
If * els
Definition: go.h:66
union re2c::Go::@4 info
Definition: go.h:161
Span * span
Definition: go.h:175
bool matches(const Span *b1, uint32_t n1, const State *s1, const Span *b2, uint32_t n2, const State *s2)
Definition: bitmap.cc:134
enum re2c::If::type_t type
std::vector< std::pair< uint32_t, uint32_t > > ranges
Definition: go.h:29
Definition: bitmap.cc:10
type_t
Definition: go.h:86
Definition: go.h:19
Binary(const Span *s, uint32_t n, const State *next)
Definition: go_construct.cc:51
State * next
Definition: adfa.h:27