Annotation of gcc/cp/except.c, revision 1.1.1.2

1.1       root        1: /* Handle exceptional things in C++.
1.1.1.2 ! root        2:    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1.1       root        3:    Contributed by Michael Tiemann <[email protected]>
                      4:    Rewritten by Mike Stump <[email protected]>, based upon an
                      5:    initial re-implementation courtesy Tad Hunt.
                      6: 
                      7: This file is part of GNU CC.
                      8: 
                      9: GNU CC is free software; you can redistribute it and/or modify
                     10: it under the terms of the GNU General Public License as published by
                     11: the Free Software Foundation; either version 2, or (at your option)
                     12: any later version.
                     13: 
                     14: GNU CC is distributed in the hope that it will be useful,
                     15: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: GNU General Public License for more details.
                     18: 
                     19: You should have received a copy of the GNU General Public License
                     20: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.2 ! root       21: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            22: Boston, MA 02111-1307, USA.  */
1.1       root       23: 
                     24: 
                     25: /* High-level class interface. */
                     26: 
                     27: #include "config.h"
                     28: #include "tree.h"
                     29: #include "rtl.h"
                     30: #include "cp-tree.h"
                     31: #include "flags.h"
                     32: #include "obstack.h"
                     33: #include "expr.h"
                     34: 
1.1.1.2 ! root       35: tree protect_list;
        !            36: 
1.1       root       37: extern void (*interim_eh_hook) PROTO((tree));
1.1.1.2 ! root       38: rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
1.1       root       39: 
                     40: /* holds the fndecl for __builtin_return_address () */
                     41: tree builtin_return_address_fndecl;
1.1.1.2 ! root       42: tree throw_fndecl;
1.1       root       43: 
                     44: static int
                     45: doing_eh (do_warn)
                     46:      int do_warn;
                     47: {
                     48:   if (! flag_handle_exceptions)
                     49:     {
                     50:       static int warned = 0;
                     51:       if (! warned && do_warn)
                     52:        {
                     53:          error ("exception handling disabled, use -fhandle-exceptions to enable.");
                     54:          warned = 1;
                     55:        }
                     56:       return 0;
                     57:     }
                     58:   return 1;
                     59: }
                     60: 
                     61: 
                     62: /*
                     63: NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
1.1.1.2 ! root       64: to supporting exception handling as per ANSI C++ working draft.
1.1       root       65: It is a complete rewrite of all the EH stuff that was here before
                     66:        Shortcomings:
1.1.1.2 ! root       67:                1. Throw specifications of functions still don't work.
1.1       root       68:        Cool Things:
                     69:                1. Destructors are called properly :-)
                     70:                2. No overhead for the non-exception thrown case.
1.1.1.2 ! root       71:                3. Fixing shortcoming 1 is simple.
1.1       root       72:                        -Tad Hunt       ([email protected])
                     73: 
                     74: */
                     75: 
                     76: /* A couple of backend routines from m88k.c */
                     77: 
                     78: /* used to cache a call to __builtin_return_address () */
                     79: static tree BuiltinReturnAddress;
1.1.1.2 ! root       80:      
1.1       root       81: 
                     82: #include <stdio.h>
                     83: 
                     84: /* XXX - Tad: for EH */
                     85: /* output an exception table entry */
                     86: 
                     87: static void
                     88: output_exception_table_entry (file, start_label, end_label, eh_label)
                     89:      FILE *file;
                     90:      rtx start_label, end_label, eh_label;
                     91: {
                     92:   char label[100];
                     93: 
1.1.1.2 ! root       94:   assemble_integer (start_label, GET_MODE_SIZE (Pmode), 1);
        !            95:   assemble_integer (end_label, GET_MODE_SIZE (Pmode), 1);
        !            96:   assemble_integer (eh_label, GET_MODE_SIZE (Pmode), 1);
1.1       root       97:   putc ('\n', file);           /* blank line */
                     98: }
                     99:    
                    100: static void
                    101: easy_expand_asm (str)
                    102:      char *str;
                    103: {
                    104:   expand_asm (build_string (strlen (str)+1, str));
                    105: }
                    106: 
                    107: 
                    108: #if 0
                    109: /* This is the startup, and finish stuff per exception table. */
                    110: 
                    111: /* XXX - Tad: exception handling section */
                    112: #ifndef EXCEPT_SECTION_ASM_OP
                    113: #define EXCEPT_SECTION_ASM_OP  "section\t.gcc_except_table,\"a\",@progbits"
                    114: #endif
                    115: 
                    116: #ifdef EXCEPT_SECTION_ASM_OP
                    117: typedef struct {
                    118:     void *start_protect;
                    119:     void *end_protect;
                    120:     void *exception_handler;
                    121:  } exception_table;
                    122: #endif /* EXCEPT_SECTION_ASM_OP */
                    123: 
                    124: #ifdef EXCEPT_SECTION_ASM_OP
                    125: 
                    126:  /* on machines which support it, the exception table lives in another section,
                    127:        but it needs a label so we can reference it...  This sets up that
                    128:     label! */
                    129: asm (EXCEPT_SECTION_ASM_OP);
                    130: exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
                    131: asm (TEXT_SECTION_ASM_OP);
                    132: 
                    133: #endif /* EXCEPT_SECTION_ASM_OP */
                    134: 
                    135: #ifdef EXCEPT_SECTION_ASM_OP
                    136: 
                    137:  /* we need to know where the end of the exception table is... so this
                    138:     is how we do it! */
                    139: 
                    140: asm (EXCEPT_SECTION_ASM_OP);
                    141: exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
                    142: asm (TEXT_SECTION_ASM_OP);
                    143: 
                    144: #endif /* EXCEPT_SECTION_ASM_OP */
                    145: 
                    146: #endif
                    147: 
                    148: void
                    149: exception_section ()
                    150: {
                    151: #ifdef ASM_OUTPUT_SECTION_NAME
1.1.1.2 ! root      152:   named_section (NULL_TREE, ".gcc_except_table");
1.1       root      153: #else
1.1.1.2 ! root      154:   if (flag_pic)
        !           155:     data_section ();
        !           156:   else
        !           157: #if defined(TARGET_POWERPC) /* are we on a __rs6000? */
        !           158:     data_section ();
        !           159: #else
        !           160:     readonly_data_section ();
        !           161: #endif
1.1       root      162: #endif
                    163: }
                    164: 
                    165: 
                    166: 
                    167: 
                    168: /* from: my-cp-except.c */
                    169: 
                    170: /* VI: ":set ts=4" */
                    171: #if 0
                    172: #include <stdio.h> */
                    173: #include "config.h"
                    174: #include "tree.h"
                    175: #include "rtl.h"
                    176: #include "cp-tree.h"
                    177: #endif
                    178: #include "decl.h"
                    179: #if 0
                    180: #include "flags.h"
                    181: #endif
                    182: #include "insn-flags.h"
                    183: #include "obstack.h"
                    184: #if 0
                    185: #include "expr.h"
                    186: #endif
                    187: 
                    188: /* ======================================================================
                    189:    Briefly the algorithm works like this:
                    190: 
                    191:      When a constructor or start of a try block is encountered,
                    192:      push_eh_entry (&eh_stack) is called.  Push_eh_entry () creates a
                    193:      new entry in the unwind protection stack and returns a label to
                    194:      output to start the protection for that block.
                    195: 
                    196:      When a destructor or end try block is encountered, pop_eh_entry
                    197:      (&eh_stack) is called.  Pop_eh_entry () returns the ehEntry it
                    198:      created when push_eh_entry () was called.  The ehEntry structure
                    199:      contains three things at this point.  The start protect label,
                    200:      the end protect label, and the exception handler label.  The end
                    201:      protect label should be output before the call to the destructor
                    202:      (if any). If it was a destructor, then its parse tree is stored
                    203:      in the finalization variable in the ehEntry structure.  Otherwise
                    204:      the finalization variable is set to NULL to reflect the fact that
                    205:      is the the end of a try block.  Next, this modified ehEntry node
                    206:      is enqueued in the finalizations queue by calling
                    207:      enqueue_eh_entry (&queue,entry).
                    208: 
                    209:        +---------------------------------------------------------------+
                    210:        |XXX: Will need modification to deal with partially             |
                    211:        |                       constructed arrays of objects           |
                    212:        |                                                               |
                    213:        |       Basically, this consists of keeping track of how many   |
                    214:        |       of the objects have been constructed already (this      |
                    215:        |       should be in a register though, so that shouldn't be a  |
                    216:        |       problem.                                                |
                    217:        +---------------------------------------------------------------+
                    218: 
                    219:      When a catch block is encountered, there is a lot of work to be
                    220:      done.
                    221: 
                    222:      Since we don't want to generate the catch block inline with the
                    223:      regular flow of the function, we need to have some way of doing
1.1.1.2 ! root      224:      so.  Luckily, we can use sequences to defer the catch sections.
        !           225:      When the start of a catch block is encountered, we start the
        !           226:      sequence.  After the catch block is generated, we end the
        !           227:      sequence.
        !           228: 
1.1       root      229:      Next we must insure that when the catch block is executed, all
                    230:      finalizations for the matching try block have been completed.  If
                    231:      any of those finalizations throw an exception, we must call
                    232:      terminate according to the ARM (section r.15.6.1).  What this
                    233:      means is that we need to dequeue and emit finalizations for each
                    234:      entry in the ehQueue until we get to an entry with a NULL
                    235:      finalization field.  For any of the finalization entries, if it
                    236:      is not a call to terminate (), we must protect it by giving it
                    237:      another start label, end label, and exception handler label,
                    238:      setting its finalization tree to be a call to terminate (), and
                    239:      enqueue'ing this new ehEntry to be output at an outer level.
                    240:      Finally, after all that is done, we can get around to outputting
                    241:      the catch block which basically wraps all the "catch (...) {...}"
                    242:      statements in a big if/then/else construct that matches the
                    243:      correct block to call.
                    244:      
                    245:      ===================================================================== */
                    246: 
                    247: extern rtx emit_insn           PROTO((rtx));
                    248: extern rtx gen_nop             PROTO(());
                    249: 
                    250: /* local globals for function calls
                    251:    ====================================================================== */
                    252: 
                    253: /* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
1.1.1.2 ! root      254:    "set_unexpected ()" after default_conversion. (lib-except.c)  */
        !           255: static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch, Throw;
