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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [Statement.cpp] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2012-2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// CC64 - 'C' derived language compiler
9
//  - 64 bit CPU
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
// ============================================================================
25
//
26
#include "stdafx.h"
27
 
28
extern TYP *head, *tail;
29
extern TYP stdbyte;
30
extern int catchdecl;
31
Statement *ParseCatchStatement();
32
int iflevel;
33
int looplevel;
34
int foreverlevel;
35
int loopexit;
36
Statement *currentStmt;
37
char *llptr;
38
extern char *lptr;
39
extern char inpline[132];
40
 
41
int     breaklab;
42
int     contlab;
43
int     retlab;
44
int             throwlab;
45
 
46
int lastsph;
47
char *semaphores[20];
48
char last_rem[132];
49
 
50
extern TYP              stdfunc;
51
 
52
static SYM *makeint(char *name)
53
{
54
        SYM *sp;
55
        TYP *tp;
56
 
57
        sp = allocSYM();
58
        tp = TYP::Make(bt_long, 8);
59
        tp->sname = new std::string("");
60
        tp->isUnsigned = FALSE;
61
        tp->isVolatile = FALSE;
62
        sp->SetName(name);
63
        sp->storage_class = sc_auto;
64
        sp->SetType(tp);
65
        currentFn->sym->lsyms.insert(sp);
66
        return (sp);
67
}
68
 
69
 
70
Statement *NewStatement(int typ, int gt) {
71
        Statement *s = (Statement *)xalloc(sizeof(Statement));
72
        ZeroMemory(s, sizeof(Statement));
73
        s->stype = typ;
74
        s->predreg = -1;
75
        s->outer = currentStmt;
76
        s->s1 = (Statement *)NULL;
77
        s->s2 = (Statement *)NULL;
78
        s->ssyms.Clear();
79
        s->lptr = my_strdup(inpline);
80
        s->prediction = 0;
81
        s->depth = stmtdepth;
82
        //memset(s->ssyms,0,sizeof(s->ssyms));
83
        if (gt) NextToken();
84
        return s;
85
};
86
 
87
 
88
Statement *ParseCheckStatement()
89
{
90
        Statement *snp;
91
        snp = NewStatement(st_check, TRUE);
92
        if (expression(&(snp->exp)) == 0)
93
                error(ERR_EXPREXPECT);
94
        needpunc(semicolon, 31);
95
        return snp;
96
}
97
 
98
Statement *Statement::ParseWhile()
99
{
100
        Statement *snp;
101
 
102
        currentFn->UsesPredicate = TRUE;
103
        snp = NewStatement(st_while, TRUE);
104
        snp->predreg = iflevel;
105
        iflevel++;
106
        looplevel++;
107
        if ((iflevel > maxPn - 1) && isThor)
108
                error(ERR_OUTOFPREDS);
109
        if (lastst != openpa)
110
                error(ERR_EXPREXPECT);
111
        else {
112
                NextToken();
113
                if (expression(&(snp->exp)) == 0)
114
                        error(ERR_EXPREXPECT);
115
                needpunc(closepa, 13);
116
                if (lastst == kw_do)
117
                        NextToken();
118
                snp->s1 = Statement::Parse();
119
                // Empty statements return NULL
120
                if (snp->s1)
121
                        snp->s1->outer = snp;
122
        }
123
        iflevel--;
124
        looplevel--;
125
        return (snp);
126
}
127
 
128
Statement *Statement::ParseUntil()
129
{
130
        Statement *snp;
131
 
132
        currentFn->UsesPredicate = TRUE;
133
        snp = NewStatement(st_until, TRUE);
134
        snp->predreg = iflevel;
135
        iflevel++;
136
        looplevel++;
137
        if ((iflevel > maxPn - 1) && isThor)
138
                error(ERR_OUTOFPREDS);
139
        if (lastst != openpa)
140
                error(ERR_EXPREXPECT);
141
        else {
142
                NextToken();
143
                if (expression(&(snp->exp)) == 0)
144
                        error(ERR_EXPREXPECT);
145
                needpunc(closepa, 14);
146
                snp->s1 = Statement::Parse();
147
                // Empty statements return NULL
148
                if (snp->s1)
149
                        snp->s1->outer = snp;
150
        }
151
        iflevel--;
152
        looplevel--;
153
        return snp;
154
}
155
 
156
Statement *Statement::ParseDo()
157
{
158
        Statement *snp;
159
 
160
        currentFn->UsesPredicate = TRUE;
161
        snp = NewStatement(st_do, TRUE);
162
        snp->predreg = iflevel;
163
        iflevel++;
164
        looplevel++;
165
        snp->s1 = Statement::Parse();
166
        // Empty statements return NULL
167
        if (snp->s1)
168
                snp->s1->outer = snp;
169
        switch (lastst) {
170
        case kw_until:  snp->stype = st_dountil; break;
171
        case kw_loop:   snp->stype = st_doloop; break;
172
        case kw_while:  snp->stype = st_dowhile; break;
173
        default:        snp->stype = st_doonce; break;
174
        }
175
        if (lastst != kw_while && lastst != kw_until && lastst != kw_loop)
176
                error(ERR_WHILEXPECT);
177
        else {
178
                NextToken();
179
                if (snp->stype != st_doloop) {
180
                        if (expression(&(snp->exp)) == 0)
181
                                error(ERR_EXPREXPECT);
182
                }
183
                if (lastst != end)
184
                        needpunc(semicolon, 15);
185
        }
186
        iflevel--;
187
        looplevel--;
188
        return (snp);
189
}
190
 
191
Statement *Statement::ParseFor()
192
{
193
        Statement *snp;
194
 
195
        currentFn->UsesPredicate = TRUE;
196
        snp = NewStatement(st_for, TRUE);
197
        snp->predreg = iflevel;
198
        iflevel++;
199
        looplevel++;
200
        if ((iflevel > maxPn - 1) && isThor)
201
                error(ERR_OUTOFPREDS);
202
        needpunc(openpa, 16);
203
        if (expression(&(snp->initExpr)) == NULL)
204
                snp->initExpr = (ENODE *)NULL;
205
        needpunc(semicolon, 32);
206
        if (expression(&(snp->exp)) == NULL)
207
                snp->exp = (ENODE *)NULL;
208
        needpunc(semicolon, 17);
209
        if (expression(&(snp->incrExpr)) == NULL)
210
                snp->incrExpr = (ENODE *)NULL;
211
        needpunc(closepa, 18);
212
        snp->s1 = Statement::Parse();
213
        // Empty statements return NULL
214
        if (snp->s1)
215
                snp->s1->outer = snp;
216
        iflevel--;
217
        looplevel--;
218
        return (snp);
219
}
220
 
221
// The forever statement tries to detect if there's an infinite loop and a
222
// warning is output if there is no obvious loop exit.
223
// Statements that might exit a loop set the loopexit variable true. These
224
// statements include throw, return, break, and goto. There are other ways
225
// to exit a loop that aren't easily detectable (exit() or setjmp).
226
 
227
Statement *Statement::ParseForever()
228
{
229
        Statement *snp;
230
        snp = NewStatement(st_forever, TRUE);
231
        snp->stype = st_forever;
232
        foreverlevel = looplevel;
233
        snp->s1 = Statement::Parse();
234
        if (loopexit == 0)
235
                error(ERR_INFINITELOOP);
236
        // Empty statements return NULL
237
        if (snp->s1)
238
                snp->s1->outer = snp;
239
        return (snp);
240
}
241
 
242
 
243
// Firstcall allocates a hidden static variable that tracks the first time
244
// the firstcall statement is entered.
245
 
246
Statement *Statement::ParseFirstcall()
247
{
248
        Statement *snp;
249
        SYM *sp;
250
        int st;
251
 
252
        dfs.puts("<ParseFirstcall>");
253
        snp = NewStatement(st_firstcall, TRUE);
254
        sp = allocSYM();
255
        //      sp->SetName(*(new std::string(snp->fcname)));
256
        sp->storage_class = sc_static;
257
        sp->value.i = nextlabel++;
258
        sp->tp = &stdbyte;
259
        st = lastst;
260
        lastst = kw_firstcall;       // fake out doinit()
261
        doinit(sp);
262
        lastst = st;
263
        // doinit should set realname
264
        snp->fcname = my_strdup(sp->realname);
265
        snp->s1 = Statement::Parse();
266
        // Empty statements return NULL
267
        if (snp->s1)
268
                snp->s1->outer = snp;
269
        dfs.puts("</ParseFirstcall>");
270
        return snp;
271
}
272
 
