memmgt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. * GTools C compiler
  3. * =================
  4. * source file :
  5. * memory management
  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. #include "define.h"
  16. _FILE(__FILE__)
  17. #include "c.h"
  18. #include "expr.h"
  19. #include "gen.h"
  20. #define USE_MEMMGT
  21. #include "cglbdec.h"
  22. int glbsize CGLOB, /* size left in current global block */
  23. locsize CGLOB, /* size left in current local block */
  24. tmpsize CGLOB, /* size left in current temp block */
  25. glbindx CGLOB, /* global index */
  26. locindx CGLOB, /* local index */
  27. tmpindx CGLOB; /* temp index */
  28. int temp_mem CGLOB,temp_local CGLOB;
  29. #ifdef MIN_TEMP_MEM
  30. int min_temp_mem CGLOB;
  31. #endif
  32. #ifdef PC
  33. int glbmem CGLOB,locmem CGLOB;
  34. #endif
  35. int max_mem CGLOB, /* statistics... */
  36. glo_mem CGLOB;
  37. struct blk *locblk CGLOB, /* pointer to local block list */
  38. *glbblk CGLOB, /* pointer to global block list */
  39. *tmpblk CGLOB; /* pointer to temporary block list */
  40. #ifdef PC
  41. //void *calloc();
  42. #endif
  43. static void _err_attr error_memory() {
  44. uerrc2("not enough memory to compile function '%s'",func_sp->name);
  45. }
  46. int *_xalloc(int siz) {
  47. struct blk *bp;
  48. char *rv;
  49. if (temp_local) /* this is NOT perfect, but it's close to being so :) */
  50. goto glb_xalloc;
  51. /* if (locmem>=50000)
  52. bkpt();*/
  53. /* if (siz>=1000)
  54. bkpt();*/
  55. #ifdef MIN_TEMP_MEM
  56. if (temp_mem<=min_temp_mem) {
  57. #else
  58. if (!temp_mem) {
  59. #endif
  60. glb_xalloc:
  61. if (global_flag) {
  62. #ifdef PC
  63. glbmem += siz;
  64. #endif
  65. if (glbsize >= siz) {
  66. rv = &(glbblk->m[glbindx]);
  67. glbsize -= siz;
  68. glbindx += siz;
  69. /* if ((long)rv==0x789388)
  70. bkpt();*/
  71. return (int *) rv;
  72. } else {
  73. // bp = (struct blk *) calloc(1, (int) sizeof(struct blk));
  74. bp = (struct blk *) malloc(sizeof(struct blk));
  75. if (!bp) {
  76. #ifdef PC
  77. msg("not enough memory.\n");
  78. _exit(1);
  79. #else
  80. error_memory();
  81. fatal("Not enough global memory");
  82. #endif
  83. }
  84. memset(bp, 0, sizeof(struct blk));
  85. glo_mem++;
  86. bp->next = glbblk;
  87. glbblk = bp;
  88. glbsize = BLKLEN - siz;
  89. glbindx = siz;
  90. return (int *) glbblk->m;
  91. }
  92. } else { /* not global */
  93. #ifdef PC
  94. locmem += siz;
  95. #endif
  96. if (locsize >= siz) {
  97. rv = &(locblk->m[locindx]);
  98. locsize -= siz;
  99. /*if ((long)rv==0x7f86bc)
  100. bkpt();*/
  101. locindx += siz;
  102. #ifdef PC
  103. if (0x80000000&(long)rv)
  104. fatal("A DIRTY HACK FAILED ON YOUR CONFIG. "
  105. "LOOK AT OUT68K_AS.C TO SOLVE THE PROBLEM");
  106. #endif
  107. /* if (func_sp) infunc("chk_curword")
  108. if ((long)rv==0x7b4bf8)
  109. bkpt();*/
  110. /* if ((long)rv==0x7e5cd0)
  111. bkpt();*/
  112. return (int *) rv;
  113. } else {
  114. // bp = (struct blk *) calloc(1, (int) sizeof(struct blk));
  115. bp = (struct blk *) malloc(sizeof(struct blk));
  116. if (!bp) {
  117. #ifdef PC
  118. msg("not enough local memory.\n");
  119. _exit(1);
  120. #else
  121. error_memory();
  122. fatal("Not enough local memory");
  123. #endif
  124. }
  125. memset(bp, 0, sizeof(struct blk));
  126. bp->next = locblk;
  127. locblk = bp;
  128. locsize = BLKLEN - siz;
  129. locindx = siz;
  130. return (int *) locblk->m;
  131. }
  132. }
  133. } else {
  134. if (tmpsize >= siz) {
  135. rv = &(tmpblk->m[tmpindx]);
  136. tmpsize -= siz;
  137. tmpindx += siz;
  138. return (int *) rv;
  139. } else {
  140. // bp = (struct blk *) calloc(1, (int) sizeof(struct blk));
  141. bp = (struct blk *) malloc(sizeof(struct blk));
  142. if (!bp) {
  143. #ifdef PC
  144. msg("not enough temporary memory.\n");
  145. _exit(1);
  146. #else
  147. error_memory();
  148. fatal("Not enough temporary memory");
  149. #endif
  150. }
  151. /* if (bp==0x789364)
  152. bkpt();*/
  153. memset(bp, 0, sizeof(struct blk));
  154. bp->next = tmpblk;
  155. tmpblk = bp;
  156. tmpsize = BLKLEN - siz;
  157. tmpindx = siz;
  158. return (int *) tmpblk->m;
  159. }
  160. }
  161. }
  162. int blk_free(struct blk *bp1) {
  163. int blkcnt = 0;
  164. struct blk *bp2;
  165. while (bp1) {
  166. bp2 = bp1->next;
  167. (void) free((char *) bp1);
  168. blkcnt++;
  169. bp1 = bp2;
  170. }
  171. return blkcnt;
  172. }
  173. #ifdef DUAL_STACK
  174. typedef struct _ds_block {
  175. void *lo,*hi;
  176. struct _ds_block *pop;
  177. void *popstackptr;
  178. } DS_BLOCK;
  179. static DS_BLOCK *ds_current CGLOB;
  180. void *dualstack CGLOB;
  181. void *ds_currentlo CGLOB,*ds_currenthi CGLOB;
  182. #ifdef PC
  183. int n_ds_allocations CGLOB;
  184. #endif
  185. void ds_allocatleast(unsigned int size) {
  186. size+=DS_BSIZE;
  187. DS_BLOCK *ds_new = malloc(sizeof(DS_BLOCK)+size);
  188. ds_new->lo = (void *)(ds_new+1);
  189. ds_new->hi = (void *)((char *)ds_new->lo+size);
  190. ds_new->pop = ds_current;
  191. ds_new->popstackptr = dualstack;
  192. ds_current = ds_new;
  193. ds_currentlo = ds_current->lo;
  194. ds_currenthi = ds_current->hi;
  195. dualstack = ds_currentlo;
  196. #ifdef PC
  197. n_ds_allocations++;
  198. #endif
  199. }
  200. void ds_free(void) {
  201. DS_BLOCK *ds_old = ds_current;
  202. ds_current = ds_old->pop;
  203. ds_currentlo = ds_current ? ds_current->lo : 0;
  204. ds_currenthi = ds_current ? ds_current->hi : 0;
  205. dualstack = ds_old->popstackptr;
  206. free(ds_old);
  207. }
  208. void rel_dualstack(void) {
  209. while (ds_current)
  210. ds_free();
  211. #ifdef PC
  212. //msg2(" performed %d dual-stack-related allocations\n",n_ds_allocations);
  213. #endif
  214. }
  215. #endif
  216. #define VERBOSE
  217. #ifdef GARBAGE_COLLECT
  218. void d_enode(struct enode **node) {
  219. struct enode *dest,*ep=*node;
  220. if (!ep) return;
  221. if (ep->nodetype==en_icon) { *node=mk_icon(ep->v.i); return; }
  222. dest=xalloc((int)sizeof(struct enode), ENODE);
  223. memcpy(dest,ep,sizeof(struct enode));
  224. *node=dest;
  225. switch (ep->nodetype) {
  226. case en_land: case en_lor:
  227. case en_asand: case en_asor: case en_asxor:
  228. case en_aslsh: case en_asrsh:
  229. case en_asmul: case en_asmod: case en_asdiv:
  230. case en_asadd: case en_assub:
  231. case en_gt: case en_ge:
  232. case en_lt: case en_le:
  233. case en_eq: case en_ne:
  234. case en_cond: case en_assign:
  235. case en_and: case en_or: case en_xor:
  236. case en_lsh: case en_rsh:
  237. case en_mul: case en_mod: case en_div:
  238. case en_add: case en_sub:
  239. case en_fcall: case en_void:
  240. d_enode(&ep->v.p[1]);
  241. case en_deref:
  242. case en_ainc: case en_adec:
  243. case en_uminus: case en_not: case en_compl:
  244. case en_ref:
  245. case en_cast: /* hum hum */
  246. case en_fieldref:
  247. d_enode(&ep->v.p[0]);
  248. case en_tempref:
  249. case en_autocon:
  250. case en_labcon:
  251. case en_nacon:
  252. case en_fcon:
  253. return;
  254. case en_compound:
  255. d_snode(&ep->v.st);
  256. return;
  257. default:
  258. ierr(D_ENODE,1);
  259. }
  260. }
  261. void d_snode(struct snode **node) {
  262. struct snode *dest,*block=*node;
  263. if (!block) return;
  264. dest=xalloc((int)sizeof(struct snode), SNODE);
  265. memcpy(dest,block,sizeof(struct snode));
  266. *node=dest;
  267. while (block != 0) {
  268. switch (block->stype) {
  269. case st_return:
  270. case st_expr:
  271. d_enode(&block->exp);
  272. break;
  273. case st_loop:
  274. d_enode(&block->exp);
  275. d_snode(&block->s1);
  276. d_enode(&block->v2.e);
  277. break;
  278. case st_while:
  279. case st_do:
  280. d_enode(&block->exp);
  281. d_snode(&block->s1);
  282. break;
  283. case st_for:
  284. d_enode(&block->exp);
  285. d_enode(&block->v1.e);
  286. d_snode(&block->s1);
  287. d_enode(&block->v2.e);
  288. break;
  289. case st_if:
  290. d_enode(&block->exp);
  291. d_snode(&block->s1);
  292. d_snode(&block->v1.s);
  293. break;
  294. case st_switch:
  295. d_enode(&block->exp);
  296. d_snode(&block->v1.s);
  297. break;
  298. case st_case:
  299. case st_default:
  300. d_snode(&block->v1.s);
  301. break;
  302. case st_compound:
  303. case st_label:
  304. d_snode(&block->s1);
  305. case st_goto:
  306. case st_break:
  307. case st_continue:
  308. break;
  309. case st_asm:
  310. d_amode(&(struct amode *)block->v1.i);
  311. break;
  312. default:
  313. ierr(D_SNODE,1);
  314. }
  315. block = block->next;
  316. }
  317. }
  318. void d_amode(struct amode **node) {
  319. struct amode *dest,*mode=*node;
  320. if (!mode) return;
  321. dest=xalloc((int)sizeof(struct amode), AMODE);
  322. memcpy(dest,mode,sizeof(struct amode));
  323. *node=dest;
  324. d_enode(&dest->offset);
  325. }
  326. extern struct ocode *_peep_head;
  327. void d_ocodes(void) {
  328. struct ocode *dest=NULL,**node=&_peep_head,*instr;
  329. while ((instr=*node)) {
  330. instr->back=dest;
  331. dest=xalloc((int)sizeof(struct ocode), OCODE);
  332. memcpy(dest,instr,sizeof(struct ocode));
  333. *node=dest;
  334. d_amode(&dest->oper1);
  335. d_amode(&dest->oper2);
  336. node=&dest->fwd;
  337. }
  338. *node=NULL;
  339. }
  340. extern struct snode *dump_stmt;
  341. void collect(int g) {
  342. struct blk *blk=glbblk;
  343. glbsize=glbindx=0;
  344. glbblk=NIL_BLK;
  345. alloc_dump(g);
  346. // dump snodes & most enodes
  347. // d_snode(&dump_stmt);
  348. // dump ocodes & amodes & the rest of enodes
  349. // d_ocodes();
  350. // dump most syms & most strs & typs & tables & the rest of syms & a few strs
  351. d_table(&gsyms); d_table(&gtags); d_table(&defsyms);
  352. // dump slits & the rest of strs
  353. //
  354. // no dump is needed for cse's since it is a cooperative garbage-collection
  355. }
  356. #endif
  357. int _k_=0;
  358. void tmp_use() {
  359. temp_mem++;
  360. _k_++;
  361. }
  362. void tmp_free() {
  363. if (!--temp_mem && tmpblk) {
  364. #ifdef PC
  365. int n=0;
  366. #endif
  367. #ifndef LIFO_TMP_FREE
  368. /* Maybe I'm wrong, but I think that this solution
  369. * is quite bad for the TIOS heap manager... */
  370. struct blk *nxt;
  371. while ((nxt=tmpblk->next))
  372. #ifdef PC
  373. n++,
  374. #endif
  375. free(tmpblk),tmpblk=nxt;
  376. #else
  377. struct blk *nxt=tmpblk->next,*tofree;
  378. while (nxt)
  379. #ifdef PC
  380. n++,
  381. #endif
  382. tofree=nxt, nxt=nxt->next, free(tofree);
  383. #endif
  384. #ifdef _DBG_SHOW_TEMPMEM
  385. printf("*");
  386. #ifdef PC
  387. printf("(%dk)",n*BLKLEN/1024);
  388. // getchar();
  389. #endif
  390. #endif
  391. tmpsize = BLKLEN;
  392. tmpindx = 0;
  393. memset(tmpblk,0,BLKLEN);
  394. /*blk_free(tmpblk);
  395. tmpblk = 0;
  396. tmpsize = 0;*/
  397. }
  398. }
  399. void rel_local() {
  400. unsigned int mem;
  401. #ifndef AS
  402. #define pos 0
  403. #else
  404. extern unsigned int pos;
  405. #endif
  406. #ifdef PC
  407. #ifdef GARBAGE_COLLECT
  408. collect(0);
  409. #endif
  410. #ifdef LISTING
  411. alloc_dump(0);
  412. #endif
  413. #endif
  414. if ((mem=blk_free(locblk))+glo_mem+(2*pos)/BLKLEN > (unsigned int)max_mem) {
  415. max_mem = mem+glo_mem+(2*pos)/BLKLEN;
  416. /*if (max_mem>330/4)
  417. bkpt();*/
  418. }
  419. #ifndef AS
  420. #undef pos
  421. #endif
  422. #ifdef PC
  423. locmem = 0;
  424. #endif
  425. locblk = 0;
  426. locsize = 0;
  427. //#ifndef PC
  428. #ifndef GTDEV
  429. #ifdef PC
  430. if (verbose)
  431. #endif
  432. msg2("%d kb\n", (int)(mem * BLKLEN/1024));
  433. #endif
  434. //#endif
  435. #ifdef VERBOSE
  436. #ifdef LISTING
  437. #if 0
  438. if (list_option)
  439. msg2(" releasing %2d kb local tables.\n",
  440. mem * BLKLEN/1024);
  441. #endif
  442. #endif
  443. #endif
  444. }
  445. void rel_global() {
  446. int mem;
  447. if ((mem=blk_free(glbblk)) > max_mem)
  448. max_mem = mem;
  449. #ifdef PC
  450. glbmem = 0;
  451. #endif
  452. glo_mem = 0;
  453. glbblk = 0;
  454. glbsize = 0;
  455. blk_free(tmpblk);
  456. tmpblk = 0;
  457. tmpsize = 0;
  458. #ifdef PC
  459. #ifdef LISTING
  460. alloc_dump(1);
  461. #endif
  462. #endif
  463. #ifdef VERBOSE
  464. #ifdef LISTING
  465. if (list_option)
  466. msg2(" releasing %2d kb global tables.\n",
  467. mem * BLKLEN/1024);
  468. #endif
  469. #ifdef DUAL_STACK
  470. //if (ds_current)
  471. // msg("oops, a dual stack remains\n");
  472. rel_dualstack();
  473. #endif
  474. #ifndef GTDEV
  475. #ifdef PC
  476. if (verbose) {
  477. msg2("Max memory request : %d kb\n",
  478. (int)(max_mem * BLKLEN/1024));
  479. msg("\n");
  480. if (max_mem * BLKLEN/1024<150)
  481. msg("On-calc portability : very good\n");
  482. else if (max_mem * BLKLEN/1024<230)
  483. msg("On-calc portability : good\n");
  484. else if (max_mem * BLKLEN/1024<290)
  485. msg("On-calc portability : questionable\n");
  486. else if (max_mem * BLKLEN/1024<360)
  487. msg("On-calc portability : difficult without splitting\n");
  488. else
  489. msg("On-calc portabilty : impossible without splitting\n");
  490. msg("\n");
  491. }
  492. #endif
  493. #endif
  494. #endif
  495. max_mem = 0;
  496. }
  497. void clean_up() {
  498. blk_free(tmpblk);
  499. blk_free(locblk);
  500. blk_free(glbblk);
  501. #ifdef DUAL_STACK
  502. //if (ds_current)
  503. // msg("oops, a dual stack remains\n");
  504. rel_dualstack();
  505. #endif
  506. temp_mem = 0;
  507. glbblk = locblk = tmpblk = 0;
  508. /*#ifdef OPTIMIZE_BSS
  509. free(bssdata);
  510. #endif*/
  511. }
  512. #undef VERBOSE
  513. // vim:ts=4:sw=4