1.1       root      256: 
                    257: /* used to cache __find_first_exception_table_match ()
                    258:    for throw (lib-except.c)  */
                    259: static tree FirstExceptionMatch;
                    260: 
1.1.1.2 ! root      261: /* used to cache a call to __unwind_function () (lib-except.c)  */
1.1       root      262: static tree Unwind;
                    263: 
1.1.1.2 ! root      264: /* holds a ready to emit call to "terminate ()".  */
1.1       root      265: static tree TerminateFunctionCall;
                    266: 
                    267: /* ====================================================================== */
                    268: 
                    269: 
                    270: 
                    271: /* data structures for my various quick and dirty stacks and queues
                    272:    Eventually, most of this should go away, because I think it can be
1.1.1.2 ! root      273:    integrated with stuff already built into the compiler.  */
1.1       root      274: 
                    275: /* =================================================================== */
                    276: 
                    277: struct labelNode {
1.1.1.2 ! root      278:   rtx label;
        !           279:   struct labelNode *chain;
        !           280: };
1.1       root      281: 
                    282: 
                    283: /* this is the most important structure here.  Basically this is how I store
                    284:    an exception table entry internally. */
                    285: struct ehEntry {
1.1.1.2 ! root      286:   rtx start_label;
        !           287:   rtx end_label;
        !           288:   rtx exception_handler_label;
        !           289: 
        !           290:   tree finalization;
        !           291:   tree context;
        !           292: };
1.1       root      293: 
                    294: struct ehNode {
1.1.1.2 ! root      295:   struct ehEntry *entry;
        !           296:   struct ehNode *chain;
        !           297: };
1.1       root      298: 
                    299: struct ehStack {
1.1.1.2 ! root      300:   struct ehNode *top;
        !           301: };
1.1       root      302: 
                    303: struct ehQueue {
1.1.1.2 ! root      304:   struct ehNode *head;
        !           305:   struct ehNode *tail;
        !           306: };
1.1       root      307: /* ========================================================================= */
                    308: 
                    309: 
                    310: 
                    311: /* local globals - these local globals are for storing data necessary for
                    312:    generating the exception table and code in the correct order.
                    313: 
                    314:    ========================================================================= */
                    315: 
                    316: /* Holds the pc for doing "throw" */
1.1.1.2 ! root      317: tree saved_pc;
1.1       root      318: /* Holds the type of the thing being thrown. */
1.1.1.2 ! root      319: tree saved_throw_type;
1.1       root      320: /* Holds the value being thrown.  */
1.1.1.2 ! root      321: tree saved_throw_value;
        !           322: 
        !           323: int throw_used;
1.1       root      324: 
1.1.1.2 ! root      325: static rtx catch_clauses;
        !           326: static first_catch_label;
1.1       root      327: 
                    328: static struct ehStack ehstack;
                    329: static struct ehQueue ehqueue;
                    330: static struct ehQueue eh_table_output_queue;
                    331: static struct labelNode *false_label_stack = NULL;
                    332: static struct labelNode *caught_return_label_stack = NULL;
                    333: /* ========================================================================= */
                    334: 
                    335: /* function prototypes */
                    336: static struct ehEntry *pop_eh_entry    PROTO((struct ehStack *stack));
                    337: static void enqueue_eh_entry           PROTO((struct ehQueue *queue, struct ehEntry *entry));
                    338: static rtx push_eh_entry               PROTO((struct ehStack *stack));
                    339: static struct ehEntry *dequeue_eh_entry        PROTO((struct ehQueue *queue));
                    340: static void new_eh_queue               PROTO((struct ehQueue *queue));
                    341: static void new_eh_stack               PROTO((struct ehStack *stack));
                    342: static void push_label_entry           PROTO((struct labelNode **labelstack, rtx label));
                    343: static rtx pop_label_entry             PROTO((struct labelNode **labelstack));
                    344: static rtx top_label_entry             PROTO((struct labelNode **labelstack));
                    345: static struct ehEntry *copy_eh_entry   PROTO((struct ehEntry *entry));
                    346: 
                    347: 
                    348: 
                    349: /* All my cheesy stack/queue/misc data structure handling routines
                    350: 
                    351:    ========================================================================= */
                    352: 
                    353: static void
                    354: push_label_entry (labelstack, label)
                    355:      struct labelNode **labelstack;
                    356:      rtx label;
                    357: {
                    358:   struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
                    359: 
                    360:   newnode->label = label;
                    361:   newnode->chain = *labelstack;
                    362:   *labelstack = newnode;
                    363: }
                    364: 
                    365: static rtx
                    366: pop_label_entry (labelstack)
                    367:      struct labelNode **labelstack;
                    368: {
                    369:   rtx label;
                    370:   struct labelNode *tempnode;
                    371: 
                    372:   if (! *labelstack) return NULL_RTX;
                    373: 
                    374:   tempnode = *labelstack;
                    375:   label = tempnode->label;
                    376:   *labelstack = (*labelstack)->chain;
                    377:   free (tempnode);
                    378: 
                    379:   return label;
                    380: }
                    381: 
                    382: static rtx
                    383: top_label_entry (labelstack)
                    384:      struct labelNode **labelstack;
                    385: {
                    386:   if (! *labelstack) return NULL_RTX;
                    387: 
                    388:   return (*labelstack)->label;
                    389: }
                    390: 
                    391: /* Push to permanent obstack for rtl generation.
                    392:    One level only!  */
                    393: static struct obstack *saved_rtl_obstack;
                    394: void
                    395: push_rtl_perm ()
                    396: {
                    397:   extern struct obstack permanent_obstack;
                    398:   extern struct obstack *rtl_obstack;
                    399:   
                    400:   saved_rtl_obstack = rtl_obstack;
                    401:   rtl_obstack = &permanent_obstack;
                    402: }
                    403: 
                    404: /* Pop back to normal rtl handling.  */
                    405: static void
                    406: pop_rtl_from_perm ()
                    407: {
                    408:   extern struct obstack permanent_obstack;
                    409:   extern struct obstack *rtl_obstack;
                    410:   
                    411:   rtl_obstack = saved_rtl_obstack;
                    412: }
                    413: 
                    414: static rtx
                    415: push_eh_entry (stack)
                    416:      struct ehStack *stack;
                    417: {
                    418:   struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
                    419:   struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
                    420: 
                    421:   if (stack == NULL) {
                    422:     free (node);
                    423:     free (entry);
                    424:     return NULL_RTX;
                    425:   }
                    426: 
                    427:   /* These are saved for the exception table.  */
                    428:   push_rtl_perm ();
                    429:   entry->start_label = gen_label_rtx ();
                    430:   entry->end_label = gen_label_rtx ();
                    431:   entry->exception_handler_label = gen_label_rtx ();
                    432:   pop_rtl_from_perm ();
                    433: 
1.1.1.2 ! root      434:   LABEL_PRESERVE_P (entry->start_label) = 1;
        !           435:   LABEL_PRESERVE_P (entry->end_label) = 1;
        !           436:   LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
        !           437: 
1.1       root      438:   entry->finalization = NULL_TREE;
1.1.1.2 ! root      439:   entry->context = current_function_decl;
1.1       root      440: 
                    441:   node->entry = entry;
                    442:   node->chain = stack->top;
                    443:   stack->top = node;
                    444: 
                    445:   enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
                    446: 
                    447:   return entry->start_label;
                    448: }
                    449: 
                    450: static struct ehEntry *
                    451: pop_eh_entry (stack)
                    452:      struct ehStack *stack;
                    453: {
                    454:   struct ehNode *tempnode;
                    455:   struct ehEntry *tempentry;
                    456: 
                    457:   if (stack && (tempnode = stack->top)) {
                    458:     tempentry = tempnode->entry;
                    459:     stack->top = stack->top->chain;
                    460:     free (tempnode);
                    461: 
                    462:     return tempentry;
                    463:   }
                    464: 
                    465:   return NULL;
                    466: }
                    467: 
                    468: static struct ehEntry *
                    469: copy_eh_entry (entry)
                    470:      struct ehEntry *entry;
                    471: {
                    472:   struct ehEntry *newentry;
                    473: 
                    474:   newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
                    475:   memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
                    476: 
                    477:   return newentry;
                    478: }
                    479: 
                    480: static void
                    481: enqueue_eh_entry (queue, entry)
                    482:      struct ehQueue *queue;
                    483:      struct ehEntry *entry;
                    484: {
                    485:   struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
                    486: 
                    487:   node->entry = entry;
                    488:   node->chain = NULL;
                    489: 
                    490:   if (queue->head == NULL)
                    491:     {
                    492:       queue->head = node;
                    493:     }
                    494:   else
                    495:     {
                    496:       queue->tail->chain = node;
                    497:     }
                    498:   queue->tail = node;
                    499: }
                    500: 
                    501: static struct ehEntry *
                    502: dequeue_eh_entry (queue)
                    503:      struct ehQueue *queue;
                    504: {
                    505:   struct ehNode *tempnode;
                    506:   struct ehEntry *tempentry;
                    507: 
                    508:   if (queue->head == NULL)
                    509:     return NULL;
                    510: 
                    511:   tempnode = queue->head;
                    512:   queue->head = queue->head->chain;
                    513: 
                    514:   tempentry = tempnode->entry;
                    515:   free (tempnode);
                    516: 
                    517:   return tempentry;
                    518: }
                    519: 
                    520: static void
                    521: new_eh_queue (queue)
                    522:      struct ehQueue *queue;
                    523: {
                    524:   queue->head = queue->tail = NULL;
                    525: }
                    526: 
                    527: static void
                    528: new_eh_stack (stack)
                    529:      struct ehStack *stack;
                    530: {
                    531:   stack->top = NULL;
                    532: }
                    533: 
