Annotation of gcc/explow.c, revision 1.1.1.8

1.1       root        1: /* Subroutines for manipulating rtx's in semantically interesting ways.
1.1.1.8 ! root        2:    Copyright (C) 1987, 1991, 1994, 1995 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.8 ! root       18: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            19: Boston, MA 02111-1307, USA.  */
1.1       root       20: 
                     21: 
                     22: #include "config.h"
                     23: #include "rtl.h"
                     24: #include "tree.h"
                     25: #include "flags.h"
                     26: #include "expr.h"
                     27: #include "hard-reg-set.h"
                     28: #include "insn-config.h"
                     29: #include "recog.h"
                     30: #include "insn-flags.h"
                     31: #include "insn-codes.h"
                     32: 
1.1.1.8 ! root       33: static rtx break_out_memory_refs       PROTO((rtx));
        !            34: 
1.1.1.4   root       35: /* Return an rtx for the sum of X and the integer C.
                     36: 
1.1.1.5   root       37:    This function should be used via the `plus_constant' macro.  */
1.1       root       38: 
                     39: rtx
1.1.1.4   root       40: plus_constant_wide (x, c)
1.1       root       41:      register rtx x;
1.1.1.4   root       42:      register HOST_WIDE_INT c;
1.1       root       43: {
                     44:   register RTX_CODE code;
                     45:   register enum machine_mode mode;
                     46:   register rtx tem;
                     47:   int all_constant = 0;
                     48: 
                     49:   if (c == 0)
                     50:     return x;
                     51: 
                     52:  restart:
                     53: 
                     54:   code = GET_CODE (x);
                     55:   mode = GET_MODE (x);
                     56:   switch (code)
                     57:     {
                     58:     case CONST_INT:
1.1.1.4   root       59:       return GEN_INT (INTVAL (x) + c);
1.1       root       60: 
                     61:     case CONST_DOUBLE:
                     62:       {
1.1.1.4   root       63:        HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
                     64:        HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
                     65:        HOST_WIDE_INT l2 = c;
                     66:        HOST_WIDE_INT h2 = c < 0 ? ~0 : 0;
                     67:        HOST_WIDE_INT lv, hv;
1.1       root       68: 
                     69:        add_double (l1, h1, l2, h2, &lv, &hv);
                     70: 
                     71:        return immed_double_const (lv, hv, VOIDmode);
                     72:       }
                     73: 
                     74:     case MEM:
                     75:       /* If this is a reference to the constant pool, try replacing it with
                     76:         a reference to a new constant.  If the resulting address isn't
                     77:         valid, don't return it because we have no way to validize it.  */
                     78:       if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
                     79:          && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
                     80:        {
                     81:          tem
                     82:            = force_const_mem (GET_MODE (x),
                     83:                               plus_constant (get_pool_constant (XEXP (x, 0)),
                     84:                                              c));
                     85:          if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
                     86:            return tem;
                     87:        }
                     88:       break;
                     89: 
                     90:     case CONST:
                     91:       /* If adding to something entirely constant, set a flag
                     92:         so that we can add a CONST around the result.  */
                     93:       x = XEXP (x, 0);
                     94:       all_constant = 1;
                     95:       goto restart;
                     96: 
                     97:     case SYMBOL_REF:
                     98:     case LABEL_REF:
                     99:       all_constant = 1;
                    100:       break;
                    101: 
                    102:     case PLUS:
                    103:       /* The interesting case is adding the integer to a sum.
                    104:         Look for constant term in the sum and combine
                    105:         with C.  For an integer constant term, we make a combined
                    106:         integer.  For a constant term that is not an explicit integer,
1.1.1.4   root      107:         we cannot really combine, but group them together anyway.  
                    108: 
                    109:         Use a recursive call in case the remaining operand is something
                    110:         that we handle specially, such as a SYMBOL_REF.  */
                    111: 
                    112:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
                    113:        return plus_constant (XEXP (x, 0), c + INTVAL (XEXP (x, 1)));
1.1       root      114:       else if (CONSTANT_P (XEXP (x, 0)))
                    115:        return gen_rtx (PLUS, mode,
                    116:                        plus_constant (XEXP (x, 0), c),
                    117:                        XEXP (x, 1));
                    118:       else if (CONSTANT_P (XEXP (x, 1)))
                    119:        return gen_rtx (PLUS, mode,
                    120:                        XEXP (x, 0),
                    121:                        plus_constant (XEXP (x, 1), c));
                    122:     }
                    123: 
                    124:   if (c != 0)
1.1.1.4   root      125:     x = gen_rtx (PLUS, mode, x, GEN_INT (c));
1.1       root      126: 
                    127:   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
                    128:     return x;
                    129:   else if (all_constant)
                    130:     return gen_rtx (CONST, mode, x);
                    131:   else
                    132:     return x;
                    133: }
                    134: 
1.1.1.4   root      135: /* This is the same as `plus_constant', except that it handles LO_SUM.
                    136: 
                    137:    This function should be used via the `plus_constant_for_output' macro.  */
1.1       root      138: 
                    139: rtx
1.1.1.4   root      140: plus_constant_for_output_wide (x, c)
1.1       root      141:      register rtx x;
1.1.1.4   root      142:      register HOST_WIDE_INT c;
1.1       root      143: {
                    144:   register RTX_CODE code = GET_CODE (x);
                    145:   register enum machine_mode mode = GET_MODE (x);
                    146:   int all_constant = 0;
                    147: 
                    148:   if (GET_CODE (x) == LO_SUM)
                    149:     return gen_rtx (LO_SUM, mode, XEXP (x, 0),
                    150:                    plus_constant_for_output (XEXP (x, 1), c));
                    151: 
                    152:   else
                    153:     return plus_constant (x, c);
                    154: }
                    155: 
                    156: /* If X is a sum, return a new sum like X but lacking any constant terms.
                    157:    Add all the removed constant terms into *CONSTPTR.
                    158:    X itself is not altered.  The result != X if and only if
                    159:    it is not isomorphic to X.  */
                    160: 
                    161: rtx
                    162: eliminate_constant_term (x, constptr)
                    163:      rtx x;
