Subversion Repositories Kolibri OS

Rev

Rev 647 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 647 Rev 6429
1
/*
1
/*
2
 *  CIL code generator for TCC
2
 *  CIL code generator for TCC
3
 * 
3
 * 
4
 *  Copyright (c) 2002 Fabrice Bellard
4
 *  Copyright (c) 2002 Fabrice Bellard
5
 *
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
6
 * This library is free software; you can redistribute it and/or
7
 *  it under the terms of the GNU General Public License as published by
7
 * modify it under the terms of the GNU Lesser General Public
8
 *  the Free Software Foundation; either version 2 of the License, or
8
 * License as published by the Free Software Foundation; either
9
 *  (at your option) any later version.
9
 * version 2 of the License, or (at your option) any later version.
10
 *
10
 *
11
 *  This program is distributed in the hope that it will be useful,
11
 * This library is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 *  GNU General Public License for more details.
14
 * Lesser General Public License for more details.
15
 *
15
 *
16
 *  You should have received a copy of the GNU General Public License
16
 * You should have received a copy of the GNU Lesser General Public
17
 *  along with this program; if not, write to the Free Software
17
 * License along with this library; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
19
 */
20
 
20
 
21
/* number of available registers */
21
/* number of available registers */
22
#define NB_REGS             3
22
#define NB_REGS             3
23
 
23
 
24
/* a register can belong to several classes. The classes must be
24
/* a register can belong to several classes. The classes must be
25
   sorted from more general to more precise (see gv2() code which does
25
   sorted from more general to more precise (see gv2() code which does
26
   assumptions on it). */
26
   assumptions on it). */
27
#define RC_ST      0x0001  /* any stack entry */
27
#define RC_ST      0x0001  /* any stack entry */
28
#define RC_ST0     0x0002  /* top of stack */
28
#define RC_ST0     0x0002  /* top of stack */
29
#define RC_ST1     0x0004  /* top - 1 */
29
#define RC_ST1     0x0004  /* top - 1 */
30
 
30
 
31
#define RC_INT     RC_ST
31
#define RC_INT     RC_ST
32
#define RC_FLOAT   RC_ST
32
#define RC_FLOAT   RC_ST
33
#define RC_IRET    RC_ST0 /* function return: integer register */
33
#define RC_IRET    RC_ST0 /* function return: integer register */
34
#define RC_LRET    RC_ST0 /* function return: second integer register */
34
#define RC_LRET    RC_ST0 /* function return: second integer register */
35
#define RC_FRET    RC_ST0 /* function return: float register */
35
#define RC_FRET    RC_ST0 /* function return: float register */
36
 
36
 
37
/* pretty names for the registers */
37
/* pretty names for the registers */
38
enum {
38
enum {
39
    REG_ST0 = 0,
39
    REG_ST0 = 0,
40
    REG_ST1,
40
    REG_ST1,
41
    REG_ST2,
41
    REG_ST2,
42
};
42
};
43
 
43
 
44
int reg_classes[NB_REGS] = {
44
const int reg_classes[NB_REGS] = {
45
    /* ST0 */ RC_ST | RC_ST0,
45
    /* ST0 */ RC_ST | RC_ST0,
46
    /* ST1 */ RC_ST | RC_ST1,
46
    /* ST1 */ RC_ST | RC_ST1,
47
    /* ST2 */ RC_ST,
47
    /* ST2 */ RC_ST,
48
};
48
};
49
 
49
 
50
/* return registers for function */
50
/* return registers for function */
51
#define REG_IRET REG_ST0 /* single word int return register */
51
#define REG_IRET REG_ST0 /* single word int return register */
52
#define REG_LRET REG_ST0 /* second word return register (for long long) */
52
#define REG_LRET REG_ST0 /* second word return register (for long long) */
53
#define REG_FRET REG_ST0 /* float return register */
53
#define REG_FRET REG_ST0 /* float return register */
54
 
54
 
55
/* defined if function parameters must be evaluated in reverse order */
55
/* defined if function parameters must be evaluated in reverse order */
56
//#define INVERT_FUNC_PARAMS
56
/* #define INVERT_FUNC_PARAMS */
57
 
57
 
58
/* defined if structures are passed as pointers. Otherwise structures
58
/* defined if structures are passed as pointers. Otherwise structures
59
   are directly pushed on stack. */
59
   are directly pushed on stack. */
60
//#define FUNC_STRUCT_PARAM_AS_PTR
60
/* #define FUNC_STRUCT_PARAM_AS_PTR */
61
 
61
 
62
/* pointer size, in bytes */
62
/* pointer size, in bytes */
63
#define PTR_SIZE 4
63
#define PTR_SIZE 4
64
 
64
 
65
/* long double size and alignment, in bytes */
65
/* long double size and alignment, in bytes */
66
#define LDOUBLE_SIZE  8
66
#define LDOUBLE_SIZE  8
67
#define LDOUBLE_ALIGN 8
67
#define LDOUBLE_ALIGN 8
68
 
68
 
69
/* function call context */
69
/* function call context */
70
typedef struct GFuncContext {
70
typedef struct GFuncContext {
71
    int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
71
    int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
72
} GFuncContext;
72
} GFuncContext;
73
 
73
 
74
/******************************************************/
74
/******************************************************/
75
/* opcode definitions */
75
/* opcode definitions */
76
 
76
 
77
#define IL_OP_PREFIX 0xFE
77
#define IL_OP_PREFIX 0xFE
78
 
