#include #include #include #include "sc.h" #include "sctracker.h" memuse_list_t *heapusage = NULL; memuse_list_t *stackusage = NULL; funcenum_t *firstenum = NULL; funcenum_t *lastenum = NULL; pstruct_t *firststruct = NULL; pstruct_t *laststruct = NULL; structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member) { int i; for (i=0; iargcount; i++) { if (strcmp(pstruct->args[i]->name, member) == 0) { return pstruct->args[i]; } } return NULL; } pstruct_t *pstructs_add(const char *name) { pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t)); memset(p, 0, sizeof(pstruct_t)); strcpy(p->name, name); if (!firststruct) { firststruct = p; laststruct = p; } else { laststruct->next = p; laststruct = p; } return p; } void pstructs_free() { pstruct_t *p, *next; p = firststruct; while (p) { while (p->argcount--) { free(p->args[p->argcount]); } free(p->args); next = p->next; free(p); p = next; } firststruct = NULL; laststruct = NULL; } pstruct_t *pstructs_find(const char *name) { pstruct_t *p = firststruct; while (p) { if (strcmp(p->name, name) == 0) { return p; } p = p->next; } return NULL; } structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg) { structarg_t *newarg; int i; for (i=0; iargcount; i++) { if (strcmp(pstruct->args[i]->name, arg->name) == 0) { /* Don't allow dup names */ return NULL; } } newarg = (structarg_t *)malloc(sizeof(structarg_t)); memcpy(newarg, arg, sizeof(structarg_t)); if (pstruct->argcount == 0) { pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1); } else { pstruct->args = (structarg_t **)realloc( pstruct->args, sizeof(structarg_t *) * (pstruct->argcount + 1)); } newarg->offs = pstruct->argcount * sizeof(cell); newarg->index = pstruct->argcount; pstruct->args[pstruct->argcount++] = newarg; return newarg; } void funcenums_free() { funcenum_t *e, *next; e = firstenum; while (e) { functag_t *tag, *nexttag; tag = e->first; while (tag) { nexttag = tag->next; free(tag); tag = nexttag; } next = e->next; free(e); e = next; } firstenum = NULL; lastenum = NULL; } funcenum_t *funcenums_find_byval(int value) { funcenum_t *e = firstenum; while (e) { if (e->value == value) { return e; } e = e->next; } return NULL; } funcenum_t *funcenums_add(const char *name) { funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t)); memset(e, 0, sizeof(funcenum_t)); if (firstenum == NULL) { firstenum = e; lastenum = e; } else { lastenum->next = e; lastenum = e; } strcpy(e->name, name); e->value = pc_addfunctag((char *)name); return e; } functag_t *functags_add(funcenum_t *en, functag_t *src) { functag_t *t = (functag_t *)malloc(sizeof(functag_t)); memcpy(t, src, sizeof(functag_t)); t->next = NULL; if (en->first == NULL) { en->first = t; en->last = t; } else { en->last->next = t; en->last = t; } return t; } /** * Creates a new mem usage tracker entry */ void _push_memlist(memuse_list_t **head) { memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t)); if (*head != NULL) { newlist->list_id = (*head)->list_id + 1; } else { newlist->list_id = 0; } newlist->prev = *head; newlist->head = NULL; *head = newlist; } /** * Pops a heap list but does not free it. */ memuse_list_t *_pop_save_memlist(memuse_list_t **head) { memuse_list_t *oldlist = *head; *head = (*head)->prev; return oldlist; } /** * Marks a memory usage on a memory list */ int _mark_memlist(memuse_list_t *head, int type, int size) { memuse_t *use; if (type==MEMUSE_STATIC && size==0) { return 0; } use=head->head; if (use && (type==MEMUSE_STATIC) && (use->type == type)) { use->size += size; } else { use=(memuse_t *)malloc(sizeof(memuse_t)); use->type=type; use->size=size; use->prev=head->head; head->head=use; } return size; } void _reset_memlist(memuse_list_t **head) { memuse_list_t *curlist = *head; memuse_list_t *tmplist; while (curlist) { memuse_t *curuse = curlist->head; memuse_t *tmpuse; while (curuse) { tmpuse = curuse->prev; free(curuse); curuse = tmpuse; } tmplist = curlist->prev; free(curlist); curlist = tmplist; } *head = NULL; } /** * Wrapper for pushing the heap list */ void pushheaplist() { _push_memlist(&heapusage); } /** * Wrapper for popping and saving the heap list */ memuse_list_t *popsaveheaplist() { return _pop_save_memlist(&heapusage); } /** * Wrapper for marking the heap */ int markheap(int type, int size) { return _mark_memlist(heapusage, type, size); } /** * Wrapper for pushing the stack list */ void pushstacklist() { _push_memlist(&stackusage); } /** * Wrapper for marking the stack */ int markstack(int type, int size) { return _mark_memlist(stackusage, type, size); } /** * Generates code to free all heap allocations on a tracker */ void _heap_freeusage(memuse_list_t *heap, int dofree) { memuse_t *cur=heap->head; memuse_t *tmp; while (cur) { if (cur->type == MEMUSE_STATIC) { modheap((-1)*cur->size*sizeof(cell)); } else { modheap_i(); } if (dofree) { tmp=cur->prev; free(cur); cur=tmp; } else { cur=cur->prev; } } if (dofree) { heap->head=NULL; } } void _stack_genusage(memuse_list_t *stack, int dofree) { memuse_t *cur = stack->head; memuse_t *tmp; while (cur) { if (cur->type == MEMUSE_DYNAMIC) { /* no idea yet */ assert(0); } else { modstk(cur->size * sizeof(cell)); } if (dofree) { tmp = cur->prev; free(cur); cur = tmp; } else { cur = cur->prev; } } if (dofree) { stack->head = NULL; } } /** * Pops a heap list and frees it. */ void popheaplist() { memuse_list_t *oldlist; assert(heapusage!=NULL); _heap_freeusage(heapusage, 1); assert(heapusage->head==NULL); oldlist=heapusage->prev; free(heapusage); heapusage=oldlist; } void genstackfree(int stop_id) { memuse_list_t *curlist = stackusage; while (curlist && curlist->list_id > stop_id) { _stack_genusage(curlist, 0); curlist = curlist->prev; } } void genheapfree(int stop_id) { memuse_list_t *curlist = heapusage; while (curlist && curlist->list_id > stop_id) { _heap_freeusage(curlist, 0); curlist = curlist->prev; } } void popstacklist(int codegen) { memuse_list_t *oldlist; assert(stackusage != NULL); if (codegen) { _stack_genusage(stackusage, 1); assert(stackusage->head==NULL); } oldlist = stackusage->prev; free(stackusage); stackusage = oldlist; } void resetstacklist() { _reset_memlist(&stackusage); } void resetheaplist() { _reset_memlist(&heapusage); }