1.1.1.2   root      164:      rtx *constptr;
1.1       root      165: {
                    166:   register rtx x0, x1;
1.1.1.2   root      167:   rtx tem;
1.1       root      168: 
                    169:   if (GET_CODE (x) != PLUS)
                    170:     return x;
                    171: 
                    172:   /* First handle constants appearing at this level explicitly.  */
1.1.1.2   root      173:   if (GET_CODE (XEXP (x, 1)) == CONST_INT
                    174:       && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
                    175:                                                XEXP (x, 1)))
                    176:       && GET_CODE (tem) == CONST_INT)
1.1       root      177:     {
1.1.1.2   root      178:       *constptr = tem;
1.1       root      179:       return eliminate_constant_term (XEXP (x, 0), constptr);
                    180:     }
                    181: 
1.1.1.2   root      182:   tem = const0_rtx;
                    183:   x0 = eliminate_constant_term (XEXP (x, 0), &tem);
                    184:   x1 = eliminate_constant_term (XEXP (x, 1), &tem);
                    185:   if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
                    186:       && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
                    187:                                                *constptr, tem))
                    188:       && GET_CODE (tem) == CONST_INT)
1.1       root      189:     {
1.1.1.2   root      190:       *constptr = tem;
1.1       root      191:       return gen_rtx (PLUS, GET_MODE (x), x0, x1);
                    192:     }
1.1.1.2   root      193: 
1.1       root      194:   return x;
                    195: }
                    196: 
                    197: /* Returns the insn that next references REG after INSN, or 0
                    198:    if REG is clobbered before next referenced or we cannot find
                    199:    an insn that references REG in a straight-line piece of code.  */
                    200: 
                    201: rtx
                    202: find_next_ref (reg, insn)
                    203:      rtx reg;
                    204:      rtx insn;
                    205: {
                    206:   rtx next;
                    207: 
                    208:   for (insn = NEXT_INSN (insn); insn; insn = next)
                    209:     {
                    210:       next = NEXT_INSN (insn);
                    211:       if (GET_CODE (insn) == NOTE)
                    212:        continue;
                    213:       if (GET_CODE (insn) == CODE_LABEL
                    214:          || GET_CODE (insn) == BARRIER)
                    215:        return 0;
                    216:       if (GET_CODE (insn) == INSN
                    217:          || GET_CODE (insn) == JUMP_INSN
                    218:          || GET_CODE (insn) == CALL_INSN)
                    219:        {
                    220:          if (reg_set_p (reg, insn))
                    221:            return 0;
                    222:          if (reg_mentioned_p (reg, PATTERN (insn)))
                    223:            return insn;
                    224:          if (GET_CODE (insn) == JUMP_INSN)
                    225:            {
                    226:              if (simplejump_p (insn))
                    227:                next = JUMP_LABEL (insn);
                    228:              else
                    229:                return 0;
                    230:            }
                    231:          if (GET_CODE (insn) == CALL_INSN
                    232:              && REGNO (reg) < FIRST_PSEUDO_REGISTER
                    233:              && call_used_regs[REGNO (reg)])
                    234:            return 0;
                    235:        }
                    236:       else
                    237:        abort ();
                    238:     }
                    239:   return 0;
                    240: }
                    241: 
                    242: /* Return an rtx for the size in bytes of the value of EXP.  */
                    243: 
                    244: rtx
                    245: expr_size (exp)
                    246:      tree exp;
                    247: {
1.1.1.6   root      248:   tree size = size_in_bytes (TREE_TYPE (exp));
                    249: 
                    250:   if (TREE_CODE (size) != INTEGER_CST
                    251:       && contains_placeholder_p (size))
                    252:     size = build (WITH_RECORD_EXPR, sizetype, size, exp);
                    253: 
                    254:   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
1.1       root      255: }
                    256: 
                    257: /* Return a copy of X in which all memory references
                    258:    and all constants that involve symbol refs
                    259:    have been replaced with new temporary registers.
                    260:    Also emit code to load the memory locations and constants
                    261:    into those registers.
                    262: 
                    263:    If X contains no such constants or memory references,
                    264:    X itself (not a copy) is returned.
                    265: 
                    266:    If a constant is found in the address that is not a legitimate constant
                    267:    in an insn, it is left alone in the hope that it might be valid in the
                    268:    address.
                    269: 
                    270:    X may contain no arithmetic except addition, subtraction and multiplication.
                    271:    Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
                    272: 
                    273: static rtx
                    274: break_out_memory_refs (x)
                    275:      register rtx x;
                    276: {
                    277:   if (GET_CODE (x) == MEM
1.1.1.5   root      278:       || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
1.1       root      279:          && GET_MODE (x) != VOIDmode))
1.1.1.7   root      280:     x = force_reg (GET_MODE (x), x);
1.1       root      281:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
                    282:           || GET_CODE (x) == MULT)
                    283:     {
                    284:       register rtx op0 = break_out_memory_refs (XEXP (x, 0));
                    285:       register rtx op1 = break_out_memory_refs (XEXP (x, 1));
1.1.1.7   root      286: 
1.1       root      287:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
                    288:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
                    289:     }
1.1.1.7   root      290: 
1.1       root      291:   return x;
                    292: }
                    293: 
1.1.1.8 ! root      294: #ifdef POINTERS_EXTEND_UNSIGNED
        !           295: 
        !           296: /* Given X, a memory address in ptr_mode, convert it to an address
        !           297:    in Pmode, or vice versa (TO_MODE says which way).  We take advantage of
        !           298:    the fact that pointers are not allowed to overflow by commuting arithmetic
        !           299:    operations over conversions so that address arithmetic insns can be
        !           300:    used.  */
        !           301: 
        !           302: rtx
        !           303: convert_memory_address (to_mode, x)
        !           304:      enum machine_mode to_mode;
        !           305:      rtx x;
        !           306: {
        !           307:   rtx temp;
        !           308: 
        !           309:   switch (GET_CODE (x))
        !           310:     {
        !           311:     case CONST_INT:
        !           312:     case CONST_DOUBLE:
        !           313:       return x;
        !           314: 
        !           315:     case LABEL_REF:
        !           316:       return gen_rtx (LABEL_REF, to_mode, XEXP (x, 0));
        !           317: 
        !           318:     case SYMBOL_REF:
        !           319:       temp = gen_rtx (SYMBOL_REF, to_mode, XSTR (x, 0));
        !           320:       SYMBOL_REF_FLAG (temp) = SYMBOL_REF_FLAG (x);
        !           321:       return temp;
        !           322: 
        !           323:     case PLUS:
        !           324:     case MULT:
        !           325:       return gen_rtx (GET_CODE (x), to_mode, 
        !           326:                      convert_memory_address (to_mode, XEXP (x, 0)),
        !           327:                      convert_memory_address (to_mode, XEXP (x, 1)));
        !           328: 
        !           329:     case CONST:
        !           330:       return gen_rtx (CONST, to_mode, 
        !           331:                      convert_memory_address (to_mode, XEXP (x, 0)));
        !           332: 
        !           333:     default:
        !           334:       return convert_modes (to_mode,
        !           335:                            to_mode == ptr_mode ? Pmode : ptr_mode,
        !           336:                            x, POINTERS_EXTEND_UNSIGNED);
        !           337:     }
        !           338: }
        !           339: #endif
        !           340: 