78
 
79
enum ILOPCodes {
79
enum ILOPCodes {
80
#define OP(name, str, n) IL_OP_ ## name = n,
80
#define OP(name, str, n) IL_OP_ ## name = n,
81
#include "il-opcodes.h"
81
#include "il-opcodes.h"
82
#undef OP
82
#undef OP
83
};
83
};
84
 
84
 
85
char *il_opcodes_str[] = {
85
char *il_opcodes_str[] = {
86
#define OP(name, str, n) [n] = str,
86
#define OP(name, str, n) [n] = str,
87
#include "il-opcodes.h"
87
#include "il-opcodes.h"
88
#undef OP
88
#undef OP
89
};
89
};
90
 
90
 
91
/******************************************************/
91
/******************************************************/
92
 
92
 
93
/* arguments variable numbers start from there */
93
/* arguments variable numbers start from there */
94
#define ARG_BASE 0x70000000
94
#define ARG_BASE 0x70000000
95
 
95
 
96
static FILE *il_outfile;
96
static FILE *il_outfile;
97
 
97
 
98
static void out_byte(int c)
98
static void out_byte(int c)
99
{
99
{
100
    *(char *)ind++ = c;
100
    *(char *)ind++ = c;
101
}
101
}
102
 
102
 
103
static void out_le32(int c)
103
static void out_le32(int c)
104
{
104
{
105
    out_byte(c);
105
    out_byte(c);
106
    out_byte(c >> 8);
106
    out_byte(c >> 8);
107
    out_byte(c >> 16);
107
    out_byte(c >> 16);
108
    out_byte(c >> 24);
108
    out_byte(c >> 24);
109
}
109
}
110
 
110
 
111
static void init_outfile(void)
111
static void init_outfile(void)
112
{
112
{
113
    if (!il_outfile) {
113
    if (!il_outfile) {
114
        il_outfile = stdout;
114
        il_outfile = stdout;
115
        fprintf(il_outfile, 
115
        fprintf(il_outfile, 
116
                ".assembly extern mscorlib\n"
116
                ".assembly extern mscorlib\n"
117
                "{\n"
117
                "{\n"
118
                ".ver 1:0:2411:0\n"
118
                ".ver 1:0:2411:0\n"
119
                "}\n\n");
119
                "}\n\n");
120
    }
120
    }
121
}
121
}
122
 
122
 
123
static void out_op1(int op)
123
static void out_op1(int op)
124
{
124
{
125
    if (op & 0x100)
125
    if (op & 0x100)
126
        out_byte(IL_OP_PREFIX);
126
        out_byte(IL_OP_PREFIX);
127
    out_byte(op & 0xff);
127
    out_byte(op & 0xff);
128
}
128
}
129
 
129
 
130
/* output an opcode with prefix */
130
/* output an opcode with prefix */
131
static void out_op(int op)
131
static void out_op(int op)
132
{
132
{
133
    out_op1(op);
133
    out_op1(op);
134
    fprintf(il_outfile, " %s\n", il_opcodes_str[op]);
134
    fprintf(il_outfile, " %s\n", il_opcodes_str[op]);
135
}
135
}
136
 
136
 
137
static void out_opb(int op, int c)
137
static void out_opb(int op, int c)
138
{
138
{
139
    out_op1(op);
139
    out_op1(op);
140
    out_byte(c);
140
    out_byte(c);
141
    fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c);
141
    fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c);
142
}
142
}
143
 
143
 
144
static void out_opi(int op, int c)
144
static void out_opi(int op, int c)
145
{
145
{
146
    out_op1(op);
146
    out_op1(op);
147
    out_le32(c);
147
    out_le32(c);
148
    fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c);
148
    fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c);
149
}
149
}
150
 
150
 
151
/* XXX: not complete */
151
/* XXX: not complete */
152
static void il_type_to_str(char *buf, int buf_size, 
152
static void il_type_to_str(char *buf, int buf_size, 
153
                           int t, const char *varstr)
153
                           int t, const char *varstr)