273
Statement *Statement::ParseIf()
274
{
275
        Statement *snp;
276
        bool needpa = true;
277
 
278
        dfs.puts("<ParseIf>");
279
        NextToken();
280
        if (lastst == kw_firstcall)
281
                return (ParseFirstcall());
282
        currentFn->UsesPredicate = TRUE;
283
        snp = NewStatement(st_if, FALSE);
284
        snp->predreg = iflevel;
285
        iflevel++;
286
        if (lastst != openpa)
287
                needpa = false;
288
        NextToken();
289
        if (expression(&(snp->exp)) == 0)
290
                error(ERR_EXPREXPECT);
291
        if (lastst == semicolon) {
292
                NextToken();
293
                snp->prediction = (GetIntegerExpression(NULL) & 1) | 2;
294
        }
295
        if (needpa)
296
                needpunc(closepa, 19);
297
        else if (lastst != kw_then)
298
                error(ERR_SYNTAX);
299
        if (lastst == kw_then)
300
                NextToken();
301
        snp->s1 = Statement::Parse();
302
        if (snp->s1)
303
                snp->s1->outer = snp;
304
        if (lastst == kw_else) {
305
                NextToken();
306
                snp->s2 = Statement::Parse();
307
                if (snp->s2)
308
                        snp->s2->outer = snp;
309
        }
310
        else if (lastst == kw_elsif) {
311
                snp->s2 = ParseIf();
312
                if (snp->s2)
313
                        snp->s2->outer = snp;
314
        }
315
        else
316
                snp->s2 = 0;
317
        iflevel--;
318
        dfs.puts("</ParseIf>");
319
        return (snp);
320
}
321
 
322
Statement *Statement::ParseCatch()
323
{
324
        Statement *snp;
325
        SYM *sp;
326
        TYP *tp, *tp1, *tp2;
327
        ENODE *node;
328
        static char buf[200];
329
 
330
        snp = NewStatement(st_catch, TRUE);
331
        currentStmt = snp;
332
        if (lastst != openpa) {
333
                snp->label = (int64_t *)NULL;
334
                snp->s2 = (Statement *)99999;
335
                snp->s1 = Statement::Parse();
336
                // Empty statements return NULL
337
                if (snp->s1)
338
                        snp->s1->outer = snp;
339
                return snp;
340
        }
341
        needpunc(openpa, 33);
342
        tp = head;
343
        tp1 = tail;
344
        catchdecl = TRUE;
345
        AutoDeclaration::Parse(NULL, &snp->ssyms);
346
        cseg();
347
        catchdecl = FALSE;
348
        tp2 = head;
349
        head = tp;
350
        tail = tp1;
351
        needpunc(closepa, 34);
352
 
353
        if ((sp = snp->ssyms.Find(*declid, false)) == NULL)
354
                sp = makeint((char *)declid->c_str());
355
        node = makenode(sp->storage_class == sc_static ? en_labcon : en_autocon, NULL, NULL);
356
        // nameref looks up the symbol using lastid, so we need to back it up and
357
        // restore it.
358
        strncpy_s(buf, sizeof(buf), lastid, 199);
359
        strncpy_s(lastid, sizeof(lastid), declid->c_str(), sizeof(lastid) - 1);
360
        nameref(&node, FALSE);
361
        strcpy_s(lastid, sizeof(lastid), buf);
362
        snp->s1 = Statement::Parse();
363
        // Empty statements return NULL
364
        if (snp->s1)
365
                snp->s1->outer = snp;
366
        snp->exp = node;        // save name reference
367
        if (sp->tp->typeno >= bt_last)
368
                error(ERR_CATCHSTRUCT);
369
        snp->num = sp->tp->GetHash();
370
        // Empty statements return NULL
371
        //      if (snp->s2)
372
        //              snp->s2->outer = snp;
373
        return snp;
374
}
375
 
376
Statement *Statement::ParseCase()
377
{
378
        Statement *snp;
379
        Statement *head, *tail;
380
        int64_t buf[256];
381
        int nn;
382
        int64_t *bf;
383
 
384
        snp = NewStatement(st_case, FALSE);
385
        if (lastst == kw_fallthru)      // ignore "fallthru"
386
                NextToken();
387
        if (lastst == kw_case) {
388
                NextToken();
389
                snp->s2 = 0;
390
                nn = 0;
391
                do {
392
                        buf[nn] = GetIntegerExpression((ENODE **)NULL);
393
                        nn++;
394
                        if (lastst != comma)
395
                                break;
396
                        NextToken();
397
                } while (nn < 256);
398
                if (nn == 256)
399
                        error(ERR_TOOMANYCASECONSTANTS);
400
                bf = (int64_t *)xalloc(sizeof(int64_t)*(nn + 1));
401
                bf[0] = nn;
402
                for (; nn > 0; nn--)
403
                        bf[nn] = buf[nn - 1];
404
                snp->casevals = (int64_t *)bf;
405
        }
406
        else if (lastst == kw_default) {
407
                NextToken();
408
                snp->s2 = (Statement *)1;
409
                snp->stype = st_default;
410
        }
411
        else {
412
                error(ERR_NOCASE);
413
                return (Statement *)NULL;
414
        }
415
        needpunc(colon, 35);
416
        head = (Statement *)NULL;
417
        while (lastst != end && lastst != kw_case && lastst != kw_default) {
418
                if (head == NULL) {
419
                        head = tail = Statement::Parse();
420
                        if (head)
421
                                head->outer = snp;
422
                }
423
                else {
424
                        tail->next = Statement::Parse();
425
                        if (tail->next != NULL) {
426
                                tail->next->outer = snp;
427
                                tail = tail->next;
428
                        }
429
                }
430
                tail->next = 0;
431
        }
432
        snp->s1 = head;
433
        return (snp);
434
}
435
 
436
int Statement::CheckForDuplicateCases()
437
{
438
        Statement *head;
439
        Statement *top, *cur, *def;
440
        int cnt, cnt2;
441
        static int64_t buf[1000];
442
        int ndx;
443
 
444
        ndx = 0;
445
        head = this;
446
        cur = top = head;
447
        for (top = head; top != (Statement *)NULL; top = top->next)
448
        {
449
                if (top->casevals) {
450
                        for (cnt = 1; cnt < top->casevals[0] + 1; cnt++) {
451
                                for (cnt2 = 0; cnt2 < ndx; cnt2++)
452
                                        if (top->casevals[cnt] == buf[cnt2])
453
                                                return (TRUE);
454
                                if (ndx > 999)
455
                                        throw new C64PException(ERR_TOOMANYCASECONSTANTS, 1);
456
                                buf[ndx] = top->casevals[cnt];
457
                                ndx++;
458
                        }
459
                }
460
        }
461
 
462
        // Check for duplicate default: statement
463
        def = nullptr;
464
        for (top = head; top != (Statement *)NULL; top = top->next)
465
        {
466
                if (top->s2 && def)
467
                        return (TRUE);
468
                if (top->s2)
469
                        def = top->s2;
470
        }
471
        return (FALSE);
472
}
473
 
474
Statement *Statement::ParseSwitch()
475
{
476
        Statement *snp;
477
        Statement *head, *tail;
478
 
479
        snp = NewStatement(st_switch, TRUE);
480
        snp->nkd = false;
481
        iflevel++;
482
        looplevel++;
483
        needpunc(openpa, 0);
484
        if (expression(&(snp->exp)) == NULL)
485
                error(ERR_EXPREXPECT);
486
        if (lastst == semicolon) {
487
                NextToken();
488
                if (lastst == kw_naked) {
489
                        NextToken();
490
                        snp->nkd = true;
491
                }
492
        }
493
        needpunc(closepa, 0);
494
        needpunc(begin, 36);
495
        head = 0;
496
        while (lastst != end) {
497
                if (head == (Statement *)NULL) {
498
                        head = tail = ParseCase();
499
                        if (head)
500
                                head->outer = snp;
501
                }
502
                else {
503
                        tail->next = ParseCase();
504
                        if (tail->next != (Statement *)NULL) {
505
                                tail->next->outer = snp;
506
                                tail = tail->next;
507
                        }
508
                }
509
                if (tail == (Statement *)NULL) break;   // end of file in switch
510
                tail->next = (Statement *)NULL;
511
        }
512
        snp->s1 = head;
513
        NextToken();
514
        if (head->CheckForDuplicateCases())
515
                error(ERR_DUPCASE);
516
        iflevel--;
517
        looplevel--;
518
        return (snp);
519
}
520
 
