value now can be casted to virtual "bool" type
[d2dqcc.git] / src / libqcc / qcc_pr_comp.c
blob909afc98c3a85e3ba93dd89d1cca501f29e0e913
1 /*
2 * QuakeC compiler for Doom2D:TL!, based on FTEQCC
3 * Copyright (C) 1996-1997 Id Software, Inc.
4 * Also copyright FrikQCC and FTEQCC authors
5 * Copyright (C) 2013 Ketmar Dark
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "qcc.h"
21 #include "hash.h"
24 static const char *basictypenames[] = {
25 "void",
26 "string",
27 "float",
28 "vector",
29 "entity",
30 "field",
31 "function",
32 "pointer",
33 "integer",
37 qccbool flag_assume_integer; // is that an integer or a float? qcc says float. but we support int too, so maybe we want that instead?
39 qccbool opt_overlaptemps; // reduce numpr_globals by reuse of temps: when they are not needed they are freed for reuse
40 qccbool opt_shortenifnots; // if(!var) is made an IF rather than NOT IFNOT
41 qccbool opt_nonvec_parms; // store_f instead of store_v on function calls, where possible
42 qccbool opt_constant_names; // take out the defs and name strings of constants
43 qccbool opt_constant_names_strings; // removes the defs of strings too (plays havok with multiprogs)
44 qccbool opt_unreferenced; // strip defs that are not referenced
45 qccbool opt_locals = 0; // strip out the names of locals and immediates
46 qccbool opt_compound_jumps; // jumps to jump statements jump to the final point
47 qccbool opt_locals_marshalling; // make the local vars of all functions occupy the same globals
48 qccbool opt_vectorcalls; // vectors can be packed into 3 floats, which can yield lower numpr_globals, but cost two more statements per call
49 qccbool opt_simplifiedifs; // if (f != 0) -> if (f). if (f == 0) -> ifnot (f)
51 //these are the results of the opt_. The values are printed out when compilation is compleate, showing effectivness.
52 int optres_shortenifnots;
53 int optres_assignments;
54 int optres_overlaptemps;
55 int optres_noduplicatestrings;
56 int optres_constantarith;
57 int optres_nonvec_parms;
58 int optres_constant_names;
59 int optres_constant_names_strings;
60 int optres_unreferenced;
61 int optres_locals;
62 int optres_dupconstdefs;
63 int optres_compound_jumps;
64 int optres_locals_marshalling;
66 qccbool simplestore;
67 qccbool expandedemptymacro;
69 QCC_pr_info_t pr;
70 //QCC_def_t **pr_global_defs/*[MAX_REGS]*/; // to find def for a global variable
72 //keeps track of how many funcs are called while parsing a statement
73 //int qcc_functioncalled;
75 //========================================
77 QCC_def_t *pr_scope; // the function being parsed, or NULL
78 qccbool pr_dumpasm;
79 QCC_string_t s_file, s_file2; // filename for function definition
81 unsigned int locals_start; // for tracking local variables vs temps
82 unsigned int locals_end; // for tracking local variables vs temps
84 jmp_buf pr_parse_abort; // longjump with this on parse error
86 qccbool qcc_usefulstatement;
88 int max_breaks;
89 int max_continues;
90 int max_cases;
91 int num_continues;
92 int num_breaks;
93 int num_cases;
94 int *pr_breaks;
95 int *pr_continues;
96 int *pr_cases;
97 QCC_def_t **pr_casesdef;
98 QCC_def_t **pr_casesdef2;
100 typedef struct {
101 int statementno;
102 int lineno;
103 char name[256];
104 } gotooperator_t;
106 int max_labels;
107 int max_gotos;
108 gotooperator_t *pr_labels;
109 gotooperator_t *pr_gotos;
110 int num_gotos;
111 int num_labels;
113 QCC_def_t *extra_parms[MAX_EXTRA_PARMS];
115 static int conditional;
116 temp_t *functemps; // floats/strings/funcs/ents...
118 static int constchecks;
119 static int varchecks;
120 static int typechecks;
123 typedef struct freeoffset_s {
124 struct freeoffset_s *next;
125 gofs_t ofs;
126 unsigned int size;
127 } freeoffset_t;
129 freeoffset_t *qcc_freeofs;
132 ////////////////////////////////////////////////////////////////////////////////
133 #include "qcc_pr_comp_operators.c"
136 ////////////////////////////////////////////////////////////////////////////////
137 static QCC_def_t *QCC_SupplyConversion (QCC_def_t *var, qcc_etype wanted, qccbool fatal);
139 static void QCC_PR_ParseStatement (qccbool nosublocs);
140 static QCC_def_t *QCC_PR_Statement (const QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement);
141 static QCC_dstatement_t *QCC_PR_SimpleStatement (int op, int var_a, int var_b, int var_c, int force);
142 static int QCC_AStatementJumpsTo (int targ, int first, int last);
143 static qccbool QCC_StatementIsAJump (int stnum, int notifdest);
144 static QCC_def_t *QCC_PR_DummyDef (QCC_type_t *type, const char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, qccbool saved);
146 static gofs_t QCC_GetFreeOffsetSpace (unsigned int size);
148 static void QCC_WriteAsmFunction (QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm);
151 enum {
152 EXPR_WARN_ABOVE_1 = 2,
153 EXPR_DISALLOW_COMMA = 4,
154 EXPR_DISALLOW_FCALL = 8
157 static QCC_def_t *QCC_PR_Expression (int priority, int exprflags);
160 ////////////////////////////////////////////////////////////////////////////////
161 static inline qccbool is_branch_op (int op) {
162 switch (op) {
163 case OP_IF_I: case OP_IFNOT_I:
164 case OP_IF_S: case OP_IFNOT_S:
165 case OP_IF_F: case OP_IFNOT_F:
166 case OP_GOTO:
167 return qcc_true;
169 return qcc_false;
173 static inline int branch_dest (int opofs) {
174 return opofs+statements[opofs].sargs[statements[opofs].op == OP_GOTO ? 0 : 1];
178 ////////////////////////////////////////////////////////////////////////////////
179 static inline qccbool OpAssignsToC (unsigned int op) {
180 // calls, switches and cases DON'T
181 if (pr_opcodes[op].type_c == &type_void) return qcc_false;
182 if (op >= OP_BITSET && op <= OP_BITCLRP) return qcc_false;
183 /*if (op >= OP_STORE_I && op <= OP_STORE_FI) return qcc_false; <- add STOREP_*?*/
184 if (op == OP_STOREP_C/* || op == OP_LOADP_C*/) return qcc_false;
185 if (op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V) return qcc_false;
186 return qcc_true;
191 static qccbool OpAssignsToB (unsigned int op) {
192 if (op >= OP_BITSET && op <= OP_BITCLRP) return qcc_true;
193 if (op >= OP_STORE_I && op <= OP_STORE_FI) return qcc_true;
194 if (op == OP_STOREP_C || op == OP_LOADP_C) return qcc_true;
195 if (op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V) return qcc_true;
196 if (op >= OP_STORE_F && op <= OP_STOREP_FNC) return qcc_true;
197 return qcc_false;
202 // no emulated opcodes
203 static inline qccbool QCC_OPCodeValid (const QCC_opcode_t *op) {
204 return (op-pr_opcodes < OP_NUMREALOPS);
208 //===========================================================================
209 static QCC_def_t *QCC_MakeDummyIntConst (void) {
210 QCC_def_t *cn;
211 // allocate a new one
212 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t));
213 cn->next = NULL;
214 pr.def_tail->next = cn;
215 pr.def_tail = cn;
216 cn->type = type_integer;
217 cn->name = "IMMEDIATE";
218 cn->constant = qcc_true;
219 cn->initialized = 1;
220 cn->scope = NULL; // always share immediates
221 cn->arraysize = 1;
222 // copy the immediate to the global area
223 cn->ofs = QCC_GetFreeOffsetSpace(type_size[type_integer->type]);
224 G_INT(cn->ofs) = 666;
225 return cn;
229 static QCC_def_t *QCC_MakeIntConst (int value) {
230 QCC_def_t *cn;
231 // check for a constant with the same value
232 for (cn = pr.def_head.next; cn != NULL; cn = cn->next) {
233 ++varchecks;
234 if (!cn->initialized) continue;
235 if (!cn->constant) continue;
236 ++constchecks;
237 if (cn->type != type_integer) continue;
238 ++typechecks;
239 if (G_INT(cn->ofs) == value) return cn;
241 // allocate a new one
242 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t));
243 cn->next = NULL;
244 pr.def_tail->next = cn;
245 pr.def_tail = cn;
246 cn->type = type_integer;
247 cn->name = "IMMEDIATE";
248 cn->constant = qcc_true;
249 cn->initialized = 1;
250 cn->scope = NULL; // always share immediates
251 cn->arraysize = 1;
252 if (!value) {
253 G_INT(cn->ofs) = 0;
254 } else {
255 // copy the immediate to the global area
256 cn->ofs = QCC_GetFreeOffsetSpace(type_size[type_integer->type]);
257 G_INT(cn->ofs) = value;
259 return cn;
263 static QCC_def_t *QCC_MakeVectorConst (float a, float b, float c) {
264 QCC_def_t *cn;
265 // check for a constant with the same value
266 for (cn = pr.def_head.next; cn != NULL; cn = cn->next) {
267 ++varchecks;
268 if (!cn->initialized) continue;
269 if (!cn->constant) continue;
270 ++constchecks;
271 if (cn->type != type_vector) continue;
272 ++typechecks;
273 if (G_FLOAT(cn->ofs+0) == a && G_FLOAT(cn->ofs+1) == b && G_FLOAT(cn->ofs+2) == c) return cn;
275 // allocate a new one
276 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t));
277 cn->next = NULL;
278 pr.def_tail->next = cn;
279 pr.def_tail = cn;
280 cn->type = type_vector;
281 cn->name = "IMMEDIATE";
282 cn->constant = qcc_true;
283 cn->initialized = 1;
284 cn->scope = NULL; // always share immediates
285 cn->arraysize = 1;
286 // copy the immediate to the global area
287 cn->ofs = QCC_GetFreeOffsetSpace(type_size[type_vector->type]);
288 G_FLOAT(cn->ofs+0) = a;
289 G_FLOAT(cn->ofs+1) = b;
290 G_FLOAT(cn->ofs+2) = c;
291 return cn;
295 static QCC_def_t *QCC_MakeFloatConst (float value) {
296 union QGG_GCC_PACKED {
297 float f;
298 int i;
299 } fi;
300 fi.f = value;
301 QCC_def_t *cn = Hash_GetKey(&floatconstdefstable, fi.i);
302 if (cn) return cn;
303 // allocate a new one
304 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t));
305 cn->next = NULL;
306 pr.def_tail->next = cn;
307 pr.def_tail = cn;
308 cn->s_file = s_file;
309 cn->s_line = pr_source_line;
310 cn->type = type_float;
311 cn->name = "IMMEDIATE";
312 cn->constant = qcc_true;
313 cn->initialized = 1;
314 cn->scope = NULL; // always share immediates
315 cn->arraysize = 1;
316 // copy the immediate to the global area
317 cn->ofs = QCC_GetFreeOffsetSpace(type_size[type_integer->type]);
318 Hash_AddKey(&floatconstdefstable, fi.i, cn, qccHunkAlloc(sizeof(hashtable_bucket_t)));
319 G_FLOAT(cn->ofs) = value;
320 return cn;
324 static QCC_def_t *QCC_MakeStringConstInternal (const char *value, qccbool translate) {
325 int string;
326 QCC_def_t *cn = Hash_Get(translate?&stringconstdefstable_trans:&stringconstdefstable, value);
327 if (cn) return cn;
328 // allocate a new one
329 if (translate) {
330 char buf[128];
331 snprintf(buf, sizeof(buf), "dotranslate_%d", ++dotranslate_count);
332 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t)+strlen(buf)+1);
333 cn->name = (char *)(cn+1);
334 strcpy(cn->name, buf);
335 } else {
336 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t));
337 cn->name = "IMMEDIATE";
339 cn->next = NULL;
340 pr.def_tail->next = cn;
341 pr.def_tail = cn;
342 cn->type = type_string;
343 cn->constant = qcc_true;
344 cn->initialized = 1;
345 cn->scope = NULL; // always share immediates
346 cn->arraysize = 1;
347 // copy the immediate to the global area
348 cn->ofs = QCC_GetFreeOffsetSpace(type_size[type_integer->type]);
349 string = QCC_CopyString(value);
350 Hash_Add((translate ? &stringconstdefstable_trans : &stringconstdefstable), strings+string, cn, qccHunkAlloc(sizeof(hashtable_bucket_t)));
351 G_INT(cn->ofs) = string;
352 return cn;
356 static QCC_def_t *QCC_MakeStringConst (const char *value) {
357 return QCC_MakeStringConstInternal(value, qcc_false);
361 static QCC_def_t *QCC_MakeTranslateStringConst (const char *value) {
362 return QCC_MakeStringConstInternal(value, qcc_true);
366 //===========================================================================
367 //assistant functions. This can safly be bipassed with the old method for more complex things.
368 static gofs_t QCC_GetFreeOffsetSpace (unsigned int size) {
369 int ofs;
370 if (opt_locals_marshalling) {
371 freeoffset_t *fofs, *prev;
372 for (fofs = qcc_freeofs, prev = NULL; fofs != NULL; fofs = fofs->next) {
373 if (fofs->size == size) {
374 if (prev) prev->next = fofs->next; else qcc_freeofs = fofs->next;
375 return fofs->ofs;
377 prev = fofs;
379 for (fofs = qcc_freeofs, prev = NULL; fofs != NULL; fofs = fofs->next) {
380 if (fofs->size > size) {
381 fofs->size -= size;
382 fofs->ofs += size;
383 return fofs->ofs-size;
385 prev = fofs;
388 ofs = numpr_globals;
389 numpr_globals += size;
390 if (numpr_globals >= MAX_REGS) {
391 if (!opt_overlaptemps || !opt_locals_marshalling) {
392 QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS - you'll need to use more optimisations");
393 } else {
394 QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS");
397 return ofs;
401 static void QCC_FreeOffset (gofs_t ofs, unsigned int size) {
402 freeoffset_t *fofs;
404 if (ofs+size == numpr_globals) {
405 //FIXME: is this a bug?
406 //k8: this SHOULD be a bug, i think: we need to allocate the
407 // whole chunk of 'globals', or some writes will miss
408 //numpr_globals -= size;
409 return;
412 for (fofs = qcc_freeofs; fofs != NULL; fofs = fofs->next) {
413 //FIXME: if this means the last block becomes free, free them all.
414 if (fofs->ofs == ofs+size) {
415 fofs->ofs -= size;
416 fofs->size += size;
417 return;
419 if (fofs->ofs+fofs->size == ofs) {
420 fofs->size += size;
421 return;
424 fofs = qccHunkAlloc(sizeof(freeoffset_t));
425 fofs->next = qcc_freeofs;
426 fofs->ofs = ofs;
427 fofs->size = size;
428 qcc_freeofs = fofs;
429 return;
433 static QCC_def_t *QCC_GetTemp (QCC_type_t *type) {
434 QCC_def_t *var_c = (void *)qccHunkAlloc(sizeof(QCC_def_t));
435 memset(var_c, 0, sizeof(QCC_def_t));
436 var_c->type = type;
437 var_c->name = "temp";
438 if (opt_overlaptemps || opt_locals_marshalling) {
439 temp_t *t = NULL; // always allocate new one for opt_locals_marshalling
440 if (opt_overlaptemps) {
441 // don't exceed; this lets us allocate a huge block, and still be able to compile smegging big funcs
442 for (t = functemps; t; t = t->next) if (!t->used && t->size == type->size) break;
443 if (t && t->scope && t->scope != pr_scope) QCC_Error(ERR_INTERNAL, "Internal error temp has scope not equal to current scope");
444 if (t) optres_overlaptemps += t->size;
446 if (t == NULL) {
447 // allocate new one
448 t = qccHunkAlloc(sizeof(temp_t));
449 t->size = type->size;
450 t->next = functemps;
451 functemps = t;
452 t->ofs = QCC_GetFreeOffsetSpace(t->size);
453 numtemps += t->size;
455 var_c->ofs = t->ofs;
456 var_c->temp = t;
457 t->lastfunc = pr_scope;
458 } else {
459 // we're not going to reallocate any temps so allocate permanently
460 var_c->ofs = QCC_GetFreeOffsetSpace(type->size);
461 numtemps += type->size;
463 var_c->s_file = s_file;
464 var_c->s_line = pr_source_line;
465 if (var_c->temp) var_c->temp->used = qcc_true;
466 return var_c;
470 // nothing else references this temp.
471 static void QCC_FreeTemp (QCC_def_t *t) {
472 if (t && t->temp) t->temp->used = qcc_false;
476 static void QCC_UnFreeTemp (QCC_def_t *t) {
477 if (t->temp) t->temp->used = qcc_true;
481 // we've just parsed a statement
482 // we can gaurentee that any used temps are now not used
483 // this is just a debugging check, can be turned off
484 static void QCC_FreeTemps (void) {
485 if (def_ret.temp && def_ret.temp->used) {
486 QCC_PR_ParseWarning(WARN_DEBUGGING, "Return value still in use in %s", pr_scope->name);
487 def_ret.temp->used = qcc_false;
489 for (temp_t *t = functemps; t != NULL; t = t->next) {
490 if (t->used && !pr_error_count) {
491 // don't print this after an error jump out
492 QCC_PR_ParseWarning(WARN_DEBUGGING, "Temp was used in %s", pr_scope->name);
493 t->used = qcc_false;
499 void QCC_PurgeTemps (void) {
500 functemps = NULL;
504 //temps that are still in use over a function call can be considered dodgy.
505 //we need to remap these to locally defined temps, on return from the function so we know we got them all.
506 static void QCC_LockActiveTemps (void) {
507 for (temp_t *t = functemps; t != NULL; t = t->next) if (t->used) t->scope = pr_scope;
511 static void QCC_LockTemp (QCC_def_t *d) {
512 if (d->temp && d->temp->used) d->temp->scope = pr_scope;
516 static void QCC_RemapLockedTemp (temp_t *t, int firststatement, int laststatement) {
517 #ifdef QCC_WRITEASM
518 char buffer[128];
519 #endif
520 QCC_def_t *def;
521 int newofs;
522 QCC_dstatement_t *st;
523 int i;
524 newofs = 0;
525 for (i = firststatement, st = &statements[i]; i < laststatement; ++i, ++st) {
526 if (pr_opcodes[st->op].type_a && st->a == t->ofs) {
527 if (!newofs) {
528 newofs = QCC_GetFreeOffsetSpace(t->size);
529 numtemps += t->size;
530 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, qcc_false, qcc_false);
531 def->nextlocal = pr.localvars;
532 def->constant = qcc_false;
533 #ifdef QCC_WRITEASM
534 snprintf(buffer, sizeof(buffer), "locked_%d", t->ofs);
535 def->name = qccHunkDupStr(buffer);
536 #endif
537 pr.localvars = def;
539 st->a = newofs;
541 if (pr_opcodes[st->op].type_b && st->b == t->ofs) {
542 if (!newofs) {
543 newofs = QCC_GetFreeOffsetSpace(t->size);
544 numtemps += t->size;
545 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, qcc_false, qcc_false);
546 def->nextlocal = pr.localvars;
547 def->constant = qcc_false;
548 #ifdef QCC_WRITEASM
549 snprintf(buffer, sizeof(buffer), "locked_%d", t->ofs);
550 def->name = qccHunkDupStr(buffer);
551 #endif
552 pr.localvars = def;
554 st->b = newofs;
556 if (pr_opcodes[st->op].type_c && st->c == t->ofs) {
557 if (!newofs) {
558 newofs = QCC_GetFreeOffsetSpace(t->size);
559 numtemps += t->size;
560 def = QCC_PR_DummyDef(type_float, NULL, pr_scope, t->size, newofs, qcc_false, qcc_false);
561 def->nextlocal = pr.localvars;
562 def->constant = qcc_false;
563 #ifdef QCC_WRITEASM
564 snprintf(buffer, sizeof(buffer), "locked_%d", t->ofs);
565 def->name = qccHunkDupStr(buffer);
566 #endif
567 pr.localvars = def;
569 st->c = newofs;
575 static void QCC_RemapLockedTemps (int firststatement, int laststatement) {
576 for (temp_t *t = functemps; t != NULL; t = t->next) {
577 if (t->scope || opt_locals_marshalling) {
578 QCC_RemapLockedTemp(t, firststatement, laststatement);
579 t->scope = NULL;
580 t->lastfunc = NULL;
586 static void QCC_fprintfLocals (FILE *f, gofs_t paramstart, gofs_t paramend) {
587 int i = 0;
588 for (const QCC_def_t *var = pr.localvars; var != NULL; var = var->nextlocal) {
589 if (var->ofs >= paramstart && var->ofs < paramend) continue;
590 if (var->arraysize != 1) {
591 fprintf(f, "local %s %s[%d]; /* at %d */\n", QCC_TypeName(var->type), var->name, var->arraysize, var->ofs);
592 } else {
593 fprintf(f, "local %s %s; /* at %d */\n", QCC_TypeName(var->type), var->name, var->ofs);
596 for (const temp_t *t = functemps; t != NULL; t = t->next, ++i) {
597 if (t->lastfunc == pr_scope) {
598 fprintf(f, "local %s temp_%d; /* at %d */\n", (t->size == 1 ? "float" : "vector"), i, t->ofs);
604 #ifdef QCC_WRITEASM
605 static const char *QCC_VarAtOffset (unsigned int ofs, unsigned int size) {
606 static char message[1024];
607 QCC_def_t *var;
608 //check the temps
609 temp_t *t;
610 int i;
611 for (t = functemps, i = 0; t != NULL; t = t->next, ++i) {
612 if (ofs >= t->ofs && ofs < t->ofs+t->size) {
613 if (size < t->size) {
614 snprintf(message, sizeof(message), "temp_%i_%c", t->ofs, 'x'+(ofs-t->ofs)%3);
615 } else {
616 snprintf(message, sizeof(message), "temp_%d", t->ofs);
618 return message;
621 for (var = pr.localvars; var != NULL; var = var->nextlocal) {
622 if (var->scope && var->scope != pr_scope) continue; // this should be an error
623 if (ofs >= var->ofs && ofs < var->ofs+var->type->size) {
624 if (*var->name) {
625 if (!strcmp(var->name, "IMMEDIATE")) continue; // continue, don't get bogged down by multiple bits of code
626 if (size < var->type->size) {
627 snprintf(message, sizeof(message), "%s_%c", var->name, 'x'+(ofs-var->ofs)%3);
628 } else {
629 snprintf(message, sizeof(message), "%s", var->name);
631 return message;
635 for (var = pr.def_head.next; var != NULL; var = var->next) {
636 if (var->scope && var->scope != pr_scope) continue;
637 if (ofs >= var->ofs && ofs < var->ofs+var->type->size) {
638 if (*var->name) {
639 if (!strcmp(var->name, "IMMEDIATE")) {
640 switch (var->type->type) {
641 case ev_string:
642 snprintf(message, sizeof(message), "\"%.1020s\"", &strings[((const int *)qcc_pr_globals)[var->ofs]]);
643 return message;
644 case ev_integer:
645 snprintf(message, sizeof(message), "%d", ((const int *)qcc_pr_globals)[var->ofs]);
646 return message;
647 case ev_float:
648 snprintf(message, sizeof(message), "%f", qcc_pr_globals[var->ofs]);
649 return message;
650 case ev_vector:
651 snprintf(message, sizeof(message), "'%f %f %f'", qcc_pr_globals[var->ofs], qcc_pr_globals[var->ofs+1], qcc_pr_globals[var->ofs+2]);
652 return message;
653 default:
654 snprintf(message, sizeof(message), "IMMEDIATE");
655 return message;
658 if (size < var->type->size) {
659 snprintf(message, sizeof(message), "%s_%c", var->name, 'x'+(ofs-var->ofs)%3);
660 } else {
661 snprintf(message, sizeof(message), "%s", var->name);
663 return message;
667 if (size >= 3) {
668 if (ofs >= OFS_RETURN && ofs < OFS_PARM0) snprintf(message, sizeof(message), "return");
669 else if (ofs >= OFS_PARM0 && ofs < OFS_PARM7) snprintf(message, sizeof(message), "parm%d", (ofs-OFS_PARM0)/3);
670 else if (ofs == OFS_PARMTHIS) snprintf(message, sizeof(message), "parmthis");
671 else snprintf(message, sizeof(message), "offset_%d", ofs);
672 } else {
673 if (ofs >= OFS_RETURN && ofs < OFS_PARM0) snprintf(message, sizeof(message), "return_%c", 'x'+ofs-OFS_RETURN);
674 else if (ofs >= OFS_PARM0 && ofs < OFS_PARM7) snprintf(message, sizeof(message), "parm%i_%c", (ofs-OFS_PARM0)/3, 'x'+(ofs-OFS_PARM0)%3);
675 else if (ofs == OFS_PARMTHIS) snprintf(message, sizeof(message), "parmthis_shit");
676 else snprintf(message, sizeof(message), "offset_%d", ofs);
678 return message;
680 #endif
683 #include "qcc_pr_comp_primstat.c"
687 ============
688 PR_ParseImmediate
690 Looks for a preexisting constant
691 ============
693 static QCC_def_t *QCC_PR_ParseImmediate (void) {
694 QCC_def_t *cn;
695 if (pr_immediate_type == type_float) {
696 cn = QCC_MakeFloatConst(pr_immediate._float);
697 QCC_PR_Lex();
698 return cn;
700 if (pr_immediate_type == type_integer) {
701 cn = QCC_MakeIntConst(pr_immediate._int);
702 QCC_PR_Lex();
703 return cn;
705 if (pr_immediate_type == type_string) {
706 char tmp[8192];
707 if (strlen(pr_immediate_string) > sizeof(tmp)-1) QCC_PR_ParseError(ERR_INVALIDSTRINGIMMEDIATE, "string too long");
708 snprintf(tmp, sizeof(tmp), "%s", pr_immediate_string);
709 for (;;) {
710 QCC_PR_Lex();
711 if (pr_token_type == TT_IMMED && pr_token_type == TT_IMMED) {
712 if (strlen(tmp)+strlen(pr_immediate_string) > sizeof(tmp)-1) {
713 QCC_PR_ParseError(ERR_INVALIDSTRINGIMMEDIATE, "string too long");
714 } else {
715 strcat(tmp, pr_immediate_string);
717 } else {
718 break;
721 cn = QCC_MakeStringConst(tmp);
722 return cn;
724 // check for a constant with the same value
725 // FIXME: hashtable
726 for (cn = pr.def_head.next; cn != NULL; cn = cn->next) {
727 if (!cn->initialized) continue;
728 if (!cn->constant) continue;
729 if (cn->type != pr_immediate_type) continue;
730 if (pr_immediate_type == type_string) {
731 if (strcmp(G_STRING(cn->ofs), pr_immediate_string) == 0) {
732 QCC_PR_Lex();
733 return cn;
735 } else if (pr_immediate_type == type_float) {
736 if (G_FLOAT(cn->ofs) == pr_immediate._float) {
737 QCC_PR_Lex();
738 return cn;
740 } else if (pr_immediate_type == type_integer) {
741 if (G_INT(cn->ofs) == pr_immediate._int) {
742 QCC_PR_Lex();
743 return cn;
745 } else if (pr_immediate_type == type_vector) {
746 if ((G_FLOAT(cn->ofs) == pr_immediate.vector[0]) &&
747 (G_FLOAT(cn->ofs+1) == pr_immediate.vector[1]) &&
748 (G_FLOAT(cn->ofs+2) == pr_immediate.vector[2])) {
749 QCC_PR_Lex();
750 return cn;
752 } else {
753 QCC_PR_ParseError(ERR_BADIMMEDIATETYPE, "weird immediate type");
756 // allocate a new one
757 cn = (void *)qccHunkAlloc(sizeof(QCC_def_t));
758 cn->next = NULL;
759 pr.def_tail->next = cn;
760 pr.def_tail = cn;
761 cn->type = pr_immediate_type;
762 cn->name = "IMMEDIATE";
763 cn->constant = qcc_true;
764 cn->initialized = 1;
765 cn->scope = NULL; // always share immediates
766 // copy the immediate to the global area
767 cn->ofs = QCC_GetFreeOffsetSpace(type_size[pr_immediate_type->type]);
768 if (pr_immediate_type == type_string) pr_immediate.string = QCC_CopyString(pr_immediate_string);
769 memcpy (qcc_pr_globals+cn->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
770 QCC_PR_Lex();
771 return cn;
775 // warning, the func could have no name set if it's a field call
776 static QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *func, QCC_def_t *arglist[], int argcount, QCC_def_t *newself) {
777 QCC_def_t *d, *oldret, *oself;
778 QCC_type_t *t;
779 QCC_dstatement_t *st;
780 /* */
781 ++func->timescalled;
782 t = func->type;
783 if (t->type != ev_function) QCC_PR_ParseErrorPrintDef(ERR_NOTAFUNCTION, func, "not a function");
784 // copy the arguments to the global parameter variables
785 if (newself != NULL) {
786 // we're entering OO code with a different self
787 // eg: other::touch(self)
788 // note: we will allocate 'self' if there is none
789 d = QCC_PR_GetDef(type_entity, "self", NULL, qcc_true, 1, qcc_false);
790 oself = QCC_GetTemp(type_entity);
791 // oself = self
792 QCC_PR_SimpleStatement(OP_STORE_ENT, d->ofs, oself->ofs, 0, qcc_false);
794 // self = other
795 QCC_PR_SimpleStatement(OP_STORE_ENT, statements[laststatement-1].a, d->ofs, 0, qcc_false);
797 QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], newself, d, QCC_STAT_NOCONV);
798 // if the args refered to self, update them to refer to oself instead (as self is now set to 'other')
799 for (int i = 0; i < argcount; ++i) if (arglist[i]->ofs == d->ofs) arglist[i] = oself;
800 } else {
801 // regular func call
802 oself = NULL;
803 d = NULL;
805 // write the arguments
806 for (int i = 0; i < argcount; ++i) {
807 d = (i >= MAX_PARMS ? extra_parms[i-MAX_PARMS] : &def_parms[i]);
808 if (arglist[i]->type->size > 1 || !opt_nonvec_parms) {
809 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], arglist[i], d, QCC_STAT_NOCONV));
810 } else {
811 d->type = arglist[i]->type;
812 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], arglist[i], d, QCC_STAT_NOCONV));
813 ++optres_nonvec_parms;
816 // if the return value was in use, save it off now, so that it doesn't get clobbered
817 oldret = (def_ret.temp->used ? QCC_GetTemp(def_ret.type) : NULL);
818 // can free temps used for arguments now
819 if (oldret && !def_ret.temp->used) {
820 QCC_FreeTemp(oldret);
821 oldret = NULL;
822 } else if (def_ret.temp->used) {
823 if (def_ret.type->size == 3) {
824 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, oldret, QCC_STAT_NOCONV));
825 } else {
826 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, oldret, QCC_STAT_NOCONV));
828 QCC_UnFreeTemp(oldret);
829 QCC_UnFreeTemp(&def_ret);
830 //k8:wtf?! QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient");
831 } else {
832 oldret = NULL;
834 // we dont need to lock the local containing the function index because its thrown away after the call anyway
835 // (if a function is called in the argument list then it'll be locked as part of that call)
836 QCC_FreeTemp(func);
837 QCC_LockActiveTemps(); // any temps before are likely to be used with the return value
838 QCC_UnFreeTemp(func);
839 // generate the call
840 if (argcount > MAX_PARMS) {
841 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_CALL0+MAX_PARMS], func, 0, &st));
842 } else if (argcount) {
843 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_CALL0+argcount], func, 0, &st));
844 } else {
845 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_CALL0], func, 0, &st));
847 // restore the class owner
848 if (oself) {
849 QCC_PR_SimpleStatement(OP_STORE_ENT, oself->ofs, d->ofs, 0, qcc_false);
850 QCC_FreeTemp(oself);
853 if (oldret) {
854 if (oldret->temp && !oldret->temp->used) QCC_PR_ParseWarning(0, "Ret was freed\n");
855 // if we preserved the ofs_ret global, restore it here
856 d = QCC_GetTemp(t->aux_type);
857 if (t->aux_type->size == 3) {
858 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, &def_ret, d, QCC_STAT_NOCONV));
859 } else {
860 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, &def_ret, d, QCC_STAT_NOCONV));
862 if (def_ret.type->size == 3) {
863 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_V, oldret, &def_ret, QCC_STAT_NOCONV));
864 } else {
865 QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_STORE_F, oldret, &def_ret, QCC_STAT_NOCONV));
867 QCC_FreeTemp(oldret);
868 QCC_UnFreeTemp(&def_ret);
869 QCC_UnFreeTemp(d);
870 return d;
872 def_ret.type = t->aux_type;
873 if (def_ret.temp->used) QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict -- output is inefficient");
874 def_ret.temp->used = qcc_true;
875 return &def_ret;
879 #include "qcc_pr_comp_intrinsics.c"
883 ============
884 PR_ParseFunctionCall
886 warning, the func could have no name set if it's a field call
887 opening paren should be eaten
888 ============
890 static QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func, QCC_def_t *newself) {
891 QCC_def_t *e, *d;
892 QCC_type_t *t, *p;
893 int extraparms = qcc_false;
894 int np, arg;
895 QCC_def_t *param[MAX_PARMS+MAX_EXTRA_PARMS];
896 /* */
897 ++func->timescalled;
898 t = func->type;
899 if (t->type != ev_function) QCC_PR_ParseErrorPrintDef(ERR_NOTAFUNCTION, func, "not a function");
900 // intrinsics
901 // these base functions have variable arguments. I would check for (...) args too,
902 // but that might be used for extended builtin functionality.
903 // (this code wouldn't compile otherwise)
904 if (!t->num_parms) {
905 for (size_t f = 0; f < sizeof(intrlist)/sizeof(intrlist[0]); ++f) {
906 if (strcmp(func->name, intrlist[f].name) == 0) return intrlist[f].fn(func);
909 // so it's not an intrinsic
910 // copy the arguments to the global parameter variables
911 arg = 0;
912 if (t->num_parms < 0) {
913 extraparms = qcc_true;
914 np = -t->num_parms-1;
915 } else {
916 np = t->num_parms;
918 // any temps referenced to build the parameters don't need to be locked
919 if (!QCC_PR_EatDelim(")")) {
920 int dont_advance = 0;
921 p = t->param;
922 do {
923 if (extraparms && arg >= MAX_PARMS) {
924 QCC_PR_ParseErrorPrintDef(ERR_TOOMANYPARAMETERSVARARGS, func, "More than %d parameters on varargs function", MAX_PARMS);
925 } else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS) {
926 QCC_PR_ParseErrorPrintDef(ERR_TOOMANYTOTALPARAMETERS, func, "More than %d parameters", MAX_PARMS+MAX_EXTRA_PARMS);
928 if (!extraparms && arg >= t->num_parms && !p) {
929 QCC_PR_ParseWarning(WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters");
930 QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func);
932 // with vectorcalls, we store the vector into the args as individual floats
933 // this allows better reuse of vector constants
934 // copy it into the offset now, because we can
935 if (opt_vectorcalls && pr_token_type == TT_IMMED && pr_immediate_type == type_vector &&
936 arg < MAX_PARMS && !def_parms[arg].temp->used) {
937 e = &def_parms[arg];
938 e->ofs = OFS_PARM0+0;
939 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[0]), e, QCC_STAT_NOCONV));
940 e->ofs = OFS_PARM0+1;
941 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[1]), e, QCC_STAT_NOCONV));
942 e->ofs = OFS_PARM0+2;
943 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(pr_immediate.vector[2]), e, QCC_STAT_NOCONV));
944 e->ofs = OFS_PARM0;
945 QCC_PR_Lex();
946 } else {
947 e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
949 if (arg >= MAX_PARMS) {
950 if (!extra_parms[arg-MAX_PARMS]) {
951 d = (QCC_def_t *)qccHunkAlloc(sizeof(QCC_def_t));
952 d->name = "extra parm";
953 d->ofs = QCC_GetFreeOffsetSpace(3);
954 extra_parms[arg-MAX_PARMS] = d;
956 d = extra_parms[arg-MAX_PARMS];
957 } else {
958 d = &def_parms[arg];
960 if (p) {
961 /*then:
962 if (e->type->type != ev_integer && p->type != ev_function)
963 if (e->type->type != ev_function && p->type != ev_integer)
964 if ( e->type->type != p->type )
966 if (qcc_typecmp(e->type, p)) {
967 if (p->type == ev_string) {
968 // convert number to string
969 if (e->type->type == ev_integer) e = QCC_PR_Statement(&pr_opcodes[OP_CONV_ITOS], e, NULL, NULL);
970 else if (e->type->type == ev_float) e = QCC_PR_Statement(&pr_opcodes[OP_CONV_FTOS], e, NULL, NULL);
971 else if (e->type->type == ev_vector) e = QCC_PR_Statement(&pr_opcodes[OP_CONV_VTOS], e, NULL, NULL);
972 else if (e->type->type == ev_entity) e = QCC_PR_Statement(&pr_opcodes[OP_CONV_ETOS], e, NULL, NULL);
973 } else if (p->type == ev_integer && e->type->type == ev_float) {
974 // convert float -> int... is this a constant?
975 //fprintf(stderr, "(%d)FCALL: f->i\n", arg);
976 e = QCC_PR_Statement(&pr_opcodes[OP_CONV_FTOI], e, NULL, NULL);
977 //fprintf(stderr, "(%d)FCALL: f->i: done\n", arg);
978 } else if (p->type == ev_float && e->type->type == ev_integer) {
979 // convert int -> float... is this a constant?
980 //fprintf(stderr, "(%d)FCALL: i->f\n", arg);
981 e = QCC_PR_Statement(&pr_opcodes[OP_CONV_ITOF], e, NULL, NULL);
982 //fprintf(stderr, "(%d)FCALL: i->f: done\n", arg);
983 } else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((qccint *)qcc_pr_globals)[e->ofs]) {
984 // you're allowed to use int 0 to pass a null function pointer
985 // this is basically because __NULL__ is defined as ~0 (int 0)
988 d->type = p;
989 //fprintf(stderr, "fcall: num_parms=%d; arg=%d; np=%d; p=%p; p->next=%p; da=%d\n", t->num_parms, arg, np, p, p->next, dont_advance);
990 if (t->num_parms < 0) {
991 // handle special case: typed vaargs
992 if (!dont_advance) {
993 if (arg == np && p->next == NULL) dont_advance = 1;
995 if (!dont_advance) p = p->next;
996 } else {
997 p = p->next;
999 } else {
1000 // a vector copy will copy everything
1001 d->type = type_void;
1003 param[arg] = e;
1005 if (e->type->size > 1) {
1006 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], e, d, (QCC_dstatement_t **)0xffffffff);
1007 } else {
1008 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], e, d, (QCC_dstatement_t **)0xffffffff);
1011 ++arg;
1012 } while (QCC_PR_EatDelim(","));
1013 if (t->num_parms != -1 && arg < np) QCC_PR_ParseWarning(WARN_TOOFEWPARAMS, "too few parameters on call to %s", func->name);
1014 QCC_PR_Expect(")");
1015 } else if (np) {
1016 QCC_PR_ParseWarning(WARN_TOOFEWPARAMS, "%s: Too few parameters", func->name);
1017 QCC_PR_ParsePrintDef(WARN_TOOFEWPARAMS, func);
1019 return QCC_PR_GenerateFunctionCall(func, param, arg, newself);
1023 QCC_type_t *QCC_PointerTypeTo (QCC_type_t *type) {
1024 QCC_type_t *newtype = QCC_PR_NewType("ptr", ev_pointer);
1025 newtype->aux_type = type;
1026 return newtype;
1031 ============
1032 PR_ParseValue
1034 Returns the global ofs for the current token
1035 ============
1037 static QCC_def_t *QCC_PR_ParseValue (qccbool allowarrayassign) {
1038 QCC_def_t *d, *tmp, *idx;
1039 QCC_type_t *t;
1040 char *name;
1041 // if the token is an immediate, allocate a constant for it
1042 if (pr_token_type == TT_IMMED) return QCC_PR_ParseImmediate();
1043 name = QCC_PR_ParseName();
1044 // look through the defs
1045 d = QCC_PR_GetDef(NULL, name, pr_scope, qcc_false, 0, qcc_false);
1046 if (!d) {
1047 // intrinsics? any old function with no args will do
1048 int intrfound = 0;
1049 for (size_t f = 0; f < sizeof(intrlist)/sizeof(intrlist[0]); ++f) {
1050 if (strcmp(name, intrlist[f].name) == 0) { intrfound = 1; break; }
1052 if (!intrfound) QCC_PR_ParseError(ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
1053 d = QCC_PR_GetDef(type_function, name, NULL, qcc_true, 1, qcc_false);
1054 d->initialized = 0;
1057 t = d->type;
1058 idx = NULL;
1059 //if ((t->type == ev_vector || (t->type == ev_field && t->aux_type->type == ev_vector)) && d->arraysize == 1) goto skipit;
1061 if (d->arraysize == 1 && t->type != ev_pointer) goto skipit;
1063 for (;;) {
1064 if (QCC_PR_EatDelim("[")) {
1065 tmp = QCC_PR_Expression(TOP_PRIORITY, 0);
1066 QCC_PR_Expect("]");
1067 //fprintf(stderr, "%d idx=%p, tmp=%p\n", t->type, idx, tmp);
1068 if (!idx && t->type == ev_pointer && d->arraysize == 1) t = t->aux_type;
1070 if (t->type == ev_string && d->arraysize == 1) {
1071 //QCC_PR_ParseErrorPrintDef(0, d, "TODO: no string indexing yet");
1072 //fprintf(stderr, "indexing string\n");
1073 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, tmp, NULL);
1075 QCC_def_t *res;
1076 tmp = QCC_SupplyConversion(tmp, ev_float, qcc_true);
1077 res = QCC_GetTemp(type_float);
1078 QCC_PR_SimpleStatement(OP_LOADP_C, d->ofs, tmp->ofs, res->ofs, qcc_false);
1079 QCC_FreeTemp(tmp);
1080 d = res;
1082 continue;
1086 if (!idx && d->type->type == ev_pointer) {
1087 // no bounds checks
1088 } else if (tmp->constant) {
1089 int i;
1090 if (tmp->type->type == ev_integer) i = G_INT(tmp->ofs);
1091 else if (tmp->type->type == ev_float) i = G_FLOAT(tmp->ofs);
1092 else abort(); //k8:!!!
1093 if (i < 0 || i >= (!idx ? d->arraysize : t->arraysize)) QCC_PR_ParseErrorPrintDef(0, d, "(constant) array index out of bounds");
1094 } else {
1095 tmp = QCC_SupplyConversion(tmp, ev_integer, qcc_true);
1096 QCC_PR_SimpleStatement(OP_BOUNDCHECK, tmp->ofs, (!idx ? d->arraysize : t->arraysize), 0, qcc_false);
1098 // don't multiply by type size if the instruction/emulation will do that instead
1099 // k8: was (idx || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
1100 if (t->size != 1 && idx != 0) {
1101 if (tmp->type->type == ev_float) {
1102 tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL);
1103 } else {
1104 tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL);
1107 idx = (idx ? QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, qcc_true), NULL) : tmp);
1108 continue;
1111 if (t->type == ev_pointer && QCC_PR_EatDelim(".")) {
1112 if (!idx && t->type == ev_pointer && d->arraysize == 1) t = t->aux_type;
1113 for (t = t->param; t; t = t->next) if (QCC_PR_EatId(t->name)) break;
1114 if (!t) QCC_PR_ParseError(0, "'%s' is not a member", pr_token);
1115 tmp = QCC_MakeIntConst(t->ofs);
1116 idx = (idx ? QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL) : tmp);
1117 continue;
1120 break;
1123 skipit:
1124 if (idx != NULL) {
1125 if (d->type->type == ev_pointer) {
1126 switch (t->type) {
1127 case ev_pointer:
1128 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1129 break;
1130 case ev_float:
1131 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1132 break;
1133 case ev_integer:
1134 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1135 break;
1136 case ev_string:
1137 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1138 break;
1139 case ev_vector:
1140 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1141 break;
1142 case ev_entity:
1143 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1144 break;
1145 case ev_field:
1146 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1147 break;
1148 case ev_function:
1149 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1150 break;
1151 default:
1152 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available");
1154 d->type = t;
1155 } else {
1156 // don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign
1157 // source type is a struct, or its an array, or something that can otherwise be directly accessed
1158 switch (t->type) {
1159 case ev_pointer:
1160 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1161 break;
1162 case ev_float:
1163 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1164 break;
1165 case ev_integer:
1166 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1167 break;
1168 case ev_string:
1169 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1170 break;
1171 case ev_vector:
1172 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1173 break;
1174 case ev_entity:
1175 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1176 break;
1177 case ev_field:
1178 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1179 break;
1180 case ev_function:
1181 d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(idx, ev_integer, qcc_true), NULL);
1182 break;
1183 default:
1184 QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available");
1186 d->type = t;
1188 } else {
1189 // no indexing
1190 t = d->type;
1191 if (t->type == ev_vector || (t->type == ev_field && t->aux_type->type == ev_vector)) {
1192 if (QCC_PR_EatDelim(".")) {
1193 // member access
1194 char *name = alloca(strlen(d->name)+4), ech;
1195 // vector.[xyz]
1196 if (QCC_PR_EatId("x")) ech = 'x';
1197 else if (QCC_PR_EatId("y")) ech = 'y';
1198 else if (QCC_PR_EatId("z")) ech = 'z';
1199 else QCC_PR_ParseError(0, "'%s' is not a vector member", pr_token);
1200 sprintf(name, "%s.%c", d->name, ech);
1201 //fprintf(stderr, "accesing vector member: [%s]\n", name);
1202 d = QCC_PR_GetDef(type_float, name, pr_scope, qcc_false, 0, qcc_false);
1203 if (d == NULL) QCC_PR_ParseError(ERR_UNKNOWNVALUE, "WTF?!! (00) [%s]", name);
1204 } else if (QCC_PR_EatDelim("[")) {
1205 // array-like vector indexing
1206 tmp = QCC_PR_Expression(TOP_PRIORITY, 0);
1207 QCC_PR_Expect("]");
1209 } else if (t->type == ev_string || (t->type == ev_field && t->aux_type->type == ev_string)) {
1210 if (QCC_PR_EatDelim("[")) {
1211 // string indexing
1212 tmp = QCC_PR_Expression(TOP_PRIORITY, 0);
1213 QCC_PR_Expect("]");
1214 d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, tmp, NULL);
1219 return d;
1223 #include "qcc_pr_comp_expr.c"
1226 int QCC_PR_IntConstExpr (void) {
1227 QCC_def_t *def = QCC_PR_Expression(TOP_PRIORITY, 0);
1228 if (def->constant) {
1229 ++def->references;
1230 if (def->type->type == ev_integer) return G_INT(def->ofs);
1231 if (def->type->type == ev_float) {
1232 int i = G_FLOAT(def->ofs);
1233 if ((float)i == G_FLOAT(def->ofs)) return i;
1236 QCC_PR_ParseError(ERR_NOTACONSTANT, "Value is not an integer constant");
1237 return qcc_true;
1241 static void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, const char *labelname) {
1242 if (num_gotos >= max_gotos) {
1243 max_gotos += 8;
1244 pr_gotos = realloc(pr_gotos, sizeof(*pr_gotos)*max_gotos);
1246 strncpy(pr_gotos[num_gotos].name, labelname, sizeof(pr_gotos[num_gotos].name)-1);
1247 pr_gotos[num_gotos].lineno = pr_source_line;
1248 pr_gotos[num_gotos].statementno = patch2 - statements;
1249 ++num_gotos;
1253 static qccbool QCC_PR_StatementBlocksMatch (const QCC_dstatement_t *p1, int p1count, const QCC_dstatement_t *p2, int p2count) {
1254 if (p1count != p2count) return qcc_false;
1255 while (p1count-- > 0) {
1256 if (p1->op != p2->op) return qcc_false;
1257 if (p1->a != p2->a) return qcc_false;
1258 if (p1->b != p2->b) return qcc_false;
1259 if (p1->c != p2->c) return qcc_false;
1260 ++p1;
1261 ++p2;
1263 return qcc_true;
1267 #include "qcc_pr_comp_statements.c"
1270 //FIXME: CONDITIONAL JUMPS TOO?
1271 static qccbool QCC_FuncJumpsTo (int first, int last, int statement) {
1272 for (int st = first; st < last; ++st) {
1273 if (is_branch_op(statements[st].op)) {
1274 int pc = branch_dest(st);
1275 if (pc == statement) {
1276 if (st != first) {
1277 if (statements[st-1].op == OP_RETURN) break;
1278 if (statements[st-1].op == OP_DONE) break;
1279 return qcc_true;
1284 return qcc_false;
1288 static void QCC_CompoundJumps (int first, int last) {
1289 // jumps to jumps are reordered so they become jumps to the final target
1290 for (int st = first; st < last; ++st) {
1291 if (is_branch_op(statements[st].op)) {
1292 int argn = (statements[st].op == OP_GOTO ? 0 : 1);
1293 int dest = branch_dest(st);
1295 int dest = st+(signed int)statements[st].args[argn];
1297 if (statements[st].op == OP_GOTO && (statements[dest].op == OP_RETURN || statements[dest].op == OP_DONE)) {
1298 // goto leads to return: copy the command out to remove the goto
1299 statements[st] = statements[dest];
1300 ++optres_compound_jumps;
1301 } else {
1302 int infloop = 1000;
1303 // traverse 'goto' chain
1304 while (statements[dest].op == OP_GOTO) {
1305 if (infloop-- == 0) { QCC_PR_ParseWarning(0, "Infinite loop detected"); break; }
1306 statements[st].sargs[argn] = statements[dest].sa+dest-st;
1307 dest = st+statements[st].sargs[argn];
1308 ++optres_compound_jumps;
1316 //QCC_CheckForDeadAndMissingReturns()
1317 #include "qcc_pr_comp_retcheck.c"
1320 // only the unconditionals
1321 static inline qccbool QCC_StatementIsAJump (int stnum, int notifdest) {
1322 switch (statements[stnum].op) {
1323 case OP_RETURN: case OP_DONE: return qcc_true;
1324 case OP_GOTO: return (branch_dest(stnum) != notifdest);
1326 return qcc_false;
1330 static int QCC_AStatementJumpsTo (int targ, int first, int last) {
1331 for (int st = first; st < last; ++st) {
1332 if (is_branch_op(statements[st].op) && branch_dest(st) == targ) return qcc_true;
1334 // assume it's used if it is labeled
1335 for (int st = 0; st < num_labels; ++st) if (pr_labels[st].statementno == targ) return qcc_true;
1336 return qcc_false;
1340 void QCC_RemapOffsets (unsigned int firststatement, unsigned int laststatement, unsigned int min,
1341 unsigned int max, unsigned int newmin)
1343 QCC_dstatement_t *st;
1344 unsigned int i;
1345 for (i = firststatement, st = &statements[i]; i < laststatement; ++i, ++st) {
1346 for (int c = 0; c < 3; ++c) {
1347 if (pr_opcodes[st->op].types[c] && st->args[c] >= min && st->args[c] < max) st->args[c] = st->args[c]-min+newmin;
1353 static void QCC_Marshal_Locals (int first, int laststatement) {
1354 QCC_def_t *local;
1355 unsigned int newofs;
1356 // clear these after each function. we arn't overlapping them so why do we need to keep track of them?
1357 //if (!opt_overlaptemps) {
1358 // temp_t *t;
1359 // for (t = functemps; t; t = t->next)
1360 // QCC_FreeOffset(t->ofs, t->size);
1361 // functemps = NULL;
1363 // nothing to marshal
1364 if (!pr.localvars) {
1365 locals_start = locals_end = 0;/*numpr_globals;*/
1366 return;
1368 if (!opt_locals_marshalling) {
1369 pr.localvars = pr.prevlocvars = NULL;
1370 return;
1372 // initial backwards bounds
1373 locals_start = MAX_REGS;
1374 locals_end = 0;
1375 newofs = MAX_REGS; // this is a handy place to put it. :)
1376 // the params need to be in the order that they were allocated
1377 // so we allocate in a backwards order
1378 for (local = pr.localvars; local; local = local->nextlocal) {
1379 if (local->constant) continue;
1380 newofs += local->type->size*local->arraysize;
1381 if (local->arraysize > 1) ++newofs;
1383 locals_start = MAX_REGS;
1384 locals_end = newofs;
1385 optres_locals_marshalling += newofs-MAX_REGS;
1386 for (local = pr.localvars; local; local = local->nextlocal) {
1387 if (local->constant) continue;
1388 if (((const int *)qcc_pr_globals)[local->ofs]) QCC_PR_ParseError(ERR_INTERNAL, "Marshall of a set value");
1389 newofs -= local->type->size*local->arraysize;
1390 if (local->arraysize > 1) --newofs;
1391 QCC_RemapOffsets(first, laststatement, local->ofs, local->ofs+local->type->size*local->arraysize, newofs);
1392 QCC_FreeOffset(local->ofs, local->type->size*local->arraysize);
1393 local->ofs = newofs;
1395 pr.localvars = pr.prevlocvars = NULL;
1399 #ifdef QCC_WRITEASM
1400 static void QCC_WriteAsmFunction (QCC_def_t *sc, unsigned int firststatement, gofs_t firstparm) {
1401 unsigned int i, p;
1402 gofs_t o;
1403 QCC_type_t *type;
1404 QCC_def_t *param;
1405 if (!asmfile) return;
1406 type = sc->type;
1407 fprintf(asmfile, "%s(", QCC_TypeName(type->aux_type));
1408 p = type->num_parms;
1409 for (o = firstparm, i = 0, type = type->param; i < p; ++i, type = type->next) {
1410 if (i) fprintf(asmfile, ", ");
1411 for (param = pr.localvars; param; param = param->nextlocal) if (param->ofs == o) break;
1412 if (param) {
1413 fprintf(asmfile, "%s %s /* at %d */", QCC_TypeName(type), param->name, o);
1414 } else {
1415 fprintf(asmfile, "%s /* at %d */", QCC_TypeName(type), o);
1417 o += type->size;
1419 fprintf(asmfile, ") %s = asm {\n", sc->name);
1420 QCC_fprintfLocals(asmfile, firstparm, o);
1421 for (i = firststatement; i < (unsigned int)numstatements; ++i) {
1422 fprintf(asmfile, " %-7s ", pr_opcodes[statements[i].op].opname);
1423 if (pr_opcodes[statements[i].op].type_a != &type_void) {
1424 if (pr_opcodes[statements[i].op].type_a) {
1425 fprintf(asmfile, "%s", QCC_VarAtOffset(statements[i].a, (*pr_opcodes[statements[i].op].type_a)->size));
1426 } else {
1427 fprintf(asmfile, "%d", statements[i].a);
1429 if (pr_opcodes[statements[i].op].type_b != &type_void) {
1430 if (pr_opcodes[statements[i].op].type_b) {
1431 fprintf(asmfile, ", %s", QCC_VarAtOffset(statements[i].b, (*pr_opcodes[statements[i].op].type_b)->size));
1432 } else {
1433 fprintf(asmfile, ", %d", statements[i].b);
1435 if (pr_opcodes[statements[i].op].type_c != &type_void && pr_opcodes[statements[i].op].associative == ASSOC_LEFT) {
1436 if (pr_opcodes[statements[i].op].type_c) {
1437 fprintf(asmfile, ", %s", QCC_VarAtOffset(statements[i].c, (*pr_opcodes[statements[i].op].type_c)->size));
1438 } else {
1439 fprintf(asmfile, ", %d", statements[i].c);
1442 } else {
1443 if (pr_opcodes[statements[i].op].type_c != &type_void) {
1444 if (pr_opcodes[statements[i].op].type_c) {
1445 fprintf(asmfile, ", %s", QCC_VarAtOffset(statements[i].c, (*pr_opcodes[statements[i].op].type_c)->size));
1446 } else {
1447 fprintf(asmfile, ", %d", statements[i].c);
1452 fprintf(asmfile, "; /*%d*/\n", statement_linenums[i]);
1454 fprintf(asmfile, "}\n\n");
1456 #endif
1460 ============
1461 PR_ParseImmediateStatements
1463 Parse a function body
1464 ============
1466 static QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) {
1467 QCC_function_t *f;
1468 QCC_def_t *defs[MAX_PARMS+MAX_EXTRA_PARMS], *e2;
1469 QCC_type_t *parm;
1470 qccbool needsdone = qcc_false;
1471 freeoffset_t *oldfofs;
1472 conditional = 0;
1473 expandedemptymacro = qcc_false;
1474 f = (void *)qccHunkAlloc(sizeof(QCC_function_t));
1475 if (type->num_parms < 0) QCC_PR_ParseError(ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
1476 f->builtin = 0;
1477 // define the parms
1478 locals_start = locals_end = numpr_globals;
1479 oldfofs = qcc_freeofs;
1480 qcc_freeofs = NULL;
1481 parm = type->param;
1482 for (int i = 0 ; i < type->num_parms; ++i) {
1483 if (!*pr_parm_names[i]) QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named");
1484 defs[i] = QCC_PR_GetDef(parm, pr_parm_names[i], pr_scope, qcc_true, 1, qcc_false);
1485 ++defs[i]->references;
1486 if (i < MAX_PARMS) {
1487 f->parm_ofs[i] = defs[i]->ofs;
1488 if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1]) QCC_Error(ERR_BADPARAMORDER, "bad parm order");
1489 if (i > 0 && f->parm_ofs[i] != f->parm_ofs[i-1]+defs[i-1]->type->size) QCC_Error(ERR_BADPARAMORDER, "parms not packed");
1491 parm = parm->next;
1493 if (type->num_parms) locals_start = locals_end = defs[0]->ofs;
1494 qcc_freeofs = oldfofs;
1495 f->code = numstatements;
1496 if (type->num_parms > MAX_PARMS) {
1497 for (int i = MAX_PARMS; i < type->num_parms; ++i) {
1498 if (!extra_parms[i-MAX_PARMS]) {
1499 e2 = (QCC_def_t *)qccHunkAlloc(sizeof(QCC_def_t));
1500 e2->name = "extra parm";
1501 e2->ofs = QCC_GetFreeOffsetSpace(3);
1502 extra_parms[i - MAX_PARMS] = e2;
1504 extra_parms[i-MAX_PARMS]->type = defs[i]->type;
1505 if (defs[i]->type->type != ev_vector) {
1506 QCC_PR_Statement(&pr_opcodes[OP_STORE_F], extra_parms[i-MAX_PARMS], defs[i], NULL);
1507 } else {
1508 QCC_PR_Statement(&pr_opcodes[OP_STORE_V], extra_parms[i-MAX_PARMS], defs[i], NULL);
1512 QCC_RemapLockedTemps(-1, -1);
1513 QCC_PR_Expect("{");
1514 // parse regular statements
1515 while (!QCC_PR_EatDelim("}")) {
1516 QCC_PR_ParseStatement(qcc_false);
1517 QCC_FreeTemps();
1519 QCC_FreeTemps();
1520 if (f->code == numstatements) {
1521 needsdone = qcc_true;
1522 } else if (statements[numstatements-1].op != OP_RETURN && statements[numstatements-1].op != OP_DONE) {
1523 needsdone = qcc_true;
1525 if (num_gotos) {
1526 for (int i = 0; i < num_gotos; ++i) {
1527 int j;
1528 for (j = 0; j < num_labels; ++j) {
1529 if (strcmp(pr_gotos[i].name, pr_labels[j].name) == 0) {
1530 if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_a) {
1531 statements[pr_gotos[i].statementno].a += pr_labels[j].statementno-pr_gotos[i].statementno;
1532 } else if (!pr_opcodes[statements[pr_gotos[i].statementno].op].type_b) {
1533 statements[pr_gotos[i].statementno].b += pr_labels[j].statementno-pr_gotos[i].statementno;
1534 } else {
1535 statements[pr_gotos[i].statementno].c += pr_labels[j].statementno-pr_gotos[i].statementno;
1537 break;
1540 if (j == num_labels) {
1541 num_gotos = 0;
1542 QCC_PR_ParseError(ERR_NOLABEL, "Goto statement with no matching label \"%s\"", pr_gotos[i].name);
1545 num_gotos = 0;
1547 if (!needsdone) needsdone = QCC_FuncJumpsTo(f->code, numstatements, numstatements);
1548 // emit an end of statements opcode
1549 if (needsdone) QCC_PR_Statement(pr_opcodes, 0,0, NULL);
1550 QCC_CheckForDeadAndMissingReturns(f->code, numstatements, type->aux_type->type);
1551 if (opt_compound_jumps) QCC_CompoundJumps(f->code, numstatements);
1552 QCC_RemapLockedTemps(f->code, numstatements);
1553 locals_end = numpr_globals;
1554 QCC_Marshal_Locals(f->code, numstatements);
1555 QCC_WriteAsmFunction(pr_scope, f->code, locals_start);
1556 if (num_labels) num_labels = 0;
1557 if (num_continues) {
1558 num_continues = 0;
1559 QCC_PR_ParseError(ERR_ILLEGALCONTINUES, "%s: function contains illegal continues", pr_scope->name);
1561 if (num_breaks) {
1562 num_breaks = 0;
1563 QCC_PR_ParseError(ERR_ILLEGALBREAKS, "%s: function contains illegal breaks", pr_scope->name);
1565 if (num_cases) {
1566 num_cases = 0;
1567 QCC_PR_ParseError(ERR_ILLEGALCASES, "%s: function contains illegal cases", pr_scope->name);
1569 return f;
1573 // register a def, and all of it's sub parts.
1574 // only the main def is of use to the compiler.
1575 // the subparts are emitted to the compiler and allow correct saving/loading
1576 // be careful with fields, this doesn't allocated space, so will it allocate fields. It only creates defs at specified offsets.
1577 static QCC_def_t *QCC_PR_DummyDef (QCC_type_t *type, const char *name, QCC_def_t *scope, int arraysize, unsigned int ofs, int referable, qccbool saved) {
1578 static const char *reserved_words[] = {
1579 //"builtin",
1580 "const",
1581 "for",
1582 "switch",
1583 "case",
1584 "default",
1585 "goto",
1586 "break",
1587 "continue",
1588 "do",
1589 "while",
1590 "if",
1591 "else",
1592 "string",
1593 "float",
1594 "int",
1595 "entity",
1596 "vector",
1597 "bool",
1599 char array[64], newname[256];
1600 QCC_def_t *def, *first = NULL;
1601 if (name) {
1602 for (size_t f = 0; f < sizeof(reserved_words)/sizeof(reserved_words[0]); ++f) {
1603 if (strcmp(name, reserved_words[f]) == 0) {
1604 QCC_PR_ParseError(ERR_KEYWORDDISABLED, "'%s' keyword used as variable name", name);
1608 //fprintf(stderr, "arraysize=%d\n", arraysize);
1609 for (int a = 0; a < arraysize; ++a) {
1610 if (a == 0) array[0] = 0; else snprintf(array, sizeof(array), "[%d]", a);
1611 if (name) {
1612 snprintf(newname, sizeof(newname), "%s%s", name, array);
1613 } else {
1614 //*newname = *"";
1615 newname[0] = 0;
1617 // allocate a new def
1618 def = (void *)qccHunkAlloc(sizeof(QCC_def_t));
1619 memset(def, 0, sizeof(*def));
1620 def->next = NULL;
1621 def->arraysize = arraysize;
1622 if (name) {
1623 pr.def_tail->next = def;
1624 pr.def_tail = def;
1626 if (a > 0) ++def->references;
1627 def->s_line = pr_source_line;
1628 def->s_file = s_file;
1629 if (a) def->initialized = 1;
1630 def->name = qccHunkDupStr(newname);
1631 def->type = type;
1632 def->scope = scope;
1633 def->saved = saved;
1634 def->constant = qcc_true; // if (type->type = ev_field)
1635 if (type->type != ev_function) {
1636 if (ofs+type->size*a >= MAX_REGS) QCC_Error(ERR_TOOMANYGLOBALS, "MAX_REGS is too small");
1637 def->ofs = ofs+type->size*a;
1638 } else {
1639 def->ofs = 0;
1641 if (!first) first = def;
1642 //qcc_printf("Emited %s\n", newname);
1643 if (arraysize == 1 && (type->type == ev_vector || (type->type == ev_field && type->aux_type->type == ev_vector))) {
1644 // do the vector thing
1645 QCC_type_t *vt = (type->type == ev_vector ? type_float : type_floatfield);
1646 //fprintf(stderr, "creating vector fielddefs: [%s]\n", name);
1647 // don't warn about unreferenced vector parts
1648 snprintf(newname, sizeof(newname), "%s.x", name);
1649 QCC_PR_DummyDef(vt, newname, scope, 1, ofs+type->size*a+0, referable, qcc_false)->references += 1;
1650 snprintf(newname, sizeof(newname), "%s.y", name);
1651 QCC_PR_DummyDef(vt, newname, scope, 1, ofs+type->size*a+1, referable, qcc_false)->references += 1;
1652 snprintf(newname, sizeof(newname), "%s.z", name);
1653 QCC_PR_DummyDef(vt, newname, scope, 1, ofs+type->size*a+2, referable, qcc_false)->references += 1;
1655 first->deftail = pr.def_tail;
1658 if (referable) {
1659 // anything above needs to be left in, and so warning about not using it is just going to pee people off
1660 if (!Hash_Get(&globalstable, "end_sys_fields")) ++first->references;
1661 if (arraysize <= 1 && first->type->type != ev_field) first->constant = qcc_false;
1662 if (scope) {
1663 Hash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(hashtable_bucket_t)));
1664 } else {
1665 Hash_Add(&globalstable, first->name, first, qccHunkAlloc(sizeof(hashtable_bucket_t)));
1667 if (!scope && asmfile) fprintf(asmfile, "%s %s; /* at %d */\n", QCC_TypeName(first->type), first->name, first->ofs);
1669 return first;
1674 ============
1675 PR_GetDef
1677 If type is NULL, it will match any type
1678 If allocate is qcc_true, a new def will be allocated if it can't be found
1679 ============
1681 QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, const char *name, QCC_def_t *scope, qccbool allocate, int arraysize, qccbool saved) {
1682 int ofs;
1683 QCC_def_t *def;
1684 //char element[MAX_NAME];
1685 //unsigned int i;
1686 QCC_def_t *foundstatic = NULL;
1687 //fprintf(stderr, "QCC_PR_GetDef: [%s] scope=%p; allocate=%d\n", name, scope, allocate);
1688 if (scope) {
1689 def = Hash_Get(&localstable, name);
1690 while (def != NULL) {
1691 if (def->scope && def->scope != scope) {
1692 def = Hash_GetNext(&localstable, name, def);
1693 continue; // in a different function
1695 if (type && qcc_typecmp(def->type, type)) {
1696 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s", name, QCC_TypeName(type), QCC_TypeName(def->type));
1697 } if (def->arraysize != arraysize && arraysize) {
1698 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match", name);
1700 if (allocate) {
1701 //HACK!HACK!HACK!
1702 //fprintf(stderr, "LALLOCATE: [%s] %d\n", name, (def->scope == scope && pr_subscopedlocals));
1703 qccbool fuckme = qcc_false;
1704 if (def->scope == scope) {
1705 // check if this definition is just a shadowed local
1706 //fprintf(stderr, "lv=%p; plv=%p\n", pr.localvars, pr.prevlocvars);
1707 for (QCC_def_t *e = pr.localvars; e != pr.prevlocvars; e = e->nextlocal) {
1708 //fprintf(stderr, "[%s] (%s)\n", def->name, e->name);
1709 if (strcmp(def->name, e->name) == 0) { fuckme = qcc_true; break; }
1712 if (!fuckme) { def = NULL; break; }
1714 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
1715 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
1716 //if (!scope) QCC_PR_ParsePrintDef(def);
1718 return def;
1721 def = Hash_Get(&globalstable, name);
1722 while (def != NULL) {
1723 if (def->scope && def->scope != scope) {
1724 def = Hash_GetNext(&globalstable, name, def);
1725 continue; // in a different function
1728 if (def->isstatic && def->s_file != s_file) {
1729 // warn? or would that be pointless?
1730 foundstatic = def;
1731 def = Hash_GetNext(&globalstable, name, def);
1732 continue; // in a different function
1735 if (type && qcc_typecmp(def->type, type)) {
1736 if (!pr_scope) {
1737 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s", name, QCC_TypeName(type), QCC_TypeName(def->type));
1740 if (def->arraysize != arraysize && arraysize) {
1741 QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match", name);
1743 if (allocate && scope) {
1744 if (pr_scope) {
1745 // warn? or would that be pointless?
1746 def = Hash_GetNext(&globalstable, name, def);
1747 continue; // in a different function
1749 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
1750 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
1751 //if (!scope) QCC_PR_ParsePrintDef(def);
1753 return def;
1755 // do we want to try case insensitive too?
1756 if (Hash_Get != &Hash_Get && !allocate) {
1757 if (scope) {
1758 def = Hash_Get(&localstable, name);
1759 while (def != NULL) {
1760 if (def->scope && def->scope != scope) {
1761 def = Hash_GetNext(&localstable, name, def);
1762 continue; // in a different function
1764 if (type && qcc_typecmp(def->type, type)) {
1765 QCC_PR_ParseError(ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s", name, QCC_TypeName(type), QCC_TypeName(def->type));
1767 if (def->arraysize != arraysize && arraysize) {
1768 QCC_PR_ParseError(ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match", name);
1770 if (allocate && scope) {
1771 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
1772 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
1773 //if (!scope) QCC_PR_ParsePrintDef(def);
1775 return def;
1778 def = Hash_Get(&globalstable, name);
1779 while (def != NULL) {
1780 if (def->scope && def->scope != scope) {
1781 def = Hash_GetNext(&globalstable, name, def);
1782 continue; // in a different function
1784 if (def->isstatic && def->s_file != s_file) {
1785 // warn? or would that be pointless?
1786 foundstatic = def;
1787 def = Hash_GetNext(&globalstable, name, def);
1788 continue; // in a different function
1790 if (type && qcc_typecmp(def->type, type)) {
1791 if (!pr_scope) {
1792 QCC_PR_ParseError(ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s", name, QCC_TypeName(type), QCC_TypeName(def->type));
1795 if (def->arraysize != arraysize && arraysize) {
1796 QCC_PR_ParseError(ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match", name);
1798 if (allocate && scope) {
1799 if (pr_scope) {
1800 //warn? or would that be pointless?
1801 def = Hash_GetNext(&globalstable, name, def);
1802 continue; // in a different function
1804 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
1805 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
1806 //if (!scope) QCC_PR_ParsePrintDef(def);
1808 return def;
1811 if (foundstatic && !allocate) {
1812 QCC_PR_ParseWarning(WARN_DUPLICATEDEFINITION, "%s defined static", name);
1813 QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, foundstatic);
1815 if (!allocate) return NULL;
1816 // allocate new definition
1817 if (arraysize < 1) QCC_PR_ParseError(ERR_ARRAYNEEDSSIZE, "First declaration of array %s with no size",name);
1818 if (scope) {
1819 if (QCC_PR_GetDef(type, name, NULL, qcc_false, arraysize, qcc_false)) {
1820 QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" defined with name of a global", name);
1823 //if (type->type == ev_function) fprintf(stderr, "ALLOCATING GLOBAL FOR FUNCTION: [%s]\n", name);
1824 if (type->type != ev_function) {
1825 ofs = numpr_globals;
1826 if (arraysize > 1) {
1827 // write the array size
1828 ofs = QCC_GetFreeOffsetSpace(1+(type->size*arraysize));
1829 ((qccint *)qcc_pr_globals)[ofs] = arraysize-1; // an array needs the size written first: this is a hexen2 opcode thing
1830 ++ofs;
1831 } else {
1832 ofs = QCC_GetFreeOffsetSpace(type->size*arraysize);
1834 } else {
1835 // don't allocate global for function
1836 ofs = 0;
1838 def = QCC_PR_DummyDef(type, name, scope, arraysize, ofs, qcc_true, saved);
1839 // fix up fields
1840 if (type->type == ev_field && allocate != 2) {
1841 // make arrays of fields work
1842 unsigned int i;
1843 for (i = 0; i < type->size*arraysize; ++i) *(qccint *)&qcc_pr_globals[def->ofs+i] = pr.size_fields+i;
1844 pr.size_fields += i;
1846 if (scope) {
1847 def->nextlocal = pr.localvars;
1848 pr.localvars = def;
1850 return def;
1854 QCC_def_t *QCC_PR_DummyFieldDef (QCC_type_t *type, char *name, QCC_def_t *scope, int arraysize, unsigned int *fieldofs, qccbool saved) {
1855 int a;
1856 char array[64];
1857 char newname[256];
1858 QCC_def_t *def, *first = NULL;
1859 unsigned int maxfield, startfield;
1860 startfield = *fieldofs;
1861 maxfield = startfield;
1862 for (a = 0; a < arraysize; ++a) {
1863 if (a == 0) *array = '\0'; else snprintf(array, sizeof(array), "[%d]", a);
1864 if (*name) {
1865 snprintf(newname, sizeof(newname), "%s%s", name, array);
1866 // allocate a new def
1867 def = (void *)qccHunkAlloc(sizeof(QCC_def_t));
1868 memset(def, 0, sizeof(*def));
1869 def->next = NULL;
1870 def->arraysize = arraysize;
1871 pr.def_tail->next = def;
1872 pr.def_tail = def;
1873 def->s_line = pr_source_line;
1874 def->s_file = s_file;
1875 def->name = qccHunkDupStr(newname);
1876 def->type = type;
1877 def->scope = scope;
1878 def->ofs = QCC_GetFreeOffsetSpace(1);
1879 ((qccint *)qcc_pr_globals)[def->ofs] = *fieldofs;
1880 ++fieldofs;
1881 if (!first) first = def;
1882 } else {
1883 def = NULL;
1885 //qcc_printf("Emited %s\n", newname);
1887 *fieldofs = maxfield; // final size of the union
1888 return first;
1892 static void QCC_PR_ParseInitializerType (int arraysize, QCC_def_t *def, QCC_type_t *type, int offset) {
1893 QCC_def_t *tmp;
1894 int i;
1895 if (arraysize > 1) {
1896 //arrays go recursive
1897 QCC_PR_Expect("{");
1898 for (i = 0; i < arraysize; ++i) {
1899 QCC_PR_ParseInitializerType(1, def, type, offset+i*type->size);
1900 if (!QCC_PR_EatDelim(",")) break;
1902 QCC_PR_Expect("}");
1903 } else {
1904 tmp = NULL;
1905 if (type->type == ev_function && (pr_token_type == TT_DELIM || strcmp(pr_token, "builtin") == 0)) {
1906 // begin function special case
1907 QCC_def_t *parentfunc = pr_scope;
1908 QCC_function_t *f;
1909 QCC_dfunction_t *df;
1910 QCC_type_t *parm;
1911 ++def->references;
1912 pr_scope = def;
1913 if (QCC_PR_EatKeyword("builtin")) {
1914 f = (void *)qccHunkAlloc(sizeof(QCC_function_t));
1915 f->builtin = 666;
1916 locals_start = locals_end = 0;
1917 } else {
1918 f = QCC_PR_ParseImmediateStatements(type);
1920 if (tmp == NULL) {
1921 int np;
1922 pr_scope = parentfunc;
1923 //tmp = QCC_MakeIntConst(numfunctions);
1924 //fprintf(stderr, "FUNC: [%s]: ofs=%u\n", def->name, def->ofs);
1925 f->def = def;
1926 f->funcnum = numfunctions;
1927 if (def->func != NULL && def->func != f) {
1928 qcc_printf("FATAL: WTF?!! (000)\n");
1929 abort();
1930 } else {
1931 def->func = f;
1933 if (def->ofs > 0) {
1934 // this function was forward-declared and now it is defined, so fix global literal
1935 G_INT(def->ofs) = f->funcnum;
1937 if (numfunctions >= MAX_FUNCTIONS) QCC_Error(ERR_INTERNAL, "Too many function defs");
1938 // fill in the dfunction
1939 df = &functions[numfunctions++];
1940 df->first_statement = (f->builtin ? -f->builtin : f->code);
1941 df->s_name = QCC_CopyString(f->def->name);
1942 df->s_file = s_file2;
1943 df->numparms = f->def->type->num_parms;
1944 if (locals_end == locals_start) locals_end = locals_start = 0;
1945 df->locals = locals_end-locals_start;
1946 df->parm_start = locals_start;
1947 //fprintf(stderr, "df->numparms=%d\n", df->numparms);
1948 np = df->numparms;
1949 if (np < 0) np = (np == -1 ? MAX_PARMS : -np-1);
1950 for (i = 0, parm = type->param; /*i < df->numparms*/parm != NULL; ++i, parm = parm->next) {
1951 //fprintf(stderr, " i=%d, parm=%p\n", i, parm);
1952 // k8: void print (string, ...): second parm is NULL (wtf?!)
1953 if (parm == NULL) {
1954 if (i != abs(df->numparms)-1) QCC_PR_ParseError(0, "internal compiler error in QCC_PR_ParseInitializerType()");
1955 df->parm_size[i] = 0;
1956 break;
1957 } else {
1958 df->parm_size[i] = parm->size|(parm->type<<8); // record argument type too
1959 if (parm->type == ev_field && parm->aux_type) {
1960 //fprintf(stderr, "arg #%d: field, ofs=%u\n", i, parm->ofs);
1961 df->parm_size[i] |= parm->aux_type->type<<16;
1965 while (i < np) df->parm_size[i++] = 0;
1966 // end function special case
1968 } else if (type->type == ev_string && QCC_PR_EatId("_")) {
1969 char trname[128];
1970 QCC_PR_Expect("(");
1971 if (pr_token_type != TT_IMMED || pr_immediate_type->type != ev_string) QCC_PR_ParseError(0, "_() intrinsic accepts only a string immediate");
1972 tmp = QCC_MakeStringConst(pr_immediate_string);
1973 QCC_PR_Lex();
1974 QCC_PR_Expect(")");
1975 if (!pr_scope || def->constant) {
1976 QCC_def_t *dt;
1977 snprintf(trname, sizeof(trname), "dotranslate_%d", ++dotranslate_count);
1978 dt = QCC_PR_DummyDef(type_string, trname, pr_scope, 1, offset, qcc_true, qcc_true);
1979 dt->references = 1;
1980 dt->constant = 1;
1981 dt->initialized = 1;
1983 } else {
1984 tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
1985 if (qcc_typecmp(type, tmp->type)) {
1986 // you can cast from const 0 to anything
1987 if (tmp->type->size == type->size && (tmp->type->type == ev_integer || tmp->type->type == ev_float) && tmp->constant && !G_INT(tmp->ofs)) {
1988 } else if (type->type == ev_float && tmp->type->type == ev_integer) {
1989 // cast from int->float will convert
1990 tmp = QCC_PR_Statement(&pr_opcodes[OP_CONV_ITOF], tmp, 0, NULL);
1991 } else if (type->type == ev_integer && tmp->type->type == ev_float) {
1992 // cast from float->int will convert
1993 tmp = QCC_PR_Statement(&pr_opcodes[OP_CONV_FTOI], tmp, 0, NULL);
1994 } else {
1995 QCC_PR_ParseErrorPrintDef(ERR_BADIMMEDIATETYPE, def, "wrong initializer type");
2000 if (!pr_scope || def->constant) {
2001 if (tmp != NULL && !tmp->constant) QCC_PR_ParseErrorPrintDef(ERR_BADIMMEDIATETYPE, def, "initializer is not constant");
2002 if (def->initialized && tmp != NULL) {
2003 for (i = 0; (unsigned int)i < type->size; ++i) {
2004 if (G_INT(offset+i) != G_INT(tmp->ofs+i)) QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "incompatible redeclaration");
2006 } else if (tmp != NULL) {
2007 for (i = 0; (unsigned int)i < type->size; ++i) G_INT(offset+i) = G_INT(tmp->ofs+i);
2009 } else if (tmp != NULL) {
2010 QCC_def_t lhs, rhs;
2011 if (def->initialized) QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s initialised twice", def->name);
2012 memset(&lhs, 0, sizeof(lhs));
2013 memset(&rhs, 0, sizeof(rhs));
2014 ++def->references;
2015 for (i = 0; (unsigned)i < type->size; ) {
2016 rhs.type = lhs.type = type_float;
2017 lhs.ofs = offset+i;
2018 ++tmp->references;
2019 rhs.ofs = tmp->ofs+i;
2020 if (type->size-i >= 3) {
2021 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &rhs, &lhs, NULL));
2022 i += 3;
2023 } else {
2024 QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &rhs, &lhs, NULL));
2025 ++i;
2029 if (tmp != NULL) QCC_FreeTemp(tmp);
2034 void QCC_PR_ParseInitializerDef (QCC_def_t *def, qccbool isvar, qccbool isconst) {
2035 def->constant = (isconst || (!isvar && !pr_scope));
2036 QCC_PR_ParseInitializerType(def->arraysize, def, def->type, def->ofs);
2037 if (!def->initialized) def->initialized = 1;
2042 ================
2043 QCC_PR_ParseEnum
2045 Parse enum definition
2046 ================
2048 static void QCC_PR_ParseEnum (void) {
2049 int iv = 0;
2050 float fv = 0.0f;
2051 int isint = QCC_PR_EatKeyword("int");
2052 if (!isint) QCC_PR_EatKeyword("float");
2053 QCC_PR_Expect("{");
2054 for (;;) {
2055 QCC_def_t *def;
2056 char *name = QCC_PR_ParseName();
2057 if (QCC_PR_EatDelim("=")) {
2058 if (pr_token_type != TT_IMMED &&
2059 ((isint && pr_immediate_type->type != ev_integer) ||
2060 (!isint && pr_immediate_type->type != ev_float))) {
2061 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, qcc_false, 0, qcc_false);
2062 if (def) {
2063 if (!def->constant) {
2064 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name);
2065 } else {
2066 if (isint) iv = G_INT(def->ofs); else fv = G_FLOAT(def->ofs);
2068 } else {
2069 QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number");
2071 } else {
2072 if (isint) iv = pr_immediate._int; else fv = pr_immediate._float;
2073 QCC_PR_Lex();
2076 def = (isint ? QCC_MakeIntConst(iv) : QCC_MakeFloatConst(fv));
2077 Hash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(hashtable_bucket_t)));
2078 if (isint) ++iv; else ++fv;
2079 if (QCC_PR_EatDelim("}")) break;
2080 QCC_PR_Expect(",");
2081 if (QCC_PR_EatDelim("}")) break; // accept trailing comma
2083 QCC_PR_Expect(";");
2088 ================
2089 QCC_PR_ParseEnumFlags
2091 Parse enumflags definition
2092 ================
2094 static void QCC_PR_ParseEnumFlags (void) {
2095 int iv = 1;
2096 float fv = 1.0f;
2097 int isint = QCC_PR_EatKeyword("int");
2098 if (!isint) QCC_PR_EatKeyword("float");
2099 QCC_PR_Expect("{");
2100 for (;;) {
2101 int bits = 0;
2102 QCC_def_t *def;
2103 char *name = QCC_PR_ParseName();
2104 if (QCC_PR_EatDelim("=")) {
2105 if (pr_token_type != TT_IMMED &&
2106 ((isint && pr_immediate_type->type != ev_integer) ||
2107 (!isint && pr_immediate_type->type != ev_float))) {
2108 def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, qcc_false, 0, qcc_false);
2109 if (def) {
2110 if (!def->constant) {
2111 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name);
2112 } else {
2113 if (isint) iv = G_INT(def->ofs); else fv = G_FLOAT(def->ofs);
2115 } else {
2116 QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number");
2118 } else {
2119 if (isint) iv = pr_immediate._int; else fv = pr_immediate._float;
2120 QCC_PR_Lex();
2123 if (isint) {
2124 int i = iv;
2125 while (i) {
2126 if (((i>>1)<<1) != i) ++bits;
2127 i >>= 1;
2129 if (bits > 1) QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %d not a single bit", (int)iv);
2130 def = QCC_MakeIntConst(iv);
2131 Hash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(hashtable_bucket_t)));
2132 iv *= 2;
2133 } else {
2134 int i = (int)fv;
2135 if (i != fv) {
2136 QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", fv);
2137 } else {
2138 while (i) {
2139 if (((i>>1)<<1) != i) ++bits;
2140 i >>= 1;
2142 if (bits > 1) QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %d not a single bit", (int)fv);
2144 def = QCC_MakeFloatConst(fv);
2145 Hash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(hashtable_bucket_t)));
2146 fv *= 2;
2148 if (QCC_PR_EatDelim("}")) break;
2149 QCC_PR_Expect(",");
2151 QCC_PR_Expect(";");
2156 ================
2157 PR_ParseDefs
2159 Called at the outer layer and when a local statement is hit
2160 'nocommas': don't process 2nd and other defs
2161 ================
2163 QCC_def_t *QCC_PR_ParseDefs (qccbool nocommas) {
2164 char *name;
2165 QCC_type_t *type;
2166 QCC_def_t *def, *d, *res = NULL;
2167 qccbool shared = qcc_false;
2168 qccbool isstatic = defaultstatic;
2169 qccbool externfnc = qcc_false;
2170 qccbool isconstant = qcc_false;
2171 qccbool isvar = qcc_false;
2172 qccbool noref = defaultnoref;
2173 qccbool nosave = qcc_true;
2174 qccbool allocatenew = qcc_true;
2175 qccbool inlinefunction = qcc_false;
2176 qccbool nonconst = qcc_false;
2177 int arraysize;
2178 int count = 0;
2180 void QCC_PR_ParseArrayDef (void) {
2181 char *oldprfile = pr_file_p;
2182 arraysize = 0;
2183 if (QCC_PR_EatDelim("]")) {
2184 QCC_PR_Expect("=");
2185 QCC_PR_Expect("{");
2186 QCC_PR_Lex();
2187 ++arraysize;
2188 for (;;) {
2189 if (pr_token_type == TT_EOF) break;
2190 if (QCC_PR_EatDelim(",")) ++arraysize;
2191 if (QCC_PR_EatDelim("}")) break;
2192 QCC_PR_Lex();
2194 pr_file_p = oldprfile;
2195 QCC_PR_Lex();
2196 } else {
2197 arraysize = QCC_PR_IntConstExpr();
2198 QCC_PR_Expect("]");
2200 if (arraysize < 1) {
2201 QCC_PR_ParseError (ERR_BADARRAYSIZE, "Definition of array (%s) size is not of a numerical value", name);
2202 arraysize = 0; // grrr...
2206 if (!nocommas) {
2207 while (QCC_PR_EatDelim(";")) ;
2209 if (QCC_PR_EatKeyword("enum")) { QCC_PR_ParseEnum(); return NULL; }
2210 if (QCC_PR_EatKeyword("enumflags")) { QCC_PR_ParseEnumFlags(); return NULL; }
2212 if (QCC_PR_EatKeyword("typedef")) {
2213 type = QCC_PR_ParseType(qcc_true, qcc_false);
2214 if (!type) QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens");
2215 type->name = QCC_CopyString(pr_token)+strings;
2216 QCC_PR_Lex();
2217 QCC_PR_Expect(";");
2218 return NULL;
2221 // parse type flags
2222 if (QCC_PR_EatKeyword("const")) isconstant = noref = qcc_true;
2224 while (QCC_PR_EatDelim("[[")) {
2225 for (;;) {
2226 if (QCC_PR_EatKeyword("shared")) {
2227 shared = qcc_true;
2228 if (pr_scope) QCC_PR_ParseError(ERR_NOSHAREDLOCALS, "Cannot have shared locals");
2230 else if (QCC_PR_EatKeyword("extern")) externfnc = qcc_true;
2231 else if (QCC_PR_EatKeyword("const")) isconstant = noref = qcc_true;
2232 else if (QCC_PR_EatKeyword("nonconst")) { isconstant = qcc_false; isvar = nonconst = qcc_true; }
2233 else if (QCC_PR_EatKeyword("var")) { isvar = qcc_true; isconstant = qcc_false; nonconst = qcc_true; }
2234 else if (!pr_scope && QCC_PR_EatKeyword("static")) isstatic = qcc_true;
2235 else if (!pr_scope && QCC_PR_EatKeyword("nonstatic")) isstatic = qcc_false;
2236 else if (QCC_PR_EatKeyword("noref")) noref = qcc_true;
2237 else if (QCC_PR_EatKeyword("save")) nosave = qcc_false;
2238 else if (QCC_PR_EatKeyword("nosave")) nosave = qcc_true;
2239 else QCC_PR_ParseError(0, "invalid attribute: '%s'", pr_token);
2240 if (QCC_PR_EatDelim("]]")) break;
2241 QCC_PR_Expect(",");
2242 if (QCC_PR_EatDelim("]]")) break;
2247 type = QCC_PR_ParseType(qcc_false, (nocommas ? qcc_true : qcc_false));
2248 if (type == NULL) return NULL; // ignore
2250 inlinefunction = type_inlinefunction;
2252 if (nocommas && (type->type == ev_function || type->type == ev_field)) {
2253 QCC_PR_ParseError(0, "function or field declaration is not allowed here");
2256 if (externfnc && type->type != ev_function) {
2257 qcc_printf("Only functions may be defined as external (yet)\n");
2258 externfnc = qcc_false;
2261 //if (pr_scope && type->type == ev_field) QCC_PR_ParseError("Fields must be global");
2262 do {
2263 if (count++ == 1 && nocommas) break;
2265 if (QCC_PR_EatDelim(";")) {
2266 QCC_PR_ParseError(ERR_TYPEWITHNONAME, "type with no name");
2267 name = NULL;
2268 } else {
2269 name = QCC_PR_ParseName();
2270 //fprintf(stderr, "type: %s; name: %s\n", type->name, name);
2272 // check for an array
2273 if (QCC_PR_EatDelim("[")) {
2274 if (nocommas) QCC_PR_ParseError(0, "array declaration is not allowed here");
2275 QCC_PR_ParseArrayDef();
2276 } else {
2277 arraysize = 1;
2279 //fprintf(stderr, "nonc: %d [%s]\n", nonconst, name);
2280 // names consists of [A-Z0-9_] are consts and norefs
2281 if (type->type == ev_field) {
2282 //noref = qcc_true; // assume that all fields are referenced
2283 } else if (!nocommas && arraysize == 1 && !nonconst) {
2284 qccbool isup = qcc_true;
2285 for (const char *n = name; *n; ++n) {
2286 if (!isdigit(*n) && !(*n >= 'A' && *n <= 'Z') && *n != '_') { isup = qcc_false; break; }
2288 if (isup) isconstant = noref = qcc_true;
2290 // function def
2291 if (QCC_PR_EatDelim("(")) {
2292 if (nocommas) QCC_PR_ParseError(0, "function declaration is not allowed here");
2293 if (inlinefunction) {
2294 QCC_PR_ParseWarning(WARN_UNSAFEFUNCTIONRETURNTYPE, "Function returning function. Is this what you meant? (suggestion: use typedefs)");
2296 inlinefunction = qcc_false;
2297 type = QCC_PR_ParseFunctionType(qcc_false, type);
2300 def = QCC_PR_GetDef(type, name, pr_scope, allocatenew, arraysize, !nosave);
2301 if (!def) QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of someshit", name);
2302 if (noref) ++def->references;
2303 if (!def->initialized && shared) {
2304 // shared count as initiialised
2305 def->shared = shared;
2306 def->initialized = qcc_true;
2308 if (externfnc) def->initialized = 2;
2309 if (isstatic) {
2310 if (def->s_file == s_file) {
2311 def->isstatic = isstatic;
2312 } else { //if (type->type != ev_function && defaultstatic) // functions don't quite consitiute a definition
2313 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "can't redefine non-static as static");
2316 // check for an initialization
2317 if (type->type == ev_function && pr_scope) {
2318 if (QCC_PR_EatDelim("=") || QCC_PR_EatDelim("{")) QCC_PR_ParseError(ERR_INITIALISEDLOCALFUNCTION, "local functions may not be initialised");
2319 d = def;
2320 while (d != def->deftail) {
2321 d = d->next;
2322 d->initialized = 1; // fake function
2323 //k8:WTF?! G_FUNCTION(d->ofs) = 0;
2325 continue;
2327 if (!nocommas &&
2328 ((type->type == ev_function && (strchr("\x7b[:", *pr_token) || strcmp(pr_token, "builtin") == 0)) ||
2329 QCC_PR_EatDelim("="))) {
2330 // this is an initialisation (or a function)
2331 if (def->shared) QCC_PR_ParseError(ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value");
2333 if (def->initialized == 1) {
2334 if (def->type->type == ev_function) {
2335 i = G_FUNCTION(def->ofs);
2336 df = &functions[i];
2337 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
2338 } else {
2339 QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
2343 QCC_PR_ParseInitializerDef(def, isvar, isconstant);
2344 } else {
2345 if (type->type == ev_function && isvar) {
2346 isconstant = !isvar;
2347 def->initialized = 1;
2349 if (type->type == ev_field) {
2350 if (isconstant) def->constant = 2; // special flag on fields, 2, makes the pointer obtained from them also constant
2351 else if (isvar) def->constant = 0;
2352 else def->constant = 1;
2353 } else {
2354 def->constant = isconstant;
2357 res = def;
2358 d = def;
2359 while (d != def->deftail) {
2360 d = d->next;
2361 d->constant = def->constant;
2362 d->initialized = def->initialized;
2364 if (nocommas) break;
2365 } while (QCC_PR_EatDelim(","));
2367 if (!nocommas) {
2368 if (type->type == ev_function) {
2369 // semicolon after function definition is optional
2370 QCC_PR_EatDelim(";");
2371 } else {
2372 if (!QCC_PR_EatDelim(";")) QCC_PR_ParseWarning(WARN_UNDESIRABLECONVENTION, "Missing semicolon at end of definition");
2376 return res;
2381 ============
2382 PR_CompileFile
2384 compiles the 0 terminated text, adding defintions to the pr structure
2385 ============
2387 qccbool QCC_PR_CompileFile (char *string, const char *filename) {
2388 jmp_buf oldjb;
2389 if (!pr.memory) QCC_Error(ERR_INTERNAL, "PR_CompileFile: Didn't clear");
2390 compilingfile = filename;
2391 s_file = s_file2 = QCC_CopyString(filename);
2392 pr_file_p = string;
2393 pr_source_line = 0;
2394 memcpy(&oldjb, &pr_parse_abort, sizeof(oldjb));
2395 if (setjmp(pr_parse_abort)) {
2396 // dont count it as error
2397 } else {
2398 //clock up the first line
2399 QCC_PR_NewLine(qcc_false);
2400 QCC_PR_Lex(); // read first token
2402 while (pr_token_type != TT_EOF) {
2403 if (setjmp(pr_parse_abort)) {
2404 if (++pr_error_count > MAX_ERRORS) {
2405 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
2406 return qcc_false;
2408 num_continues = 0;
2409 num_breaks = 0;
2410 num_cases = 0;
2411 QCC_PR_SkipToSemicolon();
2412 if (pr_token_type == TT_EOF) {
2413 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
2414 return qcc_false;
2417 pr_scope = NULL; // outside all functions
2418 QCC_PR_ParseDefs(0);
2420 memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb));
2421 return (pr_error_count == 0);
2425 qccbool QCC_Include (const char *filename) {
2426 char *newfile;
2427 char fname[512];
2428 char *opr_file_p;
2429 QCC_string_t os_file, os_file2;
2430 int opr_source_line;
2431 const char *ocompilingfile;
2432 struct qcc_includechunk_s *oldcurrentchunk;
2433 extern struct qcc_includechunk_s *currentchunk;
2435 ocompilingfile = compilingfile;
2436 os_file = s_file;
2437 os_file2 = s_file2;
2438 opr_source_line = pr_source_line;
2439 opr_file_p = pr_file_p;
2440 oldcurrentchunk = currentchunk;
2442 strcpy(fname, filename);
2443 QCC_LoadFile(fname, (void*)&newfile);
2444 currentchunk = NULL;
2445 pr_file_p = newfile;
2446 QCC_PR_CompileFile(newfile, fname);
2447 currentchunk = oldcurrentchunk;
2449 compilingfile = ocompilingfile;
2450 s_file = os_file;
2451 s_file2 = os_file2;
2452 pr_source_line = opr_source_line;
2453 pr_file_p = opr_file_p;
2455 //QCC_PR_IncludeChunk(newfile, qcc_false, fname);
2457 return qcc_true;
2461 void QCC_Clear_Memory (int dofree) {
2462 if (dofree) {
2463 if (pr_breaks) free(pr_breaks);
2464 if (pr_continues) free(pr_continues);
2465 if (pr_cases) free(pr_cases);
2466 if (pr_casesdef) free(pr_casesdef);
2467 if (pr_casesdef2) free(pr_casesdef2);
2468 if (pr_gotos) free(pr_gotos);
2469 if (pr_labels) free(pr_labels);
2471 max_breaks = num_breaks = 0;
2472 pr_breaks = NULL;
2473 max_cases = num_cases = 0;
2474 pr_cases = NULL;
2475 pr_casesdef = pr_casesdef2 = NULL;
2476 max_continues = num_continues = 0;
2477 pr_continues = NULL;
2478 max_gotos = num_gotos = 0;
2479 pr_gotos = NULL;
2480 max_labels = num_labels = 0;
2481 pr_labels = NULL;