1.1.1.2 ! root      534: /* cheesyness to save some typing. returns the return value rtx */
        !           535: rtx
        !           536: do_function_call (func, params, return_type)
        !           537:      tree func, params, return_type;
        !           538: {
        !           539:   tree func_call;
        !           540:   func_call = build_function_call (func, params);
        !           541:   expand_call (func_call, NULL_RTX, 0);
        !           542:   if (return_type != NULL_TREE)
        !           543:     return hard_function_value (return_type, func_call);
        !           544:   return NULL_RTX;
        !           545: }
        !           546: 
1.1       root      547: static void
1.1.1.2 ! root      548: expand_internal_throw (pc)
        !           549:      rtx pc;
1.1       root      550: {
1.1.1.2 ! root      551:   tree params;
        !           552: 
        !           553:   emit_move_insn (DECL_RTL (saved_pc), pc);
        !           554: #ifdef JUMP_TO_THROW
        !           555:   emit_indirect_jump (gen_rtx (SYMBOL_REF, Pmode, "__throw"));
        !           556: #else
        !           557:   do_function_call (Throw, NULL_TREE, NULL_TREE);
        !           558: #endif
        !           559:   throw_used = 1;
1.1       root      560: }
1.1.1.2 ! root      561: 
1.1       root      562: /* ========================================================================= */
                    563: 
                    564: void
                    565: lang_interim_eh (finalization)
                    566:      tree finalization;
                    567: {
                    568:   if (finalization)
                    569:     end_protect (finalization);
                    570:   else
                    571:     start_protect ();
                    572: }
                    573: 
1.1.1.2 ! root      574: extern tree auto_function PROTO((tree, tree, enum built_in_function));
        !           575: 
1.1       root      576: /* sets up all the global eh stuff that needs to be initialized at the
                    577:    start of compilation.
                    578: 
                    579:    This includes:
                    580:                - Setting up all the function call trees
                    581:                - Initializing the ehqueue
                    582:                - Initializing the eh_table_output_queue
                    583:                - Initializing the ehstack
                    584: */
                    585: 
                    586: void
                    587: init_exception_processing ()
                    588: {
                    589:   extern tree define_function ();
                    590:   tree unexpected_fndecl, terminate_fndecl;
                    591:   tree set_unexpected_fndecl, set_terminate_fndecl;
                    592:   tree catch_match_fndecl;
                    593:   tree find_first_exception_match_fndecl;
                    594:   tree unwind_fndecl;
1.1.1.2 ! root      595:   tree declspecs;
        !           596:   tree d;
1.1       root      597: 
                    598:   /* void (*)() */
1.1.1.2 ! root      599:   tree PFV = build_pointer_type (build_function_type
        !           600:                                 (void_type_node, void_list_node));
1.1       root      601: 
                    602:   /* arg list for the build_function_type call for set_terminate () and
                    603:      set_unexpected () */
1.1.1.2 ! root      604:   tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
1.1       root      605: 
1.1.1.2 ! root      606:   /* void (*pfvtype (void (*) ()))() */
        !           607:   tree pfvtype = build_function_type (PFV, pfvlist);
1.1       root      608: 
1.1.1.2 ! root      609:   /* void vtype () */
        !           610:   tree vtype = build_function_type (void_type_node, void_list_node);
        !           611:   
        !           612:   set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
        !           613:                                        pfvtype, NOT_BUILT_IN);
        !           614:   set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
        !           615:                                         pfvtype, NOT_BUILT_IN);
        !           616:   unexpected_fndecl = auto_function (get_identifier ("unexpected"),
        !           617:                                     vtype, NOT_BUILT_IN);
        !           618:   terminate_fndecl = auto_function (get_identifier ("terminate"),
        !           619:                                    vtype, NOT_BUILT_IN);
        !           620: 
        !           621:   interim_eh_hook = lang_interim_eh;
        !           622: 
        !           623:   push_lang_context (lang_name_c);
1.1       root      624: 
                    625:   catch_match_fndecl =
1.1.1.2 ! root      626:     define_function (flag_rtti
        !           627:                     ? "__throw_type_match_rtti"
        !           628:                     : "__throw_type_match",
        !           629:                     build_function_type (ptr_type_node,
        !           630:                                          tree_cons (NULL_TREE, ptr_type_node,
        !           631:                                                     tree_cons (NULL_TREE, ptr_type_node,
        !           632:                                                                tree_cons (NULL_TREE, ptr_type_node,
        !           633:                                                                           void_list_node)))),
1.1       root      634:                     NOT_BUILT_IN,
                    635:                     pushdecl,
                    636:                     0);
                    637:   find_first_exception_match_fndecl =
                    638:     define_function ("__find_first_exception_table_match",
                    639:                     build_function_type (ptr_type_node,
                    640:                                          tree_cons (NULL_TREE, ptr_type_node,
                    641:                                                     void_list_node)),
                    642:                     NOT_BUILT_IN,
                    643:                     pushdecl,
                    644:                     0);
                    645:   unwind_fndecl =
                    646:     define_function ("__unwind_function",
                    647:                     build_function_type (void_type_node,
1.1.1.2 ! root      648:                                          tree_cons (NULL_TREE, ptr_type_node,
        !           649:                                                     void_list_node)),
1.1       root      650:                     NOT_BUILT_IN,
                    651:                     pushdecl,
                    652:                     0);
1.1.1.2 ! root      653:   throw_fndecl =
        !           654:     define_function ("__throw",
        !           655:                     build_function_type (void_type_node, void_list_node),
        !           656:                     NOT_BUILT_IN,
        !           657:                     pushdecl,
        !           658:                     0);
        !           659:   DECL_EXTERNAL (throw_fndecl) = 0;
        !           660:   TREE_PUBLIC (throw_fndecl) = 0;
1.1       root      661: 
                    662:   Unexpected = default_conversion (unexpected_fndecl);
                    663:   Terminate = default_conversion (terminate_fndecl);
                    664:   SetTerminate = default_conversion (set_terminate_fndecl);
                    665:   SetUnexpected = default_conversion (set_unexpected_fndecl);
                    666:   CatchMatch = default_conversion (catch_match_fndecl);
                    667:   FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
                    668:   Unwind = default_conversion (unwind_fndecl);
1.1.1.2 ! root      669:   Throw = default_conversion (throw_fndecl);
1.1       root      670:   BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
                    671: 
                    672:   TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
                    673: 
                    674:   pop_lang_context ();
                    675: 
                    676:   new_eh_queue (&ehqueue);
                    677:   new_eh_queue (&eh_table_output_queue);
                    678:   new_eh_stack (&ehstack);
