/*!@file \brief IR Memory Implementation \details Intermediary memory management \author Jordan Lavatai \date Aug 2016 ----------------------------------------------------------------------------*/ #include #include #include //uint64_t #include //memmove #include //malloc #include void ir_init(void); void malloc_cdat(void); /* The initalization function of the IR. Mallocs the first c/v/odat and the first links and refs and inits the cdat_stack */ void ir_init() { /* Init root cdat and stack */ char root[4] = "root"; cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof(struct cdat) ); cdat_buf[num_cdats]->idx = 0; memmove(cdat_buf[num_cdats]->name, root, 4); cdat_stackp = cdat_stack; *cdat_stackp = cdat_buf[num_cdats++]; } //TODO: FREE MEMORY! void malloc_cdat() { if(curr_max_cdats <= num_cdats) { if( (realloc((void*) cdat_buf, PTRS_IN_PAGE * 4)) == NULL) perror("realloc cdat_buf failed"); curr_max_cdats += PTRS_IN_PAGE; if( (realloc( (void*) cdat_stack, PTRS_IN_PAGE * 4)) == NULL) //increase cdat_stack also perror("realloc cdat_stack failed"); } if( (cdat_buf[num_cdats] = (struct cdat*) malloc(sizeof (struct cdat)) ) == NULL ) perror("malloc cdat failed"); } /* Dynamically allocate memory for a class data structure, or cdat, after a class has been identified in a grammar. We also create a stack of class pointers so that we can access the cdat during processing of that cdats sets and elements, a requirement because the nature of recursive classes prevents us from accessing the cdat based on the previous index into cdat_buf, which is a list of all allocated cdats*/ void push_cdat ( char* name ) { malloc_cdat(); memmove(cdat_buf[num_cdats]->name, name, 32); cdat_buf[num_cdats]->idx = num_cdats; /* Set the cdat as a class of the previous cdat */ (*cdat_stackp)->class_list[(*cdat_stackp)->num_classes++] = cdat_buf[num_cdats]; /* Push the cdat onto the cdat_stack */ *++cdat_stackp = cdat_buf[num_cdats++]; } void pop_cdat () { *cdat_stackp = NULL; cdat_stackp--; } /* Called in the reduction of a set. While both odats (eles and sets) have identical label terminals, we are unable to give a single grammatical rule for both due to how we allocate odats in the odat buf. Due to the nature of bottom up parsing, all the elements will be inserted into the odat_buf first, and then the set that contains these element is inserted. Since the sets label comes before the element list in the grammar, we would be giving an element a set label in its respective odat, which would then be replaced by the elements label. Instead, we store the label in the sets representation inside CURR_CDAT and after we are done parsing the element_list and know that the CURR_ODAT is the set, we populate the sets label members in CURR_ODAT with the values we stored previously in CURR_CDAT. */ void insert_set_label ( char* name, uint64_t ref_id ) { struct set* curr_set; curr_set = curr_set(); memmove(curr_set.name,name,32); curr_set.ref_id = ref_id; } void insert_set_olink ( uint64_t ref_id ) { struct set* curr_set; struct cdat* curr_cdat; struct link* curr_link; curr_set = curr_set(); curr_cdat = curr_cdat(); curr_link = alloc_link(); curr_set.cdat_idx = curr_cdat->idx; curr_set.ref_id = ref_id; /* Will be resolved to offset when link is processed */ curr_link->type = 1; curr_link->link_t.olink.ref_id = ref_id; curr_link->cdat_idx = curr_cdat->idx; curr_link->set_idx = curr_cdat->num_sets++; curr_link->ele_idx = -1; } void insert_set_vlink ( uint64_t ref_id, char* anim_name ) { struct cdat* curr_cdat; struct link* curr_link; curr_cdat = curr_cdat(); curr_link = alloc_link(); /* Insert vlink into link_stack so that it gets processed at output time */ curr_link->type = 2; curr_link->cdat_idx = curr_cdat->idx; curr_link->set_idx = curr_cdat->num_sets; curr_link->link_t.vlink.ref_id = ref_id; memmove(curr_link->link_t.vlink.anim_name, anim_name, 32); } /* Svlinks dont have animation names */ void insert_set_svlink ( uint64_t ref_id ) { struct cdat* curr_cdat; struct link* curr_link; curr_cdat = curr_cdat(); curr_link = alloc_link(); /* Insert vlink into link_stack so that it gets processed at output time */ curr_link->type = 3; curr_link->cdat_idx = curr_cdat->idx; curr_link->set_idx = curr_cdat->num_sets; curr_link->link_t.svlink.ref_id = ref_id; } /* At the point of reducing to a set, most of the sets odat information has already been populated during the reduction of its right hand side non terminals (hitbox, root, quad_list). */ void insert_set () { struct odat* curr_odat; struct cdat* curr_cdat; struct ref* prev_ref; struct ref* curr_ref; curr_odat = alloc_odat(); curr_cdat = curr_cdat(); curr_set = curr_set(); prev_ref = prev_ref(); curr_ref = alloc_ref(); ref_id = curr_set.ref_id; // ref_id set by insert_set_label(name, ref_id) curr_set.cdat_idx = curr_cdat->idx; memmove(curr_odat->name, curr_set.name, 32); curr_cdat.num_sets++; curr_odat->cdat_idx = curr_cdaat->idx; curr_odat->refp = curr_ref; curr_ref->lastref = prev_ref; prev_ref->nextref = curr_ref; curr_ref->odatp = curr_odat; if(ref_id == -1) /* user did not define a ref_id so */ { ref_id = ss_ref_id; ss_ref_id++; } curr_ref->ref_id = ref_id; } /* Created as a seperate function, instead of setting the ODATS vdat_id and calling inc_vdat() inside of insert_set(), to account for the set reduction where a vdat is not created (o/v/svlinks). */ void insert_vdat_id () { struct odat* curr_odat; curr_odat = curr_odat(); curr_odat->vdat_id = num_vdats; //no vdat_id for odats that have vlinks/svlinks } /* Populates both the odat name and ref_id for element. */ void insert_ele_label ( char* name, uint64_t ref_id ) { struct ele* curr_ele; curr_ele = curr_ele(); memmove(curr_ele.name, name, 32); curr_ele.ref_id = ref_id; } void insert_ele_olink ( uint64_t ref_id ) { CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx; CURR_CDAT->CURR_SET.CURR_ELE.ref_id = ref_id; /* Will be resolved to offset when link is processed */ CURR_LINK->type = 1; CURR_LINK->link_t.olink.ref_id = ref_id; CURR_LINK->cdat_idx = CURR_CDAT->idx; CURR_LINK->set_idx = CURR_CDAT->num_sets++; CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele++; } void insert_ele_vlink ( uint64_t ref_id, char* anim_name ) { /* Insert vlink into link_stack so that it gets processed at output time */ CURR_LINK->cdat_idx = CURR_CDAT->idx; CURR_LINK->type = 2; CURR_LINK->set_idx = CURR_CDAT->num_sets; CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele; CURR_LINK->link_t.vlink.ref_id = ref_id; memmove(CURR_LINK->link_t.vlink.anim_name, anim_name, 32); } void insert_ele_svlink ( uint64_t ref_id ) { CURR_LINK->cdat_idx = CURR_CDAT->idx; CURR_LINK->type = 3; CURR_LINK->set_idx = CURR_CDAT->num_sets; CURR_LINK->ele_idx = CURR_CDAT->CURR_SET.num_ele; CURR_LINK->link_t.svlink.ref_id = ref_id; } //Insert element into odat_buf and cdatpages void insert_ele() { uint64_t ref_id; ref_id = CURR_CDAT->CURR_SET.CURR_ELE.ref_id; CURR_CDAT->CURR_SET.CURR_ELE.cdat_idx = CURR_CDAT->idx; memmove(CURR_ODAT->name,CURR_CDAT->CURR_SET.CURR_ELE.name, 32); CURR_CDAT->CURR_SET.num_ele++; CURR_ODAT->cdat_idx = CURR_CDAT->idx; CURR_ODAT->refp = CURR_REF; if(ref_id == -1) /* user did not define a ref_id so */ { ref_id = ss_ref_id; ss_ref_id++; } CURR_REF->ref_id = ref_id; inc_odat(); inc_ref(); } void insert_framesheet ( char direction, char* name, uint64_t ref_id, int height , int width, int num_frames ) { CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].height = height; CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].width = width; CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames = num_frames; CURR_VDAT->num_models++; } void insert_quad ( int x, int y, int z, uint64_t ref_id ) #define CURR_QUAD (CURR_ODAT->quad_list[CURR_ODAT->num_quads]) { CURR_QUAD.x = x; CURR_QUAD.y = y; CURR_QUAD.z = z; CURR_QUAD.ref_id = ref_id; CURR_ODAT->num_quads++; } /* Inserting the hitbox into the set odat. Elements that don't have a hitbox will use the sets root. */ void insert_hitbox ( int hitbox ) { CURR_ODAT->hitbox = hitbox; } /* Inserting the root into the set odat. Elements that don't have a root will use the sets root. */ void insert_root ( int x, int y, int z ) { CURR_ODAT->root.x = x; CURR_ODAT->root.y = y; CURR_ODAT->root.z = z; } void insert_frame_pointer ( char direction, void* frame ) { CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].frames[CURR_VDAT->CURR_MODEL.spritesheet[(int)direction].num_frames++] = frame; }