Subversion Repositories Kolibri OS

Rev

Rev 9847 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
9893 akron1 4
    Copyright (c) 2018-2023, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE PROG;
9
 
8859 leency 10
IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS, STRINGS, PATHS;
7597 akron1 11
 
12
 
13
CONST
14
 
15
    MAXARRDIM*    = 5;
16
    MAXSCOPE      = 16;
17
    MAXSYSVPARAM* = 26;
18
 
19
    idNONE*    =  0;  idGUARD   =  1;  idMODULE* =  2;  idCONST*   =  3;
20
    idTYPE*    =  4;  idSTFUNC* =  5;  idSTPROC* =  6;  idVAR*     =  7;
21
    idPROC*    =  8;  idVPAR*   =  9;  idPARAM*  = 10;  idSYSFUNC* = 11;
22
    idSYSPROC* = 12;  idIMP*    = 13;
23
 
24
    tINTEGER* =  1;  tBYTE*      =  2;  tCHAR*   =  3;  tSET*    =  4;
25
    tBOOLEAN* =  5;  tREAL*      =  6;  tARRAY*  =  7;  tRECORD* =  8;
26
    tPOINTER* =  9;  tPROCEDURE* = 10;  tSTRING* = 11;  tNIL*    = 12;
8097 maxcodehac 27
    tCARD32*  = 13;  tANYREC*    = 14;  tWCHAR*  = 15;  tNONE*   = 16;
7597 akron1 28
 
7696 akron1 29
    BASICTYPES* = {tINTEGER, tBYTE, tCHAR, tSET, tBOOLEAN, tREAL, tCARD32, tWCHAR};
7597 akron1 30
 
31
    stABS*  =  1;  stASR*  =  2;  stCHR*    =  3;  stFLOOR* =  4;
32
    stFLT*  =  5;  stLEN*  =  6;  stLSL*    =  7;  stODD*   =  8;
33
    stORD*  =  9;  stROR*  = 10;  stASSERT* = 11;  stDEC*   = 12;
34
    stEXCL* = 13;  stINC*  = 14;  stINCL*   = 15;  stNEW*   = 16;
35
    stPACK* = 17;  stUNPK* = 18;  sysADR*   = 19;  sysSIZE* = 20;
36
    sysGET* = 21;  sysPUT* = 22;
37
 
8097 maxcodehac 38
    stDISPOSE* = 23;  stLSR*     = 24;  stBITS*   = 25;  sysCODE*  = 26;
39
    sysMOVE*   = 27;  stLENGTH*  = 28;  stMIN*    = 29;  stMAX*    = 30;
40
    sysSADR*   = 31;  sysTYPEID* = 32;  sysCOPY*  = 33;  sysINF*   = 34;
41
    sysPUT8*   = 35;  sysPUT16*  = 36;  stCOPY*   = 37;  stWCHR*   = 38;
42
    sysWSADR*  = 39;  sysPUT32*  = 40;  (*sysNOP*   = 41;  sysEINT*  = 42;
43
    sysDINT*   = 43;*)sysGET8*   = 44;  sysGET16* = 45;  sysGET32* = 46;
9893 akron1 44
    sysVAL* = 47;
7597 akron1 45
 
8097 maxcodehac 46
    default32* =  2;  _default32* = default32 + 1;
7597 akron1 47
    stdcall*   =  4;  _stdcall*   = stdcall + 1;
8859 leency 48
    cdecl*     =  6;  _cdecl*     = cdecl + 1;
49
    ccall*     =  8;  _ccall*     = ccall + 1;
7597 akron1 50
    win64*     = 10;  _win64*     = win64 + 1;
8859 leency 51
    default64* = 12;  _default64* = default64 + 1;
52
    systemv*   = 14;  _systemv*   = systemv + 1;
53
    default16* = 16;  _default16* = default16 + 1;
54
    code*      = 18;  _code*      = code + 1;
9847 akron1 55
    fastcall*  = 20;  _fastcall*  = fastcall + 1;
7597 akron1 56
 
7693 akron1 57
    noalign* = 22;
7597 akron1 58
 
9847 akron1 59
    callee_clean_up* = {default32, _default32, stdcall, _stdcall, default64, _default64, fastcall, _fastcall};
7597 akron1 60
 
8859 leency 61
    sf_stdcall* =  0; sf_oberon*    = 1; sf_cdecl*   = 2; sf_ccall*  = 3;
62
    sf_win64*   =  4; sf_systemv*   = 5; sf_windows* = 6; sf_linux*  = 7;
9847 akron1 63
    sf_code*    =  8; sf_fastcall*  = 9;
64
    sf_noalign* = 10;
7693 akron1 65
 
9847 akron1 66
    proc_flags* = {sf_stdcall, sf_cdecl, sf_ccall, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon, sf_fastcall};
7693 akron1 67
    rec_flags*  = {sf_noalign};
68
 
7597 akron1 69
    STACK_FRAME = 2;
70
 
71
 
72
TYPE
73
 
7693 akron1 74
    OPTIONS* = RECORD
75
 
9177 akron1 76
        version*, stack*, ram*, rom*, tab*: INTEGER;
9579 akron1 77
        pic*, lower*, uses*: BOOLEAN;
7693 akron1 78
        checking*: SET
79
 
80
    END;
81
 
7597 akron1 82
    IDENT* = POINTER TO rIDENT;
83
 
84
    UNIT* = POINTER TO rUNIT;
85
 
8097 maxcodehac 86
    _TYPE* = POINTER TO rTYPE;
7597 akron1 87
 
88
    FRWPTR* = POINTER TO RECORD (LISTS.ITEM)
89
 
8097 maxcodehac 90
        _type:       _TYPE;
7597 akron1 91
        baseIdent:   SCAN.IDENT;
92
        linked:      BOOLEAN;
93
 
94
        pos*:        SCAN.POSITION;
95
        notRecord*:  BOOLEAN
96
 
97
    END;
98
 
99
    PROC* = POINTER TO RECORD (LISTS.ITEM)
100
 
101
        label*:      INTEGER;
102
        used*:       BOOLEAN;
103
        processed*:  BOOLEAN;
8097 maxcodehac 104
        _import*:    LISTS.ITEM;
7597 akron1 105
        using*:      LISTS.LIST;
106
        enter*,
107
        leave*:      LISTS.ITEM
108
 
109
    END;
110
 
111
    USED_PROC = POINTER TO RECORD (LISTS.ITEM)
112
 
113
        proc: PROC
114
 
115
    END;
116
 
117
    rUNIT = RECORD (LISTS.ITEM)
118
 
8859 leency 119
        fname*:      PATHS.PATH;
7597 akron1 120
        name*:       SCAN.IDENT;
7693 akron1 121
        idents*:     LISTS.LIST;
7597 akron1 122
        frwPointers: LISTS.LIST;
123
        gscope:      IDENT;
124
        closed*:     BOOLEAN;