1.1       root      341: /* Given a memory address or facsimile X, construct a new address,
                    342:    currently equivalent, that is stable: future stores won't change it.
                    343: 
                    344:    X must be composed of constants, register and memory references
                    345:    combined with addition, subtraction and multiplication:
                    346:    in other words, just what you can get from expand_expr if sum_ok is 1.
                    347: 
                    348:    Works by making copies of all regs and memory locations used
                    349:    by X and combining them the same way X does.
                    350:    You could also stabilize the reference to this address
                    351:    by copying the address to a register with copy_to_reg;
                    352:    but then you wouldn't get indexed addressing in the reference.  */
                    353: 
                    354: rtx
                    355: copy_all_regs (x)
                    356:      register rtx x;
                    357: {
                    358:   if (GET_CODE (x) == REG)
                    359:     {
1.1.1.6   root      360:       if (REGNO (x) != FRAME_POINTER_REGNUM
                    361: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
                    362:          && REGNO (x) != HARD_FRAME_POINTER_REGNUM
                    363: #endif
                    364:          )
1.1       root      365:        x = copy_to_reg (x);
                    366:     }
                    367:   else if (GET_CODE (x) == MEM)
                    368:     x = copy_to_reg (x);
                    369:   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
                    370:           || GET_CODE (x) == MULT)
                    371:     {
                    372:       register rtx op0 = copy_all_regs (XEXP (x, 0));
                    373:       register rtx op1 = copy_all_regs (XEXP (x, 1));
                    374:       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
                    375:        x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
                    376:     }
                    377:   return x;
                    378: }
                    379: 
                    380: /* Return something equivalent to X but valid as a memory address
                    381:    for something of mode MODE.  When X is not itself valid, this
                    382:    works by copying X or subexpressions of it into registers.  */
                    383: 
                    384: rtx
                    385: memory_address (mode, x)
                    386:      enum machine_mode mode;
                    387:      register rtx x;
                    388: {
1.1.1.7   root      389:   register rtx oldx = x;
1.1       root      390: 
1.1.1.8 ! root      391: #ifdef POINTERS_EXTEND_UNSIGNED
        !           392:   if (GET_MODE (x) == ptr_mode)
        !           393:     x = convert_memory_address (Pmode, x);
        !           394: #endif
        !           395: 
1.1       root      396:   /* By passing constant addresses thru registers
                    397:      we get a chance to cse them.  */
1.1.1.5   root      398:   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
1.1.1.7   root      399:     x = force_reg (Pmode, x);
1.1       root      400: 
                    401:   /* Accept a QUEUED that refers to a REG
                    402:      even though that isn't a valid address.
                    403:      On attempting to put this in an insn we will call protect_from_queue
                    404:      which will turn it into a REG, which is valid.  */
1.1.1.7   root      405:   else if (GET_CODE (x) == QUEUED
1.1       root      406:       && GET_CODE (QUEUED_VAR (x)) == REG)
1.1.1.7   root      407:     ;
1.1       root      408: 
                    409:   /* We get better cse by rejecting indirect addressing at this stage.
                    410:      Let the combiner create indirect addresses where appropriate.
                    411:      For now, generate the code so that the subexpressions useful to share
                    412:      are visible.  But not if cse won't be done!  */
1.1.1.7   root      413:   else
                    414:     {
                    415:       if (! cse_not_expected && GET_CODE (x) != REG)
                    416:        x = break_out_memory_refs (x);
1.1       root      417: 
1.1.1.7   root      418:       /* At this point, any valid address is accepted.  */
                    419:       GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
1.1       root      420: 
1.1.1.7   root      421:       /* If it was valid before but breaking out memory refs invalidated it,
                    422:         use it the old way.  */
                    423:       if (memory_address_p (mode, oldx))
                    424:        goto win2;
                    425: 
                    426:       /* Perform machine-dependent transformations on X
                    427:         in certain cases.  This is not necessary since the code
                    428:         below can handle all possible cases, but machine-dependent
                    429:         transformations can make better code.  */
                    430:       LEGITIMIZE_ADDRESS (x, oldx, mode, win);
                    431: 
                    432:       /* PLUS and MULT can appear in special ways
                    433:         as the result of attempts to make an address usable for indexing.
                    434:         Usually they are dealt with by calling force_operand, below.
                    435:         But a sum containing constant terms is special
                    436:         if removing them makes the sum a valid address:
                    437:         then we generate that address in a register
                    438:         and index off of it.  We do this because it often makes
                    439:         shorter code, and because the addresses thus generated
                    440:         in registers often become common subexpressions.  */
                    441:       if (GET_CODE (x) == PLUS)
                    442:        {
                    443:          rtx constant_term = const0_rtx;
                    444:          rtx y = eliminate_constant_term (x, &constant_term);
                    445:          if (constant_term == const0_rtx
                    446:              || ! memory_address_p (mode, y))
                    447:            x = force_operand (x, NULL_RTX);
                    448:          else
                    449:            {
                    450:              y = gen_rtx (PLUS, GET_MODE (x), copy_to_reg (y), constant_term);
                    451:              if (! memory_address_p (mode, y))
                    452:                x = force_operand (x, NULL_RTX);
                    453:              else
                    454:                x = y;
                    455:            }
                    456:        }
                    457: 
1.1.1.8 ! root      458:       else if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
1.1.1.7   root      459:        x = force_operand (x, NULL_RTX);
                    460: 
                    461:       /* If we have a register that's an invalid address,
                    462:         it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
                    463:       else if (GET_CODE (x) == REG)
                    464:        x = copy_to_reg (x);
                    465: 
                    466:       /* Last resort: copy the value to a register, since
                    467:         the register is a valid address.  */
1.1       root      468:       else
1.1.1.7   root      469:        x = force_reg (Pmode, x);
                    470: 
                    471:       goto done;
                    472: 
                    473:     win2:
                    474:       x = oldx;
                    475:     win:
                    476:       if (flag_force_addr && ! cse_not_expected && GET_CODE (x) != REG
                    477:          /* Don't copy an addr via a reg if it is one of our stack slots.  */
                    478:          && ! (GET_CODE (x) == PLUS
                    479:                && (XEXP (x, 0) == virtual_stack_vars_rtx
                    480:                    || XEXP (x, 0) == virtual_incoming_args_rtx)))
                    481:        {
                    482:          if (general_operand (x, Pmode))
                    483:            x = force_reg (Pmode, x);
                    484:          else
                    485:            x = force_operand (x, NULL_RTX);
                    486:        }
1.1       root      487:     }
1.1.1.7   root      488: 
                    489:  done:
                    490: 
                    491:   /* If we didn't change the address, we are done.  Otherwise, mark
                    492:      a reg as a pointer if we have REG or REG + CONST_INT.  */
                    493:   if (oldx == x)
                    494:     return x;
                    495:   else if (GET_CODE (x) == REG)
                    496:     mark_reg_pointer (x);
                    497:   else if (GET_CODE (x) == PLUS
                    498:           && GET_CODE (XEXP (x, 0)) == REG
                    499:           && GET_CODE (XEXP (x, 1)) == CONST_INT)
                    500:     mark_reg_pointer (XEXP (x, 0));
                    501: 
                    502:   /* OLDX may have been the address on a temporary.  Update the address
                    503:      to indicate that X is now used.  */
                    504:   update_temp_slot_address (oldx, x);
                    505: 
1.1       root      506:   return x;
                    507: }
                    508: 
                    509: /* Like `memory_address' but pretend `flag_force_addr' is 0.  */
                    510: 
                    511: rtx
                    512: memory_address_noforce (mode, x)
                    513:      enum machine_mode mode;
                    514:      rtx x;
                    515: {
                    516:   int ambient_force_addr = flag_force_addr;
                    517:   rtx val;
                    518: 
                    519:   flag_force_addr = 0;
                    520:   val = memory_address (mode, x);
                    521:   flag_force_addr = ambient_force_addr;
                    522:   return val;
                    523: }
                    524: 
                    525: /* Convert a mem ref into one with a valid memory address.
                    526:    Pass through anything else unchanged.  */
                    527: 
                    528: rtx
                    529: validize_mem (ref)
                    530:      rtx ref;
                    531: {
                    532:   if (GET_CODE (ref) != MEM)
                    533:     return ref;
                    534:   if (memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
                    535:     return ref;
                    536:   /* Don't alter REF itself, since that is probably a stack slot.  */
                    537:   return change_address (ref, GET_MODE (ref), XEXP (ref, 0));
                    538: }
                    539: 
                    540: /* Return a modified copy of X with its memory address copied
                    541:    into a temporary register to protect it from side effects.
                    542:    If X is not a MEM, it is returned unchanged (and not copied).
                    543:    Perhaps even if it is a MEM, if there is no need to change it.  */
                    544: 
                    545: rtx
                    546: stabilize (x)
                    547:      rtx x;
                    548: {
                    549:   register rtx addr;
                    550:   if (GET_CODE (x) != MEM)
                    551:     return x;
                    552:   addr = XEXP (x, 0);
                    553:   if (rtx_unstable_p (addr))
                    554:     {
                    555:       rtx temp = copy_all_regs (addr);
                    556:       rtx mem;
                    557:       if (GET_CODE (temp) != REG)
                    558:        temp = copy_to_reg (temp);
                    559:       mem = gen_rtx (MEM, GET_MODE (x), temp);
1.1.1.2   root      560: 
                    561:       /* Mark returned memref with in_struct if it's in an array or
                    562:         structure.  Copy const and volatile from original memref.  */
                    563: 
                    564:       MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (x) || GET_CODE (addr) == PLUS;
                    565:       RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (x);
                    566:       MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
1.1       root      567:       return mem;
                    568:     }
                    569:   return x;
                    570: }
                    571: 
                    572: /* Copy the value or contents of X to a new temp reg and return that reg.  */
                    573: 
                    574: rtx
                    575: copy_to_reg (x)
                    576:      rtx x;
                    577: {
                    578:   register rtx temp = gen_reg_rtx (GET_MODE (x));
                    579:  
                    580:   /* If not an operand, must be an address with PLUS and MULT so
                    581:      do the computation.  */ 
                    582:   if (! general_operand (x, VOIDmode))
                    583:     x = force_operand (x, temp);
                    584:   
                    585:   if (x != temp)
                    586:     emit_move_insn (temp, x);
                    587: 
                    588:   return temp;
                    589: }
                    590: 
                    591: /* Like copy_to_reg but always give the new register mode Pmode
                    592:    in case X is a constant.  */
                    593: 
                    594: rtx
                    595: copy_addr_to_reg (x)
                    596:      rtx x;
                    597: {
                    598:   return copy_to_mode_reg (Pmode, x);
                    599: }
                    600: 
                    601: /* Like copy_to_reg but always give the new register mode MODE
                    602:    in case X is a constant.  */
                    603: 
                    604: rtx
                    605: copy_to_mode_reg (mode, x)
                    606:      enum machine_mode mode;
                    607:      rtx x;
                    608: {
                    609:   register rtx temp = gen_reg_rtx (mode);
                    610:   
                    611:   /* If not an operand, must be an address with PLUS and MULT so
                    612:      do the computation.  */ 
                    613:   if (! general_operand (x, VOIDmode))
                    614:     x = force_operand (x, temp);
                    615: 
                    616:   if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
                    617:     abort ();
                    618:   if (x != temp)
                    619:     emit_move_insn (temp, x);
                    620:   return temp;
                    621: }
                    622: 
                    623: /* Load X into a register if it is not already one.
                    624:    Use mode MODE for the register.
                    625:    X should be valid for mode MODE, but it may be a constant which
                    626:    is valid for all integer modes; that's why caller must specify MODE.
                    627: 
                    628:    The caller must not alter the value in the register we return,
                    629:    since we mark it as a "constant" register.  */
                    630: 
                    631: rtx
                    632: force_reg (mode, x)
                    633:      enum machine_mode mode;
                    634:      rtx x;
                    635: {
1.1.1.7   root      636:   register rtx temp, insn, set;
1.1       root      637: 
                    638:   if (GET_CODE (x) == REG)
                    639:     return x;
                    640:   temp = gen_reg_rtx (mode);
                    641:   insn = emit_move_insn (temp, x);
1.1.1.7   root      642: 
1.1       root      643:   /* Let optimizers know that TEMP's value never changes
1.1.1.7   root      644:      and that X can be substituted for it.  Don't get confused
                    645:      if INSN set something else (such as a SUBREG of TEMP).  */
                    646:   if (CONSTANT_P (x)
                    647:       && (set = single_set (insn)) != 0
                    648:       && SET_DEST (set) == temp)
1.1       root      649:     {
1.1.1.4   root      650:       rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
1.1       root      651: 
                    652:       if (note)
                    653:        XEXP (note, 0) = x;
                    654:       else
                    655:        REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, x, REG_NOTES (insn));
                    656:     }
                    657:   return temp;
                    658: }
                    659: 
                    660: /* If X is a memory ref, copy its contents to a new temp reg and return
                    661:    that reg.  Otherwise, return X.  */
                    662: 
                    663: rtx
                    664: force_not_mem (x)
                    665:      rtx x;
                    666: {
                    667:   register rtx temp;
                    668:   if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode)
                    669:     return x;
                    670:   temp = gen_reg_rtx (GET_MODE (x));
                    671:   emit_move_insn (temp, x);
                    672:   return temp;
                    673: }
                    674: 
                    675: /* Copy X to TARGET (if it's nonzero and a reg)
                    676:    or to a new temp reg and return that reg.
1.1.1.2   root      677:    MODE is the mode to use for X in case it is a constant.  */
1.1       root      678: 
                    679: rtx