154
{
154
{
155
    int bt;
155
    int bt;
156
    Sym *s, *sa;
156
    Sym *s, *sa;
157
    char buf1[256];
157
    char buf1[256];
158
    const char *tstr;
158
    const char *tstr;
159
 
159
 
160
    t = t & VT_TYPE;
160
    t = t & VT_TYPE;
161
    bt = t & VT_BTYPE;
161
    bt = t & VT_BTYPE;
162
    buf[0] = '\0';
162
    buf[0] = '\0';
163
    if (t & VT_UNSIGNED)
163
    if (t & VT_UNSIGNED)
164
        pstrcat(buf, buf_size, "unsigned ");
164
        pstrcat(buf, buf_size, "unsigned ");
165
    switch(bt) {
165
    switch(bt) {
166
    case VT_VOID:
166
    case VT_VOID:
167
        tstr = "void";
167
        tstr = "void";
168
        goto add_tstr;
168
        goto add_tstr;
169
    case VT_BOOL:
169
    case VT_BOOL:
170
        tstr = "bool";
170
        tstr = "bool";
171
        goto add_tstr;
171
        goto add_tstr;
172
    case VT_BYTE:
172
    case VT_BYTE:
173
        tstr = "int8";
173
        tstr = "int8";
174
        goto add_tstr;
174
        goto add_tstr;
175
    case VT_SHORT:
175
    case VT_SHORT:
176
        tstr = "int16";
176
        tstr = "int16";
177
        goto add_tstr;
177
        goto add_tstr;
178
    case VT_ENUM:
178
    case VT_ENUM:
179
    case VT_INT:
179
    case VT_INT:
180
    case VT_LONG:
180
    case VT_LONG:
181
        tstr = "int32";
181
        tstr = "int32";
182
        goto add_tstr;
182
        goto add_tstr;
183
    case VT_LLONG:
183
    case VT_LLONG:
184
        tstr = "int64";
184
        tstr = "int64";
185
        goto add_tstr;
185
        goto add_tstr;
186
    case VT_FLOAT:
186
    case VT_FLOAT:
187
        tstr = "float32";
187
        tstr = "float32";
188
        goto add_tstr;
188
        goto add_tstr;
189
    case VT_DOUBLE:
189
    case VT_DOUBLE:
190
    case VT_LDOUBLE:
190
    case VT_LDOUBLE:
191
        tstr = "float64";
191
        tstr = "float64";
192
    add_tstr:
192
    add_tstr:
193
        pstrcat(buf, buf_size, tstr);
193
        pstrcat(buf, buf_size, tstr);
194
        break;
194
        break;
195
    case VT_STRUCT:
195
    case VT_STRUCT:
196
        error("structures not handled yet");
196
        tcc_error("structures not handled yet");
197
        break;
197
        break;
198
    case VT_FUNC:
198
    case VT_FUNC:
199
        s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
199
        s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
200
        il_type_to_str(buf, buf_size, s->t, varstr);
200
        il_type_to_str(buf, buf_size, s->t, varstr);
201
        pstrcat(buf, buf_size, "(");
201
        pstrcat(buf, buf_size, "(");
202
        sa = s->next;
202
        sa = s->next;
203
        while (sa != NULL) {
203
        while (sa != NULL) {
204
            il_type_to_str(buf1, sizeof(buf1), sa->t, NULL);
204
            il_type_to_str(buf1, sizeof(buf1), sa->t, NULL);
205
            pstrcat(buf, buf_size, buf1);
205
            pstrcat(buf, buf_size, buf1);
206
            sa = sa->next;
206
            sa = sa->next;
207
            if (sa)
207
            if (sa)
208
                pstrcat(buf, buf_size, ", ");
208
                pstrcat(buf, buf_size, ", ");
209
        }
209
        }
210
        pstrcat(buf, buf_size, ")");
210
        pstrcat(buf, buf_size, ")");
211
        goto no_var;
211
        goto no_var;
212
    case VT_PTR:
212
    case VT_PTR:
213
        s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
213
        s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
214
        pstrcpy(buf1, sizeof(buf1), "*");
214
        pstrcpy(buf1, sizeof(buf1), "*");
215
        if (varstr)
215
        if (varstr)
216
            pstrcat(buf1, sizeof(buf1), varstr);
216
            pstrcat(buf1, sizeof(buf1), varstr);
217
        il_type_to_str(buf, buf_size, s->t, buf1);
217
        il_type_to_str(buf, buf_size, s->t, buf1);
218
        goto no_var;
218
        goto no_var;
219
    }
219
    }
220
    if (varstr) {
220
    if (varstr) {
221
        pstrcat(buf, buf_size, " ");
221
        pstrcat(buf, buf_size, " ");
222
        pstrcat(buf, buf_size, varstr);
222
        pstrcat(buf, buf_size, varstr);
223
    }
223
    }
224
 no_var: ;
224
 no_var: ;
225
}
225
}
226
 
226
 
227
 
227
 
228
/* patch relocation entry with value 'val' */
228
/* patch relocation entry with value 'val' */
229
void greloc_patch1(Reloc *p, int val)
229
void greloc_patch1(Reloc *p, int val)
230
{
230
{
231
}
231
}
232
 
232
 
233
/* output a symbol and patch all calls to it */
233
/* output a symbol and patch all calls to it */
234
void gsym_addr(t, a)
234
void gsym_addr(t, a)
235
{
235
{
236
}
236
}
237
 
237
 
238
/* output jump and return symbol */
238
/* output jump and return symbol */
239
static int out_opj(int op, int c)
239
static int out_opj(int op, int c)
240
{
240
{
241
    out_op1(op);
241
    out_op1(op);
242
    out_le32(0);
242
    out_le32(0);
243
    if (c == 0) {
243
    if (c == 0) {
244
        c = ind - (int)cur_text_section->data;
244
        c = ind - (int)cur_text_section->data;
245
    }
245
    }
246
    fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c);
246
    fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c);
247
    return c;
247
    return c;
248
}
248
}
249
 
249
 
250
void gsym(int t)
250
void gsym(int t)
251
{
251
{
252
    fprintf(il_outfile, "L%d:\n", t);
252
    fprintf(il_outfile, "L%d:\n", t);
253
}
253
}
254
 
254
 
