func.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*
  2. * GTools C compiler
  3. * =================
  4. * source file :
  5. * function routines
  6. *
  7. * Copyright 2001-2004 Paul Froissart.
  8. * Credits to Christoph van Wuellen and Matthew Brandt.
  9. * All commercial rights reserved.
  10. *
  11. * This compiler may be redistributed as long there is no
  12. * commercial interest. The compiler must not be redistributed
  13. * without its full sources. This notice must stay intact.
  14. */
  15. #define DECLARE
  16. #include "define.h"
  17. _FILE(__FILE__)
  18. #include "c.h"
  19. #include "expr.h"
  20. #include "gen.h"
  21. #include "cglbdec.h"
  22. int is_leaf_function CGLOB, uses_link CGLOB, pushed CGLOB;
  23. XLST_TYPE reg_size CGLOB;
  24. void funcbottom(void);
  25. void block(struct sym *sp); /* CAUTION : always requires a compound_done() after call */
  26. /* function compilation routines */
  27. #ifdef REGPARM
  28. SYM *parmsp[CONVENTION_MAX_DATA+1+CONVENTION_MAX_ADDR+1+1];
  29. #endif
  30. void funcbody(SYM *sp, char *names[], int nparms) {
  31. /*
  32. * funcbody starts with the current symbol being the begin for the local
  33. * block or the first symbol of the parameter declaration
  34. */
  35. long poffset;
  36. int i, j;
  37. struct sym *sp1, *mk_int();
  38. int old_global;
  39. long old_spvalue;
  40. XLST_TYPE *p;
  41. #ifdef REGPARM
  42. int regs=sp->tp->rp_dn+sp->tp->rp_an;
  43. #endif
  44. #ifdef VERBOSE
  45. time_t ltime;
  46. #endif /* VERBOSE */
  47. #ifdef VERBOSE
  48. times(&tms_buf);
  49. ltime = tms_buf.tms_utime;
  50. #endif /* VERBOSE */
  51. /* uses_structassign=0;*/
  52. lc_auto = 0;
  53. max_scratch = 0;
  54. is_leaf_function = 1;
  55. uses_link = 0;
  56. pushed = 0;
  57. init_node = 0;
  58. old_global = global_flag;
  59. global_flag = 0;
  60. poffset = 8; /* size of return block */
  61. #ifdef REGPARM
  62. memset(parmsp,0,sizeof(parmsp));
  63. #endif
  64. /*if (!strcmp(declid,"MnuSel"))
  65. printf("sgio");*/
  66. if (bt_aggregate(sp->tp->btp->type))
  67. poffset = 12;
  68. if (!start_block(0))
  69. dodecl(sc_parms); /* declare parameters */
  70. /* undeclared parameters are int's */
  71. if (!lc_auto) /* otherwise there are declared vars that aren't parameters : error */
  72. for (i = 0; i < nparms; ++i) {
  73. if (!(sp1 = search(names[i], -1, &lsyms))) {
  74. sp1 = mk_int(names[i]);
  75. // do_warning("argument '%s' implicitly declared 'int'",names[i]);
  76. }
  77. old_spvalue = sp1->value.i;
  78. sp1->value.i = poffset;
  79. sp1->storage_class = sc_auto;
  80. #ifdef REGPARM
  81. if (regs) {
  82. int siz;
  83. if (sp1->tp->type==bt_pointer || sp1->tp->type==bt_func) {
  84. /*
  85. * arrays and functions are never passed. They are really
  86. * Pointers
  87. */
  88. if (sp1->tp->val_flag != 0) {
  89. TYP *tp1 = (TYP *) xalloc((int) sizeof(TYP), _TYP+FUNCBODY);
  90. *tp1 = *(sp1->tp);
  91. sp1->tp = tp1;
  92. tp1->st_flag = 0;
  93. sp1->tp->val_flag = 0;
  94. sp1->tp->size = 4;
  95. }
  96. }
  97. siz=sp1->tp->size;
  98. #ifdef AS
  99. sp1->value.i = -(lc_auto+siz+(siz&1)/* dirty hack, but it works */);
  100. #else
  101. sp1->value.i = -(lc_auto+siz+(siz&1)/* dirty hack, but it works */);
  102. // if (siz&1) printf("[crp]"),getchar();
  103. #endif
  104. siz+=siz&1;
  105. lc_auto+=siz;
  106. parmsp[i]=sp1;
  107. regs--;
  108. // goto ok_param;
  109. poffset -= siz; /* to undo the effect of the following statements */
  110. }
  111. #endif
  112. /*
  113. * char, unsigned char, short, unsigned short, enum have been widened
  114. * to int by the caller. This has to be un-done The same is true for
  115. * float/double but float==double actually convert x[] to *x by
  116. * clearing val_flag
  117. *
  118. * It is shown here how to do this correctly, but if we know something
  119. * about the data representation, it can be done much more
  120. * effectively. Therefore, we define MC680X0 and do the cast
  121. * by hand. This means that we can retrieve a char, widened to short
  122. * and put at machine address n, at machine address n+1. This should
  123. * work on most machines. BIGendian machines can do it like it is
  124. * shown here, LOWendian machines must not adjust sp1->value.i The
  125. * function castback is still needed if someone decides to have a
  126. * double data type which is not equivalent to float.
  127. * This approach is, of course, ugly since some
  128. * assumptions on the target machine enter the front end here, but
  129. * they do anyway through the initial value of poffset which is the
  130. * number of bytes that separate the local block from the argument
  131. * block. On a 68000 this are eight bytes since we do a link a6,...
  132. * always.
  133. */
  134. switch (sp1->tp->type) {
  135. case bt_char:
  136. case bt_uchar:
  137. #ifdef MC680X0
  138. if (short_option) {
  139. sp1->value.i += 1;
  140. poffset += 2;
  141. } else {
  142. sp1->value.i += 3;
  143. poffset += 4;
  144. }
  145. #endif
  146. #ifdef INTEL_386
  147. /* note that we only support 32-bit integers */
  148. poffset += 4; /* byte already right there */
  149. #endif
  150. break;
  151. case bt_short:
  152. case bt_ushort:
  153. #ifdef MC680X0
  154. if (short_option) {
  155. poffset += 2;
  156. } else {
  157. sp1->value.i += 2;
  158. poffset += 4;
  159. }
  160. #endif
  161. #ifdef INTEL_386
  162. poffset += 4; /* word already right there */
  163. #endif
  164. break;
  165. case bt_float:
  166. #ifdef MC68000
  167. /* float is the same as double in the 68000 implementation */
  168. poffset += float_size;
  169. #endif
  170. #ifdef INTEL_386
  171. castback(poffset, &tp_double, &tp_float);
  172. poffset += 8;
  173. #endif
  174. break;
  175. case bt_pointer:
  176. case bt_func:
  177. poffset += 4;
  178. /*
  179. * arrays and functions are never passed. They are really
  180. * Pointers
  181. */
  182. if (sp1->tp->val_flag != 0) {
  183. TYP *tp1 = (TYP *) xalloc((int) sizeof(TYP), _TYP+FUNCBODY);
  184. *tp1 = *(sp1->tp);
  185. sp1->tp = tp1;
  186. tp1->st_flag = 0;
  187. sp1->tp->val_flag = 0;
  188. sp1->tp->size = 4;
  189. }
  190. break;
  191. default:
  192. poffset += sp1->tp->size;
  193. break;
  194. }
  195. // ok_param:
  196. /*
  197. * The following code updates the reglst and autolst arrays
  198. * old_spvalue is zero for undeclared parameters (see mk_int), so it
  199. * works. We do a linear search through the reglst and autolst array,
  200. * so this is inefficient. Howewer, these arrays are usually short
  201. * since they only contain the function arguments at moment. In
  202. * short, function argument processing need not be efficient.
  203. */
  204. p=reglst; j=regptr; while (j--) {
  205. if ((XLST_TYPE)*p++ == (XLST_TYPE)old_spvalue) {
  206. p[-1] = sp1->value.i;
  207. break;
  208. }
  209. }
  210. p=autolst; j=autoptr; while (j--) {
  211. if ((XLST_TYPE)*p++ == (XLST_TYPE)old_spvalue) {
  212. p[-1] = sp1->value.i;
  213. break;
  214. }
  215. }
  216. }
  217. else
  218. /*
  219. * Check if there are declared parameters missing in the argument list.
  220. * (this needs to be done iff lc_auto!=0, so with DETAILED_ERR not defined
  221. * this is just OK)
  222. */
  223. #ifdef DETAILED_ERR
  224. for (i=0;i<N_HASH;i++) {
  225. sp1 = lsyms.h[i].tail;
  226. while (sp1 != 0) {
  227. /*
  228. * assume that value.i is negative for normal auto variables
  229. * and positive for parameters -- in fact this is correct either
  230. * with REGPARM not defined, or before the parameter scan whose code is
  231. * just above this
  232. */
  233. if (sp1->value.i <= 0)
  234. #endif
  235. error(ERR_ARG);
  236. #ifdef DETAILED_ERR
  237. sp1 = sp1->prev;
  238. }
  239. }
  240. #endif
  241. #ifdef REGPARM
  242. reg_size=lc_auto;
  243. #endif
  244. if (!start_block(0))
  245. error(ERR_BLOCK);
  246. else {
  247. block(sp);
  248. funcbottom();
  249. }
  250. global_flag = old_global;
  251. compound_done(); // due to block(sp)
  252. #ifdef VERBOSE
  253. times(&tms_buf);
  254. parse_time += tms_buf.tms_utime - ltime;
  255. #endif /* VERBOSE */
  256. }
  257. struct sym *mk_int(char *name) {
  258. struct sym *sp;
  259. TYP *tp;
  260. sp = (struct sym *) xalloc((int) sizeof(struct sym), _SYM+MK_INT);
  261. tp = (TYP *) xalloc((int) sizeof(TYP),_TYP+MK_INT);
  262. if (short_option) {
  263. tp->type = bt_short;
  264. tp->size = 2;
  265. } else {
  266. tp->type = bt_long;
  267. tp->size = 4;
  268. }
  269. #ifdef NO_CALLOC
  270. tp->btp = 0;
  271. tp->lst.tail = tp->lst.head = 0; tp->lst.hash = 0;
  272. tp->vol_flag = tp->val_flag = tp->const_flag = tp->st_flag = 0;
  273. #ifdef LISTING
  274. tp->sname = 0;
  275. #endif
  276. #endif
  277. sp->name = name;
  278. sp->storage_class = sc_auto;
  279. sp->tp = tp;
  280. #ifdef NO_CALLOC
  281. sp->value.i = 0; /* dummy -> means param is undeclared */
  282. #endif
  283. append(&sp, &lsyms);
  284. return sp;
  285. }
  286. void check_table(HTABLE *table) {
  287. SYM *head;
  288. struct htab *ptr; int i;
  289. ptr=&table->h[0];
  290. i=N_HASH;
  291. while (i--) {
  292. head=ptr->head;
  293. while (head != 0) {
  294. if (head->storage_class == sc_ulabel) {
  295. uerrc2("undefined label '%s'",head->name);
  296. // msg2("*** UNDEFINED LABEL - %s\n", head->name);
  297. #ifdef LISTING
  298. if (list_option)
  299. fprintf(list, "*** UNDEFINED LABEL - %s\n", head->name);
  300. #endif
  301. }
  302. head = head->next;
  303. }
  304. ptr++;
  305. }
  306. }
  307. void funcbottom(void) {
  308. nl();
  309. check_table(&labsyms);
  310. #ifdef LISTING
  311. // if (list_option && lsyms.head != 0) {
  312. fprintf(list, "\n\n*** argument symbol table ***\n\n");
  313. list_table(&lsyms, 0);
  314. fprintf(list, "\n\n\n");
  315. // }
  316. // if (list_option && labsyms.head != 0) {
  317. fprintf(list, "\n\n*** label symbol table ***\n\n");
  318. list_table(&labsyms, 0);
  319. fprintf(list, "\n\n\n");
  320. // }
  321. #endif
  322. #ifdef AS
  323. local_clean();
  324. #endif
  325. rel_local(); /* release local symbols */
  326. hashinit(&lsyms);
  327. hashinit(&ltags);
  328. hashinit(&labsyms);
  329. }
  330. extern char *curname;
  331. xstatic struct enode save_sp CGLOBL;
  332. struct snode *dump_stmt;
  333. SYM *func_sp CGLOB;
  334. void block(struct sym *sp) { /* CAUTION : always requires a compound_done() after call */
  335. struct snode *stmt;
  336. int local_total_errors = total_errors;
  337. int line0;
  338. #ifdef VERBOSE
  339. time_t ltime;
  340. #endif /* VERBOSE */
  341. //#ifdef VERBOSE
  342. #ifdef AS
  343. scope_init();
  344. #endif
  345. func_sp=sp;
  346. /*infunc("fire")
  347. bkpt();*/
  348. #ifndef GTDEV
  349. #ifdef PC
  350. if (verbose)
  351. #endif
  352. msg2("Compiling '%s'... ", sp->name);
  353. #endif
  354. //#endif /* VERBOSE */
  355. #ifdef ICODE
  356. if (icode_option)
  357. if (sp->storage_class == sc_external || sp->storage_class == sc_global)
  358. fprintf(icode, "%s:\n", sp->name);
  359. else
  360. fprintf(icode, "L%ld:\n", sp->value.i);
  361. #endif
  362. #ifdef SHOWSTEP
  363. printf("\nparsing");
  364. #endif
  365. start_block(1);
  366. line0=prevlineid;
  367. dump_stmt = stmt = compound(-1);
  368. #ifdef SHOWSTEP
  369. printf(" ok ");
  370. #endif
  371. #ifdef VERBOSE
  372. times(&tms_buf);
  373. ltime = tms_buf.tms_utime;
  374. #endif /* VERBOSE */
  375. /*
  376. * If errors so far, do not try to generate code
  377. */
  378. if (total_errors > local_total_errors) {
  379. cseg();
  380. dumplits();
  381. return;
  382. }
  383. lineid=line0;
  384. genfunc(stmt);
  385. #ifdef VERBOSE
  386. times(&tms_buf);
  387. gen_time += tms_buf.tms_utime - ltime;
  388. ltime = tms_buf.tms_utime;
  389. #endif /* VERBOSE */
  390. cseg();
  391. dumplits();
  392. put_align(AL_FUNC);
  393. #ifndef AS
  394. if (sp->storage_class == sc_external || sp->storage_class == sc_global)
  395. g_strlab(sp->name);
  396. else
  397. put_label((unsigned int) sp->value.i);
  398. #else
  399. put_label(splbl(sp));
  400. #endif
  401. if (!strcmp(sp->name,"__main") && !search("NO_EXIT_SUPPORT",-1,&defsyms)) {
  402. save_sp.nodetype = en_nacon;
  403. save_sp.etype = bt_pointer;
  404. save_sp.esize = 4;
  405. save_sp.v.ensp = "__save__sp__";
  406. #ifdef AS
  407. save_sp.v.enlab = label("__save__sp__");
  408. #endif
  409. g_coder(op_move,4,mk_reg(STACKPTR),mk_offset(&save_sp));
  410. }
  411. flush_peep();
  412. #ifdef AS
  413. scope_flush();
  414. #endif
  415. func_sp=NULL;
  416. #ifdef VERBOSE
  417. times(&tms_buf);
  418. flush_time += tms_buf.tms_utime - ltime;
  419. #endif /* VERBOSE */
  420. }
  421. void castback(long offset, TYP *tp1, TYP *tp2) {
  422. /*
  423. * cast an argument back which has been widened on the caller's side.
  424. * append the resulting assignment expression to init_node
  425. */
  426. struct enode *ep1, *ep2;
  427. ep2 = mk_node(en_autocon, NIL_ENODE, NIL_ENODE);
  428. ep2->v.i = offset;
  429. ep2->etype = bt_pointer;
  430. ep2->esize = 4;
  431. ep1 = copynode(ep2);
  432. ep2 = mk_node(en_ref, ep2, NIL_ENODE);
  433. ep2->etype = tp1->type;
  434. ep2->esize = tp1->size;
  435. ep2 = mk_node(en_cast, ep2, NIL_ENODE);
  436. ep2->etype = tp2->type;
  437. ep2->esize = tp2->size;
  438. ep1 = mk_node(en_ref, ep1, NIL_ENODE);
  439. ep1->etype = tp2->type;
  440. ep1->esize = tp2->size;
  441. ep1 = mk_node(en_assign, ep1, ep2);
  442. ep1->etype = tp2->type;
  443. ep1->esize = tp2->size;
  444. if (init_node == 0)
  445. init_node = ep1;
  446. else
  447. init_node = mk_node(en_void, init_node, ep1);
  448. }
  449. // vim:ts=4:sw=4