OpenCores
URL https://opencores.org/ocsvn/c16/c16/trunk

Subversion Repositories c16

[/] [c16/] [trunk/] [compiler/] [Statement.cc] - Blame information for rev 31

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jsauermann
// Statement.cc
2
 
3
#include <stdio.h>
4
#include <assert.h>
5
#include "Node.hh"
6
#include "Name.hh"
7
#include "Backend.hh"
8
 
9
class LoopStack
10
{
11
public:
12
   LoopStack(int num, LoopStack * prev)
13
   : number(num),
14 7 jsauermann
     stack_depth(Backend::GetSP()),
15 2 jsauermann
     previous(prev)
16
     {};
17
 
18
   static int Push(LoopStack * & stack);
19
   static void Pop(LoopStack * & stack, int val);
20 7 jsauermann
   static int GetNumber(LoopStack * stack)
21 2 jsauermann
      { assert(stack);   return stack->number; };
22 7 jsauermann
   static int GetStackDepth(LoopStack * stack)
23
      { assert(stack);   return stack->stack_depth; };
24 2 jsauermann
 
25
private:
26
   int number;
27 7 jsauermann
   int stack_depth;
28 2 jsauermann
   LoopStack * previous;
29
 
30
   static int next_number;
31
};
32
 
33
int LoopStack::next_number = 1;
34
 
35
LoopStack * loop_stack  = 0;
36
LoopStack * break_stack = 0;
37
 