1.1.1.2   root      680: copy_to_suggested_reg (x, target, mode)
1.1       root      681:      rtx x, target;
1.1.1.2   root      682:      enum machine_mode mode;
1.1       root      683: {
                    684:   register rtx temp;
                    685: 
                    686:   if (target && GET_CODE (target) == REG)
                    687:     temp = target;
                    688:   else
1.1.1.2   root      689:     temp = gen_reg_rtx (mode);
1.1       root      690: 
                    691:   emit_move_insn (temp, x);
                    692:   return temp;
                    693: }
                    694: 
1.1.1.7   root      695: /* Return the mode to use to store a scalar of TYPE and MODE.
                    696:    PUNSIGNEDP points to the signedness of the type and may be adjusted
                    697:    to show what signedness to use on extension operations.
                    698: 
                    699:    FOR_CALL is non-zero if this call is promoting args for a call.  */
                    700: 
                    701: enum machine_mode
                    702: promote_mode (type, mode, punsignedp, for_call)
                    703:      tree type;
                    704:      enum machine_mode mode;
                    705:      int *punsignedp;
                    706:      int for_call;
                    707: {
                    708:   enum tree_code code = TREE_CODE (type);
                    709:   int unsignedp = *punsignedp;
                    710: 
                    711: #ifdef PROMOTE_FOR_CALL_ONLY
                    712:   if (! for_call)
                    713:     return mode;
                    714: #endif
                    715: 
                    716:   switch (code)
                    717:     {
                    718: #ifdef PROMOTE_MODE
                    719:     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
                    720:     case CHAR_TYPE:      case REAL_TYPE:       case OFFSET_TYPE:
                    721:       PROMOTE_MODE (mode, unsignedp, type);
                    722:       break;
                    723: #endif
                    724: 
1.1.1.8 ! root      725: #ifdef POINTERS_EXTEND_UNSIGNED
1.1.1.7   root      726:     case POINTER_TYPE:
1.1.1.8 ! root      727:       mode = Pmode;
        !           728:       unsignedp = POINTERS_EXTEND_UNSIGNED;
1.1.1.7   root      729:       break;
1.1.1.8 ! root      730: #endif
1.1.1.7   root      731:     }
                    732: 
                    733:   *punsignedp = unsignedp;
                    734:   return mode;
                    735: }
                    736: 
