static ALIASADDRESS *LookupAddress(ALIASNAME *name, int offset) { int str[(sizeof(ALIASNAME *) + sizeof(int))/sizeof(int)]; int hash; ALIASADDRESS *addr, **search; IMODE *im; LIST *li; str[0] = offset; *((ALIASNAME **)(str + 1)) = name; hash = dhash((UBYTE *)str, sizeof(str)); search = &addresses[hash]; while (*search) { if ((*search)->name == name && (*search)->offset == offset) return (*search); search = &(*search)->next; } addr = (*search) = aAlloc(sizeof(ALIASADDRESS)); addr->name = name; addr->offset = offset; if (addr->name->byUIV) { im = addr->name->v.uiv->im; } else { im = addr->name->v.name; } switch (im->offset->type) { case en_auto: // if (im->offset->v.sp->storage_class != sc_parameter) break; case en_global: { ALIASLIST *l = aAlloc(sizeof(ALIASLIST)); l->address = addr; AliasUnion(&parmList, l); } break; default: break; } li = aAlloc(sizeof(LIST)); li->data = addr; li->next = name->addresses; name->addresses = li; return addr; }
static void AliasUnion(ALIASLIST **dest, ALIASLIST *src) { while (src) { ALIASLIST **q = dest; while (*q) { ALIASNAME *nm1 = (*q)->address->name, *nm2 = src->address->name; IMODE *im1, *im2; // we don't check the offset here because of the rule if the same // name is used with different offsets it is assumed to be an array. if (nm1 == nm2) break; if (nm1->byUIV) im1 = nm1->v.uiv->im; else im1 = nm1->v.name; if (nm2->byUIV) im2 = nm2->v.uiv->im; else im2 = nm2->v.name; if (im1 == im2) break; q = &(*q)->next; } if (!*q) { ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = src->address; *q = al; changed = TRUE; } src = src->next; } }
static void CreateMem(IMODE *im) { ALIASNAME *p; if (im->offset->type != en_pc && im->offset->type != en_sub) { if (im->mode == i_immed) { p = LookupMem(im->offset->v.sp->imvalue); } else { ALIASADDRESS *aa; p = LookupMem(im); p = LookupAliasName(p, 0); } if (im->size == ISZ_ADDR || im->offset->type == en_label || im->offset->type == en_global) { ALIASADDRESS *aa; aa = LookupAddress(p, 0); if (!aa->pointsto) { ALIASNAME *an = LookupAliasName(p, 0); aa->pointsto = aAlloc(sizeof(ALIASLIST)); aa->pointsto->address = LookupAddress(an, 0); } } } }
static void AliasUnion(ALIASLIST **dest, ALIASLIST *src) { while (src) { ALIASLIST **q = dest; while (*q) { // we don't check the offset here because of the rule if the same // name is used with different offsets it is assumed to be an array. if ((*q)->address->name == src->address->name) break; if (samebase((*q)->address->name, src->address->name)) break; q = &(*q)->next; } if (!*q) { ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = src->address; *q = al; changed = TRUE; } src = src->next; } }
static ALIASNAME *LookupMem(IMODE *im) { ALIASNAME **p; int hash ; switch (im->offset->type) { case en_global: case en_label: case en_pc: case en_auto: case en_threadlocal: if (im->offset->v.sp->imvalue) im = im->offset->v.sp->imvalue; break; default: break; } hash = dhash((UBYTE *)&im, sizeof(im)); p = &mem[hash]; while (*p) { if (((*p)->byUIV == FALSE && (*p)->v.name == im) || ((*p)->byUIV == TRUE && (*p)->v.uiv->im == im && (*p)->v.uiv->offset == NULL)) { return *p; } p = &(*p)->next; } *p = aAlloc(sizeof(ALIASNAME)); (*p)->v.name = im; switch(im->offset->type) { case en_auto: case en_label: case en_global: (*p)->v.uiv = aAlloc(sizeof(UIV)); (*p)->v.uiv->im = im; (*p)->byUIV = TRUE; break; default: break; } return *p; }
static void HandleParm(QUAD *head) { if (head->dc.left->size == ISZ_ADDR) { // temp, mem ALIASLIST *result = NULL, **base = NULL, *addr; if (head->temps & TEMP_LEFT) { base = &tempInfo[head->dc.left->offset->v.sp->value.i]->pointsto; } else if (!isintconst(head->dc.left->offset)) { ALIASNAME *an; ALIASADDRESS *aa; switch (head->dc.left->offset->type) { case en_labcon: case en_global: case en_label: case en_pc: case en_threadlocal: return; default: break; } an = LookupMem(head->dc.left->offset->v.sp->imvalue); if (head->dc.left->mode == i_direct) an = LookupAliasName(an, 0); aa = LookupAddress(an, 0); base = &aa->pointsto; } if (base) { addr = *base; AliasUnionParm(&parmList, (*base)); while (addr) { if (addr->address->name->byUIV) { if (!IntersectsUIV(addr->address->pointsto)) { ALIASNAME *an = LookupAliasName(addr->address->name, 0); ALIASADDRESS *aa = LookupAddress(an, 0); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa; AliasUnion(&addr->address->pointsto, al); } } addr = addr->next; } } } }
static ALIASNAME *LookupAliasName(ALIASNAME *name, int offset) { int str[(sizeof(ALIASNAME *) + sizeof(int))/sizeof(int)]; int hash; ALIASNAME *result; struct UIVHash **uivs; str[0] = offset; *((ALIASNAME **)(str + 1)) = name; hash = dhash((UBYTE *)str, sizeof(str)); uivs = &names[hash]; while (*uivs) { if ((*uivs)->name == name && (*uivs)->offset == offset) return (*uivs)->result; uivs = &(*uivs)->next; } *uivs = aAlloc(sizeof(struct UIVHash)); (*uivs)->name = name; (*uivs)->offset = offset; result = aAlloc(sizeof(ALIASNAME)); result->byUIV = TRUE; result->v.uiv = aAlloc(sizeof(UIV)); if (name->byUIV) { *result->v.uiv = *name->v.uiv; result->v.uiv->alias = NULL; } else { result->v.uiv->im = name->v.name; } result->v.uiv->offset = aAlloc(sizeof(struct UIVOffset)); result->v.uiv->offset->offset = offset; if (name->byUIV) result->v.uiv->offset->next = name->v.uiv->offset; (*uivs)->result = result; return result; }
static void Infer(IMODE *ans, IMODE *reg, ALIASLIST *pointsto) { if (pointsto) { ALIASLIST *result = NULL; int c = InferOffset(reg); int l = InferStride(reg); BOOL xchanged = changed; while (pointsto) { ALIASADDRESS *addr = LookupAddress(pointsto->address->name, pointsto->address->offset + c); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = addr; AliasUnion(&result, al); SetStride(pointsto->address, l); pointsto = pointsto->next; } changed = xchanged; AliasUnion(&tempInfo[ans->offset->v.sp->value.i]->pointsto, result); } }
static void CreateMem(IMODE *im) { ALIASNAME *p; if (im->offset->type != en_pc && im->offset->type != en_sub) { if (im->mode == i_immed) { if (!im->offset->v.sp->imvalue) { // make one in the case of global addresses that aren't used // directly IMODE *ap2 = (IMODE *)Alloc(sizeof(IMODE)); ap2->offset = im->offset; ap2->mode = i_direct; ap2->size = ISZ_ADDR; im->offset->v.sp->imvalue = ap2; } p = LookupMem(im->offset->v.sp->imvalue); } else { ALIASADDRESS *aa; p = LookupMem(im); p = LookupAliasName(p, 0); } if (im->size == ISZ_ADDR || im->offset->type == en_label || im->offset->type == en_global) { ALIASADDRESS *aa; aa = LookupAddress(p, 0); if (!aa->pointsto) { ALIASNAME *an = LookupAliasName(p, 0); aa->pointsto = aAlloc(sizeof(ALIASLIST)); aa->pointsto->address = LookupAddress(an, 0); } } } }
BITARRAY *aallocbit(int size) { BITARRAY *rv = aAlloc(sizeof(BITARRAY) - 1 + (size + (BITINTBITS-1))/BITINTBITS * sizeof(BITINT)); rv->count = size; return rv; }
static void HandleAdd(QUAD *head) { if ((head->ans->size == ISZ_ADDR) && (head->temps & TEMP_ANS)) { if (head->dc.opcode == i_add && head->dc.left->mode == i_immed) { if (head->temps & TEMP_RIGHT) { if (isintconst(head->dc.left->offset)) { // C + R ALIASLIST *scan = tempInfo[head->dc.right->offset->v.sp->value.i]->pointsto; ALIASLIST *result = NULL; BOOLEAN xchanged = changed; while (scan) { ALIASADDRESS *addr = LookupAddress(scan->address->name, scan->address->offset + head->dc.left->offset->v.i); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = addr; AliasUnion(&result, al); scan = scan->next; } changed = xchanged; AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, result); } else { // p + R if (head->dc.left->offset->type != en_labcon) // needed for exports { ALIASNAME *nm = LookupMem(head->dc.left->offset->v.sp->imvalue); ALIASADDRESS *aa = LookupAddress(nm, 0); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa; Infer(head->ans, head->dc.right, al); } } } else if (head->dc.right->mode == i_immed) { if (!isintconst(head->dc.left->offset) && head->dc.left->offset->type != en_labcon) { // p + C ALIASNAME *nm = LookupMem(head->dc.left->offset->v.sp->imvalue); ALIASADDRESS *aa = LookupAddress(nm, head->dc.right->offset->v.i); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa; AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto,al); } else if (!isintconst(head->dc.right->offset) && head->dc.right->offset->type != en_labcon) { // C + p ALIASNAME *nm = LookupMem(head->dc.right->offset->v.sp->imvalue); ALIASADDRESS *aa = LookupAddress(nm, head->dc.left->offset->v.i); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa; AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, al); } } } else if (head->dc.right->mode == i_immed) { if (head->temps & TEMP_LEFT) { if (isintconst(head->dc.right->offset)) { // R+C int c = head->dc.opcode == i_add ? head->dc.right->offset->v.i : -head->dc.right->offset->v.i; ALIASLIST *scan = tempInfo[head->dc.left->offset->v.sp->value.i]->pointsto; ALIASLIST *result = NULL; BOOLEAN xchanged = changed; while (scan) { ALIASADDRESS *addr = LookupAddress(scan->address->name, scan->address->offset + c); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = addr; AliasUnion(&result, al); scan = scan->next; } changed = xchanged; AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, result); } else { // R + p if (head->dc.right->offset->type != en_labcon) // needed for exports { ALIASNAME *nm = LookupMem(head->dc.right->offset->v.sp->imvalue); ALIASADDRESS *aa = LookupAddress(nm, 0); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa; Infer(head->ans, head->dc.left, al); } } } } else if ((head ->temps & (TEMP_LEFT | TEMP_RIGHT)) == (TEMP_LEFT | TEMP_RIGHT)) { // R+R ALIASLIST *src; IMODE *one = head->dc.left; IMODE *two = head->dc.right; if (two->size == ISZ_ADDR) { IMODE *three = one; one = two; two = three; } if (one->size == ISZ_ADDR) { // now one has the pointer, two has something else src = tempInfo[one->offset->v.sp->value.i]->pointsto; Infer(head->ans, two, src); } } } }
static void HandleAssn(QUAD *head) { if (head->ans == head->dc.left) return; if (head->ans->mode == i_ind) { if (head->temps & TEMP_LEFT) { // ind, temp ALIASLIST *addr; ALIASLIST *src = tempInfo[head->dc.left->offset->v.sp->value.i]->pointsto; addr = tempInfo[head->ans->offset->v.sp->value.i]->pointsto; while (addr) { AliasUnion(&addr->address->pointsto, src); addr = addr->next; } } else if (head->dc.left->mode == i_immed && head->dc.left->size == ISZ_ADDR && head->dc.left->offset->type != en_labcon ) { // ind, immed ALIASLIST *addr; ALIASNAME *an = LookupMem(head->ans->offset->v.sp->imvalue); ALIASADDRESS *aa; if (head->ans->mode == i_direct) an = LookupAliasName(an, 0); aa = LookupAddress(an, 0); addr = tempInfo[head->ans->offset->v.sp->value.i]->pointsto; while (addr) { AliasUnion(&addr->address->pointsto, aa->pointsto); addr = addr->next; } } } else if (head->dc.left->mode == i_ind && (head->temps & TEMP_ANS)) { // temp, ind ALIASLIST *result = NULL; ALIASLIST *addr = tempInfo[head->dc.left->offset->v.sp->value.i]->pointsto; BOOLEAN xchanged = changed; while (addr) { if (addr->address->name->byUIV) { if (!IntersectsUIV(addr->address->pointsto)) { ALIASNAME *an = LookupAliasName(addr->address->name, addr->address->offset); ALIASADDRESS *aa = LookupAddress(an, 0); ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa; AliasUnion(&addr->address->pointsto, al); } } AliasUnion(&result, addr->address->pointsto); addr = addr->next; } changed = xchanged; tempInfo[head->ans->offset->v.sp->value.i]->pointsto = result; } else if (head->ans->size == ISZ_ADDR) { if (!(head->temps & TEMP_ANS) && !head->ans->retval) { if (head->temps & TEMP_LEFT) { // mem, temp ALIASLIST *al; ALIASNAME *an = LookupMem(head->ans); ALIASADDRESS *aa; an = LookupAliasName(an, 0); aa = LookupAddress(an, 0); AliasUnion(&aa->pointsto, tempInfo[head->dc.left->offset->v.sp->value.i]->pointsto); } else if (head->dc.left->mode == i_immed && head->dc.left->size == ISZ_ADDR && head->dc.left->offset->type != en_labcon ) { // mem, immed ALIASNAME *an2 = LookupMem(head->dc.left); ALIASADDRESS *aa2 = LookupAddress(an2, 0); ALIASNAME *an = LookupMem(head->ans->offset->v.sp->imvalue); ALIASADDRESS *aa; ALIASLIST *al = aAlloc(sizeof(ALIASLIST)); al->address = aa2; if (head->ans->mode == i_direct) an = LookupAliasName(an, 0); aa = LookupAddress(an, 0); AliasUnion(&aa->pointsto, al); } } else if (head->temps & TEMP_ANS) { if (head->dc.left->mode == i_immed && head->dc.left->size == ISZ_ADDR && head->dc.left->offset->type != en_labcon&& !isintconst(head->dc.left->offset) ) { // temp, immed BOOLEAN xchanged = changed; ALIASNAME *an = LookupMem(head->dc.left); ALIASADDRESS *aa = LookupAddress(an, 0); ALIASLIST *al = (ALIASLIST *)aAlloc(sizeof(ALIASLIST)); al->address = aa; tempInfo[head->ans->offset->v.sp->value.i]->pointsto = NULL; AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, al); changed = xchanged; } else if (head->dc.left->retval) { AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, parmList); } else if (!(head->temps & TEMP_LEFT) && head->dc.left->mode == i_direct) { // temp, mem ALIASLIST *result = NULL; ALIASNAME *an = LookupMem(head->dc.left); ALIASADDRESS *aa; ALIASLIST *addr; BOOLEAN xchanged = changed; an = LookupAliasName(an, 0); aa = LookupAddress(an, 0); AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, aa->pointsto); changed = xchanged; } else if (head->temps & TEMP_LEFT) { // temp, temp AliasUnion(&tempInfo[head->ans->offset->v.sp->value.i]->pointsto, tempInfo[head->dc.left->offset->v.sp->value.i]->pointsto); } } } }