255
/* load 'r' from value 'sv' */
255
/* load 'r' from value 'sv' */
256
void load(int r, SValue *sv)
256
void load(int r, SValue *sv)
257
{
257
{
258
    int v, fc, ft;
258
    int v, fc, ft;
259
 
259
 
260
    v = sv->r & VT_VALMASK;
260
    v = sv->r & VT_VALMASK;
261
    fc = sv->c.i;
261
    fc = sv->c.i;
262
    ft = sv->t;
262
    ft = sv->t;
263
 
263
 
264
    if (sv->r & VT_LVAL) {
264
    if (sv->r & VT_LVAL) {
265
        if (v == VT_LOCAL) {
265
        if (v == VT_LOCAL) {
266
            if (fc >= ARG_BASE) {
266
            if (fc >= ARG_BASE) {
267
                fc -= ARG_BASE;
267
                fc -= ARG_BASE;
268
                if (fc >= 0 && fc <= 4) {
268
                if (fc >= 0 && fc <= 4) {
269
                    out_op(IL_OP_LDARG_0 + fc);
269
                    out_op(IL_OP_LDARG_0 + fc);
270
                } else if (fc <= 0xff) {
270
                } else if (fc <= 0xff) {
271
                    out_opb(IL_OP_LDARG_S, fc);
271
                    out_opb(IL_OP_LDARG_S, fc);
272
                } else {
272
                } else {
273
                    out_opi(IL_OP_LDARG, fc);
273
                    out_opi(IL_OP_LDARG, fc);
274
                }
274
                }
275
            } else {
275
            } else {
276
                if (fc >= 0 && fc <= 4) {
276
                if (fc >= 0 && fc <= 4) {
277
                    out_op(IL_OP_LDLOC_0 + fc);
277
                    out_op(IL_OP_LDLOC_0 + fc);
278
                } else if (fc <= 0xff) {
278
                } else if (fc <= 0xff) {
279
                    out_opb(IL_OP_LDLOC_S, fc);
279
                    out_opb(IL_OP_LDLOC_S, fc);
280
                } else {
280
                } else {
281
                    out_opi(IL_OP_LDLOC, fc);
281
                    out_opi(IL_OP_LDLOC, fc);
282
                }
282
                }
283
            }
283
            }
284
        } else if (v == VT_CONST) {
284
        } else if (v == VT_CONST) {
285
                /* XXX: handle globals */
285
                /* XXX: handle globals */
286
                out_opi(IL_OP_LDSFLD, 0);
286
                out_opi(IL_OP_LDSFLD, 0);
287
        } else {
287
        } else {
288
            if ((ft & VT_BTYPE) == VT_FLOAT) {
288
            if ((ft & VT_BTYPE) == VT_FLOAT) {
289
                out_op(IL_OP_LDIND_R4);
289
                out_op(IL_OP_LDIND_R4);
290
            } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
290
            } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
291
                out_op(IL_OP_LDIND_R8);
291
                out_op(IL_OP_LDIND_R8);
292
            } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
292
            } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
293
                out_op(IL_OP_LDIND_R8);
293
                out_op(IL_OP_LDIND_R8);
294
            } else if ((ft & VT_TYPE) == VT_BYTE)
294
            } else if ((ft & VT_TYPE) == VT_BYTE)
295
                out_op(IL_OP_LDIND_I1);
295
                out_op(IL_OP_LDIND_I1);
296
            else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
296
            else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
297
                out_op(IL_OP_LDIND_U1);
297
                out_op(IL_OP_LDIND_U1);
298
            else if ((ft & VT_TYPE) == VT_SHORT)
298
            else if ((ft & VT_TYPE) == VT_SHORT)
299
                out_op(IL_OP_LDIND_I2);
299
                out_op(IL_OP_LDIND_I2);
300
            else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
300
            else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
301
                out_op(IL_OP_LDIND_U2);
301
                out_op(IL_OP_LDIND_U2);
302
            else
302
            else
303
                out_op(IL_OP_LDIND_I4);
303
                out_op(IL_OP_LDIND_I4);
304
        } 
304
        } 
305
    } else {
305
    } else {
306
        if (v == VT_CONST) {
306
        if (v == VT_CONST) {
307
            /* XXX: handle globals */
307
            /* XXX: handle globals */
308
            if (fc >= -1 && fc <= 8) {
308
            if (fc >= -1 && fc <= 8) {
309
                out_op(IL_OP_LDC_I4_M1 + fc + 1); 
309
                out_op(IL_OP_LDC_I4_M1 + fc + 1); 
310
            } else {
310
            } else {
311
                out_opi(IL_OP_LDC_I4, fc);
311
                out_opi(IL_OP_LDC_I4, fc);
312
            }
312
            }
313
        } else if (v == VT_LOCAL) {
313
        } else if (v == VT_LOCAL) {
314
            if (fc >= ARG_BASE) {
314
            if (fc >= ARG_BASE) {
315
                fc -= ARG_BASE;
315
                fc -= ARG_BASE;
316
                if (fc <= 0xff) {
316
                if (fc <= 0xff) {
317
                    out_opb(IL_OP_LDARGA_S, fc);
317
                    out_opb(IL_OP_LDARGA_S, fc);
318
                } else {
318
                } else {
319
                    out_opi(IL_OP_LDARGA, fc);
319
                    out_opi(IL_OP_LDARGA, fc);
320
                }
320
                }
321
            } else {
321
            } else {
322
                if (fc <= 0xff) {
322
                if (fc <= 0xff) {
323
                    out_opb(IL_OP_LDLOCA_S, fc);
323
                    out_opb(IL_OP_LDLOCA_S, fc);
324
                } else {
324
                } else {
325
                    out_opi(IL_OP_LDLOCA, fc);
325
                    out_opi(IL_OP_LDLOCA, fc);
326
                }
326
                }
327
            }
327
            }
328
        } else {
328
        } else {
329
            /* XXX: do it */
329
            /* XXX: do it */
330
        }
330
        }
331
    }