1.1       root      737: /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
                    738:    This pops when ADJUST is positive.  ADJUST need not be constant.  */
                    739: 
                    740: void
                    741: adjust_stack (adjust)
                    742:      rtx adjust;
                    743: {
                    744:   rtx temp;
                    745:   adjust = protect_from_queue (adjust, 0);
                    746: 
                    747:   if (adjust == const0_rtx)
                    748:     return;
                    749: 
                    750:   temp = expand_binop (Pmode,
                    751: #ifdef STACK_GROWS_DOWNWARD
                    752:                       add_optab,
                    753: #else
                    754:                       sub_optab,
                    755: #endif
                    756:                       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
                    757:                       OPTAB_LIB_WIDEN);
                    758: 
                    759:   if (temp != stack_pointer_rtx)
                    760:     emit_move_insn (stack_pointer_rtx, temp);
                    761: }
                    762: 
                    763: /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
                    764:    This pushes when ADJUST is positive.  ADJUST need not be constant.  */
                    765: 
                    766: void
                    767: anti_adjust_stack (adjust)
                    768:      rtx adjust;
                    769: {
                    770:   rtx temp;
                    771:   adjust = protect_from_queue (adjust, 0);
                    772: 
                    773:   if (adjust == const0_rtx)
                    774:     return;
                    775: 
                    776:   temp = expand_binop (Pmode,
                    777: #ifdef STACK_GROWS_DOWNWARD
                    778:                       sub_optab,
                    779: #else
                    780:                       add_optab,
                    781: #endif
                    782:                       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
                    783:                       OPTAB_LIB_WIDEN);
                    784: 
                    785:   if (temp != stack_pointer_rtx)
                    786:     emit_move_insn (stack_pointer_rtx, temp);
                    787: }
                    788: 
                    789: /* Round the size of a block to be pushed up to the boundary required
                    790:    by this machine.  SIZE is the desired size, which need not be constant.  */
                    791: 
                    792: rtx
                    793: round_push (size)
                    794:      rtx size;
                    795: {
                    796: #ifdef STACK_BOUNDARY
                    797:   int align = STACK_BOUNDARY / BITS_PER_UNIT;
                    798:   if (align == 1)
                    799:     return size;
                    800:   if (GET_CODE (size) == CONST_INT)
                    801:     {
                    802:       int new = (INTVAL (size) + align - 1) / align * align;
                    803:       if (INTVAL (size) != new)
1.1.1.4   root      804:        size = GEN_INT (new);
1.1       root      805:     }
                    806:   else
                    807:     {
1.1.1.7   root      808:       /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
                    809:         but we know it can't.  So add ourselves and then do TRUNC_DIV_EXPR. */
                    810:       size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
                    811:                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
                    812:       size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
1.1.1.4   root      813:                            NULL_RTX, 1);
                    814:       size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
1.1       root      815:     }
                    816: #endif /* STACK_BOUNDARY */
                    817:   return size;
                    818: }
                    819: 