1.1.1.2 ! root      679: 
        !           680:   declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
        !           681:   d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
        !           682:   d = start_decl (d, declspecs, 0, NULL_TREE);
        !           683:   DECL_COMMON (d) = 1;
        !           684:   cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
        !           685:   saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
        !           686: 
        !           687:   declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
        !           688:   d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
        !           689:   d = start_decl (d, declspecs, 0, NULL_TREE);
        !           690:   DECL_COMMON (d) = 1;
        !           691:   cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
        !           692:   saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
        !           693: 
        !           694:   declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
        !           695:   d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
        !           696:   d = start_decl (d, declspecs, 0, NULL_TREE);
        !           697:   DECL_COMMON (d) = 1;
        !           698:   cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
        !           699:   saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
1.1       root      700: }
                    701: 
                    702: /* call this to begin a block of unwind protection (ie: when an object is
                    703:    constructed) */
                    704: void
                    705: start_protect ()
                    706: {
1.1.1.2 ! root      707:   if (! doing_eh (0))
        !           708:     return;
        !           709: 
        !           710:   emit_label (push_eh_entry (&ehstack));
1.1       root      711: }
                    712:    
                    713: /* call this to end a block of unwind protection.  the finalization tree is
                    714:    the finalization which needs to be run in order to cleanly unwind through
                    715:    this level of protection. (ie: call this when a scope is exited)*/
                    716: void
                    717: end_protect (finalization)
                    718:      tree finalization;
                    719: {
1.1.1.2 ! root      720:   struct ehEntry *entry;
1.1       root      721: 
                    722:   if (! doing_eh (0))
                    723:     return;
                    724: 
1.1.1.2 ! root      725:   entry = pop_eh_entry (&ehstack);
        !           726: 
1.1       root      727:   emit_label (entry->end_label);
1.1.1.2 ! root      728:   /* Put in something that takes up space, as otherwise the end
        !           729:      address for the EH region could have the exact same address as
        !           730:      the outer region, causing us to miss the fact that resuming
        !           731:      exception handling with this PC value would be inside the outer
        !           732:      region.  */
        !           733:   emit_insn (gen_nop ());
1.1       root      734: 
                    735:   entry->finalization = finalization;
                    736: 
                    737:   enqueue_eh_entry (&ehqueue, entry);
                    738: }
                    739: 
                    740: /* call this on start of a try block. */
                    741: void
                    742: expand_start_try_stmts ()
                    743: {
1.1.1.2 ! root      744:   if (! doing_eh (1))
        !           745:     return;
        !           746: 
        !           747:   start_protect ();
1.1       root      748: }
                    749: 
                    750: void
                    751: expand_end_try_stmts ()
                    752: {
                    753:   end_protect (integer_zero_node);
                    754: }
                    755: 
                    756: 
                    757: /* call this to start processing of all the catch blocks. */
                    758: void
                    759: expand_start_all_catch ()
                    760: {
                    761:   struct ehEntry *entry;
                    762:   rtx label;
                    763: 
                    764:   if (! doing_eh (1))
                    765:     return;
                    766: 
                    767:   emit_line_note (input_filename, lineno);
                    768:   label = gen_label_rtx ();
1.1.1.2 ! root      769: 
        !           770:   /* The label for the exception handling block we will save.  This is
        !           771:      Lresume, in the documention.  */
1.1       root      772:   emit_label (label);
                    773:   
1.1.1.2 ! root      774:   /* Put in something that takes up space, as otherwise the end
        !           775:      address for the EH region could have the exact same address as
        !           776:      the outer region, causing us to miss the fact that resuming
        !           777:      exception handling with this PC value would be inside the outer
        !           778:      region.  */
1.1       root      779:   emit_insn (gen_nop ());
                    780: 
1.1.1.2 ! root      781:   push_label_entry (&caught_return_label_stack, label);
        !           782: 
        !           783:   /* Start a new sequence for all the catch blocks.  We will add this
        !           784:      to the gloabl sequence catch_clauses, when we have completed all
        !           785:      the handlers in this handler-seq.  */
        !           786:   start_sequence ();
1.1       root      787: 
                    788:   while (1)
                    789:     {
                    790:       entry = dequeue_eh_entry (&ehqueue);
                    791:       emit_label (entry->exception_handler_label);
                    792: 
                    793:       expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
                    794: 
                    795:       /* When we get down to the matching entry, stop.  */
                    796:       if (entry->finalization == integer_zero_node)
                    797:        break;
                    798: 
1.1.1.2 ! root      799:       /* The below can be optimized away, and we could just fall into the
        !           800:         next EH handler, if we are certain they are nested.  */
        !           801:       /* Code to throw out to outer context, if we fall off end of the
        !           802:         handler.  */
        !           803:       expand_internal_throw (gen_rtx (LABEL_REF,
        !           804:                                      Pmode,
        !           805:                                      entry->end_label));
1.1       root      806:       free (entry);
                    807:     }
                    808: }
                    809: 
                    810: /* call this to end processing of all the catch blocks. */
                    811: void
                    812: expand_end_all_catch ()
                    813: {
1.1.1.2 ! root      814:   rtx new_catch_clause;
1.1       root      815: 
                    816:   if (! doing_eh (1))
                    817:     return;
                    818: 
1.1.1.2 ! root      819:   /* Code to throw out to outer context, if we fall off end of catch
        !           820:      handlers.  This is rethrow (Lresume, same id, same obj); in the
        !           821:      documentation.  */
        !           822:   expand_internal_throw (gen_rtx (LABEL_REF,
        !           823:                                  Pmode,
        !           824:                                  top_label_entry (&caught_return_label_stack)));
        !           825: 
        !           826:   /* Now we have the complete catch sequence.  */
        !           827:   new_catch_clause = get_insns ();
        !           828:   end_sequence ();
        !           829:   
1.1       root      830:   /* this level of catch blocks is done, so set up the successful catch jump
                    831:      label for the next layer of catch blocks. */
                    832:   pop_label_entry (&caught_return_label_stack);
                    833: 
1.1.1.2 ! root      834:   /* Add the new sequence of catchs to the main one for this
        !           835:      function.  */
        !           836:   push_to_sequence (catch_clauses);
        !           837:   emit_insns (new_catch_clause);
        !           838:   catch_clauses = get_insns ();
        !           839:   end_sequence ();
1.1       root      840:   
                    841:   /* Here we fall through into the continuation code.  */
                    842: }
                    843: 
1.1.1.2 ! root      844: /* Build a type value for use at runtime for a type that is matched
        !           845:    against by the exception handling system.  */
        !           846: static tree
        !           847: build_eh_type_type (type)
        !           848:      tree type;
        !           849: {
        !           850:   char *typestring;
        !           851:   tree exp;
        !           852: 
        !           853:   if (type == error_mark_node)
        !           854:     return error_mark_node;
        !           855: 
        !           856:   /* peel back references, so they match. */
        !           857:   if (TREE_CODE (type) == REFERENCE_TYPE)
        !           858:     type = TREE_TYPE (type);
1.1       root      859: 
1.1.1.2 ! root      860:   /* Peel off cv qualifiers. */
        !           861:   type = TYPE_MAIN_VARIANT (type);
1.1       root      862: 
1.1.1.2 ! root      863:   if (flag_rtti)
        !           864:     {
        !           865:       return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
        !           866:     }
1.1       root      867: 
1.1.1.2 ! root      868:   typestring = build_overload_name (type, 1, 1);
        !           869:   exp = combine_strings (build_string (strlen (typestring)+1, typestring));
        !           870:   return build1 (ADDR_EXPR, ptr_type_node, exp);
        !           871: }