331
    }
332
}
332
}
333
 
333
 
334
/* store register 'r' in lvalue 'v' */
334
/* store register 'r' in lvalue 'v' */
335
void store(int r, SValue *sv)
335
void store(int r, SValue *sv)
336
{
336
{
337
    int v, fc, ft;
337
    int v, fc, ft;
338
 
338
 
339
    v = sv->r & VT_VALMASK;
339
    v = sv->r & VT_VALMASK;
340
    fc = sv->c.i;
340
    fc = sv->c.i;
341
    ft = sv->t;
341
    ft = sv->t;
342
    if (v == VT_LOCAL) {
342
    if (v == VT_LOCAL) {
343
        if (fc >= ARG_BASE) {
343
        if (fc >= ARG_BASE) {
344
            fc -= ARG_BASE;
344
            fc -= ARG_BASE;
345
            /* XXX: check IL arg store semantics */
345
            /* XXX: check IL arg store semantics */
346
            if (fc <= 0xff) {
346
            if (fc <= 0xff) {
347
                out_opb(IL_OP_STARG_S, fc);
347
                out_opb(IL_OP_STARG_S, fc);
348
            } else {
348
            } else {
349
                out_opi(IL_OP_STARG, fc);
349
                out_opi(IL_OP_STARG, fc);
350
            }
350
            }
351
        } else {
351
        } else {
352
            if (fc >= 0 && fc <= 4) {
352
            if (fc >= 0 && fc <= 4) {
353
                out_op(IL_OP_STLOC_0 + fc);
353
                out_op(IL_OP_STLOC_0 + fc);
354
            } else if (fc <= 0xff) {
354
            } else if (fc <= 0xff) {
355
                out_opb(IL_OP_STLOC_S, fc);
355
                out_opb(IL_OP_STLOC_S, fc);
356
            } else {
356
            } else {
357
                out_opi(IL_OP_STLOC, fc);
357
                out_opi(IL_OP_STLOC, fc);
358
            }
358
            }
359
        }
359
        }
360
    } else if (v == VT_CONST) {
360
    } else if (v == VT_CONST) {
361
        /* XXX: handle globals */
361
        /* XXX: handle globals */
362
        out_opi(IL_OP_STSFLD, 0);
362
        out_opi(IL_OP_STSFLD, 0);
363
    } else {
363
    } else {
364
        if ((ft & VT_BTYPE) == VT_FLOAT)
364
        if ((ft & VT_BTYPE) == VT_FLOAT)
365
            out_op(IL_OP_STIND_R4);
365
            out_op(IL_OP_STIND_R4);
366
        else if ((ft & VT_BTYPE) == VT_DOUBLE)
366
        else if ((ft & VT_BTYPE) == VT_DOUBLE)
367
            out_op(IL_OP_STIND_R8);
367
            out_op(IL_OP_STIND_R8);
368
        else if ((ft & VT_BTYPE) == VT_LDOUBLE)
368
        else if ((ft & VT_BTYPE) == VT_LDOUBLE)
369
            out_op(IL_OP_STIND_R8);
369
            out_op(IL_OP_STIND_R8);
370
        else if ((ft & VT_BTYPE) == VT_BYTE)
370
        else if ((ft & VT_BTYPE) == VT_BYTE)
371
            out_op(IL_OP_STIND_I1);
371
            out_op(IL_OP_STIND_I1);
372
        else if ((ft & VT_BTYPE) == VT_SHORT)
372
        else if ((ft & VT_BTYPE) == VT_SHORT)
373
            out_op(IL_OP_STIND_I2);
373
            out_op(IL_OP_STIND_I2);
374
        else
374
        else
375
            out_op(IL_OP_STIND_I4);
375
            out_op(IL_OP_STIND_I4);
376
    }
376
    }
377
}
377
}
378
 
378
 
379
/* start function call and return function call context */
379
/* start function call and return function call context */
380
void gfunc_start(GFuncContext *c, int func_call)
380
void gfunc_start(GFuncContext *c, int func_call)
381
{
381
{
382
    c->func_call = func_call;
382
    c->func_call = func_call;
383
}
383
}
384
 
384
 
385
/* push function parameter which is in (vtop->t, vtop->c). Stack entry
385
/* push function parameter which is in (vtop->t, vtop->c). Stack entry
386
   is then popped. */
386
   is then popped. */
387
void gfunc_param(GFuncContext *c)
387
void gfunc_param(GFuncContext *c)
388
{
388
{
389
    if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
389
    if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
390
        error("structures passed as value not handled yet");
390
        tcc_error("structures passed as value not handled yet");
391
    } else {
391
    } else {
392
        /* simply push on stack */
392
        /* simply push on stack */
393
        gv(RC_ST0);
393
        gv(RC_ST0);
394
    }
394
    }
395
    vtop--;
395
    vtop--;
396
}
396
}
397
 
397
 
398
/* generate function call with address in (vtop->t, vtop->c) and free function
398
/* generate function call with address in (vtop->t, vtop->c) and free function
399
   context. Stack entry is popped */
399
   context. Stack entry is popped */