521
Statement *Statement::ParseReturn()
522
{
523
        Statement *snp;
524
 
525
        loopexit = TRUE;
526
        snp = NewStatement(st_return, TRUE);
527
        expression(&(snp->exp));
528
        if (lastst != end)
529
                needpunc(semicolon, 37);
530
        return (snp);
531
}
532
 
533
Statement *Statement::ParseThrow()
534
{
535
        Statement *snp;
536
        TYP *tp;
537
 
538
        currentFn->DoesThrow = TRUE;
539
        loopexit = TRUE;
540
        snp = NewStatement(st_throw, TRUE);
541
        tp = expression(&(snp->exp));
542
        snp->num = tp->GetHash();
543
        if (lastst != end)
544
                needpunc(semicolon, 38);
545
        return (snp);
546
}
547
 
548
Statement *Statement::ParseBreak()
549
{
550
        Statement *snp;
551
 
552
        snp = NewStatement(st_break, TRUE);
553
        if (lastst != end)
554
                needpunc(semicolon, 39);
555
        if (looplevel == foreverlevel)
556
                loopexit = TRUE;
557
        return (snp);
558
}
559
 
560
Statement *Statement::ParseContinue()
561
{
562
        Statement *snp;
563
 
564
        snp = NewStatement(st_continue, TRUE);
565
        if (lastst != end)
566
                needpunc(semicolon, 40);
567
        return (snp);
568
}
569
 
570
Statement *Statement::ParseStop()
571
{
572
        Statement *snp;
573
 
574
        snp = NewStatement(st_stop, TRUE);
575
        snp->num = (int)GetIntegerExpression(NULL);
576
        if (lastst != end)
577
                needpunc(semicolon, 43);
578
        return snp;
579
}
580
 
581
Statement *Statement::ParseAsm()
582
{
583
        static char buf[3501];
584
        int nn;
585
        bool first = true;
586
 
587
        Statement *snp;
588
        snp = NewStatement(st_asm, FALSE);
589
        while (my_isspace(lastch))
590
                getch();
591
        NextToken();
592
        if (lastst == kw_leafs) {
593
                currentFn->IsLeaf = FALSE;
594
                while (my_isspace(lastch))
595
                        getch();
596
                NextToken();
597
        }
598
        if (lastst != begin)
599
                error(ERR_PUNCT);
600
        nn = 0;
601
        do {
602
                // skip over leading spaces on the line
603
                getch();
604
                while (isspace(lastch)) getch();
605
                if (lastch == '}')
606
                        break;
607
                if (lastch == '\r' || lastch == '\n')
608
                        continue;
609
                if (nn < 3500) buf[nn++] = '\n';
610
                if (nn < 3500) buf[nn++] = '\t';
611
                if (nn < 3500) buf[nn++] = '\t';
612
                if (nn < 3500) buf[nn++] = '\t';
613
                if (nn < 3500) buf[nn++] = lastch;
614
                while (lastch != '\n') {
615
                        getch();
616
                        if (lastch == '}')
617
                                goto j1;
618
                        if (lastch == '\r' || lastch == '\n')
619
                                break;
620
                        if (nn < 3500) buf[nn++] = lastch;
621
                }
622
        } while (lastch != -1 && nn < 3500);
623
j1:
624
        if (nn >= 3500)
625
                error(ERR_ASMTOOLONG);
626
        buf[nn] = '\0';
627
        snp->label = (int64_t *)my_strdup(buf);
628
        return (snp);
629
}
630
 
631
Statement *Statement::ParseTry()
632
{
633
        Statement *snp;
634
        Statement *hd, *tl;
635
 
636
        hd = (Statement *)NULL;
637
        tl = (Statement *)NULL;
638
        snp = NewStatement(st_try, TRUE);
639
        snp->s1 = Statement::Parse();
640
        // Empty statements return NULL
641
        if (snp->s1)
642
                snp->s1->outer = snp;
643
        if (lastst != kw_catch)
644
                error(ERR_CATCHEXPECT);
645
        while (lastst == kw_catch) {
646
                if (hd == NULL) {
647
                        hd = tl = ParseCatch();
648
                        if (hd)
649
                                hd->outer = snp;
650
                }
651
                else {
652
                        tl->next = ParseCatch();
653
                        if (tl->next != NULL) {
654
                                tl->next->outer = snp;
655
                                tl = tl->next;
656
                        }
657
                }
658
                if (tl == (Statement *)NULL) break;     // end of file in try
659
                tl->next = (Statement *)NULL;
660
        }
661
        snp->s2 = hd;
662
        return (snp);
663
}
664
 
665
Statement *Statement::ParseExpression()
666
{
667
        Statement *snp;
668
 
669
        dfs.printf("<ParseExpression>\n");
670
        snp = NewStatement(st_expr, FALSE);
671
        if (expression(&(snp->exp)) == NULL) {
672
                error(ERR_EXPREXPECT);
673
                NextToken();
674
        }
675
        if (lastst != end)
676
                needpunc(semicolon, 44);
677
        dfs.printf("</ParseExpression>\n");
678
        return (snp);
679
}
680
 
681
// Parse a compound statement.
682
 
683
Statement *Statement::ParseCompound()
684
{
685
        Statement *snp;
686
        Statement *head, *tail;
687
        Statement *p;
688
 
689
        snp = NewStatement(st_compound, FALSE);
690
        currentStmt = snp;
691
        head = 0;
692
        if (lastst == colon) {
693
                NextToken();
694
                TRACE(printf("Compound <%s>\r\n", lastid);)
695
                        if (strcmp(lastid, "clockbug") == 0)
696
                                printf("clockbug\r\n");
697
                NextToken();
698
        }
699
        AutoDeclaration::Parse(NULL, &snp->ssyms);
700
        cseg();
701
        // Add the first statement at the head of the list.
702
        p = currentStmt;
703
        if (lastst == kw_prolog) {
704
                NextToken();
705
                currentFn->prolog = snp->prolog = Statement::Parse();
706
        }
707
        if (lastst == kw_epilog) {
708
                NextToken();
709
                currentFn->epilog = snp->epilog = Statement::Parse();
710
        }
711
        if (lastst == kw_prolog) {
712
                NextToken();
713
                currentFn->prolog = snp->prolog = Statement::Parse();
714
        }
715
        if (lastst != end) {
716
                head = tail = Statement::Parse();
717
                if (head)
718
                        head->outer = snp;
719
        }
720
        //else {
721
        //       head = tail = NewStatement(st_empty,1);
722
        //      if (head)
723
        //              head->outer = snp;
724
        //}
725
        // Add remaining statements onto the tail of the list.
726
        while (lastst != end) {
727
                if (lastst == kw_prolog) {
728
                        NextToken();
729
                        currentFn->prolog = snp->prolog = Statement::Parse();
730
                }
731
                else if (lastst == kw_epilog) {
732
                        NextToken();
733
                        currentFn->epilog = snp->epilog = Statement::Parse();
734
                }
735
                else
736
                {
737
                        tail->next = Statement::Parse();
738
                        if (tail->next != NULL) {
739
                                tail->next->outer = snp;
740
                                tail = tail->next;
741
                        }
742
                }
743
        }
744
        currentStmt = p;
745
        NextToken();
746
        snp->s1 = head;
747
        return (snp);
748
}
749
 
750
Statement *Statement::ParseLabel()
751
{
752
        Statement *snp;
753
        SYM *sp;
754
 
755
        snp = NewStatement(st_label, FALSE);
756
        if ((sp = currentFn->sym->lsyms.Find(lastid, false)) == NULL) {
757
                sp = allocSYM();
758
                sp->SetName(*(new std::string(lastid)));
759
                sp->storage_class = sc_label;
760
                sp->tp = TYP::Make(bt_label, 0);
761
                sp->value.i = nextlabel++;
762
                currentFn->sym->lsyms.insert(sp);
763
        }
764
        else {
765
                if (sp->storage_class != sc_ulabel)
766
                        error(ERR_LABEL);
767
                else
768
                        sp->storage_class = sc_label;
769
        }
770
        NextToken();       /* get past id */
771
        needpunc(colon, 45);
772
        if (sp->storage_class == sc_label) {
773
                snp->label = (int64_t *)sp->value.i;
774
                snp->next = (Statement *)NULL;
775
                return (snp);
776
        }
777
        return (0);
778
}
779
 
