Annotation of coherent/d/bin/cc/c/n1/sel0.270, revision 1.1.1.1

1.1       root        1: /*
                      2:  * C compiler.
                      3:  * Pattern selection.
                      4:  */
                      5: #ifdef   vax
                      6: #include "INC$LIB:cc1.h"
                      7: #else
                      8: #include "cc1.h"
                      9: #endif
                     10: 
                     11: #if !TINY
                     12: #define consnap(x, p)          if (sflag>x) snapf(p)
                     13: #define consnapv(x, p, v)      if (sflag>x) snapf(p, v)
                     14: #else
                     15: #define consnap(x, p)          /* consnap */
                     16: #define consnapv(x, p, v)      /* consnapv */
                     17: #endif
                     18: 
                     19: /*
                     20:  * Code selection.
                     21:  * This routine is a near duplicate of output().
                     22:  * This routine must succeed or a nomatch fatal error will result.
                     23:  */
                     24: select(tp, c, r)
                     25: register TREE *tp;
                     26: {
                     27:        register TREE *ap;
                     28:        register op;
                     29:        register TREE *xp;
                     30:        int flag;
                     31:        int rel;
                     32:        int r1;
                     33: 
                     34: #if !TINY
                     35:        if (sflag > 1) {
                     36:                snapf("select(%P, %C, ", tp, c);
                     37:                snapf(c<MFLOW ? "%R" : c<MEQ ? "%d" : "L%d", r);
                     38:                snapf(") %A\n", tp->t_op);
                     39:        }
                     40: #endif
                     41:        /* Process a few operators by hand */
                     42:        op = tp->t_op;
                     43:        if (op == COMMA) {
                     44:                if (code1(&tp->t_lp, MEFFECT, ANYR) == 0
                     45:                 || code1(&tp->t_rp, c, r) == 0)
                     46:                        return (0);
                     47:                tp->t_used = tp->t_lp->t_used | tp->t_rp->t_used;
                     48:                tp->t_treg = tp->t_rp->t_treg;
                     49:                tp->t_rreg = tp->t_rp->t_rreg;
                     50:                return (1);
                     51:        }
                     52:        if (op == QUEST) {
                     53:                if (code1(&tp->t_lp, MFLOW, 0) == 0)
                     54:                        return (0);
                     55:                ap = tp->t_rp;
                     56:                if (code1(&ap->t_lp, c, r) == 0)
                     57:                        return (0);
                     58:                ap->t_rreg = NONE;
                     59:                if (c==MLVALUE || c==MRVALUE) {
                     60:                        r = ap->t_lp->t_rreg;
                     61:                        ap->t_rreg = r;
                     62:                }
                     63:                if (code1(&ap->t_rp, c, r) == 0)
                     64:                        return (0);
                     65:                ap->t_treg = NONE;
                     66:                ap->t_used = ap->t_lp->t_used | ap->t_rp->t_used;
                     67:                tp->t_rreg = ap->t_rreg;
                     68:                tp->t_treg = NONE;
                     69:                tp->t_used = tp->t_lp->t_used | ap->t_used;
                     70:                return (1);
                     71:        }
                     72:        /* Conditionals may be unravelled to generate simpler code.
                     73:         * 'r' is true or false depending on which condition should goto 'l'. */
                     74:        if (c == MFLOW) {
                     75:                if (op == NOT) {
                     76:                        if (code1(&tp->t_lp, c, !r) == 0)
                     77:                                return(0);
                     78:                        tp->t_used = tp->t_lp->t_used;
                     79:                        return(1);
                     80:                }
                     81:                if (op == LEAF) {
                     82:                        ap = tp->t_lp;
                     83:                        if (ap->t_op==ICON || ap->t_op==LCON)
                     84:                                return (1);
                     85:                }
                     86:                if (op==ANDAND || op==OROR) {
                     87:                        r1 = r;
                     88:                        if ((op==OROR) != r)
                     89:                                r1 = !r1;
                     90:                        if (code1(&tp->t_lp, MFLOW, r1) == 0
                     91:                         || code1(&tp->t_rp, MFLOW, r) == 0)
                     92:                                return (0);
                     93:                        tp->t_used = tp->t_lp->t_used | tp->t_rp->t_used;
                     94:                        tp->t_rreg = NONE;
                     95:                        tp->t_treg = NONE;
                     96:                        return (1);
                     97:                }
                     98:                rel = NE;
                     99:                flag = 0;
                    100:                if (isrelop(op)) {
                    101:                        rel = op;
                    102:                        if (isnval(tp->t_rp, 0) && tp->t_lp->t_op != QUEST) {
                    103:                                if (rel == ULE)
                    104:                                        rel = EQ;
                    105:                                else if (rel == UGT)
                    106:                                        rel = NE;
                    107:                                ap = tp->t_lp;
                    108:                                flag = 1;
                    109:                                while ((op = ap->t_op) == COMMA)
                    110:                                        ap = ap->t_rp;
                    111:                                if (isrelop(op) || isflow(op)) {
                    112:                                        switch (rel) {
                    113:                                        case EQ:
                    114:                                        case LE:
                    115:                                        case ULE:
                    116:                                                r = !r;
                    117:                                        case NE:
                    118:                                        case GT:
                    119:                                        case UGT:
                    120:                                                if (code1(&tp->t_lp, c, r) == 0)
                    121:                                                        return(0);
                    122:                                                tp->t_used = tp->t_lp->t_used;
                    123:                                                return(1);
                    124:                                        }
                    125:                                }
                    126:                        }
                    127:                }
                    128:                if (r == 0)
                    129:                        rel = otherel[rel-EQ];
                    130:                c = MEQ + rel - EQ;
                    131:                r = ANYR;
                    132:                if (flag) {
                    133:                        if (code1(&tp->t_lp, c, r) == 0)
                    134:                                return (0);
                    135:                        tp->t_used = tp->t_lp->t_used;
                    136:                        return (1);
                    137:                }
                    138:        }
                    139:        if (op == CALL) {
                    140: #if 0
                    141:                if (c != pertype[tp->t_type].p_frcxt
                    142:                 && (c==MRVALUE || c==MLVALUE))
                    143:                        return (0);
                    144: #endif
                    145:                tp->t_used = FNUSED;
                    146:                if (tp->t_rp != NULL) {
                    147:                        if (selargs(&tp->t_rp) == 0)
                    148:                                return (0);
                    149:                        tp->t_used |= tp->t_rp->t_used;
                    150:                }
                    151:                ap = tp->t_lp;
                    152:                if (!isadr(ap->t_flag)) {
                    153: #if ICALLS
                    154:                /* Does the machine allow
                    155:                 * an extra level of indirection
                    156:                 * on calls? */
                    157:                        if (ap->t_op != STAR)
                    158:                                cbotch("call no star");
                    159:                        xp = ap->t_lp;
                    160:                        if (!isadr(xp->t_flag)) {
                    161:                                if (!isofs(xp->t_flag))
                    162:                                        store(ap, 0);
                    163:                                else {
                    164:                                        xp = findoffs(xp);
                    165:                                        if (select(xp, MLVALUE, ANYL) == 0)
                    166:                                                return (0);
                    167:                                        tp->t_used |= xp->t_used;
                    168:                                }
                    169:                        }
                    170: #else
                    171:                        if (!isofs(ap->t_flag))
                    172:                                cbotch("call not ofs");
                    173:                        ap = findoffs(ap);
                    174:                        if (select(ap, MLVALUE, ANYL) == 0)
                    175:                                return (0);
                    176:                        tp->t_used |= ap->t_used;
                    177: #endif
                    178:                }
                    179:                tp->t_treg = NONE;
                    180:                tp->t_rreg = pertype[tp->t_type].p_frreg;
                    181:                if ((c!=MLVALUE&&c!=MRVALUE)||(isrealreg(r)&&r!=tp->t_rreg))
                    182:                        selfix(tp, c, r);
                    183:                return (1);
                    184:        }
                    185:        /* Everything not previously dispatched by hand
                    186:         * must be found in the code tables by seltree */
                    187:        if (seltree(tp, c, r)) {
                    188:                if ((c==MLVALUE||c==MRVALUE) && isrealreg(r) && r!=tp->t_rreg)
                    189:                        selfix(tp, c, r);
                    190:                return (1);
                    191:        }
                    192:        /* RVALUE patterns can be fixed up into anything */
                    193:        if (c != MRVALUE && seltree(tp, MRVALUE, ANYR)) {
                    194:                selfix(tp, c, r);
                    195:                return (1);
                    196:        }
                    197: #if 0
                    198:        /* The m68000 needed this, maybe it won't next time */
                    199:        if (c != MLVALUE && seltree(tp, MLVALUE, ANYL)) {
                    200:                if (c != MEFFECT)
                    201:                        selfix(tp, c, r);
                    202:                return (1);
                    203:        }
                    204: #endif
                    205:        /* FAILURE is a fatal error */
                    206:        return (0);
                    207: }
                    208: 
                    209: /*
                    210:  * If the selector cannot find a template that will satisfy the context or the
                    211:  * requested register, an MRVALUE case will do if the result is 'fixed up'.
                    212:  * A FIXUP tree node tells the output part of the coder that a fixup is
                    213:  * needed at this point in the tree.
                    214:  * Context mismatch FIXUP's are generally benign:
                    215:  * they either push a register onto the stack as a function argument,
                    216:  * or test a register and generate a conditional branch.
                    217:  * Register mismatch FIXUP's appear to be caused
                    218:  * by table errors or overzealous node coercion
                    219:  * and should to be avoided at all costs;
                    220:  * they often lead to shuffling values back and forth between registers.
                    221:  * The typical culprit is a code table pattern
                    222:  * which specifies both a node register and an ADR subnode
                    223:  * rather than a TREG subnode shared with the node register.
                    224:  * seltree() coerces the ADR node into the wrong register
                    225:  * and the fixup copies it to the requested reg.
                    226:  */
                    227: selfix(tp, c, r)
                    228: register TREE *tp;
                    229: {
                    230:        register TREE *ap;
                    231:        TREE rnode;
                    232: 
                    233: #if !TINY
                    234:        if (sflag > 1) {
                    235:                snapf("selfix(%P, %C, ", tp, c);
                    236:                snapf(c<MFLOW ? "%R" : c<MEQ ? "%d" : "L%d", r);
                    237:                snapf(") %A\n", tp->t_op);
                    238:        }
                    239: #endif
                    240:        ap = copynode(tp);
                    241:        fixtoptype(tp);
                    242:        rnode.t_op   = REG;
                    243:        rnode.t_type = tp->t_type;
                    244:        rnode.t_size = tp->t_size;
                    245:        rnode.t_reg  = tp->t_rreg;
                    246:        tp->t_op = FIXUP;
                    247:        tp->t_lp = &rnode;
                    248:        tp->t_rp = NULL;
                    249:        walk(tp, amd);
                    250: #if !TINY
                    251:        rnode.t_treg = NONE;
                    252:        rnode.t_rreg = NONE;
                    253:        rnode.t_used = 0;
                    254:        rnode.t_patp = NULL;
                    255:        if (sflag > 2) snapf("%W%E%W", "Selfix", tp, NULL);
                    256: #endif
                    257:        if (select(tp, c, r) == 0)
                    258:                cbotch("node will not fix");
                    259:        tp->t_lp = ap;
                    260:        tp->t_used = ap->t_used;
                    261:        if (isrealreg(r))
                    262:                setused(tp, r);
                    263: }
                    264: 
                    265: /*
                    266:  * Add register 'r' to the used set of the tree node pointed to by 'tp'.
                    267:  */
                    268: setused(tp, r)
                    269: TREE *tp;
                    270: {
                    271:        tp->t_used |= reg[r].r_phys;
                    272: }
                    273: 
                    274: /*
                    275:  * Run down the (possibly null)
                    276:  * argument list of a function, making
                    277:  * the required recursive calls to the
                    278:  * walker and/or the code selector.
                    279:  * If the node is a BLK pointer,
                    280:  * it the address of a structure argument and
                    281:  * must get special treatment.
                    282:  */
                    283: selargs(tpp)
                    284: register TREE **tpp;
                    285: {
                    286:        register TREE *tp;
                    287: 
                    288:        if ((tp = *tpp) == NULL)
                    289:                return (1);
                    290:        if (tp->t_op == ARGLST) {
                    291:                if (selargs(&tp->t_lp)==0)
                    292:                        return (0);
                    293:                if (selargs(&tp->t_rp)==0)
                    294:                        return (0);
                    295:                tp->t_used = 0;
                    296:                if (tp->t_lp != NULL)
                    297:                        tp->t_used |= tp->t_lp->t_used;
                    298:                if (tp->t_rp != NULL)
                    299:                        tp->t_used |= tp->t_rp->t_used;
                    300:                return (1);
                    301:        }
                    302:        if (isblkp(tp->t_type))
                    303:                return (code1(tpp, MBLARG, MBLREG));
                    304:        return (code1(tpp, MFNARG, ANYR));
                    305: }
                    306: 
                    307: /*
                    308:  * Set up an address in an rvalue context.
                    309:  * This routine knows how to pool
                    310:  * constants on demand, how to use registers
                    311:  * as indexing temporaries and as plain old
                    312:  * value temporaries, and how to give up and
                    313:  * put a value into memory.
                    314:  * If the top operator is one of the leaf
                    315:  * nodes the register used in the setup of an
                    316:  * offset address is not made busy.
                    317:  * It is marked used by the tree.
                    318:  * These trees are more like a TREG than a RHS
                    319:  * in their use of a register.
                    320:  */
                    321: selrv(ttp, flag, didstorep)
                    322: TREE *ttp;
                    323: int *didstorep;
                    324: {
                    325:        register TREE *tp, *ap;
                    326:        register op, leaf;
                    327:        int lab, r;
                    328: 
                    329:        leaf = 1;
                    330:        tp = ttp;
                    331:        op = tp->t_op;
                    332:        if (op==CONVERT || op==CAST || op==FIXUP || op==LEAF)
                    333:                leaf = 2;
                    334: #if !TINY
                    335:        if (sflag > 1)
                    336:                snapf("selrv(%P, %d, ...) leaf=%d\n", tp, flag, leaf);
                    337: #endif
                    338:        tp = flag ? tp->t_rp : tp->t_lp;
                    339:        /* Pool constants into memory */
                    340:        if ((tp->t_flag&T_IMM) != 0) {
                    341:                for (ap=tp; ap->t_op==LEAF; ap=ap->t_lp)
                    342:                        ;
                    343:                pool(ap);
                    344:                walk(tp, amd);
                    345:                return;
                    346:        }
                    347:        /* The tree is offset addressible,
                    348:         * load the offset node into an index reg */
                    349:        if (isofs(tp->t_flag)) {
                    350:                ap = findoffs(tp);
                    351:                consnapv(2, "Rv offs %P\n", ap);
                    352:                if ((r = rallo(ap, ttp->t_used, leaf)) >= 0) {
                    353:                        consnapv(2, "Offs %R\n", r);
                    354:                        if (leaf == 1)
                    355:                                setbusy(r);
                    356:                        if (select(ap, MLVALUE, r)) {
                    357:                                ttp->t_used |= ap->t_used;
                    358:                                return;
                    359:                        }
                    360:                        if (leaf == 1)
                    361:                                clrbusy(r);
                    362:                }
                    363:        }
                    364:        /* Try to load the tree into a register */
                    365:        if ((r = rallo(tp, ttp->t_used, 0)) >= 0) {
                    366:                setbusy(r);
                    367:                if (select(tp, MRVALUE, r)) {
                    368:                        tp->t_flag   = 0;
                    369:                        ttp->t_used |= tp->t_used;
                    370:                        return;
                    371:                }
                    372:                clrbusy(r);
                    373:        }
                    374:        /* Store the tree into a stack temporary */
                    375:        store(ttp, flag);
                    376:        walk(tp, amd);
                    377:        *didstorep = 1;
                    378: }
                    379: 
                    380: /*
                    381:  * This function sets up a left context subtree in an addressing context.
                    382:  * The 'index' argument is a preferred register; if negative,
                    383:  * then indirection is legal.
                    384:  * This routine is the pits, comparable
                    385:  * in pittiness to the part of output()
                    386:  * responsible for undoing this madness.
                    387:  */
                    388: sellv(ttp, index, flag, didstorep)
                    389: TREE *ttp;
                    390: int *didstorep;
                    391: {
                    392:        register TREE *tp, *tp1, *tp2;
                    393:        int newindex;
                    394: 
                    395:        tp = flag ? ttp->t_rp : ttp->t_lp;
                    396: #if !TINY
                    397:        if (sflag > 1)
                    398:                snapf("sellv(%P, %R, %d, ...)\n", tp, index, flag);
                    399: #endif
                    400:        if (tp->t_op == FIELD) {
                    401:                tp->t_used = ttp->t_used;
                    402:                sellv(tp, index, 0, didstorep);
                    403:                ttp->t_used |= tp->t_used;
                    404:                return;
                    405:        }
                    406:        if (!isofs(tp->t_flag))
                    407:                cbotch("sellv: not an ofs");
                    408:        /* If we can indirect through a stack temporary,
                    409:         * we still try first to do it in a register,
                    410:         * but we give up with much less grief. */
                    411:        if (index < 0) {
                    412:                tp1 = findoffs(tp);
                    413:                consnapv(2, "Lv offs %P\n", tp1);
                    414:                if ((index = rallo(tp1, ttp->t_used, 1)) >= 0) {
                    415:                        consnapv(2, "Index %R\n", index);
                    416:                        setbusy(index);
                    417:                        if (select(tp1, MLVALUE, index)) {
                    418:                                tp->t_used  |= tp1->t_used;
                    419:                                ttp->t_used |= tp1->t_used;
                    420:                                return;
                    421:                        }
                    422:                        clrbusy(index);
                    423:                }
                    424:                /* The store puts a stack temp under tp
                    425:                 * which must have tp->t_op == STAR */
                    426:                store(tp, 0);
                    427:                walk(tp, amd);
                    428:                *didstorep = 1;
                    429:                return;
                    430:        }
                    431:        /* We cannot indirect through a temp,
                    432:         * so we may have to fake it. */
                    433:        tp2 = findoffs(tp);
                    434:        consnapv(2, "Offs %P\n", tp2);
                    435:        for (tp1 = tp; tp1->t_lp != tp2; tp1 = tp1->t_lp);
                    436:        /* If the offset is not directly addressible
                    437:         * then we will have to generate code to load
                    438:         * it into the index register. */
                    439:        if (!isadr(tp2->t_flag)) {
                    440:                /* If the preferred index is useable
                    441:                 * then attempt to use it */
                    442:                if ((ttp->t_used&reg[index].r_phys) == 0) {
                    443:                        if (select(tp2, MLVALUE, index)) {
                    444:                                tp->t_used  |= tp2->t_used;
                    445:                                ttp->t_used |= tp2->t_used;
                    446:                                return;
                    447:                        }
                    448:                }
                    449:                /* Since index has already been reserved for indexing,
                    450:                 * use it even if already used and set the indirect flag to
                    451:                 * defer code output until after subtree output. */
                    452:                if (select(tp2, MLVALUE, index)) {
                    453:                        tp->t_flag |= T_INDIR;
                    454:                        tp->t_used  |= tp2->t_used;
                    455:                        ttp->t_used |= tp2->t_used;
                    456:                        return;
                    457:                }
                    458:                /* Since the preferred index is already used,
                    459:                 * try to use another one. */
                    460:                if ((newindex = rallo(tp2, ttp->t_used, 1)) >= 0) {
                    461:                        setbusy(newindex);
                    462:                        if (select(tp2, MLVALUE, newindex)) {
                    463:                                ttp->t_used |= tp2->t_used;
                    464:                                tp->t_used  |= tp2->t_used;
                    465:                                return;
                    466:                        }
                    467:                        clrbusy(newindex);
                    468:                }
                    469:                /* We can't do it ourselves, but an index has been
                    470:                 * reserved to load from a stack temp, so give up
                    471:                 * and store the offset. */
                    472:                store(tp1, 0);
                    473:                walk(tp, amd);
                    474:                *didstorep = 1;
                    475:        }
                    476:        /* tp2 either was addressible to begin with,
                    477:         * or was just made into an addressible temp */
                    478:        tp2 = tp1->t_lp;
                    479:        if (tp2->t_op != LEAF) {
                    480:                tp2 = leafnode(tp2);
                    481:                tp2->t_flag = tp1->t_lp->t_flag;
                    482:                tp1->t_lp = tp2;
                    483:        }
                    484:        /* Select the addressible offset node
                    485:         * into an index register */
                    486:        if (select(tp2, MLVALUE, index) == 0)
                    487:                cbotch("sellv");
                    488:        /* This flag is for the benefit of output() */
                    489:        tp->t_flag |= T_INDIR;
                    490:        tp->t_used |= tp2->t_used;
                    491:        ttp->t_used |= tp2->t_used;
                    492: }
                    493: 
                    494: /*
                    495:  * Store a subtree of the node pointed to by 'ttp'.
                    496:  * The 'flag' argument tells which subtree;
                    497:  * true means store the right side.
                    498:  * Then rewrite the subtree to refer to the storage location.
                    499:  */
                    500: store(ttp, flag)
                    501: TREE   *ttp;
                    502: {
                    503:        register TREE   *ap;
                    504:        register TREE   *tp;
                    505:        register int    sideflag;
                    506: 
                    507:        if (nstorelist >= NSTORE)
                    508:                cbotch("more than %d stores", NSTORE);
                    509:        sideflag = MRADDR;
                    510:        if (ttp->t_op>=INCBEF && ttp->t_op<=DECAFT) {
                    511:                if (flag != 0)
                    512:                        cbotch("store");
                    513:                tp = copynode(ttp);
                    514:                sideflag = MRVALUE;
                    515:        } else if (flag != 0)
                    516:                tp = ttp->t_rp;
                    517:        else
                    518:                tp = ttp->t_lp;
                    519:        ap = tempnode(tp, 1);
                    520:        if (sideflag == MRVALUE)
                    521:                ap = leafnode(ap);
                    522:        walk(ap, amd);
                    523:        if (sideflag == MRVALUE)
                    524:                *ttp = *ap;
                    525:        else if (flag != 0)
                    526:                ttp->t_rp = ap;
                    527:        else
                    528:                ttp->t_lp = ap;
                    529:        amd(ttp);
                    530:        ap = tempnode(tp, 0);
                    531:        ap = leftnode(ASSIGN, ap, ap->t_type, ap->t_size);
                    532:        while (tp->t_op == LEAF)
                    533:                tp = tp->t_lp;
                    534:        if (tp->t_type != ap->t_type)
                    535:                tp = leftnode(CONVERT, tp, ap->t_type, ap->t_size);
                    536:        else if ((tp->t_flag&T_LEAF) != 0)
                    537:                tp = leafnode(tp);
                    538:        ap->t_rp = ripout(tp, 0);
                    539:        fixtoptype(ap);
                    540:        walk(ap, amd);
                    541:        storelist[nstorelist++] = ap;
                    542: }
                    543: 
                    544: /*
                    545:  * Return true if the top of the argument tree is a conversion of some type
                    546:  * and the conversion makes the data wider (e.g. int to long).
                    547:  */
                    548: iswiden(tp)
                    549: register TREE *tp;
                    550: {
                    551:        register TREE *lp;
                    552: 
                    553:        if (tp->t_op!=CONVERT && tp->t_op!=CAST)
                    554:                return (0);
                    555:        lp = tp->t_lp;
                    556:        if (wtype[tp->t_type] < wtype[lp->t_type])
                    557:                return (0);
                    558:        return (1);
                    559: }
                    560: 
                    561: /*
                    562:  * This routine determines if a pattern and a set of expression flags mismatch,
                    563:  * and a call to 'sellv' or 'selrv' is needed.
                    564:  * Also used by output().
                    565:  */
                    566: selmiss(pflag, eflag)
                    567: FLAG pflag;
                    568: FLAG eflag;
                    569: {
                    570:        if ((pflag&eflag&~T_OFS) == 0)
                    571:                return (1);
                    572:        return (0);
                    573: }
                    574: 
                    575: /*
                    576:  * Remove any fix nodes which may have been generated
                    577:  * before a temp was substituted for an expression by store.
                    578:  */
                    579: TREE *
                    580: ripout(tp, flag)
                    581: register TREE *tp;
                    582: {
                    583:        register op;
                    584: 
                    585:        op = tp->t_op;
                    586:        if (!isleaf(op)) {
                    587:                tp->t_lp = ripout(tp->t_lp, flag);
                    588:                if (op!=FIELD && tp->t_rp!=NULL)
                    589:                        tp->t_rp = ripout(tp->t_rp, flag);
                    590:        }
                    591:        if (op==FIXUP || (op==LEAF && flag!=0))
                    592:                tp = tp->t_lp;
                    593:        return (tp);
                    594: }
                    595: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.