400
void gfunc_call(GFuncContext *c)
400
void gfunc_call(GFuncContext *c)
401
{
401
{
402
    char buf[1024];
402
    char buf[1024];
403
 
403
 
404
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
404
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
405
        /* XXX: more info needed from tcc */
405
        /* XXX: more info needed from tcc */
406
        il_type_to_str(buf, sizeof(buf), vtop->t, "xxx");
406
        il_type_to_str(buf, sizeof(buf), vtop->t, "xxx");
407
        fprintf(il_outfile, " call %s\n", buf);
407
        fprintf(il_outfile, " call %s\n", buf);
408
    } else {
408
    } else {
409
        /* indirect call */
409
        /* indirect call */
410
        gv(RC_INT);
410
        gv(RC_INT);
411
        il_type_to_str(buf, sizeof(buf), vtop->t, NULL);
411
        il_type_to_str(buf, sizeof(buf), vtop->t, NULL);
412
        fprintf(il_outfile, " calli %s\n", buf);
412
        fprintf(il_outfile, " calli %s\n", buf);
413
    }
413
    }
414
    vtop--;
414
    vtop--;
415
}
415
}
416
 
416
 
417
/* generate function prolog of type 't' */
417
/* generate function prolog of type 't' */
418
void gfunc_prolog(int t)
418
void gfunc_prolog(int t)
419
{
419
{
420
    int addr, u, func_call;
420
    int addr, u, func_call;
421
    Sym *sym;
421
    Sym *sym;
422
    char buf[1024];
422
    char buf[1024];
423
 
423
 
424
    init_outfile();
424
    init_outfile();
425
 
425
 
426
    /* XXX: pass function name to gfunc_prolog */
426
    /* XXX: pass function name to gfunc_prolog */
427
    il_type_to_str(buf, sizeof(buf), t, funcname);
427
    il_type_to_str(buf, sizeof(buf), t, funcname);
428
    fprintf(il_outfile, ".method static %s il managed\n", buf);
428
    fprintf(il_outfile, ".method static %s il managed\n", buf);
429
    fprintf(il_outfile, "{\n");
429
    fprintf(il_outfile, "{\n");
430
    /* XXX: cannot do better now */
430
    /* XXX: cannot do better now */
431
    fprintf(il_outfile, " .maxstack %d\n", NB_REGS);
431
    fprintf(il_outfile, " .maxstack %d\n", NB_REGS);
432
    fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n");
432
    fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n");
433
    
433
    
434
    if (!strcmp(funcname, "main"))
434
    if (!strcmp(funcname, "main"))
435
        fprintf(il_outfile, " .entrypoint\n");
435
        fprintf(il_outfile, " .entrypoint\n");
436
        
436
        
437
    sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
437
    sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
438
    func_call = sym->r;
438
    func_call = sym->r;
439
 
439
 
440
    addr = ARG_BASE;
440
    addr = ARG_BASE;
441
    /* if the function returns a structure, then add an
441
    /* if the function returns a structure, then add an
442
       implicit pointer parameter */
442
       implicit pointer parameter */
443
    func_vt = sym->t;
443
    func_vt = sym->t;
-
 
444
    func_var = (sym->c == FUNC_ELLIPSIS);
444
    if ((func_vt & VT_BTYPE) == VT_STRUCT) {
445
    if ((func_vt & VT_BTYPE) == VT_STRUCT) {
445
        func_vc = addr;
446
        func_vc = addr;
446
        addr++;
447
        addr++;
447
    }
448
    }
448
    /* define parameters */
449
    /* define parameters */
449
    while ((sym = sym->next) != NULL) {
450
    while ((sym = sym->next) != NULL) {
450
        u = sym->t;
451
        u = sym->t;
451
        sym_push(sym->v & ~SYM_FIELD, u,
452
        sym_push(sym->v & ~SYM_FIELD, u,
452
                 VT_LOCAL | VT_LVAL, addr);
453
                 VT_LOCAL | lvalue_type(sym->type.t), addr);
453
        addr++;
454
        addr++;
454
    }
455
    }
455
}
456
}
456
 
457
 
457
/* generate function epilog */
458
/* generate function epilog */
458
void gfunc_epilog(void)
459
void gfunc_epilog(void)
459
{
460
{
460
    out_op(IL_OP_RET);
461
    out_op(IL_OP_RET);
461
    fprintf(il_outfile, "}\n\n");
462
    fprintf(il_outfile, "}\n\n");
462
}
463
}
463
 
464
 
464
/* generate a jump to a label */
465
/* generate a jump to a label */
465
int gjmp(int t)
466
int gjmp(int t)
466
{
467
{
467
    return out_opj(IL_OP_BR, t);
468
    return out_opj(IL_OP_BR, t);
468
}
469
}
469
 
470
 
470
/* generate a jump to a fixed address */
471
/* generate a jump to a fixed address */
471
void gjmp_addr(int a)
472
void gjmp_addr(int a)
472
{
473
{
473
    /* XXX: handle syms */
474
    /* XXX: handle syms */
474
    out_opi(IL_OP_BR, a);
475
    out_opi(IL_OP_BR, a);
475
}
476
}
476
 
477
 