125
        scopeLvl*:   INTEGER;
126
        sysimport*:  BOOLEAN;
7693 akron1 127
        scopes*:     ARRAY MAXSCOPE OF PROC
7597 akron1 128
 
129
    END;
130
 
131
    FIELD* = POINTER TO rFIELD;
132
 
133
    PARAM* = POINTER TO rPARAM;
134
 
8097 maxcodehac 135
    rTYPE = RECORD (LISTS.ITEM)
7597 akron1 136
 
137
        typ*:        INTEGER;
138
        size*:       INTEGER;
7693 akron1 139
        parSize*:    INTEGER;
7597 akron1 140
        length*:     INTEGER;
141
        align*:      INTEGER;
8097 maxcodehac 142
        base*:       _TYPE;
7693 akron1 143
        fields*:     LISTS.LIST;
144
        params*:     LISTS.LIST;
7597 akron1 145
        unit*:       UNIT;
146
        closed*:     BOOLEAN;
147
        num*:        INTEGER;
148
        call*:       INTEGER;
8097 maxcodehac 149
        _import*:    BOOLEAN;
7597 akron1 150
        noalign*:    BOOLEAN
151
 
152
    END;
153
 
154
    rFIELD = RECORD (LISTS.ITEM)
155
 
8097 maxcodehac 156
        _type*:      _TYPE;
7597 akron1 157
        name*:       SCAN.IDENT;
158
        export*:     BOOLEAN;
159
        offset*:     INTEGER
160
 
161
    END;
162
 
163
    rPARAM = RECORD (LISTS.ITEM)
164
 
165
        name*:       SCAN.IDENT;
8097 maxcodehac 166
        _type*:      _TYPE;
7597 akron1 167
        vPar*:       BOOLEAN;
168
        offset*:     INTEGER
169
 
170
    END;
171
 
172
    rIDENT = RECORD (LISTS.ITEM)
173
 
174
        name*:       SCAN.IDENT;
175
        typ*:        INTEGER;
176
        export*:     BOOLEAN;
8097 maxcodehac 177
        _import*:    LISTS.ITEM;
7597 akron1 178
        unit*:       UNIT;
179
        value*:      ARITH.VALUE;
8097 maxcodehac 180
        _type*:      _TYPE;
7597 akron1 181
        stproc*:     INTEGER;
182
        global*:     BOOLEAN;
183
        scopeLvl*:   INTEGER;
184
        offset*:     INTEGER;
185
        proc*:       PROC;
186
        pos*:        SCAN.POSITION
187
 
188
    END;
189
 
8097 maxcodehac 190
    PROGRAM = RECORD
7597 akron1 191
 
192
        recCount:    INTEGER;
7693 akron1 193
        units*:      LISTS.LIST;
7597 akron1 194
        types*:      LISTS.LIST;
195
        sysunit*:    UNIT;
196
        rtl*:        UNIT;
197
        bss*:        INTEGER;
198
        locsize*:    INTEGER;
199
 
200
        procs*:      LISTS.LIST;
201
 
7983 leency 202
        sysflags*:   SET;
203
        options*:    OPTIONS;
204
 
7693 akron1 205
        stTypes*:    RECORD
7597 akron1 206
 
7693 akron1 207
            tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*,
8097 maxcodehac 208
            tSTRING*, tNIL*, tCARD32*, tANYREC*, tNONE*: _TYPE
7597 akron1 209
 
7693 akron1 210
        END
7597 akron1 211
 
212
    END;
213
 
8097 maxcodehac 214
    DELIMPORT = PROCEDURE (_import: LISTS.ITEM);
7597 akron1 215
 
216
 
217
VAR
218
 
8859 leency 219
    LowerCase*: BOOLEAN;
7597 akron1 220
    idents: C.COLLECTION;
8097 maxcodehac 221
    program*: PROGRAM;
7597 akron1 222
 
223
 
224
PROCEDURE NewIdent (): IDENT;
225
VAR
226
    ident: IDENT;
227
    citem: C.ITEM;
228
 
229
BEGIN
230
    citem := C.pop(idents);
231
    IF citem = NIL THEN
232
        NEW(ident)
233
    ELSE
234
        ident := citem(IDENT)
235
    END
236
 
237
    RETURN ident
238
END NewIdent;
239
 
240
 
8097 maxcodehac 241
PROCEDURE getOffset* (varIdent: IDENT): INTEGER;
7597 akron1 242
VAR
9893 akron1 243
    size, glob_align: INTEGER;
7597 akron1 244
 
245
BEGIN
246
    IF varIdent.offset = -1 THEN
8097 maxcodehac 247
        size := varIdent._type.size;
7597 akron1 248
        IF varIdent.global THEN
9893 akron1 249
            IF TARGETS.WinLin THEN
250
                glob_align := 16
251
            ELSE
252
                glob_align := varIdent._type.align
253
            END;
254
            IF UTILS.Align(program.bss, glob_align) THEN
7696 akron1 255
                IF UTILS.maxint - program.bss >= size THEN
7597 akron1 256
                    varIdent.offset := program.bss;
7696 akron1 257
                    INC(program.bss, size)
7597 akron1 258
                END
259
            END
260
        ELSE
7983 leency 261
            IF UTILS.Align(size, TARGETS.WordSize) THEN
262
                size := size DIV TARGETS.WordSize;
7597 akron1 263
                IF UTILS.maxint - program.locsize >= size THEN
264
                    INC(program.locsize, size);
7696 akron1 265
                    varIdent.offset := program.locsize
7597 akron1 266
                END
267
            END
7696 akron1 268
        END;
269
 
270
        IF varIdent.offset = -1 THEN
271
            ERRORS.Error(204)
7597 akron1 272
        END
273
    END
274
 
275
    RETURN varIdent.offset
276
END getOffset;
277
 
278
 
7693 akron1 279
PROCEDURE closeUnit* (unit: UNIT);
7597 akron1 280
VAR
281
    ident, prev: IDENT;
282
    offset: INTEGER;
283
 
284
BEGIN
285
    ident := unit.idents.last(IDENT);