1.1       root      872: 
1.1.1.2 ! root      873: /* Build a type value for use at runtime for a exp that is thrown or
        !           874:    matched against by the exception handling system.  */
        !           875: static tree
        !           876: build_eh_type (exp)
        !           877:      tree exp;
        !           878: {
        !           879:   if (flag_rtti)
1.1       root      880:     {
1.1.1.2 ! root      881:       exp = build_typeid (exp);
        !           882:       return build1 (ADDR_EXPR, ptr_type_node, exp);
1.1       root      883:     }
1.1.1.2 ! root      884:   return build_eh_type_type (TREE_TYPE (exp));
1.1       root      885: }
                    886: 
                    887: /* call this to start a catch block. Typename is the typename, and identifier
                    888:    is the variable to place the object in or NULL if the variable doesn't
                    889:    matter.  If typename is NULL, that means its a "catch (...)" or catch
                    890:    everything.  In that case we don't need to do any type checking.
                    891:    (ie: it ends up as the "else" clause rather than an "else if" clause) */
                    892: void
                    893: expand_start_catch_block (declspecs, declarator)
                    894:      tree declspecs, declarator;
                    895: {
                    896:   rtx false_label_rtx;
                    897:   rtx protect_label_rtx;
1.1.1.2 ! root      898:   tree decl = NULL_TREE;
1.1       root      899:   tree init;
                    900: 
                    901:   if (! doing_eh (1))
                    902:     return;
                    903: 
                    904:   /* Create a binding level for the parm.  */
                    905:   expand_start_bindings (0);
                    906: 
                    907:   false_label_rtx = gen_label_rtx ();
1.1.1.2 ! root      908:   /* This is saved for the exception table.  */
        !           909:   push_rtl_perm ();
1.1       root      910:   protect_label_rtx = gen_label_rtx ();
                    911:   pop_rtl_from_perm ();
                    912:   push_label_entry (&false_label_stack, false_label_rtx);
                    913:   push_label_entry (&false_label_stack, protect_label_rtx);
                    914: 
1.1.1.2 ! root      915:   if (declspecs)
1.1       root      916:     {
1.1.1.2 ! root      917:       tree exp;
1.1       root      918:       rtx call_rtx, return_value_rtx;
1.1.1.2 ! root      919:       tree init_type;
1.1       root      920: 
1.1.1.2 ! root      921:       decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,
        !           922:                             NULL_TREE, NULL_TREE);
1.1       root      923: 
1.1.1.2 ! root      924:       if (decl == NULL_TREE)
        !           925:        {
        !           926:          error ("invalid catch parameter");
        !           927:          return;
        !           928:        }
1.1       root      929: 
1.1.1.2 ! root      930:       /* Figure out the type that the initializer is. */
        !           931:       init_type = TREE_TYPE (decl);
        !           932:       if (TREE_CODE (init_type) != REFERENCE_TYPE
        !           933:          && TREE_CODE (init_type) != POINTER_TYPE)
        !           934:        init_type = build_reference_type (init_type);
        !           935: 
        !           936:       exp = saved_throw_value;
        !           937:       exp = tree_cons (NULL_TREE,
        !           938:                       build_eh_type_type (TREE_TYPE (decl)),
        !           939:                       tree_cons (NULL_TREE,
        !           940:                                  saved_throw_type,
        !           941:                                  tree_cons (NULL_TREE, exp, NULL_TREE)));
        !           942:       exp = build_function_call (CatchMatch, exp);
        !           943:       call_rtx = expand_call (exp, NULL_RTX, 0);
        !           944:       assemble_external (TREE_OPERAND (CatchMatch, 0));
        !           945: 
        !           946:       return_value_rtx = hard_function_value (ptr_type_node, exp);
1.1       root      947: 
                    948:       /* did the throw type match function return TRUE? */
1.1.1.2 ! root      949:       emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
1.1       root      950:                    GET_MODE (return_value_rtx), 0, 0);
                    951: 
                    952:       /* if it returned FALSE, jump over the catch block, else fall into it */
1.1.1.2 ! root      953:       emit_jump_insn (gen_beq (false_label_rtx));
        !           954: 
        !           955:       init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
        !           956: 
        !           957:       /* Do we need the below two lines? */
        !           958:       /* Let `cp_finish_decl' know that this initializer is ok.  */
        !           959:       DECL_INITIAL (decl) = init;
        !           960:       decl = pushdecl (decl);
        !           961:       cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
1.1       root      962:     }
                    963:   else
                    964:     {
                    965:       /* Fall into the catch all section. */
                    966:     }
                    967: 
                    968:   /* This is the starting of something to protect.  */
                    969:   emit_label (protect_label_rtx);
                    970: 
                    971:   emit_line_note (input_filename, lineno);
                    972: }
                    973: 
                    974: 
1.1.1.2 ! root      975: /* this is called from expand_exception_blocks and
        !           976:    expand_end_catch_block to expand the toplevel finalizations for a
        !           977:    function.  We return the first label emitted, if any, otherwise
        !           978:    return NULL_RTX.  */
        !           979: static rtx
        !           980: expand_leftover_cleanups ()
        !           981: {
        !           982:   struct ehEntry *entry;
        !           983:   rtx first_label = NULL_RTX;
        !           984: 
        !           985:   while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
        !           986:     {
        !           987:       if (! first_label)
        !           988:        first_label = entry->exception_handler_label;
        !           989:       emit_label (entry->exception_handler_label);
        !           990: 
        !           991:       expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
        !           992: 
        !           993:       /* The below can be optimized away, and we could just fall into the
        !           994:         next EH handler, if we are certain they are nested.  */
        !           995:       /* Code to throw out to outer context, if we fall off end of the
        !           996:         handler.  */
        !           997:       expand_internal_throw (gen_rtx (LABEL_REF,
        !           998:                                      Pmode,
        !           999:                                      entry->end_label));
        !          1000: 
        !          1001:       /* leftover try block, opps.  */
        !          1002:       if (entry->finalization == integer_zero_node)
        !          1003:        abort ();
        !          1004: 
        !          1005:       free (entry);
        !          1006:     }
        !          1007: 
        !          1008:   return first_label;
        !          1009: }
        !          1010: 
1.1       root     1011: /* Call this to end a catch block.  Its responsible for emitting the
                   1012:    code to handle jumping back to the correct place, and for emitting
                   1013:    the label to jump to if this catch block didn't match.  */
                   1014: void expand_end_catch_block ()
                   1015: {
1.1.1.2 ! root     1016:   rtx start_protect_label_rtx;
        !          1017:   rtx end_protect_label_rtx;
        !          1018:   tree decls;
        !          1019:   struct ehEntry entry;
1.1       root     1020: 
1.1.1.2 ! root     1021:   if (! doing_eh (1))
        !          1022:     return;
1.1       root     1023: 
1.1.1.2 ! root     1024:   /* fall to outside the try statement when done executing handler and
        !          1025:      we fall off end of handler.  This is jump Lresume in the
        !          1026:      documentation.  */
        !          1027:   emit_jump (top_label_entry (&caught_return_label_stack));
1.1       root     1028: 
1.1.1.2 ! root     1029:   /* We end the rethrow protection region as soon as we hit a label. */
        !          1030:   end_protect_label_rtx = expand_leftover_cleanups ();
1.1       root     1031: 
1.1.1.2 ! root     1032:   /* Code to throw out to outer context, if we get a throw from within
        !          1033:      our catch handler. */
        !          1034:   /* These are saved for the exception table.  */
        !          1035:   push_rtl_perm ();
        !          1036:   entry.exception_handler_label = gen_label_rtx ();
        !          1037:   pop_rtl_from_perm ();
        !          1038:   /* This label is Lhandler in the documentation.  */
        !          1039:   emit_label (entry.exception_handler_label);
        !          1040:   expand_internal_throw (gen_rtx (LABEL_REF,
        !          1041:                                  Pmode,
        !          1042:                                  top_label_entry (&caught_return_label_stack)));
        !          1043: 
        !          1044:   /* No associated finalization.  */
        !          1045:   entry.finalization = NULL_TREE;
        !          1046:   entry.context = current_function_decl;
        !          1047: 
        !          1048:   if (end_protect_label_rtx == NULL_RTX)
        !          1049:     end_protect_label_rtx = entry.exception_handler_label;
        !          1050: 
        !          1051:   /* Because we are emitted out of line, we have to protect this. */
        !          1052:   /* label for the start of the protection region.  */
        !          1053:   start_protect_label_rtx = pop_label_entry (&false_label_stack);
        !          1054: 
        !          1055:   /* Cleanup the EH parameter.  */
        !          1056:   decls = getdecls ();
        !          1057:   expand_end_bindings (decls, decls != NULL_TREE, 0);
        !          1058:       
        !          1059:   /* label we emit to jump to if this catch block didn't match. */
        !          1060:   /* This the closing } in the `if (eq) {' of the documentation.  */
        !          1061:   emit_label (pop_label_entry (&false_label_stack));
        !          1062: 
        !          1063:   /* Because we are reordered out of line, we have to protect this. */
        !          1064:   entry.start_label = start_protect_label_rtx;
        !          1065:   entry.end_label = end_protect_label_rtx;
        !          1066: 
        !          1067:   LABEL_PRESERVE_P (entry.start_label) = 1;
        !          1068:   LABEL_PRESERVE_P (entry.end_label) = 1;
        !          1069:   LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
        !          1070: 
        !          1071:   /* These set up a call to throw the caught exception into the outer
        !          1072:      context.  */
        !          1073:   enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
1.1       root     1074: }
                   1075: 
1.1.1.2 ! root     1076: /* unwind the stack. */
        !          1077: static void
        !          1078: do_unwind (inner_throw_label)
        !          1079:      rtx inner_throw_label;
