cfad47cfa3/t2compiler/tads2/emt.c

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#ifdef RCSID
2
static char RCSid[] =
3
"$Header: d:/cvsroot/tads/TADS2/EMT.C,v 1.2 1999/05/17 02:52:11 MJRoberts Exp $";
4
#endif
5
6
/* 
7
 *   Copyright (c) 1991, 2002 Michael J. Roberts.  All Rights Reserved.
8
 *   
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
10
 *   on using and copying this software.  
11
 */
12
/*
13
Name
14
  emt.c - emitter
15
Function
16
  Code emitter
17
Notes
18
  None
19
Modified
20
  09/23/91 MJRoberts     - creation
21
*/
22
23
#include <assert.h>
24
#include "os.h"
25
#include "std.h"
26
#include "emt.h"
27
#include "opc.h"
28
#include "err.h"
29
#include "tok.h"
30
31
void emtval(emtcxdef *ctx, tokdef *tok, uchar *base)
32
{
33
    ushort oplen;
34
        
35
    switch(tok->toktyp)
36
    {
37
    case TOKTSYMBOL:
38
        switch(tok->toksym.tokstyp)
39
        {
40
        case TOKSTARGC:
41
            emtop(ctx, OPCARGC);
42
            return;
43
            
44
        case TOKSTSELF:
45
            emtop(ctx, OPCPUSHSELF);
46
            return;
47
            
48
        case TOKSTOBJ:
49
        case TOKSTFWDOBJ:
50
            emtop(ctx, OPCPUSHOBJ);
51
            break;
52
        case TOKSTLOCAL:
53
            if (tok->toksym.toksfr)
54
            {
55
                emtop(ctx, OPCGETDBLCL);   /* debug local - specifies frame */
56
                emtint2(ctx, ctx->emtcxfrob);          /* emit frame object */
57
                emtint2(ctx, tok->toksym.toksfr);      /* emit frame offset */
58
            }
59
            else
60
                emtop(ctx, OPCGETLCL);
61
            break;
62
            
63
        case TOKSTBIFN:
64
            emtop(ctx, OPCBUILTIN);
65
            emtbyte(ctx, 0);
66
            break;
67
        case TOKSTFUNC:
68
        case TOKSTFWDFN:
69
            emtop(ctx, OPCPUSHFN);
70
            break;
71
        case TOKSTPROP:
72
            emtop(ctx, OPCGETPSELF);
73
            emtbyte(ctx, 0);
74
            break;
75
        case TOKSTPROPSPEC:
76
            emtop(ctx, OPCGETPSELFDATA);
77
            break;
78
        default:
79
            errsig(ctx->emtcxerr, ERR_REQOBJ);
80
            /* NOTREACHED */
81
        }
82
        emtint2(ctx, tok->toksym.toksval);
83
        return;
84
85
    case TOKTNUMBER:
86
        emtop(ctx, OPCPUSHNUM);
87
        emtint4(ctx, tok->tokval);
88
        return;
89
90
    case TOKTNIL:
91
        emtop(ctx, OPCPUSHNIL);
92
        return;
93
    case TOKTTRUE:
94
        emtop(ctx, OPCPUSHTRUE);
95
        return;
96
        
97
    case TOKTPOUND:
98
        emtop(ctx, OPCPUSHPN);
99
        emtint2(ctx, tok->tokofs);
100
        return;
101
102
    case TOKTSSTRING:
103
        emtop(ctx, OPCPUSHSTR);
104
        break;
105
    case TOKTDSTRING:
106
        emtop(ctx, OPCSAY);
107
        break;
108
    case TOKTLIST:
109
        emtop(ctx, OPCPUSHLST);
110
        emtlst(ctx, (uint)tok->tokofs, base);
111
        return;
112
    }
113
114
    /* if we haven't returned already, we have a large operand */
115
    oplen = osrp2(base + tok->tokofs);
116
    emtmem(ctx, base + tok->tokofs, oplen);
117
}
118
119
/* emit a list value */
120
void emtlst(emtcxdef *ctx, uint ofs, uchar *base)
121
{
122
    uint      initofs;
123
    ushort    i;
124
    emtlidef *lst;
125
    emtledef *ele;
126
        
127
    initofs = ctx->emtcxofs;                        /* save starting offset */
128
    emtint2(ctx, 2);                             /* emit placeholder length */
129
    if (ofs == 0) return;              /* nothing more to do for empty list */
130
131
    lst = (emtlidef *)(base + ofs);
132
133
    for (i = lst->emtlicnt, ele = &lst->emtliele[i-1] ; i ; --ele, --i)
134
    {
135
        uchar dat;
136
        
137
        switch(ele->emtletyp)
138
        {
139
        case TOKTLIST:
140
            emtbyte(ctx, DAT_LIST);
141
            emtlst(ctx, (uint)ele->emtleval, base);
142
            continue;
143
144
        case TOKTSSTRING:
145
        {
146
            uint oplen = osrp2(base + ele->emtleval);
147
            
148
            emtbyte(ctx, DAT_SSTRING);
149
            emtmem(ctx, base + ele->emtleval, oplen);
150
            continue;
151
        }
152
153
        case TOKTNUMBER:
154
            dat = DAT_NUMBER;
155
            break;
156
        case TOKTNIL:
157
            dat = DAT_NIL;
158
            break;
159
        case TOKTTRUE:
160
            dat = DAT_TRUE;
161
            break;
162
163
        case TOKTPOUND:
164
            dat = DAT_PROPNUM;
165
            goto symbol;
166
        case TOKTFUNCTION:
167
            dat = DAT_FNADDR;
168
            goto symbol;
169
        case TOKTOBJECT:
170
            dat = DAT_OBJECT;
171
            goto symbol;
172
        case TOKTDOT:
173
            dat = DAT_PROPNUM;
174
            /* FALLTHROUGH */
175
        symbol:
176
            emtbyte(ctx, dat);
177
            emtint2(ctx, (ushort)ele->emtleval);
178
            continue;
179
180
        default:
181
            assert(FALSE);
182
            break;
183
        }
184
        
185
        /* if we get here, emit datatype in dat, plus value */
186
        emtbyte(ctx, dat);
187
        if (dat != DAT_TRUE && dat != DAT_NIL)
188
            emtint4(ctx, ele->emtleval);
189
    }
190
    oswp2(ctx->emtcxptr + initofs, ctx->emtcxofs - initofs);
191
}
192
193
/* reserve space for code, expanding object if needed */
194
void emtres(emtcxdef *ctx, ushort bytes)
195
{
196
    ushort oldsiz = mcmobjsiz(ctx->emtcxmem, ctx->emtcxobj);
197
    ushort need;
198
    
199
    need = ctx->emtcxofs + bytes + 1;
200
    
201
    if (need > oldsiz)
202
    {
203
        ushort newsiz;
204
        
205
        newsiz = need + EMTINC;
206
        if (newsiz < oldsiz) errsig(ctx->emtcxerr, ERR_OBJOVF);
207
        ctx->emtcxptr = mcmrealo(ctx->emtcxmem, ctx->emtcxobj, newsiz);
208
        assert(mcmobjsiz(ctx->emtcxmem, ctx->emtcxobj) >= need);
209
    }
210
}
211
212
/* get a new temporary label */
213
uint emtglbl(emtcxdef *ctx)
214
{
215
    uint ret = ctx->emtcxlfre;
216
217
    if (ctx->emtcxlfre == EMTLLNKEND) errsig(ctx->emtcxerr, ERR_NOLBL);
218
    ctx->emtcxlfre = ctx->emtcxlbl[ret].emtllnk;
219
    ctx->emtcxlbl[ret].emtllnk = EMTLLNKEND;     /* nothing in label's list */
220
    ctx->emtcxlbl[ret].emtlflg = 0;                 /* label is not yet set */
221
    return(ret);
222
}
223
224
/* get a new label and set to the current position */
225
uint emtgslbl(emtcxdef *ctx)
226
{
227
    uint ret = ctx->emtcxlfre;
228
229
    if (ctx->emtcxlfre == EMTLLNKEND) errsig(ctx->emtcxerr, ERR_NOLBL);
230
    ctx->emtcxlfre = ctx->emtcxlbl[ret].emtllnk;
231
    ctx->emtcxlbl[ret].emtllnk = EMTLLNKEND;     /* nothing in label's list */
232
    ctx->emtcxlbl[ret].emtlflg = EMTLFSET;          /* label is not yet set */
233
    ctx->emtcxlbl[ret].emtlofs = ctx->emtcxofs;             /* set position */
234
    return(ret);
235
}
236
237
/* set a temporary label */
238
void emtslbl(emtcxdef *ctx, noreg uint *lblp, int release)
239
{
240
    uint     lbl = *lblp;
241
    emtldef *p = &ctx->emtcxlbl[lbl];
242
    uint     fwd;
243
    emtldef *fwdp;
244
    ushort   nxt;
245
    short    diff;
246
    ushort   curpos = ctx->emtcxofs;
247
    
248
    p->emtlofs = curpos;
249
    p->emtlflg |= EMTLFSET;
250
    
251
    /* run through forward reference list, fixing up each reference */
252
    for (fwd = p->emtllnk ; fwd != EMTLLNKEND ; fwd = nxt)
253
    {
254
        fwdp = &ctx->emtcxlbl[fwd];        /* get pointer to current record */
255
        nxt = fwdp->emtllnk;                    /* remember the next record */
256
257
        /* write the fixup, and release the forward reference */
258
        diff = curpos - fwdp->emtlofs;
259
        oswp2(ctx->emtcxptr + fwdp->emtlofs, diff);
260
        fwdp->emtllnk = EMTLLNKEND;
261
        emtdlbl(ctx, &fwd);
262
    }
263
264
    p->emtllnk = EMTLLNKEND;    /* there are no more forward refs for label */
265
    if (release) emtdlbl(ctx, lblp);
266
}
267
268
/* release a temporary label */
269
void emtdlbl(emtcxdef *ctx, noreg uint *lblp)
270
{
271
    /* if label has forward references, internal error: label never set */
272
    if (ctx->emtcxlbl[*lblp].emtllnk != EMTLLNKEND)
273
        errsig(ctx->emtcxerr, ERR_LBNOSET);
274
          
275
    ctx->emtcxlbl[*lblp].emtllnk = ctx->emtcxlfre;
276
    ctx->emtcxlfre = *lblp;
277
    *lblp = EMTLLNKEND;
278
}
279
280
/* clear a temporary label without error checking */
281
void emtclbl(emtcxdef *ctx, noreg uint *lblp)
282
{
283
    emtslbl(ctx, lblp, TRUE);         /* clear up forward ref's, and delete */
284
}
285
286
/* emit a jump to a temporary label */
287
void emtjmp(emtcxdef *ctx, uchar op, uint lbl)
288
{
289
    emtldef *p = &ctx->emtcxlbl[lbl];
290
    short    diff;
291
    uint     fwd;
292
    
293
    emtop(ctx, op);
294
    
295
    if (p->emtlflg & EMTLFSET)
296
        diff = p->emtlofs - ctx->emtcxofs;      /* back ref - compute delta */
297
    else
298
    {
299
        diff = 0;
300
        fwd = emtglbl(ctx);             /* get a forward ref fixup reminder */
301
        ctx->emtcxlbl[fwd].emtllnk = p->emtllnk;  /* link into label's list */
302
        ctx->emtcxlbl[fwd].emtlofs = ctx->emtcxofs;       /* remember where */
303
        p->emtllnk = fwd;          /* make it new head of this label's list */
304
    }
305
    emtint2(ctx, diff);
306
}
307
308
/* set up the labels - put all in free list */
309
void emtlini(emtcxdef *ctx)
310
{
311
    int      i;
312
    emtldef *p;
313
    int      max;
314
    
315
    for (max = ctx->emtcxlcnt, i = 1, p = ctx->emtcxlbl ; i < max ; ++p, ++i)
316
        p->emtllnk = i;
317
    p->emtllnk = EMTLLNKEND;
318
    ctx->emtcxlfre = 0;
319
}