477
/* generate a test. set 'inv' to invert test. Stack entry is popped */
478
/* generate a test. set 'inv' to invert test. Stack entry is popped */
478
int gtst(int inv, int t)
479
int gtst(int inv, int t)
479
{
480
{
480
    int v, *p, c;
481
    int v, *p, c;
481
 
482
 
482
    v = vtop->r & VT_VALMASK;
483
    v = vtop->r & VT_VALMASK;
483
    if (v == VT_CMP) {
484
    if (v == VT_CMP) {
484
        c = vtop->c.i ^ inv;
485
        c = vtop->c.i ^ inv;
485
        switch(c) {
486
        switch(c) {
486
        case TOK_EQ:
487
        case TOK_EQ:
487
            c = IL_OP_BEQ;
488
            c = IL_OP_BEQ;
488
            break;
489
            break;
489
        case TOK_NE:
490
        case TOK_NE:
490
            c = IL_OP_BNE_UN;
491
            c = IL_OP_BNE_UN;
491
            break;
492
            break;
492
        case TOK_LT:
493
        case TOK_LT:
493
            c = IL_OP_BLT;
494
            c = IL_OP_BLT;
494
            break;
495
            break;
495
        case TOK_LE:
496
        case TOK_LE:
496
            c = IL_OP_BLE;
497
            c = IL_OP_BLE;
497
            break;
498
            break;
498
        case TOK_GT:
499
        case TOK_GT:
499
            c = IL_OP_BGT;
500
            c = IL_OP_BGT;
500
            break;
501
            break;
501
        case TOK_GE:
502
        case TOK_GE:
502
            c = IL_OP_BGE;
503
            c = IL_OP_BGE;
503
            break;
504
            break;
504
        case TOK_ULT:
505
        case TOK_ULT:
505
            c = IL_OP_BLT_UN;
506
            c = IL_OP_BLT_UN;
506
            break;
507
            break;
507
        case TOK_ULE:
508
        case TOK_ULE:
508
            c = IL_OP_BLE_UN;
509
            c = IL_OP_BLE_UN;
509
            break;
510
            break;
510
        case TOK_UGT:
511
        case TOK_UGT:
511
            c = IL_OP_BGT_UN;
512
            c = IL_OP_BGT_UN;
512
            break;
513
            break;
513
        case TOK_UGE:
514
        case TOK_UGE:
514
            c = IL_OP_BGE_UN;
515
            c = IL_OP_BGE_UN;
515
            break;
516
            break;
516
        }
517
        }
517
        t = out_opj(c, t);
518
        t = out_opj(c, t);
518
    } else if (v == VT_JMP || v == VT_JMPI) {
519
    } else if (v == VT_JMP || v == VT_JMPI) {
519
        /* && or || optimization */
520
        /* && or || optimization */
520
        if ((v & 1) == inv) {
521
        if ((v & 1) == inv) {
521
            /* insert vtop->c jump list in t */
522
            /* insert vtop->c jump list in t */
522
            p = &vtop->c.i;
523
            p = &vtop->c.i;
523
            while (*p != 0)
524
            while (*p != 0)
524
                p = (int *)*p;
525
                p = (int *)*p;
525
            *p = t;
526
            *p = t;
526
            t = vtop->c.i;
527
            t = vtop->c.i;
527
        } else {
528
        } else {
528
            t = gjmp(t);
529
            t = gjmp(t);
529
            gsym(vtop->c.i);
530
            gsym(vtop->c.i);
530
        }
531
        }
531
    } else {
-
 
532
        if (is_float(vtop->t)) {
-
 
533
            vpushi(0);
-
 
534
            gen_op(TOK_NE);
-
 
535
        }
-
 
536
        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
-
 
537
            /* constant jmp optimization */
-
 
538
            if ((vtop->c.i != 0) != inv) 
-
 
539
                t = gjmp(t);
-
 
540
        } else {
-
 
541
            v = gv(RC_INT);
-
 
542
            t = out_opj(IL_OP_BRTRUE - inv, t);
-
 
543
        }
-
 
544
    }
532
    }
545
    vtop--;
533
    vtop--;
546
    return t;
534
    return t;
547
}
535
}
548
 
536
 