1.1       root     1080: {
1.1.1.2 ! root     1081: #if defined(SPARC_STACK_ALIGN) /* was sparc */
        !          1082:   tree fcall;
        !          1083:   tree params;
        !          1084:   rtx return_val_rtx;
        !          1085:   rtx temp;
        !          1086: 
        !          1087:   /* call to  __builtin_return_address () */
        !          1088:   params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
        !          1089:   fcall = build_function_call (BuiltinReturnAddress, params);
        !          1090:   return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
        !          1091:   /* In the return, the new pc is pc+8, as the value coming in is
        !          1092:      really the address of the call insn, not the next insn.  */
        !          1093:   temp = gen_reg_rtx (Pmode);
        !          1094:   emit_move_insn (temp, inner_throw_label);
        !          1095:   emit_move_insn (return_val_rtx, plus_constant (temp, -8));
        !          1096:   easy_expand_asm ("ret");
        !          1097:   easy_expand_asm ("restore");
        !          1098:   emit_barrier ();
        !          1099: #endif
        !          1100: #if defined(ARM_FRAME_RTX)  /* was __arm */
        !          1101:   if (flag_omit_frame_pointer)
        !          1102:     sorry ("this implementation of exception handling requires a frame pointer");
        !          1103: 
        !          1104:   emit_move_insn (stack_pointer_rtx,
        !          1105:                  gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
        !          1106:   emit_move_insn (hard_frame_pointer_rtx,
        !          1107:                  gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
        !          1108: #endif
        !          1109: #if defined(TARGET_88000) /* was m88k */
        !          1110:   rtx temp_frame = frame_pointer_rtx;
        !          1111: 
        !          1112:   temp_frame = memory_address (Pmode, temp_frame);
        !          1113:   temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
        !          1114: 
        !          1115:   /* hopefully this will successfully pop the frame! */
        !          1116:   emit_move_insn (frame_pointer_rtx, temp_frame);
        !          1117:   emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
        !          1118:   emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
        !          1119:   emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
        !          1120:                                                     (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
        !          1121: 
        !          1122: #if 0
        !          1123:   emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
        !          1124:                                                   -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
        !          1125: 
        !          1126:   emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
        !          1127: 
        !          1128:   emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
        !          1129:                                                     (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
        !          1130: #endif
        !          1131: #endif
        !          1132: #if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN)
        !          1133:   tree fcall;
        !          1134:   tree params;
        !          1135:   rtx return_val_rtx;
        !          1136: 
        !          1137:   /* call to  __builtin_return_address () */
        !          1138:   params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
        !          1139:   fcall = build_function_call (BuiltinReturnAddress, params);
        !          1140:   return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
        !          1141: #if 0
        !          1142:   /* I would like to do this here, but doesn't seem to work. */
        !          1143:   emit_move_insn (return_val_rtx, inner_throw_label);
        !          1144:   /* So, for now, just pass throw label to stack unwinder. */
        !          1145: #endif
        !          1146:   params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
        !          1147:                                            inner_throw_label), NULL_TREE);
        !          1148:   
        !          1149:   do_function_call (Unwind, params, NULL_TREE);
        !          1150:   assemble_external (TREE_OPERAND (Unwind, 0));
        !          1151:   emit_barrier ();
        !          1152: #endif
1.1       root     1153: }
                   1154: 
                   1155: 
1.1.1.2 ! root     1156: /* is called from expand_exception_blocks () to generate the code in a function
        !          1157:    to "throw" if anything in the function needs to perform a throw.
1.1       root     1158: 
1.1.1.2 ! root     1159:    expands "throw" as the following pseudo code:
1.1       root     1160: 
                   1161:        throw:
                   1162:                eh = find_first_exception_match (saved_pc);
                   1163:            if (!eh) goto gotta_rethrow_it;
                   1164:                goto eh;
                   1165: 
                   1166:        gotta_rethrow_it:
                   1167:                saved_pc = __builtin_return_address (0);
                   1168:                pop_to_previous_level ();
                   1169:                goto throw;
                   1170: 
                   1171:  */
1.1.1.2 ! root     1172: void
1.1       root     1173: expand_builtin_throw ()
                   1174: {
                   1175:   tree fcall;
                   1176:   tree params;
                   1177:   rtx return_val_rtx;
1.1.1.2 ! root     1178:   rtx gotta_rethrow_it;
        !          1179:   rtx gotta_call_terminate;
        !          1180:   rtx unwind_and_throw;
        !          1181:   rtx goto_unwind_and_throw;
        !          1182:   rtx top_of_loop;
        !          1183:   rtx unwind_first;
        !          1184:   tree t;
        !          1185: 
        !          1186:   if (! doing_eh (0))
        !          1187:     return;
        !          1188: 
        !          1189:   if (! throw_used)
        !          1190:     return;
1.1       root     1191: 
1.1.1.2 ! root     1192:   params = void_list_node;
        !          1193:   t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);
        !          1194:   start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
        !          1195:                                  void_list_node),
        !          1196:                  t, NULL_TREE, NULL_TREE, 0);
        !          1197:   store_parm_decls ();
        !          1198:   pushlevel (0);
        !          1199:   clear_last_expr ();
        !          1200:   push_momentary ();
        !          1201:   expand_start_bindings (0);
        !          1202: 
        !          1203:   gotta_rethrow_it = gen_label_rtx ();
        !          1204:   gotta_call_terminate = gen_label_rtx ();
        !          1205:   unwind_and_throw = gen_label_rtx ();
        !          1206:   goto_unwind_and_throw = gen_label_rtx ();
        !          1207:   top_of_loop = gen_label_rtx ();
        !          1208:   unwind_first = gen_label_rtx ();
        !          1209: 
        !          1210:   emit_jump (unwind_first);
        !          1211: 
        !          1212:   emit_label (top_of_loop);
1.1       root     1213: 
                   1214:   /* search for an exception handler for the saved_pc */
                   1215:   return_val_rtx = do_function_call (FirstExceptionMatch,
1.1.1.2 ! root     1216:                                     tree_cons (NULL_TREE, saved_pc, NULL_TREE),
1.1       root     1217:                                     ptr_type_node);
1.1.1.2 ! root     1218:   assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
1.1       root     1219: 
                   1220:   /* did we find one? */
                   1221:   emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
                   1222:                 GET_MODE (return_val_rtx), 0, 0);
                   1223: 
                   1224:   /* if not, jump to gotta_rethrow_it */
                   1225:   emit_jump_insn (gen_beq (gotta_rethrow_it));
                   1226: 
                   1227:   /* we found it, so jump to it */
                   1228:   emit_indirect_jump (return_val_rtx);
                   1229: 
                   1230:   /* code to deal with unwinding and looking for it again */
                   1231:   emit_label (gotta_rethrow_it);
                   1232: 
                   1233:   /* call to  __builtin_return_address () */
1.1.1.2 ! root     1234: #if defined(ARM_FRAME_RTX)  /* was __arm */
        !          1235: /* This replaces a 'call' to __builtin_return_address */
        !          1236:   return_val_rtx = gen_reg_rtx (Pmode);
        !          1237:   emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
        !          1238: #else
        !          1239:   params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
1.1       root     1240:   fcall = build_function_call (BuiltinReturnAddress, params);
1.1.1.2 ! root     1241:   return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
        !          1242: #endif
1.1       root     1243: 
                   1244:   /* did __builtin_return_address () return a valid address? */
                   1245:   emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
                   1246:                 GET_MODE (return_val_rtx), 0, 0);
                   1247: 
                   1248:   emit_jump_insn (gen_beq (gotta_call_terminate));
                   1249: 
1.1.1.2 ! root     1250: #if defined(ARM_FRAME_RTX)  /* was __arm */
        !          1251:   /* On the ARM, '__builtin_return_address',  must have 4
        !          1252:      subtracted from it. */
        !          1253:   emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4)));
        !          1254: 
        !          1255:   /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit
        !          1256:      mode, the condition codes must be masked out of the return value, or else
        !          1257:      they will confuse BuiltinReturnAddress.  This does not apply to ARM6 and
        !          1258:      later processors when running in 32 bit mode. */
        !          1259:   if (!TARGET_6)
        !          1260:     emit_insn (gen_rtx (SET, Pmode, return_val_rtx, gen_rtx (AND, Pmode, return_val_rtx, GEN_INT (0x03fffffc))));
        !          1261: #else
        !          1262: #if !defined(SPARC_STACK_ALIGN) /* was sparc */
        !          1263:   /* On the SPARC, __builtin_return_address is already -8, no need to
        !          1264:      subtract any more from it. */
        !          1265:   return_val_rtx = plus_constant (return_val_rtx, -1);
        !          1266: #endif
        !          1267: #endif
        !          1268: 
1.1       root     1269:   /* yes it did */
1.1.1.2 ! root     1270:   t = build_modify_expr (saved_pc, NOP_EXPR, make_tree (ptr_type_node, return_val_rtx));
        !          1271:   expand_expr (t, const0_rtx, VOIDmode, 0);
        !          1272: 
        !          1273:   do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
        !          1274:   emit_jump (top_of_loop);
1.1       root     1275: 
                   1276:   /* no it didn't --> therefore we need to call terminate */
                   1277:   emit_label (gotta_call_terminate);
                   1278:   do_function_call (Terminate, NULL_TREE, NULL_TREE);
