BRIGGS_SET *briggsAlloc(int size) { BRIGGS_SET *p = oAlloc(sizeof(BRIGGS_SET)); p-> indexes = oAlloc(sizeof(*p->indexes) * size); p->data = oAlloc(sizeof(*p->data) * size); p->size = size ; return p; }
void insertDefines(QUAD *head, BLOCK *b, int tnum) { LIST *l = oAlloc(sizeof(LIST)); l->data = (void *)head; l->next = tempInfo[tnum]->idefines; tempInfo[tnum]->idefines = l; l = oAlloc(sizeof(LIST)); l->data = (void *)b; l->next = tempInfo[tnum]->bdefines; tempInfo[tnum]->bdefines = l; }
static int AllocTempOpt(int size1) { // int n = nextTemp; int t; int i; /* for (i= nextTemp; i < tempCount; i++) if (!tempInfo[i]->inUse && tempInfo[i]->enode) { EXPRESSION *rv = tempInfo[i]->enode; rv->v.sp->imvalue->size = size1; rv->v.sp->imind = NULL; memset(tempInfo[i], 0, sizeof(TEMP_INFO)); tempInfo[i]->enode = rv; t = i; break; } if (i == tempCount) { for (i=0; i < nextTemp; i++) if (!tempInfo[i]->inUse && tempInfo[i]->enode) { EXPRESSION *rv = tempInfo[i]->enode; rv->v.sp->imvalue->size = size1; rv->v.sp->imind = NULL; memset(tempInfo[i], 0, sizeof(TEMP_INFO)); tempInfo[i]->enode = rv; t = i; break; } if (i == nextTemp) {*/ IMODE *rv = tempreg(size1, FALSE); t = rv->offset->v.sp->value.i; if (t >= tempSize) { TEMP_INFO **temp = oAlloc((tempSize + 1000) * sizeof(TEMP_INFO *)); memcpy(temp, tempInfo, sizeof(TEMP_INFO *) * tempSize); tempSize += 1000; tempInfo = temp; } if (!tempInfo[t]) tempInfo[t] = (TEMP_INFO *)oAlloc(sizeof(TEMP_INFO)); tempInfo[t]->enode = rv->offset; // } // } nextTemp = t; tempInfo[t]-> partition = t; tempInfo[t]->color = -1; tempInfo[t]->inUse = TRUE; return t; }
/* finds all the successors to the loop */ static void CalculateSuccessors(LOOP *lp) { LIST *contains; contains = lp->contains; while(contains) { LOOP *current = (LOOP *)contains->data; if (lp->type != LT_BLOCK) CalculateSuccessors(current); contains = contains->next; } contains = lp->contains; while (contains) { LOOP *inner = (LOOP *)contains->data; if (inner->type == LT_BLOCK) { BLOCKLIST *bl = inner->entry->succ; while (bl) { BLOCKLIST *newExit = oAlloc(sizeof(BLOCKLIST)); newExit->next = lp->successors; lp->successors = newExit; newExit->block = bl->block; bl = bl->next; } } else { /* only have to add blocks that exited an inner loop * and only if they also exit this loop */ BLOCKLIST *prevSuccessors = inner->successors; while (prevSuccessors) { if (!briggsTest(inner->blocks, prevSuccessors->block->blocknum)) { BLOCKLIST *newExit = oAlloc(sizeof(BLOCKLIST)); newExit->next = lp->successors; lp->successors = newExit; newExit->block = prevSuccessors->block; } prevSuccessors = prevSuccessors->next; } } contains = contains->next; } }
/* insert on a flowgraph node */ static void flowinsert(BLOCKLIST **pos, BLOCK *valuesource) { BLOCKLIST *nblock = oAlloc(sizeof(BLOCKLIST)); nblock->next = (*pos); (*pos) = nblock; nblock->block = valuesource; }
static void FindLoop(BLOCK *b) { BLOCKLIST *loop = NULL; BLOCKLIST *bl; BLOCK *Z = b; bl = b->pred; while (bl) { if (getEdgeType(bl->block->blocknum, b->blocknum) == F_BACKEDGE) { Z = findCommonDominator(Z, bl->block); if (bl->block != b) // we don't care about duplicates, they will be filtered later { BLOCKLIST *bm = oAlloc(sizeof(BLOCKLIST)); bm->block = bl->block; bm->next = loop; loop = bm; } } bl = bl->next; } if (Z != b) { /* again we don't care about duplicates */ BLOCKLIST **bp = &Z->loopGenerators; while (*bp) bp = &(*bp)->next; (*bp) = loop; } else { FindBody(loop, b, LT_SINGLE); } }
/* add a thunk block to get us out of an infinite loop */ static void makeNonInfinite(BLOCK *b) { BLOCKLIST *bi = newBlock(), *bi2, **bt; QUAD *quad, *quad2; blockArray[bi->block->blocknum] = bi->block; bi->block->unuseThunk = TRUE; bi->block->succ = oAlloc(sizeof(BLOCKLIST)); bi->block->succ->block = blockArray[exitBlock]; bi->block->pred = oAlloc(sizeof(BLOCKLIST)); bi->block->pred->block = b; bt = &b->succ; while (*bt) bt = &(*bt)->next; *bt = bi; bi2 = oAlloc(sizeof(BLOCKLIST)); bi2->block = bi->block; bt = &blockArray[exitBlock]->pred; while (*bt) bt = &(*bt)->next; *bt = bi2; /* note : the following does NOT insert jmps for the * newly added block */ *criticalThunkPtr = quad = Alloc(sizeof(QUAD)); criticalThunkPtr = & quad->fwd; quad->dc.opcode = i_block; quad->block = bi->block; quad->dc.v.label = bi->block->blocknum; *criticalThunkPtr = quad2 = Alloc(sizeof(QUAD)); criticalThunkPtr = & quad2->fwd; quad2->back = quad; quad2->dc.opcode = i_blockend; quad2->block = bi->block; // quad2->dc.v.label = bi->block->blocknum; bi->block->head = quad; bi->block->tail = quad2; }
static void EnterRef(QUAD *old, QUAD *newVal) { struct reflist *newRef = oAlloc(sizeof(struct reflist)); newRef->old = old; newRef->newVal = newVal; newRef->next = refs; refs = newRef; }
void insertUses(QUAD *head, int dest) { LIST **l = & tempInfo[dest]->iuses; while (*l) { if ((*l)->data == (void *)head) return ; l = &(*l)->next; } *l = oAlloc(sizeof(LIST)); (*l)->data = (void *)head; }
/* we are also calculating the reverse postorder here * it will be needed later for the loop handling */ static void DominanceFrontier(BLOCK *b, int *count) { BLOCKLIST *c = b->dominates, *s; while (c) { DominanceFrontier(c->block, count); c = c->next; } b->reversePostOrder = (*count)++; s = b->succ; while (s) { if (s->block->idom != b->blocknum) { BLOCKLIST *t = oAlloc(sizeof(BLOCKLIST)); t->next = b->dominanceFrontier; t->block = s->block; b->dominanceFrontier = t; } s = s->next; } c = b->dominates; while (c) { BLOCKLIST *bl = c->block->dominanceFrontier; int i; while (bl) { if (!dominatedby(bl->block, b)) { BLOCKLIST *t = oAlloc(sizeof(BLOCKLIST)); t->next = b->dominanceFrontier; t->block = bl->block; b->dominanceFrontier = t; } bl = bl->next; } c = c->next; } }
static void basicFlowInfo(void) { QUAD *head = intermed_head, *block; int low = INT_MAX, high = 0; blockArray = oAlloc(sizeof(BLOCK *) * (blockCount + 1000)); while (head) { criticalThunks = intermed_head; if (head->dc.opcode == i_block) { if (!head->block->dead) blockArray[head->dc.v.label] = head->block ; } if (head->dc.opcode == i_label) { if (head->dc.v.label < low) low = head->dc.v.label; if (head->dc.v.label >= high) high = head->dc.v.label + 1; } head = head->fwd ; } labels = oAlloc(sizeof(BLOCK *) * (high - low)) ; firstLabel = low ; head = intermed_head; block = NULL; while (head) { if (head->dc.opcode == i_block) { block = head ; } if (head->dc.opcode == i_label) { labels[head->dc.v.label - firstLabel] = block->block ; /* the block num*/ } head = head->fwd ; } }
/* this returns a two-layer list * the top layer is a linked list of strong regions * each secondary layer is the induction set for the region * first element of list is the anchors */ static LIST *strongRegions(LOOP *lp, LIST **anchors) { int i; QUAD *head; LIST *rv = NULL; *anchors = NULL; strongStack = oAlloc(sizeof(unsigned short) *tempCount); max_dfs = 0; strongStackTop = 0; for (i=0; i < tempCount; i++) { tempInfo[i]->dfstOrder = 0; tempInfo[i]->visiteddfst = FALSE; tempInfo[i]->temp = INT_MAX; } head = lp->entry->head->fwd; while (head != lp->entry->tail->fwd && (head->ignoreMe || head->dc.opcode == i_label)) head = head->fwd; while (head != lp->entry->tail->fwd && head->dc.opcode == i_phi) { PHIDATA *pd = head->dc.v.phi; if (briggsTest(candidates, pd->T0) && tempInfo[pd->T0]->size < ISZ_FLOAT) { LIST *l1 = strongRegiondfs(pd->T0); if (l1) { l1->next = rv; rv = l1; } l1 = oAlloc(sizeof(LIST)); l1->data = (void *)pd->T0; l1->next = *anchors; *anchors = l1; } head = head->fwd; } return rv; }
static int gatherEdges(enum e_fgtype type, BLOCK *parent, BLOCK *in) { if (parent) { EDGE *edge = oAlloc(sizeof(EDGE)); int bucket = hashfunc(parent->blocknum, in->blocknum); edge->first = parent->blocknum; edge->second = in->blocknum; edge->edgetype = type; edge->next = edgeHash[bucket]; edgeHash[bucket] = edge; } return TRUE; }
void peep_icode(BOOLEAN branches) { int i; BOOLEAN changed; golist = oAlloc(sizeof(QUAD*)*(nextLabel - firstLabel)); scan_gotos(intermed_head); scan_abnormal(); for (i=0; i < blockCount; i++) if (blockArray[i]) blockArray[i]->visiteddfst = FALSE; do { changed = FALSE; for (i=0; i < blockCount; i++) if (blockArray[i]) changed |= peep(blockArray[i], branches); } while (changed); }
LIST *strongRegiondfs(int tnum) { TEMP_INFO *t = tempInfo[tnum]; INSTRUCTIONLIST *u = t->instructionUses; LIST *rv = NULL; t->temp = t->dfstOrder = max_dfs++; strongStack[strongStackTop++] = tnum; t->visiteddfst = TRUE; t->onstack = TRUE; while (u) { int ux = -1; switch (u->ins->dc.opcode) { case i_phi: { PHIDATA *pd = u->ins->dc.v.phi; if (tempInfo[pd->T0]->size < ISZ_FLOAT) ux = pd->T0; } break; case i_add: case i_sub: case i_assn: case i_neg: if (u->ins->temps & TEMP_ANS) { ux = u->ins->ans->offset->v.sp->value.i; if (tempInfo[ux]->size >= ISZ_FLOAT) ux = -1; } break; default: break; } if (ux >= 0) { TEMP_INFO *up = tempInfo[ux]; if (!up->visiteddfst) { LIST *l3 = strongRegiondfs(ux); if (up->temp < t->temp) t->temp = up->temp; if (l3) { l3->next = rv; rv = l3; } } else if (up->onstack) { if (up->dfstOrder < t->temp) t->temp = up->dfstOrder; } } u = u->next; } if (t->temp == t->dfstOrder) { int vp; LIST *region = NULL, *temp; do { vp = strongStack[--strongStackTop]; tempInfo[vp]->onstack = FALSE; temp = oAlloc(sizeof(LIST)); temp->data = (void *)vp; temp->next = region; region = temp; } while (vp != tnum); temp = oAlloc(sizeof(LIST)); temp->data = region; temp->next = rv; rv = temp; } return rv; }
BITARRAY *allocbit(int size) { BITARRAY *rv = oAlloc(sizeof(BITARRAY) - 1 + (size + (BITINTBITS-1))/BITINTBITS); rv->count = size; return rv; }
static void Dominators(void) { int w, i; domCount = 0; WalkFlowgraph(blockArray[0], domNumber, TRUE); vectorData = tAlloc(sizeof(struct _tarjan *) * (domCount + 1)); for (i=0; i <= domCount; i++) { vectorData[i] = tAlloc(sizeof(struct _tarjan)); vectorData[i]->bucket = briggsAlloct(domCount+1); } WalkFlowgraph(blockArray[0], domInit, TRUE); for (w = domCount; w>=2; w--) { int p = vectorData[w]->parent; int j; struct _tarjan *v = vectorData[w]; BLOCKLIST *bl = v->preds; while (bl) { int u = domEval(bl->block->dfstOrder); if (vectorData[w]->semi > vectorData[u]->semi) vectorData[w]->semi = vectorData[u]->semi; bl = bl->next; } briggsSet(vectorData[vectorData[w]->semi]->bucket, w); domLink(p, w); for (j = vectorData[p]->bucket->top -1 ; j >= 0; j--) { int v = vectorData[p]->bucket->data[j]; int u = domEval(v); if (vectorData[u]->semi >= p) vectorData[v]->idom = p; else vectorData[v]->idom = u; } briggsClear(vectorData[p]->bucket); } for (w=2; w <=domCount; w++) { if (vectorData[w]->idom != vectorData[w]->semi) { vectorData[w]->idom = vectorData[vectorData[w]->idom]->idom; } /* transfer idom to our block struct */ blockArray[vectorData[w]->blocknum]->idom = vectorData[vectorData[w]->idom]->blocknum; } /* now make the forward tree */ for (i=blockCount-1; i >=1; i--) { /* make dominates lists by walking the idom tree backwards from each node*/ if (blockArray[i] && blockArray[i]->pred) { int w = blockArray[i]->idom; BLOCK *ub = blockArray[w]; BLOCKLIST *bl = oAlloc(sizeof(BLOCKLIST)); bl->block = blockArray[i]; bl->next = ub->dominates; ub->dominates = bl; } } tFree(); }
/* not even thinking about assert() or longjmp() */ static int RemoveCriticalEdges(enum e_fgtype type, BLOCK *parent, BLOCK *in) { (void)parent; if (type == F_TREE) { BLOCKLIST *f = in->succ; if (f && f->next) { while (f) { BLOCKLIST *b = f->block->pred; if (b && b->next) { /* critical edge, we need to insert something... */ /* we won't need to revist this so we don't care what * it does to the presetn tree walk */ BLOCKLIST *m = newBlock(); BLOCKLIST *q ; QUAD *quad, *quad2; m->block->critical = TRUE; /* note : the following does NOT insert jmps for the * newly added block */ *criticalThunkPtr = quad = Alloc(sizeof(QUAD)); criticalThunkPtr = & quad->fwd; quad->dc.opcode = i_block; quad->block = m->block; quad->dc.v.label = m->block->blocknum; *criticalThunkPtr = quad2 = Alloc(sizeof(QUAD)); criticalThunkPtr = & quad2->fwd; quad2->back = quad; quad2->dc.opcode = i_blockend; quad2->block = m->block; // quad2->dc.v.label = m->block->blocknum; m->block->head = quad; m->block->tail = quad2; q = oAlloc(sizeof(BLOCKLIST)); q->block = in; m->block->pred = q; q = oAlloc(sizeof(BLOCKLIST)); q->block = f->block; m->block->succ = q; f->block = m->block; q = b; while (q) { if (q->block->blocknum == in->blocknum) { q->block = m->block; break; } q = q->next; } } f = f->next; } } } return TRUE; }
static void InitTempInfo(void) { QUAD *head = intermed_head; int i; nextTemp = tempCount; tempSize = tempCount + 1000; tempInfo = (TEMP_INFO **)oAlloc(sizeof(TEMP_INFO *) * (tempSize)); for (i=0; i < tempCount; i++) { tempInfo[i] = oAlloc(sizeof(TEMP_INFO)); tempInfo[i]-> partition = i; tempInfo[i]->color = -1; tempInfo[i]->inUse = TRUE; } while (head) { head->temps = 0; if (head->dc.opcode != i_block && !head->ignoreMe && head->dc.opcode != i_passthrough && head->dc.opcode != i_label) { if (head->ans && (head->ans->mode == i_ind || head->ans->mode == i_direct)) { if (head->ans->offset->type == en_tempref) { int tnum = head->ans->offset->v.sp->value.i; if (!head->ans->retval) head->temps |= TEMP_ANS; tempInfo[tnum]->enode = head->ans->offset; tempInfo[tnum]->size = head->ans->offset->v.sp->imvalue->size; if (tempInfo[tnum]->size < 0) tempInfo[tnum]->size = - tempInfo[tnum]->size; if (tempInfo[tnum]->size == ISZ_UINT) tempInfo[tnum]->size = chosenAssembler->arch->compatibleIntSize; if (tempInfo[tnum]->size == ISZ_ADDR) { tempInfo[tnum]->usedAsAddress = TRUE; tempInfo[tnum]->size = chosenAssembler->arch->compatibleAddrSize; } if (tempInfo[tnum]->size >= ISZ_FLOAT) tempInfo[tnum]->usedAsFloat = TRUE; } } if (head->dc.left && (head->dc.left->mode == i_ind || head->dc.left->mode == i_direct)) { if (head->dc.left->offset->type == en_tempref) { int tnum = head->dc.left->offset->v.sp->value.i; if (!head->dc.left->retval) head->temps |= TEMP_LEFT; tempInfo[tnum]->enode = head->dc.left->offset; tempInfo[tnum]->size = head->dc.left->offset->v.sp->imvalue->size; if (tempInfo[tnum]->size < 0) tempInfo[tnum]->size = - tempInfo[tnum]->size; if (tempInfo[tnum]->size == ISZ_UINT) tempInfo[tnum]->size = chosenAssembler->arch->compatibleIntSize; if (tempInfo[tnum]->size == ISZ_ADDR) { tempInfo[tnum]->usedAsAddress = TRUE; tempInfo[tnum]->size = chosenAssembler->arch->compatibleAddrSize; } if (tempInfo[tnum]->size >= ISZ_FLOAT) tempInfo[tnum]->usedAsFloat = TRUE; } } if (head->dc.right && (head->dc.right->mode == i_ind || head->dc.right->mode == i_direct)) { if (head->dc.right->offset->type == en_tempref) { int tnum = head->dc.right->offset->v.sp->value.i; if (!head->dc.right->retval) head->temps |= TEMP_RIGHT; tempInfo[tnum]->enode = head->dc.right->offset; tempInfo[tnum]->size = head->dc.right->offset->v.sp->imvalue->size; if (tempInfo[tnum]->size < 0) tempInfo[tnum]->size = - tempInfo[tnum]->size; if (tempInfo[tnum]->size == ISZ_UINT) tempInfo[tnum]->size = chosenAssembler->arch->compatibleIntSize; if (tempInfo[tnum]->size == ISZ_ADDR) { tempInfo[tnum]->usedAsAddress = TRUE; tempInfo[tnum]->size = chosenAssembler->arch->compatibleAddrSize; } if (tempInfo[tnum]->size >= ISZ_FLOAT) tempInfo[tnum]->usedAsFloat = TRUE; } } } head = head->fwd ; } }
void doms_only(BOOL always) { int dfsCount = 0; int i; int n = blockCount; (void)always; if (always) { criticalThunks = NULL; criticalThunkPtr = &criticalThunks; } WalkFlowgraph(blockArray[0], RemoveCriticalEdges, TRUE); if (blockCount != n) { QUAD *head = intermed_head; blockArray = oAlloc(sizeof(BLOCK *) * (blockCount + 1000)); // fixme... while (head) { if (head->dc.opcode == i_block) { blockArray[head->dc.v.label] = head->block ; } head = head->fwd ; } head = criticalThunks; while (head) { if (head->dc.opcode == i_block) { blockArray[head->dc.v.label] = head->block ; } head = head->fwd ; } *criticalThunkPtr = Alloc(sizeof(QUAD)); (*criticalThunkPtr)->dc.opcode = i_label; (*criticalThunkPtr)->dc.v.label = -1; criticalThunkPtr = (QUAD **)*criticalThunkPtr; } CancelInfinite(blockCount); for (i=1; i < blockCount; i++) { if (blockArray[i]) { removeDeadBlock(blockArray[i]); blockArray[i]->idom = 0; blockArray[i]->dominates = NULL; } } Dominators(); PostDominators(); for (i=0; i < blockCount; i++) { if (blockArray[i]) { blockArray[i]->visiteddfst = blockArray[i]->pred != NULL; blockArray[i]->dominanceFrontier = NULL; } } DominanceFrontier(blockArray[0], &dfsCount); CalculateEdges(blockArray[0]); BuildLoopTree(); }
void CalculateInduction(void) { int i; inductionCandidateStack = oAlloc(sizeof(unsigned short) * tempCount); candidates = briggsAlloc(tempCount); CalculateLoopInvariants(blockArray[0]); for (i=0; i < loopCount; i++) { LOOP *lp = loopArray[i]; if (lp && lp->type == LT_SINGLE) { LIST *strongTemps; LIST *anchors = NULL; CalculateInductionCandidates(lp); strongTemps = strongRegions(lp, &anchors); if (strongTemps && anchors) { LIST *regions = strongTemps; while (regions) { LIST *r = (LIST *)regions->data; if (r->next) { LIST *t = anchors; while (t) { while (r) { if (t->data == r->data) break; r = r->next; } if (!r || t->data == r->data) break; t = t->next; } if (t || r) { INDUCTION_LIST *temp = oAlloc(sizeof(INDUCTION_LIST)); LIST *q; temp->vars = regions->data; temp->next = lp->inductionSets; lp->inductionSets = temp; q = regions->data; while (q) { /* the dominator walk will visit inner loops first, * the outer loops have higher indexes * we want the outermost loop */ tempInfo[(int)q->data]->inductionLoop = max(i, tempInfo[(int)q->data]->inductionLoop); q = q->next; } } } regions = regions->next; } } } } }
void BuildLoopTree(void) { BLOCKLIST bl; BLOCK *b; int i; QUAD *tail; BOOL skip = FALSE; /* this is padded, but, in a really really complex program it could get to be too small */ loopArray = oAlloc(sizeof(LOOP *) * blockCount * 4); loopItems = briggsAlloc((blockCount) * 4); loopCount = 0; for (i=0; i < blockCount; i++) { if (blockArray[i]) { blockArray[i]->visiteddfst = FALSE; blockArray[i]->loopParent = NULL; blockArray[i]->loopName = oAlloc(sizeof(LOOP)); blockArray[i]->loopName->type = LT_BLOCK; blockArray[i]->loopName->entry = blockArray[i]; blockArray[i]->loopName->loopnum = loopCount; blockArray[i]->loopGenerators = NULL; loopArray[loopCount++] = blockArray[i]->loopName; } // else // loopCount++; } Loop(blockArray[0]); // CalculateSuccessors(loopArray[loopCount-1]); memset(&bl, 0, sizeof(bl)); bl.block = blockArray[exitBlock]; FindBody(&bl, blockArray[0], LT_ROOT); CalculateLoopedBlocks(loopArray[loopCount-1]); if (cparams.prm_icdfile) { fprintf(icdFile, "; loop dump\n"); dump_loops(); } tail = intermed_tail; b = tail->block; while (tail) { switch(tail->dc.opcode) { case i_skipcompare: skip = !skip; break; case i_block: b = tail->block; break; } if (tail->block) { if (skip) { tail->block->inclusiveLoopParent = b->loopParent; } else { tail->block->inclusiveLoopParent = tail->block->loopParent; } } tail = tail->back; } if (loopCount >= blockCount * 4) fatal("internal error"); }
static void FindBody(BLOCKLIST *gen, BLOCK *head, enum e_lt type) { LIST *queue = NULL, **qx; LOOP *lp, **lpp ; int i; if (!gen) return; briggsClear(loopItems); while (gen) { LOOP *l = LoopAncestor(gen->block); if (l && !briggsTest(loopItems, l->loopnum)) { LIST *bl = oAlloc(sizeof(LIST)); bl->data = l; bl->next = queue; queue = bl; briggsSet(loopItems, l->loopnum); } gen = gen->next; } while (queue) { if (((LOOP *)queue->data)->entry) { BLOCKLIST *p = ((LOOP *)queue->data)->entry->pred; queue = queue->next; while (p) { if (p->block != head) { LOOP *l = LoopAncestor(p->block); if (l && !briggsTest(loopItems, l->loopnum)) { LIST *bl = oAlloc(sizeof(LIST)); bl->data = l; bl->next = queue; queue = bl; briggsSet(loopItems, l->loopnum); } } p = p->next; } } else queue = queue->next; } lp = oAlloc(sizeof(LOOP)); loopArray[loopCount] = lp; lp->type = type; lp->loopnum = loopCount++; lp->entry = head; lp->parent = NULL; head->loopParent = lp; qx = &lp->contains; *qx = oAlloc(sizeof(LIST)); (*qx)->data = head->loopName; qx = &(*qx)->next; for (i=0; i < loopItems->top; i++) { LIST *l = oAlloc(sizeof(LIST)); int n = loopItems->data[i]; l->data = loopArray[n]; *qx = l; qx = &(*qx)->next; if (loopArray[n]->type == LT_BLOCK) loopArray[n]->entry->loopParent = lp; else loopArray[n]->parent = lp; } }