780
Statement *Statement::ParseGoto()
781
{
782
        Statement *snp;
783
        SYM *sp;
784
 
785
        NextToken();
786
        loopexit = TRUE;
787
        if (lastst != id) {
788
                error(ERR_IDEXPECT);
789
                return ((Statement *)NULL);
790
        }
791
        snp = NewStatement(st_goto, FALSE);
792
        if ((sp = currentFn->sym->lsyms.Find(lastid, false)) == NULL) {
793
                sp = allocSYM();
794
                sp->SetName(*(new std::string(lastid)));
795
                sp->value.i = nextlabel++;
796
                sp->storage_class = sc_ulabel;
797
                sp->tp = 0;
798
                currentFn->sym->lsyms.insert(sp);
799
        }
800
        NextToken();       /* get past label name */
801
        if (lastst != end)
802
                needpunc(semicolon, 46);
803
        if (sp->storage_class != sc_label && sp->storage_class != sc_ulabel)
804
                error(ERR_LABEL);
805
        else {
806
                snp->stype = st_goto;
807
                snp->label = (int64_t *)sp->value.i;
808
                snp->next = (Statement *)NULL;
809
                return (snp);
810
        }
811
        return ((Statement *)NULL);
812
}
813
 
814
Statement *Statement::Parse()
815
{
816
        Statement *snp;
817
        dfs.puts("<Parse>");
818
        switch (lastst) {
819
        case semicolon:
820
                snp = NewStatement(st_empty, 1);
821
                break;
822
        case begin:
823
                NextToken();
824
                stmtdepth++;
825
                snp = ParseCompound();
826
                stmtdepth--;
827
                return snp;
828
        case kw_check:
829
                snp = ParseCheckStatement();
830
                break;
831
                /*
832
                case kw_prolog:
833
                snp = NewStatement(st_empty,1);
834
                currentFn->prolog = Statement::Parse(); break;
835
                case kw_epilog:
836
                snp = NewStatement(st_empty,1);
837
                currentFn->epilog = Statement::Parse(); break;
838
                */
839
        case kw_if: snp = ParseIf(); break;
840
        case kw_while: snp = ParseWhile(); break;
841
        case kw_until: snp = ParseUntil(); break;
842
        case kw_for:   snp = ParseFor();   break;
843
        case kw_forever: snp = ParseForever(); break;
844
        case kw_firstcall: snp = ParseFirstcall(); break;
845
        case kw_return: snp = ParseReturn(); break;
846
        case kw_break: snp = ParseBreak(); break;
847
        case kw_goto: snp = ParseGoto(); break;
848
        case kw_continue: snp = ParseContinue(); break;
849
        case kw_do:
850
        case kw_loop: snp = ParseDo(); break;
851
        case kw_switch: snp = ParseSwitch(); break;
852
        case kw_try: snp = ParseTry(); break;
853
        case kw_throw: snp = ParseThrow(); break;
854
        case kw_stop: snp = ParseStop(); break;
855
        case kw_asm: snp = ParseAsm(); break;
856
        case id:
857
                SkipSpaces();
858
                if (lastch == ':')
859
                        return ParseLabel();
860
                // else fall through to parse expression
861
        default:
862
                snp = ParseExpression();
863
                break;
864
        }
865
        if (snp != NULL) {
866
                snp->next = (Statement *)NULL;
867
        }
868
        dfs.puts("</Parse>");
869
        return (snp);
870
}
871
 
872
 
873
/*
874
*      repcse will scan through a block of statements replacing the
875
*      optimized expressions with their temporary references.
876
*/
877
void Statement::repcse()
878
{
879
        Statement *block = this;
880
 
881
        while (block != NULL) {
882
                switch (block->stype) {
883
                case st_compound:
884
                        block->prolog->repcse();
885
                        block->repcse_compound();
886
                        block->epilog->repcse();
887
                        break;
888
                case st_return:
889
                case st_throw:
890
                        block->exp->repexpr();
891
                        break;
892
                case st_check:
893
                        block->exp->repexpr();
894
                        break;
895
                case st_expr:
896
                        block->exp->repexpr();
897
                        break;
898
                case st_while:
899
                case st_until:
900
                case st_dowhile:
901
                case st_dountil:
902
                        block->exp->repexpr();
903
                case st_do:
904
                case st_doloop:
905
                case st_forever:
906
                        block->s1->repcse();
907
                        block->s2->repcse();
908
                        break;
909
                case st_for:
910
                        block->initExpr->repexpr();
911
                        block->exp->repexpr();
912
                        block->s1->repcse();
913
                        block->incrExpr->repexpr();
914
                        break;
915
                case st_if:
916
                        block->exp->repexpr();
917
                        block->s1->repcse();
918
                        block->s2->repcse();
919
                        break;
920
                case st_switch:
921
                        block->exp->repexpr();
922
                        block->s1->repcse();
923
                        break;
924
                case st_try:
925
                case st_catch:
926
                case st_case:
927
                case st_default:
928
                case st_firstcall:
929
                        block->s1->repcse();
930
                        break;
931
                }
932
                block = block->next;
933
        }
934
}
935
 
936
void Statement::repcse_compound()
937
{
938
        SYM *sp;
939
 
940
        sp = sp->GetPtr(ssyms.GetHead());
941
        while (sp) {
942
                if (sp->initexp) {
943
                        sp->initexp->repexpr();
944
                }
945
                sp = sp->GetNextPtr();
946
        }
947
        s1->repcse();
948
}
949
 
950
void Statement::scan_compound()
951
{
952
        SYM *sp;
953
 
954
        sp = sp->GetPtr(ssyms.GetHead());
955
        while (sp) {
956
                if (sp->initexp) {
957
                        opt_const(&sp->initexp);
958
                        sp->initexp->scanexpr(0);
959
                }
960
                sp = sp->GetNextPtr();
961
        }
962
        s1->scan();
963
}
964
 
965
 
966
//      scan will gather all optimizable expressions into the expression
967
//      list for a block of statements.
968
 
969
void Statement::scan()
970
{
971
        Statement *block = this;
972
 
973
        dfs.printf("<Statement__Scan>");
974
        loop_active = 1;
975
        while (block != NULL) {
976
                dfs.printf("B");
977
                switch (block->stype) {
978
                case st_compound:
979
                        dfs.printf("C\n");
980
                        block->prolog->scan();
981
                        block->scan_compound();
982
                        block->epilog->scan();
983
                        dfs.printf("c");
984
                        break;
985
                case st_check:
986
                case st_return:
987
                case st_throw:
988
                case st_expr:
989
                        dfs.printf("E");
990
                        opt_const(&block->exp);
991
                        block->exp->scanexpr(0);
992
                        dfs.printf("e");
993
                        break;
994
                case st_dowhile:
995
                        dfs.printf("{do}");
996
                        loop_active++;
997
                        opt_const(&block->exp);
998
                        block->exp->scanexpr(0);
999
                        block->s1->scan();
1000
                        loop_active--;
1001
                        dfs.printf("{/do}");
1002
                        break;
1003
                case st_while:
1004
                case st_until:
1005
                case st_dountil:
1006
                        loop_active++;
1007
                        opt_const(&block->exp);
1008
                        block->exp->scanexpr(0);
1009
                        block->s1->scan();
1010
                        loop_active--;
1011
                        break;
1012
                case st_do:
1013
                case st_doloop:
1014
                case st_forever:
1015
                        loop_active++;
1016
                        block->s1->scan();
1017
                        loop_active--;
1018
                        break;
1019
                case st_for:
1020
                        loop_active++;
1021
                        opt_const(&block->initExpr);
1022
                        block->initExpr->scanexpr(0);
1023
                        opt_const(&block->exp);
1024
                        block->exp->scanexpr(0);
1025
                        block->s1->scan();
1026
                        opt_const(&block->incrExpr);
1027
                        block->incrExpr->scanexpr(0);
1028
                        loop_active--;
1029
                        break;
1030
                case st_if:
1031
                        dfs.printf("{if}");
1032
                        opt_const(&block->exp);
1033
                        block->exp->scanexpr(0);
1034
                        block->s1->scan();
1035
                        block->s2->scan();
1036
                        dfs.printf("{/if}");
1037
                        break;
1038
                case st_switch:
1039
                        opt_const(&block->exp);
1040
                        block->exp->scanexpr(0);
1041
                        block->s1->scan();
1042
                        break;
1043
                case st_firstcall:
1044
                case st_case:
1045
                case st_default:
1046
                        block->s1->scan();
1047
                        break;
1048
                        //case st_spinlock:
1049
                        //        scan(block->s1);
1050
                        //        scan(block->s2);
1051
                        //        break;
1052
                        // nothing to process for these statement
1053
                case st_break:
1054
                case st_continue:
1055
                case st_goto:
1056
                        break;
1057
                default:;// printf("Uncoded statement in scan():%d\r\n", block->stype);
1058
                }
1059
                block = block->next;
1060
        }
1061
        dfs.printf("</Statement__Scan>");
1062
}
1063
 