38
//-----------------------------------------------------------------------------
39
int LoopStack::Push(LoopStack * & stack)
40
{
41
   stack = new LoopStack(next_number++, stack);
42
   return stack->number;
43
}
44
//-----------------------------------------------------------------------------
45
void LoopStack::Pop(LoopStack * & stack, int val)
46
{
47
   assert(stack);
48
   assert(val == stack->number);
49
 
50
LoopStack * del = stack;
51
   stack = stack->previous;
52
   delete del;
53
}
54
//=============================================================================
55
void ExpressionStatement::Emit(FILE * out)
56
{
57
   EmitStart(out);
58
   if (expression)   expression->Emit(out);
59
   EmitEnd(out);
60
}
61
//-----------------------------------------------------------------------------
62
void SwitchStatement::Emit(FILE * out)
63
{
64
const int brk = LoopStack::Push(break_stack);
65
 
66
   EmitStart(out);
67
 
68
   assert(condition);
69
   condition->Emit(out);
70
   Backend::move_rr_to_ll();
71
 
72
   assert(case_stat);
73
   case_stat->EmitCaseJumps(out, condition->GetSize());
74
 
75
   EmitEnd(out);
76
 
77
   LoopStack::Pop(break_stack, brk);
78
}
79
//-----------------------------------------------------------------------------
80
void IfElseStatement::Emit(FILE * out)
81
{
82
const int loop = LoopStack::Push(loop_stack);   // just get a number
83
   LoopStack::Pop(loop_stack, loop);
84
 
85
   EmitStart(out);
86
   assert(condition);
87
   condition->Emit(out);
88
 
89
const int size = condition->GetSize();
90
 
91
   if (if_stat)
92
      {
93
        if (else_stat)   // if and else
94
           {
95
             Backend::branch_false("else", loop, size);
96
             if_stat->Emit(out);
97
             Backend::branch("endif", loop);
98
             Backend::label("else", loop);
99
             else_stat->Emit(out);
100
             Backend::label("endif", loop);
101
           }
102
        else             // if only
103
           {
104
             Backend::branch_false("endif", loop, size);
105
             if_stat->Emit(out);
106
             Backend::label("endif", loop);
107
           }
108
      }
109
   else
110
      {
111
        if (else_stat)   // else only
112
           {
113
             Backend::branch_true("endif", loop, size);
114
             else_stat->Emit(out);
115
             Backend::label("endif", loop);
116
           }
117
        else             // nothing
118
           {
119
           }
120
      }
121
 
122
   EmitEnd(out);
123
}
124
//-----------------------------------------------------------------------------
125
void DoWhileStatement::Emit(FILE * out)
126
{
127
const int loop = LoopStack::Push(loop_stack);
128
const int brk  = LoopStack::Push(break_stack);
129
 
130
   EmitStart(out);
131
 
132
   assert(condition);
133
   assert(body);
134
 
135
const int size = condition->GetSize();
136
 
137
   Backend::label("loop", loop);
138
   body->Emit(out);
139
 
140
   Backend::label("cont", loop);
141
   condition->Emit(out);
142
   Backend::branch_true("loop", loop, size);
143
 
144
   Backend::label("brk", brk);
145
 
146
   EmitEnd(out);
147
 
148
   LoopStack::Pop(break_stack, brk);
149
   LoopStack::Pop(loop_stack, loop);
150
}
151
//-----------------------------------------------------------------------------
152
void WhileStatement::Emit(FILE * out)
153
{
154
const int loop = LoopStack::Push(loop_stack);
155
const int brk  = LoopStack::Push(break_stack);
156
 
157
   EmitStart(out);
158
 
159
   assert(condition);
160
   assert(body);
161
 
162
const int size = condition->GetSize();
163
 
164
   if (body->NotEmpty())   Backend::branch("cont", loop);
165
 
166
   Backend::label("loop", loop);
167
   body->Emit(out);
168
 
169
   Backend::label("cont", loop);
170
   condition->Emit(out);
171
   Backend::branch_true("loop", loop, size);
172
 
173
   Backend::label("brk", brk);
174
 
175
   EmitEnd(out);
176
 
177
   LoopStack::Pop(break_stack,  brk);
178
   LoopStack::Pop(loop_stack, loop);
179
}
180
//-----------------------------------------------------------------------------
181
void ForStatement::Emit(FILE * out)
182
{
183
const int loop = LoopStack::Push(loop_stack);
184
const int brk  = LoopStack::Push(break_stack);
185
 
186
   EmitStart(out);
187
 
188
   assert(for_1);
189
   assert(for_2);
190
   assert(body);
191
 
192
Expression * cond = for_2->GetExpression();
193
 
194
int size = 0;
195
   if (cond)   size = cond->GetSize();
196
 
197
   for_1->Emit(out);
198
 
199
   if (cond)   Backend::branch("tst", loop);
200
 
201
   Backend::label("loop", loop);
202
   body->Emit(out);
203
 
204
   Backend::label("cont", loop);
205
   if (for_3)   for_3->Emit(out);
206
 
207
 
208
   if (cond)
209
      {
210
        Backend::label("tst", loop);
211
        cond->Emit(out);
212
        Backend::branch_true("loop", loop, size);
213
      }
214
   else
215
      {
216
        Backend::branch("loop", loop);
217
      }
218
 
219
   Backend::label("brk", brk);
220
 
221
   EmitEnd(out);
222
 
223
   LoopStack::Pop(break_stack, brk);
224
   LoopStack::Pop(loop_stack, loop);
225
}
226
//-----------------------------------------------------------------------------
227
void LabelStatement::Emit(FILE * out)
228
{
229
   EmitStart(out);
230
 
231
   assert(label_name);
232
   assert(statement);
233
 
234
   Backend::label(label_name);
235
   statement->Emit(out);
236
 
237
   EmitEnd(out);
238
}
239
//-----------------------------------------------------------------------------
240
void GotoStatement::Emit(FILE * out)
241
{
242
   EmitStart(out);
243
 
244
   assert(label_name);
245
 
246
   Backend::branch(label_name);
247
 
248
   EmitEnd(out);
249
}
250
//-----------------------------------------------------------------------------
251
void ReturnStatement::Emit(FILE * out)
252
{
253
   EmitStart(out);
254
 
255
   if (retval)   retval->Emit(out);
256
 
257 7 jsauermann
   Backend::ret();
258 2 jsauermann
 
259
   EmitEnd(out);
260
}
261
//-----------------------------------------------------------------------------
262
void ContStatement::Emit(FILE * out)
263
{
264
   EmitStart(out);
265
 
266 7 jsauermann
LoopStack * ls;
267
const char * ln;
268
 
269
   if (do_break)   { ls = break_stack;   ln = "brk"; }
270
   else            { ls = loop_stack;    ln = "cont"; };
271
 
272
const int stack_diff = LoopStack::GetStackDepth(ls) - Backend::GetSP();
273
 
274
   if (stack_diff < 0)
275 2 jsauermann
      {
276 7 jsauermann
        fprintf(stderr, "Jump over initialization\n");
277
        semantic_errors++;
278 2 jsauermann
      }
279 7 jsauermann
 
280
   if (stack_diff > 0)   Backend::pop_jump(stack_diff);
281
   Backend::branch(ln, LoopStack::GetNumber(ls));
282 2 jsauermann
 
283
   EmitEnd(out);
284
}
285
//-----------------------------------------------------------------------------
286
void CompoundStatement::Emit(FILE * out)
287
{
288
   EmitStart(out);
289 7 jsauermann
 
290
   Name::PushContext();
291
 
292
const int autosize = EmitAutovars(out);
293
 
294 2 jsauermann
   if (stat_list)   stat_list->Emit(out);
295 7 jsauermann
 
296
   Backend::pop(autosize);
297
 
298
   Name::PopContext();
299 2 jsauermann
   EmitEnd(out);
300
}
301
//-----------------------------------------------------------------------------
302
int CompoundStatement::EmitAutovars(FILE * out)
303
{
304
int ret = 0;
305
 
306
   for (DeclarationList * d = decl_list; d; d = d->Tail())
307
       {
308
         Declaration * di = d->Head();
309
         assert(di);
310
         int len = di->EmitAutovars(out);
311
         assert(len > 0);
312
         ret += len;
313
       }
314
 
315
   return ret;
316
}
317
//-----------------------------------------------------------------------------
318
void CompoundStatement::EmitCaseJumps(FILE * out, int size)
319
{
320 7 jsauermann
const int brk = LoopStack::GetNumber(break_stack);
321 2 jsauermann
 
322
bool has_default = false;
323
 
324
   for (StatementList * sl = stat_list; sl; sl = sl->Tail())
325
       {
326
         Statement * s = sl->Head();
327
         assert(s);
328
         s->EmitCaseJump(out, false, brk, size);
329
       }
330
 
331
   for (StatementList * sl = stat_list; sl; sl = sl->Tail())
332
       {
333
         Statement * s = sl->Head();
334
         assert(s);
335
         if (s->EmitCaseJump(out, true, brk, size))   has_default = true;
336
       }
337
 
338
   if (!has_default)
339
      {
340
        Backend::branch("brk", brk);
341
      }
342
 
343
   Emit(out);
344
 
345
   Backend::label("brk", brk);
346
}
347
//-----------------------------------------------------------------------------
348
void CaseStatement::Emit(FILE * out)
349
{
350 7 jsauermann
const int brk = LoopStack::GetNumber(break_stack);
351 2 jsauermann
 
352
   EmitStart(out);
353
   if (case_value)
354
      {
355
        if (case_value->IsConstant())
356
           {
357
             const int value = case_value->GetConstantNumericValue();
358
             Backend::label("case", brk, value);
359
           }
360
        else
361
           {
362
             fprintf(stderr, "Case value not constant\r\n");
363
             semantic_errors++;
364
           }
365
      }
366
   else
367
      {
368
        Backend::label("deflt", brk);
369
      }
370
 
371
   if (statement)   statement->Emit(out);
372
   EmitEnd(out);
373
}
374
//-----------------------------------------------------------------------------
375
//
376
// return true iff this is a default clause
377
//
378
bool CaseStatement::EmitCaseJump(FILE * out, bool def, int loop, int size)
379
{
380
bool ret = false;
381
 
382
   if (def)   // default branch
383
      {
384
        if (!case_value)   { Backend::branch("deflt", loop);   ret = true; }
385
      }
386
   else       // case branch
387
      {
388
        if (case_value)
389
           {
390
             if (!case_value->IsConstant())
391
                {
392
                  fprintf(stderr, "case value not constant\r\n");
393
                  semantic_errors++;
394
                  return false;
395
                }
396
 
397
             const int value = case_value->GetConstantNumericValue();
398
             Backend::branch_case("case", loop, size, value);
399
           }
400
      }
401
 
402
   if (statement)   ret = ret || statement->EmitCaseJump(out, def, loop, size);
403
   return ret;
404
}
405
//-----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.