static void sliceStructs_Gather(SymInfo *sia, elem *e) { while (1) { switch (e->Eoper) { case OPvar: { SYMIDX si = e->EV.sp.Vsym->Ssymnum; if (si >= 0 && sia[si].canSlice) { assert(si < globsym.top); unsigned sz = tysize(e->Ety); if (sz == 2 * REGSIZE && !tyfv(e->Ety)) { // Rewritten as OPpair later } else if (sz == REGSIZE && (e->Eoffset == 0 || e->Eoffset == REGSIZE)) { if (!sia[si].accessSlice) { sia[si].ty0 = TYnptr; sia[si].ty1 = TYnptr; } sia[si].accessSlice = true; if (e->Eoffset == 0) sia[si].ty0 = tybasic(e->Ety); else sia[si].ty1 = tybasic(e->Ety); } else { sia[si].canSlice = false; } } return; } default: if (OTassign(e->Eoper)) { if (OTbinary(e->Eoper)) sliceStructs_Gather(sia, e->E2); // Assignment to a whole var will disallow SROA if (e->E1->Eoper == OPvar) { elem *e1 = e->E1; SYMIDX si = e1->EV.sp.Vsym->Ssymnum; if (si >= 0 && sia[si].canSlice) { assert(si < globsym.top); if (tysize(e1->Ety) != REGSIZE || (e1->Eoffset != 0 && e1->Eoffset != REGSIZE)) { sia[si].canSlice = false; } } return; } e = e->E1; break; } if (OTunary(e->Eoper)) { e = e->E1; break; } if (OTbinary(e->Eoper)) { sliceStructs_Gather(sia, e->E2); e = e->E1; break; } return; } } }
static void sliceStructs_Gather(SymInfo *sia, elem *e) { while (1) { switch (e->Eoper) { case OPvar: { SYMIDX si = e->EV.sp.Vsym->Ssymnum; if (si >= 0 && sia[si].canSlice) { assert(si < globsym.top); unsigned sz = tysize(e->Ety); if (sz == 2 * REGSIZE) { // Rewrite as OPpair later sia[si].usePair = true; /* OPpair cannot handle XMM registers, cdpair() and fixresult() */ if (tyfloating(sia[si].ty0) || tyfloating(sia[si].ty1)) sia[si].canSlice = false; } else if (sz == REGSIZE && (e->Eoffset == 0 || e->Eoffset == REGSIZE)) { if (!sia[si].accessSlice) { sia[si].ty0 = TYnptr; sia[si].ty1 = TYnptr; } sia[si].accessSlice = true; if (e->Eoffset == 0) sia[si].ty0 = tybasic(e->Ety); else sia[si].ty1 = tybasic(e->Ety); // Cannot slice float fields if the symbol is also accessed using OPpair (see above) if (sia[si].usePair && (tyfloating(sia[si].ty0) || tyfloating(sia[si].ty1))) sia[si].canSlice = false; } else { sia[si].canSlice = false; } } return; } default: if (OTassign(e->Eoper)) { if (OTbinary(e->Eoper)) sliceStructs_Gather(sia, e->E2); // Assignment to a whole var will disallow SROA if (e->E1->Eoper == OPvar) { elem *e1 = e->E1; SYMIDX si = e1->EV.sp.Vsym->Ssymnum; if (si >= 0 && sia[si].canSlice) { assert(si < globsym.top); if (tysize(e1->Ety) != REGSIZE || (e1->Eoffset != 0 && e1->Eoffset != REGSIZE)) { sia[si].canSlice = false; } } return; } e = e->E1; break; } if (OTunary(e->Eoper)) { e = e->E1; break; } if (OTbinary(e->Eoper)) { sliceStructs_Gather(sia, e->E2); e = e->E1; break; } return; } } }