1064
 
1065
//=============================================================================
1066
//=============================================================================
1067
// C O D E   G E N E R A T I O N
1068
//=============================================================================
1069
//=============================================================================
1070
 
1071
void Statement::GenMixedSource()
1072
{
1073
        if (mixedSource) {
1074
                rtrim(lptr);
1075
                if (strcmp(lptr, last_rem) != 0) {
1076
                        GenerateMonadic(op_rem, 0, make_string(lptr));
1077
                        strncpy_s(last_rem, 131, lptr, 130);
1078
                        last_rem[131] = '\0';
1079
                }
1080
        }
1081
}
1082
 
1083
void Statement::GenerateWhile()
1084
{
1085
        int lab1, lab2;
1086
 
1087
        initstack();
1088
        lab1 = contlab;
1089
        lab2 = breaklab;
1090
        contlab = nextlabel++;
1091
        GenerateLabel(contlab);
1092
        if (s1 != NULL)
1093
        {
1094
                breaklab = nextlabel++;
1095
                initstack();
1096
                GenerateFalseJump(exp, breaklab, 2);
1097
                looplevel++;
1098
                s1->Generate();
1099
                looplevel--;
1100
                GenerateMonadic(op_bra, 0, make_clabel(contlab));
1101
                GenerateLabel(breaklab);
1102
                breaklab = lab2;
1103
        }
1104
        else
1105
        {
1106
                initstack();
1107
                GenerateTrueJump(exp, contlab, prediction);
1108
        }
1109
        contlab = lab1;
1110
}
1111
 
1112
void Statement::GenerateUntil()
1113
{
1114
        int lab1, lab2;
1115
 
1116
        initstack();
1117
        lab1 = contlab;
1118
        lab2 = breaklab;
1119
        contlab = nextlabel++;
1120
        GenerateLabel(contlab);
1121
        if (s1 != NULL)
1122
        {
1123
                breaklab = nextlabel++;
1124
                initstack();
1125
                GenerateTrueJump(exp, breaklab, 2);
1126
                looplevel++;
1127
                s1->Generate();
1128
                looplevel--;
1129
                GenerateMonadic(op_bra, 0, make_clabel(contlab));
1130
                GenerateLabel(breaklab);
1131
                breaklab = lab2;
1132
        }
1133
        else
1134
        {
1135
                initstack();
1136
                GenerateFalseJump(exp, contlab, prediction);
1137
        }
1138
        contlab = lab1;
1139
}
1140
 
1141
 
1142
void Statement::GenerateFor()
1143
{
1144
        int old_break, old_cont, exit_label, loop_label;
1145
 
1146
        old_break = breaklab;
1147
        old_cont = contlab;
1148
        loop_label = nextlabel++;
1149
        exit_label = nextlabel++;
1150
        contlab = nextlabel++;
1151
        initstack();
1152
        if (initExpr != NULL)
1153
                ReleaseTempRegister(GenerateExpression(initExpr, F_ALL | F_NOVALUE
1154
                        , GetNaturalSize(initExpr)));
1155
        GenerateLabel(loop_label);
1156
        initstack();
1157
        if (exp != NULL)
1158
                GenerateFalseJump(exp, exit_label, 2);
1159
        if (s1 != NULL)
1160
        {
1161
                breaklab = exit_label;
1162
                looplevel++;
1163
                s1->Generate();
1164
                looplevel--;
1165
        }
1166
        GenerateLabel(contlab);
1167
        initstack();
1168
        if (incrExpr != NULL)
1169
                ReleaseTempRegister(GenerateExpression(incrExpr, F_ALL | F_NOVALUE, GetNaturalSize(incrExpr)));
1170
        GenerateMonadic(op_bra, 0, make_clabel(loop_label));
1171
        breaklab = old_break;
1172
        contlab = old_cont;
1173
        GenerateLabel(exit_label);
1174
}
1175
 
1176
 
1177
void Statement::GenerateForever()
1178
{
1179
        int old_break, old_cont, exit_label, loop_label;
1180
        old_break = breaklab;
1181
        old_cont = contlab;
1182
        loop_label = nextlabel++;
1183
        exit_label = nextlabel++;
1184
        contlab = loop_label;
1185
        GenerateLabel(loop_label);
1186
        if (s1 != NULL)
1187
        {
1188
                breaklab = exit_label;
1189
                looplevel++;
1190
                s1->Generate();
1191
                looplevel--;
1192
        }
1193
        GenerateMonadic(op_bra, 0, make_clabel(loop_label));
1194
        breaklab = old_break;
1195
        contlab = old_cont;
1196
        GenerateLabel(exit_label);
1197
}
1198
 
1199
void Statement::GenerateIf()
1200
{
1201
        int lab1, lab2, oldbreak;
1202
        ENODE *ep, *node;
1203
        int size;
1204
        Operand *ap1;
1205
 
1206
        lab1 = nextlabel++;     // else label
1207
        lab2 = nextlabel++;     // exit label
1208
        oldbreak = breaklab;    // save break label
1209
        initstack();            // clear temps
1210
        ep = node = exp;
1211
 
1212
        // Note the compiler makes two passes at code generation. During the first pass
1213
        // the node type is set to en_bchk and the node pointers are manipulated. So for
1214
        // the second pass this does not need to be done again.
1215
        /*
1216
        if (ep->nodetype == en_bchk) {
1217
        size = GetNaturalSize(node);
1218
        ap1 = GenerateExpression(node->p[0], F_REG, size);
1219
        ap2 = GenerateExpression(node->p[1], F_REG, size);
1220
        ap3 = GenerateExpression(node->p[2], F_REG|F_IMM0, size);
1221
        if (ap3->mode == am_imm) {
1222
        ReleaseTempReg(ap3);
1223
        ap3 = makereg(0);
1224
        }
1225
        Generate4adic(op_bchk, 0, ap1, ap3, ap2, make_label(lab1));     // the nodes are processed in reversed order
1226
        ReleaseTempRegister(ap3);
1227
        ReleaseTempRegister(ap2);
1228
        ReleaseTempRegister(ap1);
1229
        }
1230
        else if (!opt_nocgo && ep->nodetype==en_lor && ep->p[0]->nodetype == en_lt && ep->p[1]->nodetype == en_ge && equalnode(ep->p[0]->p[0], ep->p[1]->p[0])) {
1231
        ep->nodetype = en_bchk;
1232
        if (ep->p[0])
1233
        ep->p[2] = ep->p[0]->p[1];
1234
        else
1235
        ep->p[2] = NULL;
1236
        ep->p[1] = ep->p[1]->p[1];
1237
        ep->p[0] = ep->p[0]->p[0];
1238
        size = GetNaturalSize(node);
1239
        ap1 = GenerateExpression(node->p[0], F_REG, size);
1240
        ap2 = GenerateExpression(node->p[1], F_REG, size);
1241
        ap3 = GenerateExpression(node->p[2], F_REG, size);
1242
        Generate4adic(op_bchk, 0, ap1, ap2, ap3, make_label(lab1));
1243
        ReleaseTempRegister(ap3);
1244
        ReleaseTempRegister(ap2);
1245
        ReleaseTempRegister(ap1);
1246
        }
1247
        else
1248
        */
1249
        // Check for bbc optimization
1250
        if (!opt_nocgo && ep->nodetype == en_and && ep->p[1]->nodetype == en_icon && pwrof2(ep->p[1]->i) >= 0) {
1251
                size = GetNaturalSize(node);
1252
                ap1 = GenerateExpression(node->p[0], F_REG, size);
1253
                GenerateTriadic(op_bbc, 0, ap1, make_immed(pwrof2(ep->p[1]->i)), make_label(lab1));
1254
                ReleaseTempRegister(ap1);
1255
        }
1256
        else
1257
                GenerateFalseJump(exp, lab1, prediction);
1258
        s1->Generate();
1259
        if (s2 != 0)             /* else part exists */
1260
        {
1261
                GenerateDiadic(op_bra, 0, make_clabel(lab2), 0);
1262
                if (mixedSource)
1263
                        GenerateMonadic(op_rem, 0, make_string("; else"));
1264
                GenerateLabel(lab1);
1265
                s2->Generate();
1266
                GenerateLabel(lab2);
1267
        }
1268
        else
1269
                GenerateLabel(lab1);
1270
        breaklab = oldbreak;
1271
}
1272
 