1.1.1.3   root      820: /* Save the stack pointer for the purpose in SAVE_LEVEL.  PSAVE is a pointer
                    821:    to a previously-created save area.  If no save area has been allocated,
                    822:    this function will allocate one.  If a save area is specified, it
                    823:    must be of the proper mode.
                    824: 
                    825:    The insns are emitted after insn AFTER, if nonzero, otherwise the insns
                    826:    are emitted at the current position.  */
                    827: 
                    828: void
                    829: emit_stack_save (save_level, psave, after)
                    830:      enum save_level save_level;
                    831:      rtx *psave;
                    832:      rtx after;
                    833: {
                    834:   rtx sa = *psave;
                    835:   /* The default is that we use a move insn and save in a Pmode object.  */
                    836:   rtx (*fcn) () = gen_move_insn;
                    837:   enum machine_mode mode = Pmode;
                    838: 
                    839:   /* See if this machine has anything special to do for this kind of save.  */
                    840:   switch (save_level)
                    841:     {
                    842: #ifdef HAVE_save_stack_block
                    843:     case SAVE_BLOCK:
                    844:       if (HAVE_save_stack_block)
                    845:        {
                    846:          fcn = gen_save_stack_block;
                    847:          mode = insn_operand_mode[CODE_FOR_save_stack_block][0];
                    848:        }
                    849:       break;
                    850: #endif
                    851: #ifdef HAVE_save_stack_function
                    852:     case SAVE_FUNCTION:
                    853:       if (HAVE_save_stack_function)
                    854:        {
                    855:          fcn = gen_save_stack_function;
                    856:          mode = insn_operand_mode[CODE_FOR_save_stack_function][0];
                    857:        }
                    858:       break;
                    859: #endif
                    860: #ifdef HAVE_save_stack_nonlocal
                    861:     case SAVE_NONLOCAL:
                    862:       if (HAVE_save_stack_nonlocal)
                    863:        {
                    864:          fcn = gen_save_stack_nonlocal;
1.1.1.6   root      865:          mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
1.1.1.3   root      866:        }
                    867:       break;
                    868: #endif
                    869:     }
                    870: 
                    871:   /* If there is no save area and we have to allocate one, do so.  Otherwise
                    872:      verify the save area is the proper mode.  */
                    873: 
                    874:   if (sa == 0)
                    875:     {
                    876:       if (mode != VOIDmode)
                    877:        {
                    878:          if (save_level == SAVE_NONLOCAL)
                    879:            *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
                    880:          else
                    881:            *psave = sa = gen_reg_rtx (mode);
                    882:        }
                    883:     }
                    884:   else
                    885:     {
                    886:       if (mode == VOIDmode || GET_MODE (sa) != mode)
                    887:        abort ();
                    888:     }
                    889: 
                    890:   if (after)
                    891:     {
                    892:       rtx seq;
                    893: 
                    894:       start_sequence ();
1.1.1.5   root      895:       /* We must validize inside the sequence, to ensure that any instructions
                    896:         created by the validize call also get moved to the right place.  */
                    897:       if (sa != 0)
                    898:        sa = validize_mem (sa);
1.1.1.3   root      899:       emit_insn (fcn (sa, stack_pointer_rtx));
                    900:       seq = gen_sequence ();
                    901:       end_sequence ();
                    902:       emit_insn_after (seq, after);
                    903:     }
                    904:   else
1.1.1.5   root      905:     {
                    906:       if (sa != 0)
                    907:        sa = validize_mem (sa);
                    908:       emit_insn (fcn (sa, stack_pointer_rtx));
                    909:     }
1.1.1.3   root      910: }
                    911: 
                    912: /* Restore the stack pointer for the purpose in SAVE_LEVEL.  SA is the save
                    913:    area made by emit_stack_save.  If it is zero, we have nothing to do. 
                    914: 
                    915:    Put any emitted insns after insn AFTER, if nonzero, otherwise at 
                    916:    current position.  */
                    917: 
                    918: void
                    919: emit_stack_restore (save_level, sa, after)
                    920:      enum save_level save_level;
                    921:      rtx after;
                    922:      rtx sa;
                    923: {
                    924:   /* The default is that we use a move insn.  */
                    925:   rtx (*fcn) () = gen_move_insn;
                    926: 
                    927:   /* See if this machine has anything special to do for this kind of save.  */
                    928:   switch (save_level)
                    929:     {
                    930: #ifdef HAVE_restore_stack_block
                    931:     case SAVE_BLOCK:
                    932:       if (HAVE_restore_stack_block)
                    933:        fcn = gen_restore_stack_block;
                    934:       break;
                    935: #endif
                    936: #ifdef HAVE_restore_stack_function
                    937:     case SAVE_FUNCTION:
                    938:       if (HAVE_restore_stack_function)
                    939:        fcn = gen_restore_stack_function;
                    940:       break;
                    941: #endif
                    942: #ifdef HAVE_restore_stack_nonlocal
                    943: 
                    944:     case SAVE_NONLOCAL:
                    945:       if (HAVE_restore_stack_nonlocal)
                    946:        fcn = gen_restore_stack_nonlocal;
                    947:       break;
                    948: #endif
                    949:     }
                    950: 
                    951:   if (sa != 0)
                    952:     sa = validize_mem (sa);
                    953: 
                    954:   if (after)
                    955:     {
                    956:       rtx seq;
                    957: 
                    958:       start_sequence ();
                    959:       emit_insn (fcn (stack_pointer_rtx, sa));
                    960:       seq = gen_sequence ();
                    961:       end_sequence ();
                    962:       emit_insn_after (seq, after);
                    963:     }
                    964:   else
                    965:     emit_insn (fcn (stack_pointer_rtx, sa));
                    966: }
                    967: 
