static bool next_rec(Trie *t, const char **pkey, size_t *plen, void **pval) { if(isbranch(t)) { // Recurse to find either this leaf (*pkey != NULL) // or the next one (*pkey == NULL). Tbitmap b = twigbit(t, *pkey, *plen); uint s, m; TWIGOFFMAX(s, m, t, b); for(; s < m; s++) if(next_rec(twig(t, s), pkey, plen, pval)) return(true); return(false); } // We have found the next leaf. if(*pkey == NULL) { *pkey = t->leaf.key; *plen = strlen(*pkey); *pval = t->leaf.val; return(true); } // We have found this leaf, so start looking for the next one. if(strcmp(*pkey, t->leaf.key) == 0) { *pkey = NULL; *plen = 0; return(false); } // No match. return(false); }
static int ckfpuse(Prog *p, Prog *ct, Sym *fp, Sym *r) { int reg; USED(fp); USED(ct); if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){ reg = p->to.reg; for(p = p->link; p != P && p->as != ATEXT; p = p->link){ if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg) return 1; if(!debug['F'] && (isbranch(p) || p->as == ARET)){ // print("%s: branch %P in %s\n", fp->name, p, ct->from.sym->name); return 0; } if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){ if(!debug['F'] && p->to.type != D_REG){ // print("%s: store %P in %s\n", fp->name, p, ct->from.sym->name); return 0; } reg = p->to.reg; } } } // print("%s: no MOVW O(R), R\n", fp->name); return debug['F']; }
stringbuf& operator <<(stringbuf& sb, const TransOpBase& op) { static const char* size_names[4] = {"b", "w", "d", ""}; // e.g. addfp, addfv, addfd, xxx static const char* fptype_names[4] = {".s", ".vs", ".d", ".d"}; bool ld = isload(op.opcode); bool st = isstore(op.opcode); bool fp = (isclass(op.opcode, OPCLASS_FP_ALU)); bool br = isbranch(op.opcode); stringbuf sbname; sbname << nameof(op.opcode); if (!(opinfo[op.opcode].flagops & opNOSIZE)) sbname << (fp ? fptype_names[op.size] : size_names[op.size]); if (isclass(op.opcode, OPCLASS_USECOND)) sbname << ".", cond_code_names[op.cond]; if (ld|st) { if (op.opcode == OP_mf) { static const char* mf_names[4] = {"none", "st", "ld", "all"}; sbname << '.', mf_names[op.extshift]; } sbname << ((op.cond == LDST_ALIGN_LO) ? ".lo" : (op.cond == LDST_ALIGN_HI) ? ".hi" : ""); } else if ((op.opcode == OP_mask) || (op.opcode == OP_maskb)) { sbname << ((op.cond == 0) ? "" : (op.cond == 1) ? ".z" : (op.cond == 2) ? ".x" : ".???"); } if ((ld|st) && (op.cachelevel > 0)) sbname << ".L", (char)('1' + op.cachelevel); if ((ld|st) && (op.locked)) sbname << ((ld) ? ".acq" : ".rel"); if (op.internal) sbname << ".p"; if (op.eom) sbname << ".", (op.any_flags_in_insn ? "+" : "-"); sb << padstring((char*)sbname, -12), " ", arch_reg_names[op.rd]; if ((op.rd < ARCHREG_COUNT) & (!op.final_arch_in_insn)) sb << ".t"; sb << " = "; if (ld|st) sb << "["; sb << arch_reg_names[op.ra]; if (op.rb == REG_imm) { if (abs(op.rbimm) <= 32768) sb << ",", op.rbimm; else sb << ",", (void*)op.rbimm; } else { sb << ",", arch_reg_names[op.rb]; } if (ld|st) sb << "]"; if ((op.opcode == OP_mask) | (op.opcode == OP_maskb)) { MaskControlInfo mci(op.rcimm); int sh = (op.opcode == OP_maskb) ? 3 : 0; sb << ",[ms=", (mci.info.ms >> sh), " mc=", (mci.info.mc >> sh), " ds=", (mci.info.ds >> sh), "]"; } else {
static void size_rec(Trie *t, uint d, size_t *rsize, size_t *rdepth, size_t *rleaves) { *rsize += sizeof(*t); if(isbranch(t)) { for(uint i = 0; i < 64; i++) { uint64_t b = twigbit(i); if(hastwig(t, b)) size_rec(twig(t, twigoff(t, b)), d+1, rsize, rdepth, rleaves); } } else { *rdepth += d; *rleaves += 1; } }
bool Tgetkv(Tbl *tbl, const char *key, size_t len, const char **pkey, void **pval) { if(tbl == NULL) return(false); Trie *t = &tbl->root; while(isbranch(t)) { __builtin_prefetch(t->branch.twigs); Tbitmap b = twigbit(t, key, len); if(!hastwig(t, b)) return(false); t = twig(t, twigoff(t, b)); } if(strcmp(key, t->leaf.key) != 0) return(false); *pkey = t->leaf.key; *pval = t->leaf.val; return(true); }
static void dump_rec(Trie *t, int d) { if(isbranch(t)) { printf("Tdump%*s branch %p\n", d, "", t); for(uint i = 0; i < 64; i++) { uint64_t b = twigbit(i); if(hastwig(t, b)) { printf("Tdump%*s twig %d\n", d, "", i); dump_rec(twig(t, twigoff(t, b)), d+1); } } } else { printf("Tdump%*s leaf %p\n", d, "", t); printf("Tdump%*s leaf key %p %s\n", d, "", t->leaf.key, t->leaf.key); printf("Tdump%*s leaf val %p\n", d, "", t->leaf.val); } }
/* Partition quadruples into basic blocks. */ void partition(context* ctx, intermediate* icode) { int i; for (i=0; i<icode->nextslot; i++) icode->quadruples[i].isleader = 0; for (i=0; i<ctx->sbt.nextslot; i++) /* first statement is leader */ if (ctx->sbt.table[i].isfunction) icode->quadruples[ctx->sbt.table[i].firstquad].isleader = 1; for (i=0; i<icode->nextslot; i++) { if (isbranch(&icode->quadruples[i])) /* branch target is leader */ icode->quadruples[icode->quadruples[i].opdest.entity.entity.ival].isleader = 1; /* branch follower is leader */ if (isbbranch(&icode->quadruples[i]) && i+1<icode->nextslot) { icode->quadruples[i].isleader = 1; icode->quadruples[i+1].isleader = 1; } } }
Tbl * Tdelkv(Tbl *tbl, const char *key, size_t len, const char **pkey, void **pval) { if(tbl == NULL) return(NULL); Trie *t = &tbl->root, *p = NULL; Tbitmap b = 0; while(isbranch(t)) { __builtin_prefetch(t->branch.twigs); b = twigbit(t, key, len); if(!hastwig(t, b)) return(tbl); p = t; t = twig(t, twigoff(t, b)); } if(strcmp(key, t->leaf.key) != 0) return(tbl); *pkey = t->leaf.key; *pval = t->leaf.val; if(p == NULL) { free(tbl); return(NULL); } t = p; p = NULL; // Becuase t is the usual name uint s, m; TWIGOFFMAX(s, m, t, b); if(m == 2) { // Move the other twig to the parent branch. Trie *twigs = t->branch.twigs; *t = *twig(t, !s); free(twigs); return(tbl); } memmove(t->branch.twigs+s, t->branch.twigs+s+1, sizeof(Trie) * (m - s - 1)); t->branch.bitmap &= ~b; // We have now correctly removed the twig from the trie, so if // realloc() fails we can ignore it and continue to use the // slightly oversized twig array. Trie *twigs = realloc(t->branch.twigs, sizeof(Trie) * (m - 1)); if(twigs != NULL) t->branch.twigs = twigs; return(tbl); }
static void setfpuse(Prog *p, Sym *fp, Sym *r) { int reg; if(p->from.sym == r && p->as == AMOVW && (p->from.type == D_CONST || p->from.type == D_OREG) && p->reg == NREG && p->to.type == D_REG){ reg = p->to.reg; for(p = p->link; p != P && p->as != ATEXT; p = p->link){ if((p->as == ABL || p->as == ABX) && p->to.type == D_OREG && p->to.reg == reg){ fp->fnptr = 0; p->as = ABL; // safe to do so // print("simplified %s call\n", fp->name); break; } if(!debug['F'] && (isbranch(p) || p->as == ARET)) diag("bad setfpuse call"); if((p->from.type == D_REG || p->from.type == D_OREG) && p->from.reg == reg){ if(!debug['F'] && p->to.type != D_REG) diag("bad setfpuse call"); reg = p->to.reg; } } } }
Tbl * Tsetl(Tbl *tbl, const char *key, size_t len, void *val) { // Ensure flag bits are zero. if(((uint64_t)val & 1) != 0 || len > 0xFFFFFF) { errno = EINVAL; return(NULL); } if(val == NULL) return(Tdell(tbl, key, len)); // First leaf in an empty tbl? if(tbl == NULL) { tbl = malloc(sizeof(*tbl)); if(tbl == NULL) return(NULL); tbl->root.leaf.key = key; tbl->root.leaf.val = val; return(tbl); } Trie *t = &tbl->root; // Find the most similar leaf node in the trie. We will compare // its key with our new key to find the first differing nibble, // which can be at a lower index than the point at which we // detect a difference. while(isbranch(t)) { __builtin_prefetch(t->branch.twigs); Tbitmap b = twigbit(t, key, len); // Even if our key is missing from this branch we need to // keep iterating down to a leaf. It doesn't matter which // twig we choose since the keys are all the same up to this // index. Note that blindly using twigoff(t, b) can cause // an out-of-bounds index if it equals twigmax(t). uint i = hastwig(t, b) ? twigoff(t, b) : 0; t = twig(t, i); } // Do the keys differ, and if so, where? size_t i; uint f; for(i = 0; i <= len; i++) { f = (byte)key[i] ^ (byte)t->leaf.key[i]; if(f != 0) goto newkey; } t->leaf.val = val; return(tbl); newkey:; // We have the branch's byte index; what is its chunk index? size_t bit = i * 8 + __builtin_clz(f) + 8 - sizeof(uint) * 8; size_t qi = bit / 5; i = qi * 5 / 8; f = qi * 5 % 8 << 1 | 1; // re-index keys with adjusted i uint k1 = (byte)key[i] << 8; uint k2 = (byte)t->leaf.key[i] << 8; k1 |= (k1 ? (byte)key[i+1] : 0); k2 |= (k2 ? (byte)t->leaf.key[i+1] : 0); Tbitmap b1 = nibbit(k1, f); // Prepare the new leaf. Trie t1 = { .leaf = { .key = key, .val = val } }; // Find where to insert a branch or grow an existing branch. t = &tbl->root; while(isbranch(t)) { __builtin_prefetch(t->branch.twigs); if(i == t->branch.index && f == t->branch.flags) goto growbranch; if(i == t->branch.index && f < t->branch.flags) goto newbranch; if(i < t->branch.index) goto newbranch; Tbitmap b = twigbit(t, key, len); assert(hastwig(t, b)); t = twig(t, twigoff(t, b)); } newbranch:; Trie *twigs = malloc(sizeof(Trie) * 2); if(twigs == NULL) return(NULL); Trie t2 = *t; // Save before overwriting. Tbitmap b2 = nibbit(k2, f); t->branch.twigs = twigs; t->branch.flags = f; t->branch.index = i; t->branch.bitmap = b1 | b2; *twig(t, twigoff(t, b1)) = t1; *twig(t, twigoff(t, b2)) = t2; return(tbl); growbranch:; assert(!hastwig(t, b1)); uint s, m; TWIGOFFMAX(s, m, t, b1); twigs = realloc(t->branch.twigs, sizeof(Trie) * (m + 1)); if(twigs == NULL) return(NULL); memmove(twigs+s+1, twigs+s, sizeof(Trie) * (m - s)); memmove(twigs+s, &t1, sizeof(Trie)); t->branch.twigs = twigs; t->branch.bitmap |= b1; return(tbl); }
void translate(context* ctx, assembly* casm) { int i,j,k,l,m; symbol *s, *t; intermediate* icode = ctx->prog; tryarr* ta; if (!icode) return; partition(ctx, icode); /*printquadruples(icode);*/ for (i=0; i<icode->nextslot; i++) { icode->quadruples[i].firstinstruction = casm->nextslot; ctx->inleader = icode->quadruples[i].isleader; ctx->insord = 0; transquad(ctx, casm, i); icode->quadruples[i].lastinstruction = casm->nextslot-1; } /* Adjust branch instructions' target address. */ for (i=0; i<casm->nextslot; i++) if (isbranch(&casm->instructions[i])) { j = casm->instructions[i].opdest.ival; casm->instructions[i].opdest.ival = icode->quadruples[j].firstinstruction; } /* Adjust functional variables. */ for (i=0; i<ctx->funcs.nextslot; i++) { j = ctx->funcs.funcs[i].slot; s = lookup(ctx, &ctx->sbt, ctx->funcs.funcs[i].caller); k = icode->quadruples[j+s->firstquad].firstinstruction; l = icode->quadruples[j+s->firstquad].lastinstruction; if (!ishostfunction(ctx->funcs.funcs[i].callee)) { t = lookup(ctx, &ctx->sbt, ctx->funcs.funcs[i].callee); for (m=k; m<=l; m++) if (casm->instructions[m].op == opLFUNC) casm->instructions[m].op1.ival = icode->quadruples[t->firstquad].firstinstruction; } else casm->instructions[k].op1.ival = (int)zen_getfunc(ctx->funcs.funcs[i].callee); } /* Adjust tryblock records for each of the functions. */ for (i=0; i<ctx->sbt.nextslot; i++) if (ctx->sbt.table[i].isfunction) { if ((ta=ctx->sbt.table[i].ta) == 0) continue; for (j=0; j<ta->nextslot; j++) { ta->tr[j].first += ctx->sbt.table[i].firstquad; ta->tr[j].first = icode->quadruples[ta->tr[j].first].firstinstruction; ta->tr[j].last += ctx->sbt.table[i].firstquad; ta->tr[j].last = icode->quadruples[ta->tr[j].last].lastinstruction; ta->tr[j].catchentry += ctx->sbt.table[i].firstquad; ta->tr[j].catchentry = icode->quadruples[ta->tr[j].catchentry].firstinstruction; } } casm->stacksize = ZEN_DEFAULT_STACK_SIZE; /*printinstructions(casm);*/ }
noeud* ttos_unres_rooted(int** ttree, int nbotu, int nbbi, char** nom, double* lgbi_init, double* lgbp, double fracroot1, int l1, char** list1, int l2, char** list2, double** lgbi_pt){ noeud *tabnd, nd1, nd2, nd3; int i, j, k, *kill_bi, min, rang_min, ** sorted, *nbfeuille, *fils, nbfils, cpt, *remain; double arg6, *lgbi; branche* br_list; int mo1=-1; tabnd=(noeud*)check_alloc(2*nbotu, sizeof(noeud)); kill_bi=(int*)check_alloc(nbbi, sizeof(int)); remain=(int*)check_alloc(nbbi, sizeof(int)); if(lgbi_init) lgbi=(double*)check_alloc(nbbi, sizeof(double)); else lgbi=NULL; sorted=(int**)check_alloc(nbotu, sizeof(int*)); for(i=0;i<nbotu;i++) sorted[i]=(int*)check_alloc(nbbi, sizeof(int)); nbfeuille=(int*)check_alloc(nbbi, sizeof(int)); fils=(int*)check_alloc(2*nbotu, sizeof(int)); br_list=(branche*)check_alloc(2*nbotu-3, sizeof(branche)); for(i=0;i<2*nbotu-3;i++){ br_list[i]=(branche)check_alloc(1, sizeof(struct branche)); br_list[i]->bout1=NULL; } /* SORT BRANCHES , REFRESH TREE */ for(i=0;i<nbbi;i++){ nbfeuille[i]=0; for(j=0;j<nbotu;j++) if(ttree[j][i]==1) nbfeuille[i]++; if(nbfeuille[i]>nbotu/2){ nbfeuille[i]=nbotu-nbfeuille[i]; for(j=0;j<nbotu;j++) ttree[j][i]=1-ttree[j][i]; } } for(i=0;i<nbbi;i++) kill_bi[i]=0; for(i=0;i<nbbi;i++){ min=nbotu+1; rang_min=-1; for(j=0;j<nbbi;j++){ if(nbfeuille[j]<min && kill_bi[j]==0){ min=nbfeuille[j]; rang_min=j; } } for(j=0;j<nbotu;j++) sorted[j][i]=ttree[j][rang_min]; if(lgbi_init){ lgbi[i]=lgbi_init[rang_min]; remain[i]=rang_min; } kill_bi[rang_min]=1; } /* CREATE NBOTU TERMINAL NODES */ for(i=0;i<nbotu;i++){ if(lgbp==NULL) arg6=-1.0; else arg6=lgbp[i]; tabnd[i]=create_node(NULL, NULL, NULL, 0., 0., arg6, 0., 0., 1., nom[i]); } /* CREATE NBBI ALIVE INTERNAL NODES + A FEW NONALIVE ONES*/ cpt=0; for(i=0;i<nbbi;i++){ /* find and record sons */ nbfils=0; for(j=0;j<nbbi;j++) kill_bi[j]=0; for(j=0;j<nbotu;j++){ if(sorted[j][i]==1){ for(k=i-1;k>=0;k--){ if(sorted[j][k]==1){ if(kill_bi[k]) break; /* internal son node (possible index : nbotu, nbotu+1, ..., nbotu+nbbi-1) */ nbfils++; fils[nbfils-1]=nbotu+k; kill_bi[k]=1; break; } } if(k==-1){ /* terminal son node (possible index : 0, 1, ..., nbotu-1) */ nbfils++; fils[nbfils-1]=j; } } } if(nbfils<2) { printf("Bad tree:\n"); printf("%d sons found for branch %d in sorted tree\n", nbfils, i); /* debug_printree(sorted, nbotu, nbbi);*/ exit(EXIT_FAILURE); } /* create node(s) */ if(lgbi==NULL) arg6=-1.0; else arg6=lgbi[i]; if(nbfils==2){ nd1=tabnd[fils[0]]; nd2=tabnd[fils[1]]; tabnd[nbotu+i]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, arg6, 1., 1., 1., NULL); nd1->v3=nd2->v3=tabnd[nbotu+i]; if(lgbi_pt) lgbi_pt[remain[i]]=&(tabnd[nbotu+i]->l3); } else{ nd1=tabnd[fils[0]]; nd2=tabnd[fils[1]]; tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 1., 0., NULL); nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt]; cpt++; for(j=0;j<nbfils-3;j++){ nd1=tabnd[fils[j+2]]; nd2=tabnd[nbotu+nbbi+cpt-1]; tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 0., 0., NULL); nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt]; cpt++; } nd1=tabnd[fils[nbfils-1]]; nd2=tabnd[nbotu+nbbi+cpt-1]; tabnd[nbotu+i]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, arg6, 1., 0., 1., NULL); nd1->v3=nd2->v3=tabnd[nbotu+i]; } } /* JOIN HANGING NODES */ nbfils=0; for(i=0;i<nbotu+nbbi+cpt;i++){ if(tabnd[i]->v3==NULL){ fils[nbfils]=i; nbfils++; } } if(nbfils<3){ printf("Bad tree 2\n"); exit(EXIT_FAILURE); } if(nbfils==3){ nd1=tabnd[fils[0]]; nd2=tabnd[fils[1]]; nd3=tabnd[fils[2]]; tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, nd3, nd1->l3, nd2->l3, nd3->l3, 1., 1., 1., NULL); nd1->v3=nd2->v3=nd3->v3=tabnd[nbotu+nbbi+cpt]; } if(nbfils>3){ nd1=tabnd[fils[0]]; nd2=tabnd[fils[1]]; tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 1., 0., NULL); nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt]; cpt++; for(i=0;i<nbfils-4;i++){ nd1=tabnd[fils[i+2]]; nd2=tabnd[nbotu+nbbi+cpt-1]; tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, NULL, nd1->l3, nd2->l3, -1., 1., 0., 0., NULL); nd1->v3=nd2->v3=tabnd[nbotu+nbbi+cpt]; cpt++; } nd1=tabnd[fils[nbfils-2]]; nd2=tabnd[fils[nbfils-1]]; nd3=tabnd[nbotu+nbbi+cpt-1]; tabnd[nbotu+nbbi+cpt]=create_node(nd1, nd2, nd3, nd1->l3, nd2->l3, nd3->l3, 1., 1., 0., NULL); nd1->v3=nd2->v3=nd3->v3=tabnd[nbotu+nbbi+cpt]; } /* ROOT */ root=create_node(NULL, NULL, NULL, -1., -1., -1., 1., 1., 0., "ROOT"); makelistbr_unrooted(NULL, tabnd[0], br_list, NULL, 2*nbotu-3); for(i=0;i<2*nbotu-3;i++){ if(isbranch(br_list[i], l1, list1, l2, list2)==1){ root_s(br_list[i], fracroot1); break; } if(isbranch(br_list[i], l1, list1, l2, list2)==2){ root_s(br_list[i], 1.-fracroot1); break; } } if(i==2*nbotu-3) printf("Erreur racinage\n"); organize_tree(NULL, root); free(kill_bi); if(lgbi_init) free(lgbi); for(i=0;i<nbotu;i++) free(sorted[i]); free(sorted); free(nbfeuille); free(fils); for(i=0;i<2*nbotu-3;i++) free(br_list[i]); free(br_list); free(remain); return(tabnd); }