1273
void Statement::GenerateDoOnce()
1274
{
1275
        int oldcont, oldbreak;
1276
        oldcont = contlab;
1277
        oldbreak = breaklab;
1278
        contlab = nextlabel++;
1279
        GenerateLabel(contlab);
1280
        breaklab = nextlabel++;
1281
        looplevel++;
1282
        s1->Generate();
1283
        looplevel--;
1284
        GenerateLabel(breaklab);
1285
        breaklab = oldbreak;
1286
        contlab = oldcont;
1287
}
1288
 
1289
void Statement::GenerateDoWhile()
1290
{
1291
        int oldcont, oldbreak;
1292
        oldcont = contlab;
1293
        oldbreak = breaklab;
1294
        contlab = nextlabel++;
1295
        GenerateLabel(contlab);
1296
        breaklab = nextlabel++;
1297
        looplevel++;
1298
        s1->Generate();
1299
        looplevel--;
1300
        initstack();
1301
        GenerateTrueJump(exp, contlab, 3);
1302
        GenerateLabel(breaklab);
1303
        breaklab = oldbreak;
1304
        contlab = oldcont;
1305
}
1306
 
1307
void Statement::GenerateDoUntil()
1308
{
1309
        int oldcont, oldbreak;
1310
        oldcont = contlab;
1311
        oldbreak = breaklab;
1312
        contlab = nextlabel++;
1313
        GenerateLabel(contlab);
1314
        breaklab = nextlabel++;
1315
        looplevel++;
1316
        s1->Generate();
1317
        looplevel--;
1318
        initstack();
1319
        GenerateFalseJump(exp, contlab, 3);
1320
        GenerateLabel(breaklab);
1321
        breaklab = oldbreak;
1322
        contlab = oldcont;
1323
}
1324
 
1325
void Statement::GenerateDoLoop()
1326
{
1327
        int oldcont, oldbreak;
1328
        oldcont = contlab;
1329
        oldbreak = breaklab;
1330
        contlab = nextlabel++;
1331
        GenerateLabel(contlab);
1332
        breaklab = nextlabel++;
1333
        looplevel++;
1334
        s1->Generate();
1335
        looplevel--;
1336
        GenerateMonadic(op_bra, 0, make_clabel(contlab));
1337
        GenerateLabel(breaklab);
1338
        breaklab = oldbreak;
1339
        contlab = oldcont;
1340
}
1341
 
1342
 
1343
/*
1344
*      generate a call to a library routine.
1345
*/
1346
//void call_library(char *lib_name)
1347
//{    
1348
//      SYM     *sp;
1349
//    sp = gsearch(lib_name);
1350
//    if( sp == NULL )
1351
//    {
1352
//              ++global_flag;
1353
//              sp = allocSYM();
1354
//              sp->tp = &stdfunc;
1355
//              sp->name = lib_name;
1356
//              sp->storage_class = sc_external;
1357
//              insert(sp,&gsyms);
1358
//              --global_flag;
1359
//    }
1360
//    GenerateDiadic(op_call,0,make_strlab(lib_name),NULL);
1361
//}
1362
 
1363
//
1364
// Generate a switch composed of a series of compare and branch instructions.
1365
// Also called a linear switch.
1366
//
1367
void Statement::GenerateLinearSwitch()
1368
{
1369
        int curlab;
1370
        int64_t *bf;
1371
        int nn, jj;
1372
        Statement *defcase, *stmt;
1373
        Operand *ap, *ap1;
1374
 
1375
        curlab = nextlabel++;
1376
        defcase = 0;
1377
        initstack();
1378
        if (exp == NULL) {
1379
                error(ERR_BAD_SWITCH_EXPR);
1380
                return;
1381
        }
1382
        ap = GenerateExpression(exp, F_REG, GetNaturalSize(exp));
1383
        //        if( ap->preg != 0 )
1384
        //                GenerateDiadic(op_mov,0,makereg(1),ap);
1385
        //              ReleaseTempRegister(ap);
1386
        for (stmt = s1; stmt != NULL; stmt = stmt->next)
1387
        {
1388
                stmt->GenMixedSource();
1389
                if (stmt->s2)          /* default case ? */
1390
                {
1391
                        stmt->label = (int64_t *)curlab;
1392
                        defcase = stmt;
1393
                }
1394
                else
1395
                {
1396
                        bf = (int64_t *)stmt->casevals;
1397
                        for (nn = (int)bf[0]; nn >= 1; nn--) {
1398
                                if ((jj = pwrof2(bf[nn])) != -1) {
1399
                                        GenerateTriadic(op_bbs, 0, ap, make_immed(jj), make_clabel(curlab));
1400
                                }
1401
                                else if (bf[nn] < -256 || bf[nn] > 255) {
1402
                                        ap1 = GetTempRegister();
1403
                                        GenerateTriadic(op_xor, 0, ap1, ap, make_immed(bf[nn]));
1404
                                        ReleaseTempRegister(ap1);
1405
                                        GenerateTriadic(op_beq, 0, ap1, makereg(0), make_clabel(curlab));
1406
                                }
1407
                                else {
1408
                                        GenerateTriadic(op_beqi, 0, ap, make_immed(bf[nn]), make_clabel(curlab));
1409
                                }
1410
                        }
1411
                        //GenerateDiadic(op_dw,0,make_label(curlab), make_direct(stmt->label));
1412
                        stmt->label = (int64_t *)curlab;
1413
                }
1414
                if (stmt->s1 != NULL && stmt->next != NULL)
1415
                        curlab = nextlabel++;
1416
        }
1417
        if (defcase == NULL)
1418
                GenerateMonadic(op_bra, 0, make_clabel(breaklab));
1419
        else
1420
                GenerateMonadic(op_bra, 0, make_clabel((int)defcase->label));
1421
        ReleaseTempRegister(ap);
1422
}
1423
 
1424
 
1425
// generate all cases for a switch statement.
1426
//
1427
void Statement::GenerateCase()
1428
{
1429
        Statement *stmt;
1430
 
1431
        for (stmt = this; stmt != (Statement *)NULL; stmt = stmt->next)
1432
        {
1433
                stmt->GenMixedSource();
1434
                if (stmt->s1 != (Statement *)NULL)
1435
                {
1436
                        GenerateLabel((int)stmt->label);
1437
                        stmt->s1->Generate();
1438
                }
1439
                else if (stmt->next == (Statement *)NULL)
1440
                        GenerateLabel((int)stmt->label);
1441
        }
1442
}
1443
 
1444
static int casevalcmp(const void *a, const void *b)
1445
{
1446
        int64_t aa, bb;
1447
        aa = ((scase *)a)->val;
1448
        bb = ((scase *)b)->val;
1449
        if (aa < bb)
1450
                return -1;
1451
        else if (aa == bb)
1452
                return 0;
1453
        else
1454
                return 1;
1455
}
1456
 
1457
 
1458
// Currently inline in GenerateSwitch()
1459
void Statement::GenerateTabularSwitch()
1460
{
1461
}
1462
 