1.1       root      968: /* Return an rtx representing the address of an area of memory dynamically
                    969:    pushed on the stack.  This region of memory is always aligned to
                    970:    a multiple of BIGGEST_ALIGNMENT.
                    971: 
                    972:    Any required stack pointer alignment is preserved.
                    973: 
                    974:    SIZE is an rtx representing the size of the area.
1.1.1.3   root      975:    TARGET is a place in which the address can be placed.
                    976: 
                    977:    KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */
1.1       root      978: 
                    979: rtx
1.1.1.3   root      980: allocate_dynamic_stack_space (size, target, known_align)
1.1       root      981:      rtx size;
                    982:      rtx target;
1.1.1.3   root      983:      int known_align;
1.1       root      984: {
1.1.1.7   root      985:   /* If we're asking for zero bytes, it doesn't matter what we point
1.1.1.8 ! root      986:      to since we can't dereference it.  But return a reasonable
1.1.1.7   root      987:      address anyway.  */
                    988:   if (size == const0_rtx)
                    989:     return virtual_stack_dynamic_rtx;
                    990: 
                    991:   /* Otherwise, show we're calling alloca or equivalent.  */
                    992:   current_function_calls_alloca = 1;
                    993: 
1.1       root      994:   /* Ensure the size is in the proper mode.  */
                    995:   if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
                    996:     size = convert_to_mode (Pmode, size, 1);
                    997: 
                    998:   /* We will need to ensure that the address we return is aligned to
                    999:      BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't
                   1000:      always know its final value at this point in the compilation (it 
                   1001:      might depend on the size of the outgoing parameter lists, for
                   1002:      example), so we must align the value to be returned in that case.
                   1003:      (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if
                   1004:      STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
                   1005:      We must also do an alignment operation on the returned value if
                   1006:      the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
                   1007: 
                   1008:      If we have to align, we must leave space in SIZE for the hole
                   1009:      that might result from the alignment operation.  */
                   1010: 
1.1.1.8 ! root     1011: #if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS) || ! defined (STACK_BOUNDARY)
        !          1012: #define MUST_ALIGN 1
        !          1013: #else
        !          1014: #define MUST_ALIGN (STACK_BOUNDARY < BIGGEST_ALIGNMENT)
1.1       root     1015: #endif
                   1016: 
1.1.1.8 ! root     1017:   if (MUST_ALIGN)
1.1.1.3   root     1018:     {
                   1019:       if (GET_CODE (size) == CONST_INT)
1.1.1.4   root     1020:        size = GEN_INT (INTVAL (size)
                   1021:                        + (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1));
1.1.1.3   root     1022:       else
                   1023:        size = expand_binop (Pmode, add_optab, size,
1.1.1.4   root     1024:                             GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
                   1025:                             NULL_RTX, 1, OPTAB_LIB_WIDEN);
1.1.1.3   root     1026:     }
1.1.1.4   root     1027: 
1.1       root     1028: #ifdef SETJMP_VIA_SAVE_AREA
                   1029:   /* If setjmp restores regs from a save area in the stack frame,
                   1030:      avoid clobbering the reg save area.  Note that the offset of
                   1031:      virtual_incoming_args_rtx includes the preallocated stack args space.
                   1032:      It would be no problem to clobber that, but it's on the wrong side
                   1033:      of the old save area.  */
                   1034:   {
                   1035:     rtx dynamic_offset
                   1036:       = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
1.1.1.4   root     1037:                      stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
1.1       root     1038:     size = expand_binop (Pmode, add_optab, size, dynamic_offset,
1.1.1.4   root     1039:                         NULL_RTX, 1, OPTAB_LIB_WIDEN);
1.1       root     1040:   }
                   1041: #endif /* SETJMP_VIA_SAVE_AREA */
                   1042: 
                   1043:   /* Round the size to a multiple of the required stack alignment.
                   1044:      Since the stack if presumed to be rounded before this allocation,
                   1045:      this will maintain the required alignment.
                   1046: 
                   1047:      If the stack grows downward, we could save an insn by subtracting
                   1048:      SIZE from the stack pointer and then aligning the stack pointer.
                   1049:      The problem with this is that the stack pointer may be unaligned
                   1050:      between the execution of the subtraction and alignment insns and
                   1051:      some machines do not allow this.  Even on those that do, some
                   1052:      signal handlers malfunction if a signal should occur between those
                   1053:      insns.  Since this is an extremely rare event, we have no reliable
                   1054:      way of knowing which systems have this problem.  So we avoid even
                   1055:      momentarily mis-aligning the stack.  */
                   1056: 
1.1.1.3   root     1057: #ifdef STACK_BOUNDARY
1.1.1.4   root     1058:   /* If we added a variable amount to SIZE,
                   1059:      we can no longer assume it is aligned.  */
1.1.1.8 ! root     1060: #if !defined (SETJMP_VIA_SAVE_AREA)
        !          1061:   if (MUST_ALIGN || known_align % STACK_BOUNDARY != 0)
1.1.1.4   root     1062: #endif
1.1.1.3   root     1063:     size = round_push (size);
                   1064: #endif
1.1       root     1065: 
                   1066:   do_pending_stack_adjust ();
                   1067: 
1.1.1.3   root     1068:   /* Don't use a TARGET that isn't a pseudo.  */
                   1069:   if (target == 0 || GET_CODE (target) != REG
                   1070:       || REGNO (target) < FIRST_PSEUDO_REGISTER)
1.1       root     1071:     target = gen_reg_rtx (Pmode);
                   1072: 
1.1.1.3   root     1073:   mark_reg_pointer (target);
                   1074: 
1.1       root     1075: #ifndef STACK_GROWS_DOWNWARD
                   1076:   emit_move_insn (target, virtual_stack_dynamic_rtx);
                   1077: #endif
                   1078: 
                   1079:   /* Perform the required allocation from the stack.  Some systems do
                   1080:      this differently than simply incrementing/decrementing from the
                   1081:      stack pointer.  */
                   1082: #ifdef HAVE_allocate_stack
                   1083:   if (HAVE_allocate_stack)
                   1084:     {
                   1085:       enum machine_mode mode
                   1086:        = insn_operand_mode[(int) CODE_FOR_allocate_stack][0];
                   1087: 
1.1.1.8 ! root     1088:       size = convert_modes (mode, ptr_mode, size, 1);
        !          1089: 
1.1       root     1090:       if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]
                   1091:          && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])
                   1092:                (size, mode)))
                   1093:        size = copy_to_mode_reg (mode, size);
                   1094: 
                   1095:       emit_insn (gen_allocate_stack (size));
                   1096:     }
                   1097:   else
                   1098: #endif