549
/* generate an integer binary operation */
537
/* generate an integer binary operation */
550
void gen_opi(int op)
538
void gen_opi(int op)
551
{
539
{
552
    gv2(RC_ST1, RC_ST0);
540
    gv2(RC_ST1, RC_ST0);
553
    switch(op) {
541
    switch(op) {
554
    case '+':
542
    case '+':
555
        out_op(IL_OP_ADD);
543
        out_op(IL_OP_ADD);
556
        goto std_op;
544
        goto std_op;
557
    case '-':
545
    case '-':
558
        out_op(IL_OP_SUB);
546
        out_op(IL_OP_SUB);
559
        goto std_op;
547
        goto std_op;
560
    case '&':
548
    case '&':
561
        out_op(IL_OP_AND);
549
        out_op(IL_OP_AND);
562
        goto std_op;
550
        goto std_op;
563
    case '^':
551
    case '^':
564
        out_op(IL_OP_XOR);
552
        out_op(IL_OP_XOR);
565
        goto std_op;
553
        goto std_op;
566
    case '|':
554
    case '|':
567
        out_op(IL_OP_OR);
555
        out_op(IL_OP_OR);
568
        goto std_op;
556
        goto std_op;
569
    case '*':
557
    case '*':
570
        out_op(IL_OP_MUL);
558
        out_op(IL_OP_MUL);
571
        goto std_op;
559
        goto std_op;
572
    case TOK_SHL:
560
    case TOK_SHL:
573
        out_op(IL_OP_SHL);
561
        out_op(IL_OP_SHL);
574
        goto std_op;
562
        goto std_op;
575
    case TOK_SHR:
563
    case TOK_SHR:
576
        out_op(IL_OP_SHR_UN);
564
        out_op(IL_OP_SHR_UN);
577
        goto std_op;
565
        goto std_op;
578
    case TOK_SAR:
566
    case TOK_SAR:
579
        out_op(IL_OP_SHR);
567
        out_op(IL_OP_SHR);
580
        goto std_op;
568
        goto std_op;
581
    case '/':
569
    case '/':
582
    case TOK_PDIV:
570
    case TOK_PDIV:
583
        out_op(IL_OP_DIV);
571
        out_op(IL_OP_DIV);
584
        goto std_op;
572
        goto std_op;
585
    case TOK_UDIV:
573
    case TOK_UDIV:
586
        out_op(IL_OP_DIV_UN);
574
        out_op(IL_OP_DIV_UN);
587
        goto std_op;
575
        goto std_op;
588
    case '%':
576
    case '%':
589
        out_op(IL_OP_REM);
577
        out_op(IL_OP_REM);
590
        goto std_op;
578
        goto std_op;
591
    case TOK_UMOD:
579
    case TOK_UMOD:
592
        out_op(IL_OP_REM_UN);
580
        out_op(IL_OP_REM_UN);
593
    std_op:
581
    std_op:
594
        vtop--;
582
        vtop--;
595
        vtop[0].r = REG_ST0;
583
        vtop[0].r = REG_ST0;
596
        break;
584
        break;
597
    case TOK_EQ:
585
    case TOK_EQ:
598
    case TOK_NE:
586
    case TOK_NE:
599
    case TOK_LT:
587
    case TOK_LT:
600
    case TOK_LE:
588
    case TOK_LE:
601
    case TOK_GT:
589
    case TOK_GT:
602
    case TOK_GE:
590
    case TOK_GE:
603
    case TOK_ULT:
591
    case TOK_ULT:
604
    case TOK_ULE:
592
    case TOK_ULE:
605
    case TOK_UGT:
593
    case TOK_UGT:
606
    case TOK_UGE:
594
    case TOK_UGE:
607
        vtop--;
595
        vtop--;
608
        vtop[0].r = VT_CMP;
596
        vtop[0].r = VT_CMP;
609
        vtop[0].c.i = op;
597
        vtop[0].c.i = op;
610
        break;
598
        break;
611
    }
599
    }
612
}
600
}
613
 
601
 
614
/* generate a floating point operation 'v = t1 op t2' instruction. The
602
/* generate a floating point operation 'v = t1 op t2' instruction. The
615
   two operands are guaranted to have the same floating point type */
603
   two operands are guaranted to have the same floating point type */
616
void gen_opf(int op)
604
void gen_opf(int op)
617
{
605
{
618
    /* same as integer */
606
    /* same as integer */
619
    gen_opi(op);
607
    gen_opi(op);
620
}
608
}
621
 
609
 
622
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
610
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
623
   and 'long long' cases. */
611
   and 'long long' cases. */
624
void gen_cvt_itof(int t)
612
void gen_cvt_itof(int t)
625
{
613
{
626
    gv(RC_ST0);
614
    gv(RC_ST0);
627
    if (t == VT_FLOAT)
615
    if (t == VT_FLOAT)
628
        out_op(IL_OP_CONV_R4);
616
        out_op(IL_OP_CONV_R4);
629
    else
617
    else
630
        out_op(IL_OP_CONV_R8);
618
        out_op(IL_OP_CONV_R8);
631
}
619
}
632
 
620
 
633
/* convert fp to int 't' type */
621
/* convert fp to int 't' type */
634
/* XXX: handle long long case */
622
/* XXX: handle long long case */
635
void gen_cvt_ftoi(int t)
623
void gen_cvt_ftoi(int t)
636
{
624
{
637
    gv(RC_ST0);
625
    gv(RC_ST0);
638
    switch(t) {
626
    switch(t) {
639
    case VT_INT | VT_UNSIGNED:
627
    case VT_INT | VT_UNSIGNED:
640
        out_op(IL_OP_CONV_U4);
628
        out_op(IL_OP_CONV_U4);
641
        break;
629
        break;
642
    case VT_LLONG:
630
    case VT_LLONG:
643
        out_op(IL_OP_CONV_I8);
631
        out_op(IL_OP_CONV_I8);
644
        break;
632
        break;
645
    case VT_LLONG | VT_UNSIGNED:
633
    case VT_LLONG | VT_UNSIGNED:
646
        out_op(IL_OP_CONV_U8);
634
        out_op(IL_OP_CONV_U8);
647
        break;
635
        break;
648
    default:
636
    default:
649
        out_op(IL_OP_CONV_I4);
637
        out_op(IL_OP_CONV_I4);
650
        break;
638
        break;
651
    }
639
    }
652
}
640
}
653
 
641
 
654
/* convert from one floating point type to another */
642
/* convert from one floating point type to another */
655
void gen_cvt_ftof(int t)
643
void gen_cvt_ftof(int t)
656
{
644
{
657
    gv(RC_ST0);
645
    gv(RC_ST0);
658
    if (t == VT_FLOAT) {
646
    if (t == VT_FLOAT) {
659
        out_op(IL_OP_CONV_R4);
647
        out_op(IL_OP_CONV_R4);
660
    } else {
648
    } else {
661
        out_op(IL_OP_CONV_R8);
649
        out_op(IL_OP_CONV_R8);
662
    }
650
    }
663
}
651
}
664
 
652
 
665
/* end of CIL code generator */
653
/* end of CIL code generator */
666
/*************************************************************/
654
/*************************************************************/