1463
//
1464
// Analyze and generate best switch statement.
1465
//
1466
void Statement::GenerateSwitch()
1467
{
1468
        Operand *ap, *ap1, *ap2;
1469
        Statement *st, *defcase;
1470
        int oldbreak;
1471
        int tablabel;
1472
        int64_t *bf;
1473
        int64_t nn;
1474
        int64_t mm, kk;
1475
        int64_t minv, maxv;
1476
        int deflbl;
1477
        int curlab;
1478
        oldbreak = breaklab;
1479
        breaklab = nextlabel++;
1480
        bf = (int64_t *)label;
1481
        minv = 0x7FFFFFFFL;
1482
        maxv = 0;
1483
        struct scase casetab[512];
1484
 
1485
        st = s1;
1486
        mm = 0;
1487
        deflbl = 0;
1488
        defcase = nullptr;
1489
        curlab = nextlabel++;
1490
        // Determine minimum and maximum values in all cases
1491
        // Record case values and labels.
1492
        for (st = s1; st != (Statement *)NULL; st = st->next)
1493
        {
1494
                if (st->s2) {
1495
                        defcase = st->s2;
1496
                        deflbl = curlab;
1497
                        curlab = nextlabel++;
1498
                }
1499
                else {
1500
                        bf = st->casevals;
1501
                        for (nn = bf[0]; nn >= 1; nn--) {
1502
                                minv = min(bf[nn], minv);
1503
                                maxv = max(bf[nn], maxv);
1504
                                st->label = (int64_t *)curlab;
1505
                                casetab[mm].label = curlab;
1506
                                casetab[mm].val = bf[nn];
1507
                                mm++;
1508
                        }
1509
                        curlab = nextlabel++;
1510
                }
1511
        }
1512
        //
1513
        // check case density
1514
        // If there are enough cases
1515
        // and if the case is dense enough use a computed jump
1516
        if (mm * 100 / max((maxv - minv), 1) > 50 && (maxv - minv) > (nkd ? 7 : 12)) {
1517
                if (deflbl == 0)
1518
                        deflbl = nextlabel++;
1519
                for (nn = mm; nn < 512; nn++) {
1520
                        casetab[nn].label = deflbl;
1521
                        casetab[nn].val = maxv + 1;
1522
                }
1523
                for (kk = minv; kk < maxv; kk++) {
1524
                        for (nn = 0; nn < mm; nn++) {
1525
                                if (casetab[nn].val == kk)
1526
                                        goto j1;
1527
                        }
1528
                        // value not found
1529
                        casetab[mm].val = kk;
1530
                        casetab[mm].label = defcase ? (int)defcase->label : breaklab;
1531
                        mm++;
1532
                j1:;
1533
                }
1534
                qsort(&casetab[0], 512, sizeof(struct scase), casevalcmp);
1535
                tablabel = caselit(casetab, maxv - minv + 1);
1536
                ap = GenerateExpression(exp, F_REG, GetNaturalSize(exp));
1537
                ap1 = GetTempRegister();
1538
                ap2 = GetTempRegister();
1539
                if (!nkd) {
1540
                        GenerateDiadic(op_ldi, 0, ap1, make_immed(minv));
1541
                        GenerateTriadic(op_blt, 0, ap, ap1, make_clabel(defcase ? (int)defcase->label : breaklab));
1542
                        GenerateDiadic(op_ldi, 0, ap2, make_immed(maxv + 1));
1543
                        GenerateTriadic(op_bge, 0, ap, ap2, make_clabel(defcase ? (int)defcase->label : breaklab));
1544
                        //Generate4adic(op_chk,0,ap,ap1,ap2,make_clabel(defcase ? (int)defcase->label : breaklab));
1545
                }
1546
                if (minv != 0)
1547
                        GenerateTriadic(op_sub, 0, ap, ap, make_immed(minv));
1548
                GenerateTriadic(op_shl, 0, ap, ap, make_immed(3));
1549
                GenerateDiadic(op_lw, 0, ap, make_indexed2(tablabel, ap->preg));
1550
                GenerateDiadic(op_jal, 0, makereg(0), make_indexed(0, ap->preg));
1551
                s1->GenerateCase();
1552
                GenerateLabel(breaklab);
1553
                return;
1554
        }
1555
        GenerateLinearSwitch();
1556
        s1->GenerateCase();
1557
        GenerateLabel(breaklab);
1558
        breaklab = oldbreak;
1559
}
1560
 
1561
void Statement::GenerateTry()
1562
{
1563
        int lab1, curlab;
1564
        int oldthrow;
1565
        Operand *a, *ap2;
1566
        ENODE *node;
1567
        Statement *stmt;
1568
 
1569
        lab1 = nextlabel++;
1570
        oldthrow = throwlab;
1571
        throwlab = nextlabel++;
1572
 
1573
        a = make_clabel(throwlab);
1574
        a->mode = am_imm;
1575
        GenerateDiadic(op_ldi, 0, makereg(regXLR), a);
1576
        s1->Generate();
1577
        GenerateMonadic(op_bra, 0, make_clabel(lab1));
1578
        GenerateLabel(throwlab);
1579
        // Generate catch statements
1580
        // r1 holds the value to be assigned to the catch variable
1581
        // r2 holds the type number
1582
        for (stmt = s2; stmt; stmt = stmt->next) {
1583
                stmt->GenMixedSource();
1584
                throwlab = oldthrow;
1585
                curlab = nextlabel++;
1586
                GenerateLabel(curlab);
1587
                if (stmt->num == 99999)
1588
                        ;
1589
                else {
1590
                        ap2 = GetTempRegister();
1591
                        GenerateDiadic(op_ldi, 0, ap2, make_immed(stmt->num));
1592
                        ReleaseTempReg(ap2);
1593
                        GenerateTriadic(op_bne, 0, makereg(2), ap2, make_clabel(nextlabel));
1594
                }
1595
                // move the throw expression result in 'r1' into the catch variable.
1596
                node = stmt->exp;
1597
                ap2 = GenerateExpression(node, F_REG | F_MEM, GetNaturalSize(node));
1598
                if (ap2->mode == am_reg)
1599
                        GenerateDiadic(op_mov, 0, ap2, makereg(1));
1600
                else
1601
                        GenStore(makereg(1), ap2, GetNaturalSize(node));
1602
                ReleaseTempRegister(ap2);
1603
                //            GenStore(makereg(1),make_indexed(sym->value.i,regFP),sym->tp->size);
1604
                stmt->s1->Generate();
1605
        }
1606
        GenerateLabel(nextlabel);
1607
        nextlabel++;
1608
        GenerateLabel(lab1);
1609
        a = make_clabel(oldthrow);
1610
        a->mode = am_imm;
1611
        GenerateDiadic(op_ldi, 0, makereg(regXLR), a);
1612
}
1613
 
1614
void Statement::GenerateThrow()
1615
{
1616
        Operand *ap;
1617
 
1618
        if (exp != NULL)
1619
        {
1620
                initstack();
1621
                ap = GenerateExpression(exp, F_ALL, 8);
1622
                if (ap->mode == am_imm)
1623
                        GenerateDiadic(op_ldi, 0, makereg(1), ap);
1624
                else if (ap->mode != am_reg)
1625
                        GenerateDiadic(op_lw, 0, makereg(1), ap);
1626
                else if (ap->preg != 1)
1627
                        GenerateDiadic(op_mov, 0, makereg(1), ap);
1628
                ReleaseTempRegister(ap);
1629
                // If a system exception is desired create an appropriate BRK instruction.
1630
                if (num == bt_exception) {
1631
                        GenerateDiadic(op_brk, 0, makereg(1), make_immed(1));
1632
                        return;
1633
                }
1634
                GenerateDiadic(op_ldi, 0, makereg(2), make_immed(num));
1635
        }
1636
        GenerateMonadic(op_bra, 0, make_clabel(throwlab));
1637
}
1638
 