1.1.1.2 ! root     1279:   assemble_external (TREE_OPERAND (Terminate, 0));
        !          1280: 
        !          1281:   {
        !          1282:     rtx ret_val, return_val_rtx;
        !          1283:     emit_label (unwind_first);
        !          1284:     ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
        !          1285:                                          0, hard_frame_pointer_rtx);
        !          1286: 
        !          1287:     /* Set it up so that we continue inside, at the top of the loop.  */
        !          1288:     emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
        !          1289: #ifdef NORMAL_RETURN_ADDR_OFFSET
        !          1290:   return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET);
        !          1291:     if (return_val_rtx != ret_val)
        !          1292:       emit_move_insn (ret_val, return_val_rtx);
        !          1293: #endif
        !          1294: 
        !          1295:     /* Fall into epilogue to unwind prologue. */
        !          1296:   }
        !          1297: 
        !          1298:   expand_end_bindings (getdecls(), 1, 0);
        !          1299:   poplevel (1, 0, 0);
        !          1300:   pop_momentary ();
        !          1301: 
        !          1302:   finish_function (lineno, 0, 0);
1.1       root     1303: }
                   1304: 
                   1305: 
1.1.1.2 ! root     1306: void
        !          1307: expand_start_eh_spec ()
        !          1308: {
        !          1309:   start_protect ();
        !          1310: }
        !          1311: 
        !          1312: void
        !          1313: expand_end_eh_spec (raises)
        !          1314:      tree raises;
        !          1315: {
        !          1316:   tree expr, second_try;
        !          1317:   rtx check = gen_label_rtx ();
        !          1318:   rtx cont;
        !          1319:   rtx ret = gen_reg_rtx (Pmode);
        !          1320:   rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
        !          1321:   rtx end = gen_label_rtx ();
        !          1322: 
        !          1323:   expr = make_node (RTL_EXPR);
        !          1324:   TREE_TYPE (expr) = void_type_node;
        !          1325:   RTL_EXPR_RTL (expr) = const0_rtx;
        !          1326:   TREE_SIDE_EFFECTS (expr) = 1;
        !          1327:   start_sequence_for_rtl_expr (expr);
        !          1328:   cont = gen_label_rtx ();
        !          1329:   emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
        !          1330:   emit_jump (check);
        !          1331:   emit_label (cont);
        !          1332:   jumpif (make_tree (integer_type_node, flag), end);
        !          1333:   do_function_call (Terminate, NULL_TREE, NULL_TREE);
        !          1334:   assemble_external (TREE_OPERAND (Terminate, 0));
        !          1335:   emit_barrier ();
        !          1336:   RTL_EXPR_SEQUENCE (expr) = get_insns ();
        !          1337:   end_sequence ();
        !          1338:   
        !          1339:   second_try = expr;
        !          1340: 
        !          1341:   expr = make_node (RTL_EXPR);
        !          1342:   TREE_TYPE (expr) = void_type_node;
        !          1343:   RTL_EXPR_RTL (expr) = const0_rtx;
        !          1344:   TREE_SIDE_EFFECTS (expr) = 1;
        !          1345:   start_sequence_for_rtl_expr (expr);
        !          1346: 
        !          1347:   cont = gen_label_rtx ();
        !          1348:   emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
        !          1349:   emit_jump (check);
        !          1350:   emit_label (cont);
        !          1351:   jumpif (make_tree (integer_type_node, flag), end);
        !          1352:   start_protect ();
        !          1353:   do_function_call (Unexpected, NULL_TREE, NULL_TREE);
        !          1354:   assemble_external (TREE_OPERAND (Unexpected, 0));
        !          1355:   emit_barrier ();
        !          1356:   end_protect (second_try);
        !          1357:   
        !          1358:   emit_label (check);
        !          1359:   emit_move_insn (flag, const1_rtx);
        !          1360:   cont = gen_label_rtx ();
        !          1361:   while (raises)
        !          1362:     {
        !          1363:       tree exp;
        !          1364:       tree match_type = TREE_VALUE (raises);
        !          1365:       
        !          1366:       if (match_type)
        !          1367:        {
        !          1368:          /* check TREE_VALUE (raises) here */
        !          1369:          exp = saved_throw_value;
        !          1370:          exp = tree_cons (NULL_TREE,
        !          1371:                           build_eh_type_type (match_type),
        !          1372:                           tree_cons (NULL_TREE,
        !          1373:                                      saved_throw_type,
        !          1374:                                      tree_cons (NULL_TREE, exp, NULL_TREE)));
        !          1375:          exp = build_function_call (CatchMatch, exp);
        !          1376:          assemble_external (TREE_OPERAND (CatchMatch, 0));
        !          1377: 
        !          1378:          jumpif (exp, cont);
        !          1379:        }
        !          1380: 
        !          1381:       raises = TREE_CHAIN (raises);
        !          1382:     }
        !          1383:   emit_move_insn (flag, const0_rtx);
        !          1384:   emit_label (cont);
        !          1385:   emit_indirect_jump (ret);
        !          1386:   emit_label (end);
        !          1387:   
        !          1388:   RTL_EXPR_SEQUENCE (expr) = get_insns ();
        !          1389:   end_sequence ();
        !          1390:   
        !          1391:   end_protect (expr);
        !          1392: }
        !          1393: 
1.1       root     1394: /* This is called to expand all the toplevel exception handling
                   1395:    finalization for a function.  It should only be called once per
                   1396:    function.  */
                   1397: void
                   1398: expand_exception_blocks ()
                   1399: {
                   1400:   static rtx funcend;
1.1.1.2 ! root     1401:   rtx insns;
        !          1402: 
        !          1403:   start_sequence ();
1.1       root     1404: 
                   1405:   funcend = gen_label_rtx ();
                   1406:   emit_jump (funcend);
                   1407:   /* expand_null_return (); */
                   1408: 
1.1.1.2 ! root     1409:   start_sequence ();
        !          1410: 
        !          1411:   /* Add all the catch clauses here.  */
        !          1412:   emit_insns (catch_clauses);
        !          1413:   catch_clauses = NULL_RTX;
1.1       root     1414: 
                   1415:   expand_leftover_cleanups ();
                   1416: 
1.1.1.2 ! root     1417:   insns = get_insns ();
        !          1418:   end_sequence ();
        !          1419:   
        !          1420:   /* Do this after we expand leftover cleanups, so that the end_protect
        !          1421:      that expand_end_eh_spec does will match the right start_protect,
        !          1422:      and make sure it comes out before the terminate protected region.  */
        !          1423:   if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
        !          1424:     {
        !          1425:       expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
        !          1426:       push_to_sequence (insns);
        !          1427: 
        !          1428:       /* Now expand any new ones.  */
        !          1429:       expand_leftover_cleanups ();
        !          1430: 
        !          1431:       insns = get_insns ();
        !          1432:       end_sequence ();
        !          1433:     }
        !          1434: 
        !          1435:   if (insns)
        !          1436:     {
        !          1437:       struct ehEntry entry;
        !          1438: 
        !          1439:       /* These are saved for the exception table.  */
        !          1440:       push_rtl_perm ();
        !          1441:       entry.start_label = gen_label_rtx ();
        !          1442:       entry.end_label = gen_label_rtx ();
        !          1443:       entry.exception_handler_label = gen_label_rtx ();
        !          1444:       entry.finalization = TerminateFunctionCall;
        !          1445:       entry.context = current_function_decl;
        !          1446:       assemble_external (TREE_OPERAND (Terminate, 0));
        !          1447:       pop_rtl_from_perm ();
        !          1448: 
        !          1449:       LABEL_PRESERVE_P (entry.start_label) = 1;
        !          1450:       LABEL_PRESERVE_P (entry.end_label) = 1;
        !          1451:       LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
        !          1452: 
        !          1453:       emit_label (entry.start_label);
        !          1454:       emit_insns (insns);
        !          1455: 
        !          1456:       enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
        !          1457: 
        !          1458:       emit_label (entry.exception_handler_label);
        !          1459:       expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
        !          1460:       emit_label (entry.end_label);
        !          1461:       emit_barrier ();
        !          1462:     }
        !          1463: 
1.1       root     1464:   {
1.1.1.2 ! root     1465:     /* Mark the end of the stack unwinder.  */
        !          1466:     rtx unwind_insns;
        !          1467:     start_sequence ();
        !          1468:     end_eh_unwinder (funcend);
        !          1469:     expand_leftover_cleanups ();
        !          1470:     unwind_insns = get_insns ();
        !          1471:     end_sequence ();
        !          1472:     if (unwind_insns)
1.1       root     1473:       {
1.1.1.2 ! root     1474:        insns = unwind_insns;
        !          1475:        emit_insns (insns);
1.1       root     1476:       }
                   1477:   }
1.1.1.2 ! root     1478: 
1.1       root     1479:   emit_label (funcend);
1.1.1.2 ! root     1480: 
        !          1481:   /* Only if we had previous insns do we want to emit the jump around
        !          1482:      them.  If there weren't any, then insns will remain NULL_RTX.  */
        !          1483:   if (insns)
        !          1484:     insns = get_insns ();
        !          1485:   end_sequence ();
        !          1486: 
        !          1487:   emit_insns (insns);
1.1       root     1488: }
                   1489: 
                   1490: 
                   1491: /* call this to expand a throw statement.  This follows the following
                   1492:    algorithm:
                   1493: 
                   1494:        1. Allocate space to save the current PC onto the stack.
                   1495:        2. Generate and emit a label and save its address into the
1.1.1.2 ! root     1496:                newly allocated stack space since we can't save the pc directly.
1.1       root     1497:        3. If this is the first call to throw in this function:
                   1498:                generate a label for the throw block
                   1499:        4. jump to the throw block label.  */
                   1500: void
                   1501: expand_throw (exp)
                   1502:      tree exp;
                   1503: {
                   1504:   rtx label;
                   1505: 
                   1506:   if (! doing_eh (1))
                   1507:     return;
                   1508: 
                   1509:   /* This is the label that represents where in the code we were, when
                   1510:      we got an exception.  This needs to be updated when we rethrow an
                   1511:      exception, so that the matching routine knows to search out.  */
                   1512:   label = gen_label_rtx ();
                   1513:   emit_label (label);
                   1514: 
                   1515:   if (exp)
                   1516:     {
1.1.1.2 ! root     1517:       tree throw_type;
        !          1518:       tree e;
        !          1519: 
1.1       root     1520:       /* throw expression */
                   1521:       /* First, decay it. */
1.1.1.2 ! root     1522:       exp = decay_conversion (exp);
1.1       root     1523: 
1.1.1.2 ! root     1524:       if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
        !          1525:        {
        !          1526:          throw_type = build_eh_type (exp);
        !          1527:          exp = build_reinterpret_cast (ptr_type_node, exp);
        !          1528:        }
        !          1529:       else
        !          1530:        {
        !          1531:          /* Make a copy of the thrown object.  WP 15.1.5  */
        !          1532:          exp = build_new (NULL_TREE, TREE_TYPE (exp),
        !          1533:                           build_tree_list (NULL_TREE, exp),
        !          1534:                           0);
        !          1535: 
        !          1536:          if (exp == error_mark_node)
        !          1537:            error ("  in thrown expression");
        !          1538: 
        !          1539:          throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
        !          1540:        }
        !          1541: 
        !          1542:       e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
        !          1543:       expand_expr (e, const0_rtx, VOIDmode, 0);
        !          1544:       e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
        !          1545:       e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
        !          1546:       expand_expr (e, const0_rtx, VOIDmode, 0);
1.1       root     1547:     }
                   1548:   else
                   1549:     {
                   1550:       /* rethrow current exception */
1.1.1.2 ! root     1551:       /* This part is easy, as we don't have to do anything else.  */
1.1       root     1552:     }
                   1553: 
1.1.1.2 ! root     1554:   expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label));
1.1       root     1555: }
                   1556: 