286
    WHILE (ident # NIL) & (ident.typ # idGUARD) DO
287
        IF (ident.typ = idVAR) & (ident.offset = -1) THEN
7693 akron1 288
            ERRORS.HintMsg(ident.name.s, ident.pos.line, ident.pos.col, 0);
7597 akron1 289
            IF ident.export THEN
8097 maxcodehac 290
                offset := getOffset(ident)
7597 akron1 291
            END
292
        END;
293
        ident := ident.prev(IDENT)
294
    END;
295
 
296
    ident := unit.idents.last(IDENT);
297
    WHILE ident # NIL DO
298
        prev := ident.prev(IDENT);
299
        IF ~ident.export THEN
300
            LISTS.delete(unit.idents, ident);
301
            C.push(idents, ident)
302
        END;
303
        ident := prev
304
    END;
305
 
306
    unit.closed := TRUE
7693 akron1 307
END closeUnit;
7597 akron1 308
 
309
 
8859 leency 310
PROCEDURE IdEq* (a, b: SCAN.IDENT): BOOLEAN;
311
    RETURN (a.hash = b.hash) & (a.s = b.s)
312
END IdEq;
313
 
314
 
7597 akron1 315
PROCEDURE unique (unit: UNIT; ident: SCAN.IDENT): BOOLEAN;
316
VAR
317
    item: IDENT;
318
 
319
BEGIN
320
    item := unit.idents.last(IDENT);
8859 leency 321
    WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO
7597 akron1 322
        item := item.prev(IDENT)
323
    END
324
 
325
    RETURN item.typ = idGUARD
326
END unique;
327
 
328
 
7693 akron1 329
PROCEDURE addIdent* (unit: UNIT; ident: SCAN.IDENT; typ: INTEGER): IDENT;
7597 akron1 330
VAR
7693 akron1 331
    item:  IDENT;
332
    res:   BOOLEAN;
333
    proc:  PROC;
7597 akron1 334
 
335
BEGIN
336
    ASSERT(unit # NIL);
337
 
338
    res := unique(unit, ident);
339
 
340
    IF res THEN
341
        item := NewIdent();
342
 
8097 maxcodehac 343
        item.name    := ident;
344
        item.typ     := typ;
345
        item.unit    := NIL;
346
        item.export  := FALSE;
347
        item._import := NIL;
348
        item._type   := NIL;
7597 akron1 349
        item.value.typ := 0;
350
        item.stproc := 0;
351
 
352
        item.global := unit.scopeLvl = 0;
353
        item.scopeLvl := unit.scopeLvl;
354
        item.offset := -1;
355
 
356
        IF item.typ IN {idPROC, idIMP} THEN
357
            NEW(proc);
8097 maxcodehac 358
            proc._import := NIL;
7597 akron1 359
            proc.label := 0;
360
            proc.used := FALSE;
361
            proc.processed := FALSE;
362
            proc.using := LISTS.create(NIL);
8097 maxcodehac 363
            LISTS.push(program.procs, proc);
7597 akron1 364
            item.proc := proc
365
        END;
366
 
367
        LISTS.push(unit.idents, item)
368
    ELSE
369
        item := NIL
370
    END
371
 
372
    RETURN item
373
END addIdent;
374
 
375
 
376
PROCEDURE UseProc* (unit: UNIT; call_proc: PROC);
377
VAR
7693 akron1 378
    procs: LISTS.LIST;
379
    cur:   LISTS.ITEM;
380
    proc:  USED_PROC;
7597 akron1 381
 
382
BEGIN
383
    IF unit.scopeLvl = 0 THEN
384
        call_proc.used := TRUE
385
    ELSE
386
        procs := unit.scopes[unit.scopeLvl].using;
387
 
388
        cur := procs.first;
389
        WHILE (cur # NIL) & (cur(USED_PROC).proc # call_proc) DO
390
            cur := cur.next
391
        END;
392
 
393
        IF cur = NIL THEN
394
            NEW(proc);
395
            proc.proc := call_proc;
396
            LISTS.push(procs, proc)
397
        END
398
    END
399
END UseProc;
400
 
401
 
8097 maxcodehac 402
PROCEDURE setVarsType* (unit: UNIT; _type: _TYPE);
7597 akron1 403
VAR
404
    item: IDENT;
405
 
406
BEGIN
8097 maxcodehac 407
    ASSERT(_type # NIL);
7597 akron1 408
 
409
    item := unit.idents.last(IDENT);
8097 maxcodehac 410
    WHILE (item # NIL) & (item.typ = idVAR) & (item._type = NIL) DO
411
        item._type := _type;
7597 akron1 412
        item := item.prev(IDENT)
413
    END
7693 akron1 414
END setVarsType;
7597 akron1 415
 
416
 
7693 akron1 417
PROCEDURE getIdent* (unit: UNIT; ident: SCAN.IDENT; currentScope: BOOLEAN): IDENT;
7597 akron1 418
VAR
419
    item: IDENT;
420
 
421
BEGIN
422
    item := unit.idents.last(IDENT);
423
 
7693 akron1 424
    IF item # NIL THEN
7597 akron1 425
 
7693 akron1 426
        IF currentScope THEN
8859 leency 427
            WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO
7693 akron1 428
                item := item.prev(IDENT)
429
            END;
8859 leency 430
            IF item.typ = idGUARD THEN
7693 akron1 431
                item := NIL
432
            END
433
        ELSE
8859 leency 434
            WHILE (item # NIL) & ~IdEq(item.name, ident) DO
7693 akron1 435
                item := item.prev(IDENT)
436
            END
7597 akron1 437
        END
7693 akron1 438
 
7597 akron1 439
    END
440
 
441
    RETURN item
442
END getIdent;
443
 
444
 
7693 akron1 445
PROCEDURE openScope* (unit: UNIT; proc: PROC): BOOLEAN;
7597 akron1 446
VAR
447
    item: IDENT;
448
    res:  BOOLEAN;
449
 
450
BEGIN
451
    INC(unit.scopeLvl);
452
 
453
    res := unit.scopeLvl < MAXSCOPE;
454
 
455
    IF res THEN
456
 
457
        unit.scopes[unit.scopeLvl] := proc;
458
 
459
        NEW(item);
460
        item := NewIdent();
461
 
8859 leency 462
        item.name.s := "";
463
        item.name.hash := 0;
7597 akron1 464
        item.typ  := idGUARD;
465
 
466
        LISTS.push(unit.idents, item)
467
    END
468
 
469
    RETURN res
470
END openScope;
471
 
472
 
8859 leency 473
PROCEDURE closeScope* (unit: UNIT);
7597 akron1 474
VAR
475
    item: IDENT;
476
    del:  IDENT;
477
 
478
BEGIN
479
    item := unit.idents.last(IDENT);
480
 
481
    WHILE (item # NIL) & (item.typ # idGUARD) DO
482
        del  := item;
483
        item := item.prev(IDENT);
484
        IF (del.typ = idVAR) & (del.offset = -1) THEN
7693 akron1 485
            ERRORS.HintMsg(del.name.s, del.pos.line, del.pos.col, 0)
7597 akron1 486
        END;
487
        LISTS.delete(unit.idents, del);
488
        C.push(idents, del)
489
    END;
490
 
491
    IF (item # NIL) & (item.typ = idGUARD) THEN
492
        LISTS.delete(unit.idents, item);
493
        C.push(idents, item)
494
    END;
495
 
496
    DEC(unit.scopeLvl)
497
END closeScope;
498
 
499
 
8097 maxcodehac 500
PROCEDURE frwPtr* (unit: UNIT; _type: _TYPE; baseIdent: SCAN.IDENT; pos: SCAN.POSITION);
7597 akron1 501
VAR
502
    newptr: FRWPTR;
503
 
504
BEGIN
505
    ASSERT(unit # NIL);
8097 maxcodehac 506
    ASSERT(_type # NIL);
7597 akron1 507
 
508
    NEW(newptr);
509
 
8097 maxcodehac 510
    newptr._type      := _type;
7693 akron1 511
    newptr.baseIdent := baseIdent;
512
    newptr.pos       := pos;
513
    newptr.linked    := FALSE;
514
    newptr.notRecord := FALSE;
7597 akron1 515
 
516
    LISTS.push(unit.frwPointers, newptr)
7693 akron1 517
END frwPtr;
7597 akron1 518
 
519
 
7693 akron1 520
PROCEDURE linkPtr* (unit: UNIT): FRWPTR;
7597 akron1 521
VAR
522
    item:  FRWPTR;
523
    ident: IDENT;
524
    res:   FRWPTR;
525
 
526
BEGIN
527
    res  := NIL;
528
    item := unit.frwPointers.last(FRWPTR);
529
 
530
    WHILE (item # NIL) & ~item.linked & (res = NIL) DO
7693 akron1 531
        ident := getIdent(unit, item.baseIdent, TRUE);
7597 akron1 532
 
533
        IF (ident # NIL) THEN
8097 maxcodehac 534
            IF (ident.typ = idTYPE) & (ident._type.typ = tRECORD) THEN
535
                item._type.base := ident._type;
7597 akron1 536
                item.linked := TRUE
537
            ELSE
538
                item.notRecord := TRUE;
539
                res := item
540
            END
541
        ELSE
542
            item.notRecord := FALSE;
543
            res := item
544
        END;
545
 
546
        item := item.prev(FRWPTR)
547
    END
548
 
549
    RETURN res
7693 akron1 550
END linkPtr;
7597 akron1 551
 
552
 
8097 maxcodehac 553
PROCEDURE isTypeEq* (t1, t2: _TYPE): BOOLEAN;
7597 akron1 554
VAR
555
    res: BOOLEAN;
556
    param1, param2: LISTS.ITEM;
557
 
558
BEGIN
559
    IF t1 = t2 THEN
560
        res := TRUE
561
    ELSIF (t1 = NIL) OR (t2 = NIL) THEN
562
        res := FALSE
563
    ELSIF (t1.typ = tPROCEDURE) & (t2.typ = tPROCEDURE) THEN
564
 
565
        param1 := t1.params.first;
566
        param2 := t2.params.first;
567
 
7693 akron1 568
        res := ((t1.call = t2.call) OR (t1.call IN {code, _code}) OR (t2.call IN {code, _code})) & ((param1 # NIL) = (param2 # NIL));
7597 akron1 569
 
570
        WHILE res & (param1 # NIL) & (param2 # NIL) DO
8097 maxcodehac 571
            res := (param1(PARAM).vPar = param2(PARAM).vPar) & isTypeEq(param1(PARAM)._type, param2(PARAM)._type);
7597 akron1 572
            param1 := param1.next;
573
            param2 := param2.next;
574
            res := res & ((param1 # NIL) = (param2 # NIL))
575
        END;
576
 
577
        res := res & isTypeEq(t1.base, t2.base)
578
 
579
    ELSIF (t1.typ = tARRAY) & (t2.typ = tARRAY) THEN
580
        res := (t1.length = 0) & (t2.length = 0) & isTypeEq(t1.base, t2.base)
581
    ELSE
582
        res := FALSE
583
    END
584
 
585
    RETURN res
586
END isTypeEq;
587
 
588
 
8097 maxcodehac 589
PROCEDURE isBaseOf* (t0, t1: _TYPE): BOOLEAN;
7597 akron1 590
VAR
591
    res: BOOLEAN;
592
 
593
BEGIN
7693 akron1 594
    res := (t0.typ = t1.typ) & (t0.typ IN {tPOINTER, tRECORD});
7597 akron1 595
 
7693 akron1 596
    IF res & (t0.typ = tPOINTER) THEN
7597 akron1 597
        t0 := t0.base;
598
        t1 := t1.base
599
    END;
600
 
7693 akron1 601
    IF res THEN
602
        WHILE (t1 # NIL) & (t1 # t0) DO
603
            t1 := t1.base
604
        END;
605
        res := t1 # NIL
7597 akron1 606
    END
607
 
7693 akron1 608
    RETURN res
7597 akron1 609
END isBaseOf;
610
 
611
 
8097 maxcodehac 612
PROCEDURE isOpenArray* (t: _TYPE): BOOLEAN;
7597 akron1 613
    RETURN (t.typ = tARRAY) & (t.length = 0)
614
END isOpenArray;
615
 
616
 
8097 maxcodehac 617
PROCEDURE arrcomp* (src, dst: _TYPE): BOOLEAN;
7696 akron1 618
    RETURN (dst.typ = tARRAY) & isOpenArray(src) &
619
            ~isOpenArray(src.base) & ~isOpenArray(dst.base) &
620
            isTypeEq(src.base, dst.base)
621
END arrcomp;
622
 
623
 
8859 leency 624
PROCEDURE getUnit* (name: PATHS.PATH): UNIT;
7597 akron1 625
VAR
626
    item: UNIT;
627
 
628
BEGIN
7693 akron1 629
    item := program.units.first(UNIT);
7597 akron1 630
 
8859 leency 631
    WHILE (item # NIL) & (item.fname # name) DO
7597 akron1 632
        item := item.next(UNIT)
633
    END;
634
 
8859 leency 635
    IF (item = NIL) & ((name = "SYSTEM") OR LowerCase & (name = "system")) THEN
7693 akron1 636
        item := program.sysunit
7597 akron1 637
    END
638
 
639
    RETURN item
7693 akron1 640
END getUnit;
7597 akron1 641
 
642
 
8097 maxcodehac 643
PROCEDURE enterStTypes (unit: UNIT);
7597 akron1 644
 
645
 
8859 leency 646
    PROCEDURE enter (unit: UNIT; nameStr: SCAN.IDSTR; _type: _TYPE);
8097 maxcodehac 647
    VAR
648
        ident: IDENT;
8859 leency 649
        upper: SCAN.IDSTR;
650
        name:  SCAN.IDENT;
7597 akron1 651
 
8097 maxcodehac 652
    BEGIN
653
        IF LowerCase THEN
8859 leency 654
            SCAN.setIdent(name, nameStr);
655
            ident := addIdent(unit, name, idTYPE);
8097 maxcodehac 656
            ident._type := _type
657
        END;
8859 leency 658
        upper := nameStr;
8097 maxcodehac 659
        STRINGS.UpCase(upper);
8859 leency 660
        SCAN.setIdent(name, upper);
661
        ident := addIdent(unit, name, idTYPE);
8097 maxcodehac 662
        ident._type := _type
663
    END enter;
7597 akron1 664
 
665
 
8097 maxcodehac 666
BEGIN
667
    enter(unit, "integer", program.stTypes.tINTEGER);
668
    enter(unit, "byte",    program.stTypes.tBYTE);
669
    enter(unit, "char",    program.stTypes.tCHAR);
670
    enter(unit, "set",     program.stTypes.tSET);
671
    enter(unit, "boolean", program.stTypes.tBOOLEAN);
7597 akron1 672
 
7983 leency 673
    IF TARGETS.RealSize # 0 THEN
8097 maxcodehac 674
        enter(unit, "real", program.stTypes.tREAL)
7983 leency 675
    END;
7597 akron1 676
 
7983 leency 677
    IF TARGETS.BitDepth >= 32 THEN
8097 maxcodehac 678
        enter(unit, "wchar", program.stTypes.tWCHAR)
7693 akron1 679
    END
7597 akron1 680
END enterStTypes;
681
 
682
 
683
PROCEDURE enterStProcs (unit: UNIT);
684
 
685
 
8859 leency 686
    PROCEDURE Enter (unit: UNIT; nameStr: SCAN.IDSTR; nfunc, tfunc: INTEGER);
7597 akron1 687
    VAR
688
        ident: IDENT;
8859 leency 689
        upper: SCAN.IDSTR;
690
        name:  SCAN.IDENT;
8097 maxcodehac 691
 
7597 akron1 692
    BEGIN
8097 maxcodehac 693
        IF LowerCase THEN
8859 leency 694
            SCAN.setIdent(name, nameStr);
695
            ident := addIdent(unit, name, tfunc);
696
            ident.stproc := nfunc;
8097 maxcodehac 697
            ident._type := program.stTypes.tNONE
698
        END;
8859 leency 699
        upper := nameStr;
8097 maxcodehac 700
        STRINGS.UpCase(upper);
8859 leency 701
        SCAN.setIdent(name, upper);
702
        ident := addIdent(unit, name, tfunc);
703
        ident.stproc := nfunc;
8097 maxcodehac 704
        ident._type := program.stTypes.tNONE
8859 leency 705
    END Enter;
7597 akron1 706
 
707
 
708
BEGIN
8859 leency 709
    Enter(unit, "assert", stASSERT, idSTPROC);
710
    Enter(unit, "dec",    stDEC,    idSTPROC);
711
    Enter(unit, "excl",   stEXCL,   idSTPROC);
712
    Enter(unit, "inc",    stINC,    idSTPROC);
713
    Enter(unit, "incl",   stINCL,   idSTPROC);
714
    Enter(unit, "new",    stNEW,    idSTPROC);
715
    Enter(unit, "copy",   stCOPY,   idSTPROC);
7597 akron1 716
 
8859 leency 717
    Enter(unit, "abs",    stABS,    idSTFUNC);
718
    Enter(unit, "asr",    stASR,    idSTFUNC);
719
    Enter(unit, "chr",    stCHR,    idSTFUNC);
720
    Enter(unit, "len",    stLEN,    idSTFUNC);
721
    Enter(unit, "lsl",    stLSL,    idSTFUNC);
722
    Enter(unit, "odd",    stODD,    idSTFUNC);
723
    Enter(unit, "ord",    stORD,    idSTFUNC);
724
    Enter(unit, "ror",    stROR,    idSTFUNC);
725
    Enter(unit, "bits",   stBITS,   idSTFUNC);
726
    Enter(unit, "lsr",    stLSR,    idSTFUNC);
727
    Enter(unit, "length", stLENGTH, idSTFUNC);
728
    Enter(unit, "min",    stMIN,    idSTFUNC);
729
    Enter(unit, "max",    stMAX,    idSTFUNC);
7693 akron1 730
 
7983 leency 731
    IF TARGETS.RealSize # 0 THEN
8859 leency 732
        Enter(unit, "pack",  stPACK,  idSTPROC);
733
        Enter(unit, "unpk",  stUNPK,  idSTPROC);
734
        Enter(unit, "floor", stFLOOR, idSTFUNC);
735
        Enter(unit, "flt",   stFLT,   idSTFUNC)
7983 leency 736
    END;
7693 akron1 737
 
7983 leency 738
    IF TARGETS.BitDepth >= 32 THEN
8859 leency 739
        Enter(unit, "wchr", stWCHR, idSTFUNC)
7983 leency 740
    END;
741
 
742
    IF TARGETS.Dispose THEN
8859 leency 743
        Enter(unit, "dispose", stDISPOSE, idSTPROC)
7693 akron1 744
    END
745
 
7597 akron1 746
END enterStProcs;
747
 
748
 
8097 maxcodehac 749
PROCEDURE newUnit* (name: SCAN.IDENT): UNIT;
7597 akron1 750
VAR
7693 akron1 751
    unit: UNIT;
7597 akron1 752
 
753
BEGIN
754
    NEW(unit);
755
 
756
    unit.name        := name;
757
    unit.closed      := FALSE;
7693 akron1 758
    unit.idents      := LISTS.create(NIL);
7597 akron1 759
    unit.frwPointers := LISTS.create(NIL);
760
 
7693 akron1 761
    ASSERT(openScope(unit, NIL));
7597 akron1 762
 
8097 maxcodehac 763
    enterStTypes(unit);
7597 akron1 764
    enterStProcs(unit);
765
 
7693 akron1 766
    ASSERT(openScope(unit, NIL));
7597 akron1 767
 
768
    unit.gscope := unit.idents.last(IDENT);
769
 
7693 akron1 770
    LISTS.push(program.units, unit);
7597 akron1 771
 
772
    unit.scopeLvl := 0;
773
    unit.scopes[0] := NIL;
774
 
775
    unit.sysimport := FALSE;
776
 
7983 leency 777
    IF unit.name.s = UTILS.RTL_NAME THEN
7693 akron1 778
        program.rtl := unit
7597 akron1 779
    END
780
 
781
    RETURN unit
7693 akron1 782
END newUnit;
7597 akron1 783
 
784
 
8097 maxcodehac 785
PROCEDURE getField* (self: _TYPE; name: SCAN.IDENT; unit: UNIT): FIELD;
7597 akron1 786
VAR
7693 akron1 787
    field: FIELD;
7597 akron1 788
 
789
BEGIN
790
    ASSERT(self # NIL);
791
    ASSERT(unit # NIL);
792
 
793
    field := NIL;
794
    WHILE (self # NIL) & (field = NIL) DO
795
 
796
        field := self.fields.first(FIELD);
797
 
8859 leency 798
        WHILE (field # NIL) & ~IdEq(field.name, name) DO
7597 akron1 799
            field := field.next(FIELD)
800
        END;
801
 
802
        IF field = NIL THEN
803
            self := self.base
804
        END
805
 
806
    END;
807
 
808
    IF (field # NIL) & (self.unit # unit) & ~field.export THEN
809
        field := NIL
810
    END
811
 
812
    RETURN field
813
END getField;
814
 
815
 
8097 maxcodehac 816
PROCEDURE addField* (self: _TYPE; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN;
7597 akron1 817
VAR
7693 akron1 818
    field: FIELD;
819
    res:   BOOLEAN;
7597 akron1 820
 
821
BEGIN
822
    res := getField(self, name, self.unit) = NIL;
823
 
824
    IF res THEN
825
        NEW(field);
826
 
827
        field.name   := name;
828
        field.export := export;
8097 maxcodehac 829
        field._type  := NIL;
7597 akron1 830
        field.offset := self.size;
831
 
832
        LISTS.push(self.fields, field)
833
    END
834
 
835
    RETURN res
836
END addField;
837
 
838
 
8097 maxcodehac 839
PROCEDURE setFields* (self: _TYPE; _type: _TYPE): BOOLEAN;
7597 akron1 840
VAR
841
    item: FIELD;
842
    res:  BOOLEAN;
843
 
844
BEGIN
8097 maxcodehac 845
    ASSERT(_type # NIL);
7597 akron1 846
 
847
    item := self.fields.first(FIELD);
848
 
8097 maxcodehac 849
    WHILE (item # NIL) & (item._type # NIL) DO
7597 akron1 850
        item := item.next(FIELD)
851
    END;
852
 
853
    res := TRUE;
854
 
8097 maxcodehac 855
    WHILE res & (item # NIL) & (item._type = NIL) DO
856
        item._type := _type;
7597 akron1 857
        IF ~self.noalign THEN
8097 maxcodehac 858
            res := UTILS.Align(self.size, _type.align)
7597 akron1 859
        ELSE
860
            res := TRUE
861
        END;
862
        item.offset := self.size;
8097 maxcodehac 863
        res := res & (UTILS.maxint - self.size >= _type.size);
7597 akron1 864
        IF res THEN
8097 maxcodehac 865
            INC(self.size, _type.size)
7597 akron1 866
        END;
867
        item := item.next(FIELD)
868
    END
869
 
870
    RETURN res
871
END setFields;
872
 
873
 
8097 maxcodehac 874
PROCEDURE getParam* (self: _TYPE; name: SCAN.IDENT): PARAM;
7597 akron1 875
VAR
7693 akron1 876
    item: PARAM;
7597 akron1 877
 
878
BEGIN
879
    item := self.params.first(PARAM);
880
 
8859 leency 881
    WHILE (item # NIL) & ~IdEq(item.name, name) DO
7597 akron1 882
        item := item.next(PARAM)
883
    END
884
 
885
    RETURN item
886
END getParam;
887
 
888
 
8097 maxcodehac 889
PROCEDURE addParam* (self: _TYPE; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN;
7597 akron1 890
VAR
7693 akron1 891
    param: PARAM;
892
    res:   BOOLEAN;
7597 akron1 893
 
894
BEGIN
7693 akron1 895
    res := getParam(self, name) = NIL;
7597 akron1 896
 
897
    IF res THEN
898
        NEW(param);
899
 
8097 maxcodehac 900
        param.name  := name;
901
        param._type := NIL;
902
        param.vPar  := vPar;
7597 akron1 903
 
904
        LISTS.push(self.params, param)
905
    END
906
 
907
    RETURN res
908
END addParam;
909
 
910
 
8097 maxcodehac 911
PROCEDURE Dim* (t: _TYPE): INTEGER;
7597 akron1 912
VAR
913
    res: INTEGER;
914
 
915
BEGIN
916
    res := 0;
917
    WHILE isOpenArray(t) DO
918
        t := t.base;
919
        INC(res)
920
    END
921
    RETURN res
922
END Dim;
923
 
924
 
8097 maxcodehac 925
PROCEDURE OpenBase* (t: _TYPE): _TYPE;
7597 akron1 926
BEGIN
927
    WHILE isOpenArray(t) DO t := t.base END
928
    RETURN t
929
END OpenBase;
930
 
931
 
8097 maxcodehac 932
PROCEDURE getFloatParamsPos* (self: _TYPE; maxoffs: INTEGER; VAR int, flt: INTEGER): SET;
7597 akron1 933
VAR
934
    res: SET;
935
    param: PARAM;
936
 
937
BEGIN
938
    res := {};
939
    int := 0;
940
    flt := 0;
941
    param := self.params.first(PARAM);
942
    WHILE (param # NIL) & (param.offset <= maxoffs + STACK_FRAME) DO
8097 maxcodehac 943
        IF ~param.vPar & (param._type.typ = tREAL) THEN
7597 akron1 944
            INCL(res, param.offset - STACK_FRAME);
945
            INC(flt)
946
        END;
947
        param := param.next(PARAM)
948
    END;
949
 
7693 akron1 950
    int := self.parSize - flt
7597 akron1 951
 
952
    RETURN res
953
END getFloatParamsPos;
954
 
955
 
8097 maxcodehac 956
PROCEDURE setParams* (self: _TYPE; _type: _TYPE);
7597 akron1 957
VAR
958
    item: LISTS.ITEM;
959
    param: PARAM;
960
    word, size: INTEGER;
961
 
962
BEGIN
8097 maxcodehac 963
    ASSERT(_type # NIL);
7597 akron1 964
 
7693 akron1 965
    word := UTILS.target.bit_depth DIV 8;
7597 akron1 966
 
967
    item := self.params.first;
968
 
8097 maxcodehac 969
    WHILE (item # NIL) & (item(PARAM)._type # NIL) DO
7597 akron1 970
        item := item.next
971
    END;
972
 
8097 maxcodehac 973
    WHILE (item # NIL) & (item(PARAM)._type = NIL) DO
7597 akron1 974
        param := item(PARAM);
8097 maxcodehac 975
        param._type := _type;
7597 akron1 976
        IF param.vPar THEN
8097 maxcodehac 977
            IF _type.typ = tRECORD THEN
7597 akron1 978
                size := 2
8097 maxcodehac 979
            ELSIF isOpenArray(_type) THEN
980
                size := Dim(_type) + 1
7597 akron1 981
            ELSE
982
                size := 1
983
            END;
8097 maxcodehac 984
            param.offset := self.parSize + ORD(_type.typ = tRECORD) + Dim(_type) + STACK_FRAME;
7693 akron1 985
            INC(self.parSize, size)
7597 akron1 986
        ELSE
8097 maxcodehac 987
            IF _type.typ IN {tRECORD, tARRAY} THEN
988
                IF isOpenArray(_type) THEN
989
                    size := Dim(_type) + 1
7597 akron1 990
                ELSE
991
                    size := 1
992
                END
993
            ELSE
8097 maxcodehac 994
                size := _type.size;
7693 akron1 995
                ASSERT(UTILS.Align(size, word));
7597 akron1 996
                size := size DIV word
997
            END;
8097 maxcodehac 998
            param.offset := self.parSize + Dim(_type) + STACK_FRAME;
7693 akron1 999
            INC(self.parSize, size)
7597 akron1 1000
        END;
1001
 
1002
        item := item.next
1003
    END
1004
 
1005
END setParams;
1006
 
1007
 
8097 maxcodehac 1008
PROCEDURE enterType* (typ, size, length: INTEGER; unit: UNIT): _TYPE;
7597 akron1 1009
VAR
8097 maxcodehac 1010
    t: _TYPE;
7597 akron1 1011
 
1012
BEGIN
1013
    NEW(t);
1014
 
1015
    t.typ     := typ;
1016
    t.size    := size;
1017
    t.length  := length;
1018
    t.align   := 0;
1019
    t.base    := NIL;
7693 akron1 1020
    t.fields  := LISTS.create(NIL);
1021
    t.params  := LISTS.create(NIL);
7597 akron1 1022
    t.unit    := unit;
1023
    t.num     := 0;
7693 akron1 1024
 
7983 leency 1025
    CASE TARGETS.BitDepth OF
7693 akron1 1026
    |16: t.call := default16
1027
    |32: t.call := default32
1028
    |64: t.call := default64
7597 akron1 1029
    END;
7693 akron1 1030
 
8097 maxcodehac 1031
    t._import := FALSE;
7597 akron1 1032
    t.noalign := FALSE;
7693 akron1 1033
    t.parSize := 0;
7597 akron1 1034
 
1035
    IF typ IN {tARRAY, tRECORD} THEN
1036
        t.closed := FALSE;
1037
        IF typ = tRECORD THEN
1038
            INC(program.recCount);
1039
            t.num := program.recCount
1040
        END
1041
    ELSE
1042
        t.closed := TRUE
1043
    END;
1044
 
1045
    LISTS.push(program.types, t)
1046
 
1047
    RETURN t
1048
END enterType;
1049
 
1050
 
8097 maxcodehac 1051
PROCEDURE getType* (typ: INTEGER): _TYPE;
7597 akron1 1052
VAR
8097 maxcodehac 1053
    res: _TYPE;
7597 akron1 1054
 
1055
BEGIN
1056
 
7696 akron1 1057
    CASE typ OF
1058
    |ARITH.tINTEGER: res := program.stTypes.tINTEGER
1059
    |ARITH.tREAL:    res := program.stTypes.tREAL
1060
    |ARITH.tSET:     res := program.stTypes.tSET
1061
    |ARITH.tBOOLEAN: res := program.stTypes.tBOOLEAN
1062
    |ARITH.tCHAR:    res := program.stTypes.tCHAR
1063
    |ARITH.tWCHAR:   res := program.stTypes.tWCHAR
1064
    |ARITH.tSTRING:  res := program.stTypes.tSTRING
1065
    END
7597 akron1 1066
 
1067
    RETURN res
1068
END getType;
1069
 
1070
 
8097 maxcodehac 1071
PROCEDURE createSysUnit;
7597 akron1 1072
VAR
1073
    ident: IDENT;
1074
    unit:  UNIT;
8859 leency 1075
    name:  SCAN.IDENT;
7597 akron1 1076
 
1077
 
8859 leency 1078
    PROCEDURE EnterProc (sys: UNIT; nameStr: SCAN.IDSTR; idtyp, proc: INTEGER);
7597 akron1 1079
    VAR
1080
        ident: IDENT;
8859 leency 1081
        upper: SCAN.IDSTR;
1082
        name:  SCAN.IDENT;
8097 maxcodehac 1083
 
7597 akron1 1084
    BEGIN
8097 maxcodehac 1085
        IF LowerCase THEN
8859 leency 1086
            SCAN.setIdent(name, nameStr);
1087
            ident := addIdent(sys, name, idtyp);
8097 maxcodehac 1088
            ident.stproc := proc;
1089
            ident._type := program.stTypes.tNONE;
1090
            ident.export := TRUE
1091
        END;
8859 leency 1092
        upper := nameStr;
8097 maxcodehac 1093
        STRINGS.UpCase(upper);
8859 leency 1094
        SCAN.setIdent(name, upper);
1095
        ident := addIdent(sys, name, idtyp);
7597 akron1 1096
        ident.stproc := proc;
8097 maxcodehac 1097
        ident._type := program.stTypes.tNONE;
7597 akron1 1098
        ident.export := TRUE
1099
    END EnterProc;
1100
 
1101
 
1102
BEGIN
8859 leency 1103
    SCAN.setIdent(name, "$SYSTEM");
1104
    unit := newUnit(name);
1105
    unit.fname := "SYSTEM";
7597 akron1 1106
 
8097 maxcodehac 1107
    EnterProc(unit, "adr",    idSYSFUNC, sysADR);
1108
    EnterProc(unit, "size",   idSYSFUNC, sysSIZE);
1109
    EnterProc(unit, "sadr",   idSYSFUNC, sysSADR);
1110
    EnterProc(unit, "typeid", idSYSFUNC, sysTYPEID);
7597 akron1 1111
 
8097 maxcodehac 1112
    EnterProc(unit, "get",    idSYSPROC, sysGET);
1113
    EnterProc(unit, "get8",   idSYSPROC, sysGET8);
1114
    EnterProc(unit, "put",    idSYSPROC, sysPUT);
1115
    EnterProc(unit, "put8",   idSYSPROC, sysPUT8);
1116
    EnterProc(unit, "code",   idSYSPROC, sysCODE);
1117
    EnterProc(unit, "move",   idSYSPROC, sysMOVE);
9893 akron1 1118
    EnterProc(unit, "val",    idSYSPROC, sysVAL);
7693 akron1 1119
           (*
1120
    IF program.target.sys = mConst.Target_iMSP430 THEN
8097 maxcodehac 1121
        EnterProc(unit, "nop",  idSYSPROC, sysNOP);
1122
        EnterProc(unit, "eint", idSYSPROC, sysEINT);
1123
        EnterProc(unit, "dint", idSYSPROC, sysDINT)
7693 akron1 1124
    END;
1125
         *)
7983 leency 1126
    IF TARGETS.RealSize # 0 THEN
8097 maxcodehac 1127
        EnterProc(unit, "inf",    idSYSFUNC, sysINF);
7983 leency 1128
    END;
1129
 
1130
    IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN
8097 maxcodehac 1131
        EnterProc(unit, "copy",   idSYSPROC, sysCOPY)
7983 leency 1132
    END;
1133
 
1134
    IF TARGETS.BitDepth >= 32 THEN
8097 maxcodehac 1135
        EnterProc(unit, "wsadr",  idSYSFUNC, sysWSADR);
1136
        EnterProc(unit, "put16",  idSYSPROC, sysPUT16);
1137
        EnterProc(unit, "put32",  idSYSPROC, sysPUT32);
1138
        EnterProc(unit, "get16",  idSYSPROC, sysGET16);
1139
        EnterProc(unit, "get32",  idSYSPROC, sysGET32);
7597 akron1 1140
 
8097 maxcodehac 1141
        IF LowerCase THEN
8859 leency 1142
            SCAN.setIdent(name, "card32");
1143
            ident := addIdent(unit, name, idTYPE);
8097 maxcodehac 1144
            ident._type := program.stTypes.tCARD32;
1145
            ident.export := TRUE
1146
        END;
8859 leency 1147
        SCAN.setIdent(name, "CARD32");
1148
        ident := addIdent(unit, name, idTYPE);
8097 maxcodehac 1149
        ident._type := program.stTypes.tCARD32;
1150
        ident.export := TRUE;
7693 akron1 1151
    END;
7597 akron1 1152
 
7693 akron1 1153
    closeUnit(unit);
7597 akron1 1154
 
1155
    program.sysunit := unit
1156
END createSysUnit;
1157
 
1158
 
8097 maxcodehac 1159
PROCEDURE DelUnused* (DelImport: DELIMPORT);
7597 akron1 1160
VAR
7693 akron1 1161
    proc: PROC;
1162
    flag: BOOLEAN;
7597 akron1 1163
 
1164
 
1165
    PROCEDURE process (proc: PROC);
1166
    VAR
1167
        used_proc: LISTS.ITEM;
1168
 
1169
    BEGIN
1170
        proc.processed := TRUE;
1171
 
1172
        used_proc := proc.using.first;
1173
        WHILE used_proc # NIL DO
1174
            used_proc(USED_PROC).proc.used := TRUE;
1175
            used_proc := used_proc.next
1176
        END
1177
 
1178
    END process;
1179
 
1180
 
1181
BEGIN
1182
 
1183
    REPEAT
1184
        flag := FALSE;
1185
        proc := program.procs.first(PROC);
1186
 
1187
        WHILE proc # NIL DO
1188
            IF proc.used & ~proc.processed THEN
1189
                process(proc);
1190
                flag := TRUE
1191
            END;
1192
            proc := proc.next(PROC)
1193
        END
1194
 
1195
    UNTIL ~flag;
1196
 
1197
    proc := program.procs.first(PROC);
1198
 
1199
    WHILE proc # NIL DO
1200
        IF ~proc.used THEN
8097 maxcodehac 1201
            IF proc._import = NIL THEN
7693 akron1 1202
                IL.delete2(proc.enter, proc.leave)
7597 akron1 1203
            ELSE
8097 maxcodehac 1204
                DelImport(proc._import)
7597 akron1 1205
            END
1206
        END;
1207
        proc := proc.next(PROC)
1208
    END
1209
 
1210
END DelUnused;
1211
 
1212
 
8097 maxcodehac 1213
PROCEDURE ResetLocSize*;
1214
BEGIN
1215
    program.locsize := 0
1216
END ResetLocSize;
7597 akron1 1217
 
8097 maxcodehac 1218
 
1219
PROCEDURE create* (options: OPTIONS);
7597 akron1 1220
BEGIN
8097 maxcodehac 1221
    LowerCase := options.lower;
1222
    SCAN.init(options.lower);
7597 akron1 1223
    idents := C.create();
1224
 
7983 leency 1225
    UTILS.SetBitDepth(TARGETS.BitDepth, TARGETS.RealSize = 8);
7597 akron1 1226
 
7983 leency 1227
    program.options := options;
7597 akron1 1228
 
7983 leency 1229
    CASE TARGETS.OS OF
9847 akron1 1230
    |TARGETS.osWIN32:    program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign}
1231
    |TARGETS.osLINUX32:  program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign}
1232
    |TARGETS.osKOS:      program.sysflags := {sf_oberon, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign}
8859 leency 1233
    |TARGETS.osWIN64:    program.sysflags := {sf_oberon, sf_windows, sf_win64, sf_systemv, sf_ccall, sf_noalign}
1234
    |TARGETS.osLINUX64:  program.sysflags := {sf_oberon, sf_linux, sf_win64, sf_systemv, sf_ccall, sf_noalign}
7983 leency 1235
    |TARGETS.osNONE:     program.sysflags := {sf_code}
7693 akron1 1236
    END;
1237
 
7597 akron1 1238
    program.recCount := -1;
1239
    program.bss := 0;
1240
 
7693 akron1 1241
    program.units := LISTS.create(NIL);
7597 akron1 1242
    program.types := LISTS.create(NIL);
1243
    program.procs := LISTS.create(NIL);
1244
 
8097 maxcodehac 1245
    program.stTypes.tINTEGER := enterType(tINTEGER, TARGETS.WordSize, 0, NIL);
1246
    program.stTypes.tBYTE    := enterType(tBYTE,                   1, 0, NIL);
1247
    program.stTypes.tCHAR    := enterType(tCHAR,                   1, 0, NIL);
1248
    program.stTypes.tSET     := enterType(tSET,     TARGETS.WordSize, 0, NIL);
1249
    program.stTypes.tBOOLEAN := enterType(tBOOLEAN,                1, 0, NIL);
7693 akron1 1250
 
7983 leency 1251
    program.stTypes.tINTEGER.align := TARGETS.WordSize;
1252
    program.stTypes.tBYTE.align    := 1;
1253
    program.stTypes.tCHAR.align    := 1;
1254
    program.stTypes.tSET.align     := TARGETS.WordSize;
1255
    program.stTypes.tBOOLEAN.align := 1;
1256
 
1257
    IF TARGETS.BitDepth >= 32 THEN
8097 maxcodehac 1258
        program.stTypes.tWCHAR  := enterType(tWCHAR,  2, 0, NIL);
1259
        program.stTypes.tCARD32 := enterType(tCARD32, 4, 0, NIL);
7983 leency 1260
        program.stTypes.tWCHAR.align  := 2;
1261
        program.stTypes.tCARD32.align := 4
7693 akron1 1262
    END;
1263
 
7983 leency 1264
    IF TARGETS.RealSize # 0 THEN
8097 maxcodehac 1265
        program.stTypes.tREAL := enterType(tREAL, TARGETS.RealSize, 0, NIL);
9893 akron1 1266
        IF TARGETS.OS = TARGETS.osLINUX32 THEN
1267
            program.stTypes.tREAL.align := 4
1268
        ELSE
1269
            program.stTypes.tREAL.align := TARGETS.RealSize
1270
        END
7983 leency 1271
    END;
7693 akron1 1272
 
8097 maxcodehac 1273
    program.stTypes.tSTRING := enterType(tSTRING, TARGETS.WordSize, 0, NIL);
1274
    program.stTypes.tNIL    := enterType(tNIL,    TARGETS.WordSize, 0, NIL);
1275
    program.stTypes.tNONE   := enterType(tNONE,   0, 0, NIL);
1276
    program.stTypes.tANYREC := enterType(tRECORD, 0, 0, NIL);
7597 akron1 1277
    program.stTypes.tANYREC.closed := TRUE;
1278
 
8097 maxcodehac 1279
    createSysUnit
7597 akron1 1280
END create;
1281
 
1282
 
7983 leency 1283
END PROG.