1.1.1.8 ! root     1099:     {
        !          1100:       size = convert_modes (Pmode, ptr_mode, size, 1);
        !          1101:       anti_adjust_stack (size);
        !          1102:     }
1.1       root     1103: 
                   1104: #ifdef STACK_GROWS_DOWNWARD
                   1105:   emit_move_insn (target, virtual_stack_dynamic_rtx);
                   1106: #endif
                   1107: 
1.1.1.8 ! root     1108:   if (MUST_ALIGN)
1.1.1.3   root     1109:     {
1.1.1.7   root     1110:       /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
                   1111:         but we know it can't.  So add ourselves and then do TRUNC_DIV_EXPR. */
                   1112:       target = expand_binop (Pmode, add_optab, target,
                   1113:                             GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
                   1114:                             NULL_RTX, 1, OPTAB_LIB_WIDEN);
                   1115:       target = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, target,
1.1.1.4   root     1116:                              GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
                   1117:                              NULL_RTX, 1);
1.1.1.3   root     1118:       target = expand_mult (Pmode, target,
1.1.1.4   root     1119:                            GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
                   1120:                            NULL_RTX, 1);
1.1.1.3   root     1121:     }
1.1       root     1122:   
                   1123:   /* Some systems require a particular insn to refer to the stack
                   1124:      to make the pages exist.  */
                   1125: #ifdef HAVE_probe
                   1126:   if (HAVE_probe)
                   1127:     emit_insn (gen_probe ());
                   1128: #endif
                   1129: 
1.1.1.7   root     1130:   /* Record the new stack level for nonlocal gotos.  */
                   1131:   if (nonlocal_goto_handler_slot != 0)
                   1132:     emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
                   1133: 
1.1       root     1134:   return target;
                   1135: }
                   1136: 
                   1137: /* Return an rtx representing the register or memory location
                   1138:    in which a scalar value of data type VALTYPE
                   1139:    was returned by a function call to function FUNC.
                   1140:    FUNC is a FUNCTION_DECL node if the precise function is known,
                   1141:    otherwise 0.  */
                   1142: 
                   1143: rtx
                   1144: hard_function_value (valtype, func)
                   1145:      tree valtype;
                   1146:      tree func;
                   1147: {
1.1.1.8 ! root     1148:   rtx val = FUNCTION_VALUE (valtype, func);
        !          1149:   if (GET_CODE (val) == REG
        !          1150:       && GET_MODE (val) == BLKmode)
        !          1151:     {
        !          1152:       int bytes = int_size_in_bytes (valtype);
        !          1153:       enum machine_mode tmpmode;
        !          1154:       for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
        !          1155:            tmpmode != MAX_MACHINE_MODE;
        !          1156:            tmpmode = GET_MODE_WIDER_MODE (tmpmode))
        !          1157:         {
        !          1158:           /* Have we found a large enough mode?  */
        !          1159:           if (GET_MODE_SIZE (tmpmode) >= bytes)
        !          1160:             break;
        !          1161:         }
        !          1162: 
        !          1163:       /* No suitable mode found.  */
        !          1164:       if (tmpmode == MAX_MACHINE_MODE)
        !          1165:         abort ();
        !          1166: 
        !          1167:       PUT_MODE (val, tmpmode);
        !          1168:     }      
        !          1169:   return val;
1.1       root     1170: }
                   1171: 
                   1172: /* Return an rtx representing the register or memory location
                   1173:    in which a scalar value of mode MODE was returned by a library call.  */
                   1174: 
                   1175: rtx
                   1176: hard_libcall_value (mode)
                   1177:      enum machine_mode mode;
                   1178: {
                   1179:   return LIBCALL_VALUE (mode);
                   1180: }
1.1.1.5   root     1181: 
                   1182: /* Look up the tree code for a given rtx code
                   1183:    to provide the arithmetic operation for REAL_ARITHMETIC.
                   1184:    The function returns an int because the caller may not know
                   1185:    what `enum tree_code' means.  */
                   1186: 
                   1187: int
                   1188: rtx_to_tree_code (code)
                   1189:      enum rtx_code code;
                   1190: {
                   1191:   enum tree_code tcode;
                   1192: 
                   1193:   switch (code)
                   1194:     {
                   1195:     case PLUS:
                   1196:       tcode = PLUS_EXPR;
                   1197:       break;
                   1198:     case MINUS:
                   1199:       tcode = MINUS_EXPR;
                   1200:       break;
                   1201:     case MULT:
                   1202:       tcode = MULT_EXPR;
                   1203:       break;
                   1204:     case DIV:
                   1205:       tcode = RDIV_EXPR;
                   1206:       break;
                   1207:     case SMIN:
                   1208:       tcode = MIN_EXPR;
                   1209:       break;
                   1210:     case SMAX:
                   1211:       tcode = MAX_EXPR;
                   1212:       break;
                   1213:     default:
                   1214:       tcode = LAST_AND_UNUSED_TREE_CODE;
                   1215:       break;
                   1216:     }
                   1217:   return ((int) tcode);
                   1218: }

unix.superglobalmegacorp.com

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