1.1.1.2 ! root     1557: void
        !          1558: end_protect_partials () {
        !          1559:   while (protect_list)
        !          1560:     {
        !          1561:       end_protect (TREE_VALUE (protect_list));
        !          1562:       protect_list = TREE_CHAIN (protect_list);
        !          1563:     }
        !          1564: }
1.1       root     1565: 
1.1.1.2 ! root     1566: int
        !          1567: might_have_exceptions_p ()
        !          1568: {
        !          1569:   if (eh_table_output_queue.head)
        !          1570:     return 1;
        !          1571:   return 0;
        !          1572: }
1.1       root     1573: 
                   1574: /* Output the exception table.
                   1575:  Return the number of handlers.  */
1.1.1.2 ! root     1576: void
        !          1577: emit_exception_table ()
1.1       root     1578: {
                   1579:   int count = 0;
                   1580:   extern FILE *asm_out_file;
                   1581:   struct ehEntry *entry;
                   1582:   tree eh_node_decl;
                   1583: 
                   1584:   if (! doing_eh (0))
1.1.1.2 ! root     1585:     return;
        !          1586: 
        !          1587:   exception_section ();
        !          1588: 
        !          1589:   /* Beginning marker for table. */
        !          1590:   assemble_align (GET_MODE_ALIGNMENT (Pmode));
        !          1591:   assemble_label ("__EXCEPTION_TABLE__");
        !          1592:   output_exception_table_entry (asm_out_file,
        !          1593:                                const0_rtx, const0_rtx, const0_rtx);
1.1       root     1594: 
                   1595:  while (entry = dequeue_eh_entry (&eh_table_output_queue))
                   1596:    {
1.1.1.2 ! root     1597:      tree context = entry->context;
        !          1598: 
        !          1599:      if (context && ! TREE_ASM_WRITTEN (context))
        !          1600:        continue;
        !          1601: 
1.1       root     1602:      count++;
                   1603:      output_exception_table_entry (asm_out_file,
                   1604:                                   entry->start_label, entry->end_label,
                   1605:                                   entry->exception_handler_label);
                   1606:   }
                   1607: 
1.1.1.2 ! root     1608:   /* Ending marker for table. */
        !          1609:   assemble_label ("__EXCEPTION_END__");
        !          1610:   output_exception_table_entry (asm_out_file,
        !          1611:                                constm1_rtx, constm1_rtx, constm1_rtx);
1.1       root     1612: }
                   1613: 
                   1614: void
                   1615: register_exception_table ()
                   1616: {
                   1617:   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
                   1618:                     VOIDmode, 1,
                   1619:                     gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
                   1620:                     Pmode);
                   1621: }
                   1622: 
                   1623: /* Build a throw expression.  */
                   1624: tree
                   1625: build_throw (e)
                   1626:      tree e;
                   1627: {
1.1.1.2 ! root     1628:   if (e != error_mark_node)
        !          1629:     {
        !          1630:       e = build1 (THROW_EXPR, void_type_node, e);
        !          1631:       TREE_SIDE_EFFECTS (e) = 1;
        !          1632:       TREE_USED (e) = 1;
        !          1633:     }
1.1       root     1634:   return e;
                   1635: }
1.1.1.2 ! root     1636: 
        !          1637: start_eh_unwinder ()
        !          1638: {
        !          1639:   start_protect ();
        !          1640: }
        !          1641: 
        !          1642: end_eh_unwinder (end)
        !          1643:      rtx end;
        !          1644: {
        !          1645:   tree expr;
        !          1646:   rtx return_val_rtx, ret_val, label;
        !          1647: 
        !          1648:   if (! doing_eh (0))
        !          1649:     return;
        !          1650: 
        !          1651:   expr = make_node (RTL_EXPR);
        !          1652:   TREE_TYPE (expr) = void_type_node;
        !          1653:   RTL_EXPR_RTL (expr) = const0_rtx;
        !          1654:   TREE_SIDE_EFFECTS (expr) = 1;
        !          1655:   start_sequence_for_rtl_expr (expr);
        !          1656: 
        !          1657:   ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
        !          1658:                                        0, hard_frame_pointer_rtx);
        !          1659:   return_val_rtx = copy_to_reg (ret_val);
        !          1660: #ifdef NORMAL_RETURN_ADDR_OFFSET
        !          1661:   return_val_rtx = plus_constant (return_val_rtx, NORMAL_RETURN_ADDR_OFFSET-1);
        !          1662: #else
        !          1663:   return_val_rtx = plus_constant (return_val_rtx, -1);
        !          1664: #endif
        !          1665:   emit_move_insn (DECL_RTL (saved_pc), return_val_rtx);
        !          1666:   
        !          1667: #ifdef JUMP_TO_THROW
        !          1668:   emit_move_insn (ret_val, gen_rtx (SYMBOL_REF, Pmode, "__throw"));
        !          1669: #else
        !          1670:   label = gen_label_rtx ();
        !          1671:   emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, label));
        !          1672: #endif
        !          1673: 
        !          1674: #ifdef NORMAL_RETURN_ADDR_OFFSET
        !          1675:   return_val_rtx = plus_constant (ret_val, -NORMAL_RETURN_ADDR_OFFSET);
        !          1676:   if (return_val_rtx != ret_val)
        !          1677:     emit_move_insn (ret_val, return_val_rtx);
        !          1678: #endif
        !          1679:   
        !          1680:   emit_jump (end);  
        !          1681: 
        !          1682: #ifndef JUMP_TO_THROW
        !          1683:   emit_label (label);
        !          1684:   do_function_call (Throw, NULL_TREE, NULL_TREE);
        !          1685: #endif
        !          1686:   
        !          1687:   RTL_EXPR_SEQUENCE (expr) = get_insns ();
        !          1688:   end_sequence ();
        !          1689:   end_protect (expr);
        !          1690: }

unix.superglobalmegacorp.com

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