1639
void Statement::GenerateCheck()
1640
{
1641
        Operand *ap1, *ap2, *ap3;
1642
        ENODE *node, *ep;
1643
        int size;
1644
 
1645
        initstack();
1646
        ep = node = exp;
1647
        if (ep->p[0]->nodetype == en_lt && ep->p[1]->nodetype == en_ge && ENODE::IsEqual(ep->p[0]->p[0], ep->p[1]->p[0])) {
1648
                ep->nodetype = en_chk;
1649
                if (ep->p[0])
1650
                        ep->p[2] = ep->p[0]->p[1];
1651
                else
1652
                        ep->p[2] = NULL;
1653
                ep->p[1] = ep->p[1]->p[1];
1654
                ep->p[0] = ep->p[0]->p[0];
1655
        }
1656
        else if (ep->p[0]->nodetype == en_ge && ep->p[1]->nodetype == en_lt && ENODE::IsEqual(ep->p[0]->p[0], ep->p[1]->p[0])) {
1657
                ep->nodetype = en_chk;
1658
                if (ep->p[1])
1659
                        ep->p[2] = ep->p[1]->p[1];
1660
                else
1661
                        ep->p[2] = NULL;
1662
                ep->p[1] = ep->p[0]->p[1];
1663
                ep->p[0] = ep->p[0]->p[0];
1664
        }
1665
        if (ep->nodetype != en_chk) {
1666
                /*
1667
                printf("ep->p[0]->p[0]->i %d\r\n", ep->p[0]->p[0]->i);
1668
                printf("ep->p[1]->p[0]->i %d\r\n", ep->p[1]->p[0]->i);
1669
                printf("ep->p[0]->p[0]->nt: %d\r\n", ep->p[0]->p[0]->nodetype);
1670
                printf("ep->p[1]->p[0]->nt: %d\r\n", ep->p[1]->p[0]->nodetype);
1671
                printf("ep->p[0]->nodetype=%s ",ep->p[0]->nodetype==en_lt ? "en_lt" : ep->p[0]->nodetype==en_ge ? "en_ge" : "en_??");
1672
                printf("ep->p[1]->nodetype=%s\r\n",ep->p[1]->nodetype==en_lt ? "en_lt" : ep->p[1]->nodetype==en_ge ? "en_ge" : "en_??");
1673
                printf("equalnode:%d\r\n",equalnode(ep->p[0]->p[0],ep->p[1]->p[0]));
1674
                */
1675
                error(ERR_CHECK);
1676
                return;
1677
        }
1678
        size = GetNaturalSize(node);
1679
        ap1 = GenerateExpression(node->p[0], F_REG, size);
1680
        ap2 = GenerateExpression(node->p[1], F_REG | F_IMM0, size);
1681
        ap3 = GenerateExpression(node->p[2], F_REG | F_IMMED, size);
1682
        if (ap2->mode == am_imm) {
1683
                ap2->mode = am_reg;
1684
                ap2->preg = 0;
1685
        }
1686
        GenerateTriadic(ap3->mode == am_imm ? op_chki : op_chk, 0, ap1, ap2, ap3);
1687
        ReleaseTempRegister(ap3);
1688
        ReleaseTempRegister(ap2);
1689
        ReleaseTempRegister(ap1);
1690
}
1691
 
1692
void Statement::GenerateCompound()
1693
{
1694
        SYM *sp;
1695
 
1696
        sp = sp->GetPtr(ssyms.GetHead());
1697
        while (sp) {
1698
                if (sp->initexp) {
1699
                        initstack();
1700
                        ReleaseTempRegister(GenerateExpression(sp->initexp, F_ALL, 8));
1701
                }
1702
                sp = sp->GetNextPtr();
1703
        }
1704
        // Generate statement will process the entire list of statements in
1705
        // the block.
1706
        s1->Generate();
1707
}
1708
 
1709
// The same as generating a compound statement but leaves out the generation of
1710
// the prolog and epilog clauses.
1711
void Statement::GenerateFuncBody()
1712
{
1713
        SYM *sp;
1714
 
1715
        sp = sp->GetPtr(ssyms.GetHead());
1716
        while (sp) {
1717
                if (sp->initexp) {
1718
                        initstack();
1719
                        ReleaseTempRegister(GenerateExpression(sp->initexp, F_ALL, 8));
1720
                }
1721
                sp = sp->GetNextPtr();
1722
        }
1723
        // Generate statement will process the entire list of statements in
1724
        // the block.
1725
        s1->Generate();
1726
}
1727
 
1728
void Statement::Generate()
1729
{
1730
        Operand *ap;
1731
        Statement *stmt;
1732
 
1733
        for (stmt = this; stmt != NULL; stmt = stmt->next)
1734
        {
1735
                stmt->GenMixedSource();
1736
                switch (stmt->stype)
1737
                {
1738
                case st_funcbody:
1739
                        stmt->GenerateFuncBody();
1740
                        break;
1741
                case st_compound:
1742
                        stmt->GenerateCompound();
1743
                        break;
1744
                case st_try:
1745
                        stmt->GenerateTry();
1746
                        break;
1747
                case st_throw:
1748
                        stmt->GenerateThrow();
1749
                        break;
1750
                case st_stop:
1751
                        stmt->GenerateStop();
1752
                        break;
1753
                case st_asm:
1754
                        stmt->GenerateAsm();
1755
                        break;
1756
                case st_label:
1757
                        GenerateLabel((int64_t)stmt->label);
1758
                        break;
1759
                case st_goto:
1760
                        GenerateMonadic(op_bra, 0, make_clabel((int64_t)stmt->label));
1761
                        break;
1762
                        //case st_critical:
1763
                        //                    GenerateCritical(stmt);
1764
                        //                    break;
1765
                case st_check:
1766
                        stmt->GenerateCheck();
1767
                        break;
1768
                case st_expr:
1769
                        initstack();
1770
                        ap = GenerateExpression(stmt->exp, F_ALL | F_NOVALUE,
1771
                                GetNaturalSize(stmt->exp));
1772
                        ReleaseTempRegister(ap);
1773
                        tmpFreeAll();
1774
                        break;
1775
                case st_return:
1776
                        currentFn->GenReturn(stmt);
1777
                        break;
1778
                case st_if:
1779
                        stmt->GenerateIf();
1780
                        break;
1781
                case st_do:
1782
                case st_dowhile:
1783
                        stmt->GenerateDoWhile();
1784
                        break;
1785
                case st_dountil:
1786
                        stmt->GenerateDoUntil();
1787
                        break;
1788
                case st_doloop:
1789
                        stmt->GenerateForever();
1790
                        break;
1791
                case st_doonce:
1792
                        stmt->GenerateDoOnce();
1793
                        break;
1794
                case st_while:
1795
                        stmt->GenerateWhile();
1796
                        break;
1797
                case st_until:
1798
                        stmt->GenerateUntil();
1799
                        break;
1800
                case st_for:
1801
                        stmt->GenerateFor();
1802
                        break;
1803
                case st_forever:
1804
                        stmt->GenerateForever();
1805
                        break;
1806
                case st_firstcall:
1807
                        stmt->GenerateFirstcall();
1808
                        break;
1809
                case st_continue:
1810
                        if (contlab == -1)
1811
                                error(ERR_NOT_IN_LOOP);
1812
                        GenerateDiadic(isThor ? op_br : op_bra, 0, make_clabel(contlab), 0);
1813
                        break;
1814
                case st_break:
1815
                        if (breaklab == -1)
1816
                                error(ERR_NOT_IN_LOOP);
1817
                        GenerateDiadic(op_bra, 0, make_clabel(breaklab), 0);
1818
                        break;
1819
                case st_switch:
1820
                        stmt->GenerateSwitch();
1821
                        break;
1822
                case st_empty:
1823
                        break;
1824
                default:
1825
                        printf("DIAG - unknown statement.\n");
1826
                        break;
1827
                }
1828
        }
1829
}
1830
 
1831
void Statement::GenerateStop()
1832
{
1833
        GenerateMonadic(op_stop, 0, make_immed(num));
1834
}
1835
 
1836
void Statement::GenerateAsm()
1837
{
1838
        GenerateMonadic(op_asm, 0, make_string((char *)label));
1839
}
1840
 
1841
void Statement::GenerateFirstcall()
1842
{
1843
        int     lab1, lab2;
1844
        Operand *ap1;
1845
 
1846
        lab1 = contlab;
1847
        lab2 = breaklab;
1848
        contlab = nextlabel++;
1849
        if (s1 != NULL)
1850
        {
1851
                initstack();
1852
                breaklab = nextlabel++;
1853
                ap1 = GetTempRegister();
1854
                GenerateDiadic(op_lh, 0, ap1, make_string(fcname));
1855
                GenerateTriadic(op_beq, 0, ap1, makereg(0), make_clabel(breaklab));
1856
                ReleaseTempRegister(ap1);
1857
                GenerateDiadic(op_sh, 0, makereg(0), make_string(fcname));
1858
                s1->Generate();
1859
                GenerateLabel(breaklab);
1860
                breaklab = lab2;
1861
        }
1862
        contlab = lab1;
1863
}

powered by: WebSVN 2.1.0

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