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

1.1       root        1: /* Handle exceptional things in C++.
                      2:    Copyright (C) 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
                      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
                     21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     22: 
                     23: 
                     24: /* High-level class interface. */
                     25: 
                     26: #include "config.h"
                     27: #include "tree.h"
                     28: #include "rtl.h"
                     29: #include "cp-tree.h"
                     30: #include "flags.h"
                     31: #include "obstack.h"
                     32: #include "expr.h"
                     33: 
                     34: extern void (*interim_eh_hook) PROTO((tree));
                     35: 
                     36: /* holds the fndecl for __builtin_return_address () */
                     37: tree builtin_return_address_fndecl;
                     38: 
                     39: /* Define at your own risk!  */
                     40: #ifndef CROSS_COMPILE
                     41: #ifdef sun
                     42: #ifdef sparc
                     43: #define TRY_NEW_EH
                     44: #endif
                     45: #endif
                     46: #endif
                     47: 
                     48: #ifndef TRY_NEW_EH
                     49: 
                     50: static void
                     51: sorry_no_eh ()
                     52: {
                     53:   static int warned = 0;
                     54:   if (! warned)
                     55:     {
                     56:       sorry ("exception handling not supported");
                     57:       warned = 1;
                     58:     }
                     59: }
                     60: 
                     61: void
                     62: expand_exception_blocks ()
                     63: {
                     64: }
                     65: 
                     66: void
                     67: start_protect ()
                     68: {
                     69: }
                     70: 
                     71: void
                     72: end_protect (finalization)
                     73:      tree finalization;
                     74: {
                     75: }
                     76: 
                     77: void
                     78: expand_start_try_stmts ()
                     79: {
                     80:   sorry_no_eh ();
                     81: }
                     82: 
                     83: void
                     84: expand_end_try_stmts ()
                     85: {
                     86: }
                     87: 
                     88: void
                     89: expand_start_all_catch ()
                     90: {
                     91: }
                     92: 
                     93: void
                     94: expand_end_all_catch ()
                     95: {
                     96: }
                     97: 
                     98: void
                     99: expand_start_catch_block (declspecs, declarator)
                    100:      tree declspecs, declarator;
                    101: {
                    102: }
                    103: 
                    104: void
                    105: expand_end_catch_block ()
                    106: {
                    107: }
                    108: 
                    109: void
                    110: init_exception_processing ()
                    111: {
                    112: }
                    113: 
                    114: void
                    115: expand_throw (exp)
                    116:      tree exp;
                    117: {
                    118:   sorry_no_eh ();
                    119: }
                    120: 
                    121: #else
                    122: 
                    123: static int
                    124: doing_eh (do_warn)
                    125:      int do_warn;
                    126: {
                    127:   if (! flag_handle_exceptions)
                    128:     {
                    129:       static int warned = 0;
                    130:       if (! warned && do_warn)
                    131:        {
                    132:          error ("exception handling disabled, use -fhandle-exceptions to enable.");
                    133:          warned = 1;
                    134:        }
                    135:       return 0;
                    136:     }
                    137:   return 1;
                    138: }
                    139: 
                    140: 
                    141: /*
                    142: NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
                    143: to supporting exception handling as per Stroustrup's 2nd edition.
                    144: It is a complete rewrite of all the EH stuff that was here before
                    145:        Shortcomings:
                    146:                1. The type of the throw and catch must still match
                    147:                   exactly (no support yet for matching base classes)
                    148:                2. Throw specifications of functions still doesnt't work.
                    149:        Cool Things:
                    150:                1. Destructors are called properly :-)
                    151:                2. No overhead for the non-exception thrown case.
                    152:                3. Fixing shortcomings 1 and 2 is simple.
                    153:                        -Tad Hunt       ([email protected])
                    154: 
                    155: */
                    156: 
                    157: /* A couple of backend routines from m88k.c */
                    158: 
                    159: /* used to cache a call to __builtin_return_address () */
                    160: static tree BuiltinReturnAddress;
                    161: 
                    162: 
                    163: 
                    164: 
                    165: 
                    166: #include <stdio.h>
                    167: 
                    168: /* XXX - Tad: for EH */
                    169: /* output an exception table entry */
                    170: 
                    171: static void
                    172: output_exception_table_entry (file, start_label, end_label, eh_label)
                    173:      FILE *file;
                    174:      rtx start_label, end_label, eh_label;
                    175: {
                    176:   char label[100];
                    177: 
                    178:   assemble_integer (start_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
                    179:   assemble_integer (end_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
                    180:   assemble_integer (eh_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
                    181:   putc ('\n', file);           /* blank line */
                    182: }
                    183:    
                    184: static void
                    185: easy_expand_asm (str)
                    186:      char *str;
                    187: {
                    188:   expand_asm (build_string (strlen (str)+1, str));
                    189: }
                    190: 
                    191: /* unwind the stack. */
                    192: static void
                    193: do_unwind (throw_label)
                    194:      rtx throw_label;
                    195: {
                    196: #ifdef sparc
                    197:   extern FILE *asm_out_file;
                    198:   tree fcall;
                    199:   tree params;
                    200:   rtx return_val_rtx;
                    201: 
                    202:   /* call to  __builtin_return_address () */
                    203:   params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
                    204:   fcall = build_function_call (BuiltinReturnAddress, params);
                    205:   return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
                    206:   /* In the return, the new pc is pc+8, as the value comming in is
                    207:      really the address of the call insn, not the next insn.  */
                    208:   emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
                    209:                                                         Pmode,
                    210:                                                         throw_label), -8));
                    211:   /* We use three values, PC, type, and value */
                    212:   easy_expand_asm ("st %l0,[%fp]");
                    213:   easy_expand_asm ("st %l1,[%fp+4]");
                    214:   easy_expand_asm ("st %l2,[%fp+8]");
                    215:   easy_expand_asm ("ret");
                    216:   easy_expand_asm ("restore");
                    217:   emit_barrier ();
                    218: #endif
                    219: #if m88k
                    220:   rtx temp_frame = frame_pointer_rtx;
                    221: 
                    222:   temp_frame = memory_address (Pmode, temp_frame);
                    223:   temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
                    224: 
                    225:   /* hopefully this will successfully pop the frame! */
                    226:   emit_move_insn (frame_pointer_rtx, temp_frame);
                    227:   emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
                    228:   emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
                    229:   emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
                    230:                                                     (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
                    231: 
                    232: #if 0
                    233:   emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
                    234:                                                   -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
                    235: 
                    236:   emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
                    237: 
                    238:   emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
                    239:                                                     (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
                    240: #endif
                    241: #endif
                    242: }
                    243: 
                    244: 
                    245: 
                    246: #if 0
                    247: /* This is the startup, and finish stuff per exception table. */
                    248: 
                    249: /* XXX - Tad: exception handling section */
                    250: #ifndef EXCEPT_SECTION_ASM_OP
                    251: #define EXCEPT_SECTION_ASM_OP  "section\t.gcc_except_table,\"a\",@progbits"
                    252: #endif
                    253: 
                    254: #ifdef EXCEPT_SECTION_ASM_OP
                    255: typedef struct {
                    256:     void *start_protect;
                    257:     void *end_protect;
                    258:     void *exception_handler;
                    259:  } exception_table;
                    260: #endif /* EXCEPT_SECTION_ASM_OP */
                    261: 
                    262: #ifdef EXCEPT_SECTION_ASM_OP
                    263: 
                    264:  /* on machines which support it, the exception table lives in another section,
                    265:        but it needs a label so we can reference it...  This sets up that
                    266:     label! */
                    267: asm (EXCEPT_SECTION_ASM_OP);
                    268: exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
                    269: asm (TEXT_SECTION_ASM_OP);
                    270: 
                    271: #endif /* EXCEPT_SECTION_ASM_OP */
                    272: 
                    273: #ifdef EXCEPT_SECTION_ASM_OP
                    274: 
                    275:  /* we need to know where the end of the exception table is... so this
                    276:     is how we do it! */
                    277: 
                    278: asm (EXCEPT_SECTION_ASM_OP);
                    279: exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
                    280: asm (TEXT_SECTION_ASM_OP);
                    281: 
                    282: #endif /* EXCEPT_SECTION_ASM_OP */
                    283: 
                    284: #endif
                    285: 
                    286: void
                    287: exception_section ()
                    288: {
                    289: #ifdef ASM_OUTPUT_SECTION_NAME
                    290:   named_section (".gcc_except_table");
                    291: #else
                    292:   text_section ();
                    293: #endif
                    294: }
                    295: 
                    296: 
                    297: 
                    298: 
                    299: /* from: my-cp-except.c */
                    300: 
                    301: /* VI: ":set ts=4" */
                    302: #if 0
                    303: #include <stdio.h> */
                    304: #include "config.h"
                    305: #include "tree.h"
                    306: #include "rtl.h"
                    307: #include "cp-tree.h"
                    308: #endif
                    309: #include "decl.h"
                    310: #if 0
                    311: #include "flags.h"
                    312: #endif
                    313: #include "insn-flags.h"
                    314: #include "obstack.h"
                    315: #if 0
                    316: #include "expr.h"
                    317: #endif
                    318: 
                    319: /* ======================================================================
                    320:    Briefly the algorithm works like this:
                    321: 
                    322:      When a constructor or start of a try block is encountered,
                    323:      push_eh_entry (&eh_stack) is called.  Push_eh_entry () creates a
                    324:      new entry in the unwind protection stack and returns a label to
                    325:      output to start the protection for that block.
                    326: 
                    327:      When a destructor or end try block is encountered, pop_eh_entry
                    328:      (&eh_stack) is called.  Pop_eh_entry () returns the ehEntry it
                    329:      created when push_eh_entry () was called.  The ehEntry structure
                    330:      contains three things at this point.  The start protect label,
                    331:      the end protect label, and the exception handler label.  The end
                    332:      protect label should be output before the call to the destructor
                    333:      (if any). If it was a destructor, then its parse tree is stored
                    334:      in the finalization variable in the ehEntry structure.  Otherwise
                    335:      the finalization variable is set to NULL to reflect the fact that
                    336:      is the the end of a try block.  Next, this modified ehEntry node
                    337:      is enqueued in the finalizations queue by calling
                    338:      enqueue_eh_entry (&queue,entry).
                    339: 
                    340:        +---------------------------------------------------------------+
                    341:        |XXX: Will need modification to deal with partially             |
                    342:        |                       constructed arrays of objects           |
                    343:        |                                                               |
                    344:        |       Basically, this consists of keeping track of how many   |
                    345:        |       of the objects have been constructed already (this      |
                    346:        |       should be in a register though, so that shouldn't be a  |
                    347:        |       problem.                                                |
                    348:        +---------------------------------------------------------------+
                    349: 
                    350:      When a catch block is encountered, there is a lot of work to be
                    351:      done.
                    352: 
                    353:      Since we don't want to generate the catch block inline with the
                    354:      regular flow of the function, we need to have some way of doing
                    355:      so.  Luckily, we have a couple of routines "get_last_insn ()" and
                    356:      "set_last_insn ()" provided.  When the start of a catch block is
                    357:      encountered, we save a pointer to the last insn generated.  After
                    358:      the catch block is generated, we save a pointer to the first
                    359:      catch block insn and the last catch block insn with the routines
                    360:      "NEXT_INSN ()" and "get_last_insn ()".  We then set the last insn
                    361:      to be the last insn generated before the catch block, and set the
                    362:      NEXT_INSN (last_insn) to zero.
                    363: 
                    364:      Since catch blocks might be nested inside other catch blocks, and
                    365:      we munge the chain of generated insns after the catch block is
                    366:      generated, we need to store the pointers to the last insn
                    367:      generated in a stack, so that when the end of a catch block is
                    368:      encountered, the last insn before the current catch block can be
                    369:      popped and set to be the last insn, and the first and last insns
                    370:      of the catch block just generated can be enqueue'd for output at
                    371:      a later time.
                    372:                
                    373:      Next we must insure that when the catch block is executed, all
                    374:      finalizations for the matching try block have been completed.  If
                    375:      any of those finalizations throw an exception, we must call
                    376:      terminate according to the ARM (section r.15.6.1).  What this
                    377:      means is that we need to dequeue and emit finalizations for each
                    378:      entry in the ehQueue until we get to an entry with a NULL
                    379:      finalization field.  For any of the finalization entries, if it
                    380:      is not a call to terminate (), we must protect it by giving it
                    381:      another start label, end label, and exception handler label,
                    382:      setting its finalization tree to be a call to terminate (), and
                    383:      enqueue'ing this new ehEntry to be output at an outer level.
                    384:      Finally, after all that is done, we can get around to outputting
                    385:      the catch block which basically wraps all the "catch (...) {...}"
                    386:      statements in a big if/then/else construct that matches the
                    387:      correct block to call.
                    388:      
                    389:      ===================================================================== */
                    390: 
                    391: extern rtx emit_insn           PROTO((rtx));
                    392: extern rtx gen_nop             PROTO(());
                    393: 
                    394: /* local globals for function calls
                    395:    ====================================================================== */
                    396: 
                    397: /* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
                    398:    "set_unexpected ()" after default_conversion. (lib-except.c) */
                    399: static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
                    400: 
                    401: /* used to cache __find_first_exception_table_match ()
                    402:    for throw (lib-except.c)  */
                    403: static tree FirstExceptionMatch;
                    404: 
                    405: /* used to cache a call to __unwind_function () (lib-except.c) */
                    406: static tree Unwind;
                    407: 
                    408: /* holds a ready to emit call to "terminate ()". */
                    409: static tree TerminateFunctionCall;
                    410: 
                    411: /* ====================================================================== */
                    412: 
                    413: 
                    414: 
                    415: /* data structures for my various quick and dirty stacks and queues
                    416:    Eventually, most of this should go away, because I think it can be
                    417:    integrated with stuff already built into the compiler. */
                    418: 
                    419: /* =================================================================== */
                    420: 
                    421: struct labelNode {
                    422:     rtx label;
                    423:        struct labelNode *chain;
                    424:  };
                    425: 
                    426: 
                    427: /* this is the most important structure here.  Basically this is how I store
                    428:    an exception table entry internally. */
                    429: struct ehEntry {
                    430:     rtx start_label;
                    431:        rtx end_label;
                    432:        rtx exception_handler_label;
                    433: 
                    434:        tree finalization;
                    435:  };
                    436: 
                    437: struct ehNode {
                    438:     struct ehEntry *entry;
                    439:        struct ehNode *chain;
                    440:  };
                    441: 
                    442: struct ehStack {
                    443:     struct ehNode *top;
                    444:  };
                    445: 
                    446: struct ehQueue {
                    447:     struct ehNode *head;
                    448:        struct ehNode *tail;
                    449:  };
                    450: 
                    451: struct exceptNode {
                    452:     rtx catchstart;
                    453:        rtx catchend;
                    454: 
                    455:        struct exceptNode *chain;
                    456:  };
                    457: 
                    458: struct exceptStack {
                    459:        struct exceptNode *top;
                    460:  };
                    461: /* ========================================================================= */
                    462: 
                    463: 
                    464: 
                    465: /* local globals - these local globals are for storing data necessary for
                    466:    generating the exception table and code in the correct order.
                    467: 
                    468:    ========================================================================= */
                    469: 
                    470: /* Holds the pc for doing "throw" */
                    471: rtx saved_pc;
                    472: /* Holds the type of the thing being thrown. */
                    473: rtx saved_throw_type;
                    474: /* Holds the value being thrown.  */
                    475: rtx saved_throw_value;
                    476: 
                    477: rtx throw_label;
                    478: 
                    479: static struct ehStack ehstack;
                    480: static struct ehQueue ehqueue;
                    481: static struct ehQueue eh_table_output_queue;
                    482: static struct exceptStack exceptstack;
                    483: static struct labelNode *false_label_stack = NULL;
                    484: static struct labelNode *caught_return_label_stack = NULL;
                    485: /* ========================================================================= */
                    486: 
                    487: /* function prototypes */
                    488: static struct ehEntry *pop_eh_entry    PROTO((struct ehStack *stack));
                    489: static void enqueue_eh_entry           PROTO((struct ehQueue *queue, struct ehEntry *entry));
                    490: static void push_except_stmts          PROTO((struct exceptStack *exceptstack,
                    491:                                         rtx catchstart, rtx catchend));
                    492: static int pop_except_stmts            PROTO((struct exceptStack *exceptstack,
                    493:                                         rtx *catchstart, rtx *catchend));
                    494: static rtx push_eh_entry               PROTO((struct ehStack *stack));
                    495: static struct ehEntry *dequeue_eh_entry        PROTO((struct ehQueue *queue));
                    496: static void new_eh_queue               PROTO((struct ehQueue *queue));
                    497: static void new_eh_stack               PROTO((struct ehStack *stack));
                    498: static void new_except_stack           PROTO((struct exceptStack *queue));
                    499: static void push_last_insn             PROTO(());
                    500: static rtx pop_last_insn               PROTO(());
                    501: static void push_label_entry           PROTO((struct labelNode **labelstack, rtx label));
                    502: static rtx pop_label_entry             PROTO((struct labelNode **labelstack));
                    503: static rtx top_label_entry             PROTO((struct labelNode **labelstack));
                    504: static struct ehEntry *copy_eh_entry   PROTO((struct ehEntry *entry));
                    505: 
                    506: 
                    507: 
                    508: /* All my cheesy stack/queue/misc data structure handling routines
                    509: 
                    510:    ========================================================================= */
                    511: 
                    512: static void
                    513: push_label_entry (labelstack, label)
                    514:      struct labelNode **labelstack;
                    515:      rtx label;
                    516: {
                    517:   struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
                    518: 
                    519:   newnode->label = label;
                    520:   newnode->chain = *labelstack;
                    521:   *labelstack = newnode;
                    522: }
                    523: 
                    524: static rtx
                    525: pop_label_entry (labelstack)
                    526:      struct labelNode **labelstack;
                    527: {
                    528:   rtx label;
                    529:   struct labelNode *tempnode;
                    530: 
                    531:   if (! *labelstack) return NULL_RTX;
                    532: 
                    533:   tempnode = *labelstack;
                    534:   label = tempnode->label;
                    535:   *labelstack = (*labelstack)->chain;
                    536:   free (tempnode);
                    537: 
                    538:   return label;
                    539: }
                    540: 
                    541: static rtx
                    542: top_label_entry (labelstack)
                    543:      struct labelNode **labelstack;
                    544: {
                    545:   if (! *labelstack) return NULL_RTX;
                    546: 
                    547:   return (*labelstack)->label;
                    548: }
                    549: 
                    550: static void
                    551: push_except_stmts (exceptstack, catchstart, catchend)
                    552:      struct exceptStack *exceptstack;
                    553:      rtx catchstart, catchend;
                    554: {
                    555:   struct exceptNode *newnode = (struct exceptNode*)
                    556:     xmalloc (sizeof (struct exceptNode));
                    557: 
                    558:   newnode->catchstart = catchstart;
                    559:   newnode->catchend = catchend;
                    560:   newnode->chain = exceptstack->top;
                    561: 
                    562:   exceptstack->top = newnode;
                    563: }
                    564: 
                    565: static int
                    566: pop_except_stmts (exceptstack, catchstart, catchend)
                    567:      struct exceptStack *exceptstack;
                    568:      rtx *catchstart, *catchend;
                    569: {
                    570:   struct exceptNode *tempnode;
                    571: 
                    572:   if (!exceptstack->top) {
                    573:     *catchstart = *catchend = NULL_RTX;
                    574:     return 0;
                    575:   }
                    576: 
                    577:   tempnode = exceptstack->top;
                    578:   exceptstack->top = exceptstack->top->chain;
                    579: 
                    580:   *catchstart = tempnode->catchstart;
                    581:   *catchend = tempnode->catchend;
                    582:   free (tempnode);
                    583: 
                    584:   return 1;
                    585: }
                    586: 
                    587: /* Push to permanent obstack for rtl generation.
                    588:    One level only!  */
                    589: static struct obstack *saved_rtl_obstack;
                    590: void
                    591: push_rtl_perm ()
                    592: {
                    593:   extern struct obstack permanent_obstack;
                    594:   extern struct obstack *rtl_obstack;
                    595:   
                    596:   saved_rtl_obstack = rtl_obstack;
                    597:   rtl_obstack = &permanent_obstack;
                    598: }
                    599: 
                    600: /* Pop back to normal rtl handling.  */
                    601: static void
                    602: pop_rtl_from_perm ()
                    603: {
                    604:   extern struct obstack permanent_obstack;
                    605:   extern struct obstack *rtl_obstack;
                    606:   
                    607:   rtl_obstack = saved_rtl_obstack;
                    608: }
                    609: 
                    610: static rtx
                    611: push_eh_entry (stack)
                    612:      struct ehStack *stack;
                    613: {
                    614:   struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
                    615:   struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
                    616: 
                    617:   if (stack == NULL) {
                    618:     free (node);
                    619:     free (entry);
                    620:     return NULL_RTX;
                    621:   }
                    622: 
                    623:   /* These are saved for the exception table.  */
                    624:   push_rtl_perm ();
                    625:   entry->start_label = gen_label_rtx ();
                    626:   entry->end_label = gen_label_rtx ();
                    627:   entry->exception_handler_label = gen_label_rtx ();
                    628:   pop_rtl_from_perm ();
                    629: 
                    630:   entry->finalization = NULL_TREE;
                    631: 
                    632:   node->entry = entry;
                    633:   node->chain = stack->top;
                    634:   stack->top = node;
                    635: 
                    636:   enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
                    637: 
                    638:   return entry->start_label;
                    639: }
                    640: 
                    641: static struct ehEntry *
                    642: pop_eh_entry (stack)
                    643:      struct ehStack *stack;
                    644: {
                    645:   struct ehNode *tempnode;
                    646:   struct ehEntry *tempentry;
                    647: 
                    648:   if (stack && (tempnode = stack->top)) {
                    649:     tempentry = tempnode->entry;
                    650:     stack->top = stack->top->chain;
                    651:     free (tempnode);
                    652: 
                    653:     return tempentry;
                    654:   }
                    655: 
                    656:   return NULL;
                    657: }
                    658: 
                    659: static struct ehEntry *
                    660: copy_eh_entry (entry)
                    661:      struct ehEntry *entry;
                    662: {
                    663:   struct ehEntry *newentry;
                    664: 
                    665:   newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
                    666:   memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
                    667: 
                    668:   return newentry;
                    669: }
                    670: 
                    671: static void
                    672: enqueue_eh_entry (queue, entry)
                    673:      struct ehQueue *queue;
                    674:      struct ehEntry *entry;
                    675: {
                    676:   struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
                    677: 
                    678:   node->entry = entry;
                    679:   node->chain = NULL;
                    680: 
                    681:   if (queue->head == NULL)
                    682:     {
                    683:       queue->head = node;
                    684:     }
                    685:   else
                    686:     {
                    687:       queue->tail->chain = node;
                    688:     }
                    689:   queue->tail = node;
                    690: }
                    691: 
                    692: static struct ehEntry *
                    693: dequeue_eh_entry (queue)
                    694:      struct ehQueue *queue;
                    695: {
                    696:   struct ehNode *tempnode;
                    697:   struct ehEntry *tempentry;
                    698: 
                    699:   if (queue->head == NULL)
                    700:     return NULL;
                    701: 
                    702:   tempnode = queue->head;
                    703:   queue->head = queue->head->chain;
                    704: 
                    705:   tempentry = tempnode->entry;
                    706:   free (tempnode);
                    707: 
                    708:   return tempentry;
                    709: }
                    710: 
                    711: static void
                    712: new_eh_queue (queue)
                    713:      struct ehQueue *queue;
                    714: {
                    715:   queue->head = queue->tail = NULL;
                    716: }
                    717: 
                    718: static void
                    719: new_eh_stack (stack)
                    720:      struct ehStack *stack;
                    721: {
                    722:   stack->top = NULL;
                    723: }
                    724: 
                    725: static void
                    726: new_except_stack (stack)
                    727:      struct exceptStack *stack;
                    728: {
                    729:   stack->top = NULL;
                    730: }
                    731: /* ========================================================================= */
                    732: 
                    733: void
                    734: lang_interim_eh (finalization)
                    735:      tree finalization;
                    736: {
                    737:   if (finalization)
                    738:     end_protect (finalization);
                    739:   else
                    740:     start_protect ();
                    741: }
                    742: 
                    743: /* sets up all the global eh stuff that needs to be initialized at the
                    744:    start of compilation.
                    745: 
                    746:    This includes:
                    747:                - Setting up all the function call trees
                    748:                - Initializing the ehqueue
                    749:                - Initializing the eh_table_output_queue
                    750:                - Initializing the ehstack
                    751:                - Initializing the exceptstack
                    752: */
                    753: 
                    754: void
                    755: init_exception_processing ()
                    756: {
                    757:   extern tree define_function ();
                    758:   tree unexpected_fndecl, terminate_fndecl;
                    759:   tree set_unexpected_fndecl, set_terminate_fndecl;
                    760:   tree catch_match_fndecl;
                    761:   tree find_first_exception_match_fndecl;
                    762:   tree unwind_fndecl;
                    763:   tree temp, PFV;
                    764: 
                    765:   interim_eh_hook = lang_interim_eh;
                    766: 
                    767:   /* void (*)() */
                    768:   PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
                    769: 
                    770:   /* arg list for the build_function_type call for set_terminate () and
                    771:      set_unexpected () */
                    772:   temp = tree_cons (NULL_TREE, PFV, void_list_node);
                    773: 
                    774:   push_lang_context (lang_name_c);
                    775: 
                    776:   set_terminate_fndecl =
                    777:     define_function ("set_terminate",
                    778:                     build_function_type (PFV, temp),
                    779:                     NOT_BUILT_IN,
                    780:                     pushdecl,
                    781:                     0);
                    782:   set_unexpected_fndecl =
                    783:     define_function ("set_unexpected",
                    784:                     build_function_type (PFV, temp),
                    785:                     NOT_BUILT_IN,
                    786:                     pushdecl,
                    787:                     0);
                    788: 
                    789:   unexpected_fndecl =
                    790:     define_function ("unexpected",
                    791:                     build_function_type (void_type_node, void_list_node),
                    792:                     NOT_BUILT_IN,
                    793:                     pushdecl,
                    794:                     0);
                    795:   terminate_fndecl =
                    796:     define_function ("terminate",
                    797:                     build_function_type (void_type_node, void_list_node),
                    798:                     NOT_BUILT_IN,
                    799:                     pushdecl,
                    800:                     0);
                    801:   catch_match_fndecl =
                    802:     define_function ("__throw_type_match",
                    803:                     build_function_type (integer_type_node,
                    804:                                          tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))),
                    805:                     NOT_BUILT_IN,
                    806:                     pushdecl,
                    807:                     0);
                    808:   find_first_exception_match_fndecl =
                    809:     define_function ("__find_first_exception_table_match",
                    810:                     build_function_type (ptr_type_node,
                    811:                                          tree_cons (NULL_TREE, ptr_type_node,
                    812:                                                     void_list_node)),
                    813:                     NOT_BUILT_IN,
                    814:                     pushdecl,
                    815:                     0);
                    816:   unwind_fndecl =
                    817:     define_function ("__unwind_function",
                    818:                     build_function_type (void_type_node,
                    819:                                          tree_cons (NULL_TREE, ptr_type_node, void_list_node)),
                    820:                     NOT_BUILT_IN,
                    821:                     pushdecl,
                    822:                     0);
                    823: 
                    824:   Unexpected = default_conversion (unexpected_fndecl);
                    825:   Terminate = default_conversion (terminate_fndecl);
                    826:   SetTerminate = default_conversion (set_terminate_fndecl);
                    827:   SetUnexpected = default_conversion (set_unexpected_fndecl);
                    828:   CatchMatch = default_conversion (catch_match_fndecl);
                    829:   FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
                    830:   Unwind = default_conversion (unwind_fndecl);
                    831:   BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
                    832: 
                    833:   TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
                    834: 
                    835:   pop_lang_context ();
                    836:   throw_label = gen_label_rtx ();
                    837:   saved_pc = gen_rtx (REG, Pmode, 16);
                    838:   saved_throw_type = gen_rtx (REG, Pmode, 17);
                    839:   saved_throw_value = gen_rtx (REG, Pmode, 18);
                    840: 
                    841:   new_eh_queue (&ehqueue);
                    842:   new_eh_queue (&eh_table_output_queue);
                    843:   new_eh_stack (&ehstack);
                    844:   new_except_stack (&exceptstack);
                    845: }
                    846: 
                    847: /* call this to begin a block of unwind protection (ie: when an object is
                    848:    constructed) */
                    849: void
                    850: start_protect ()
                    851: {
                    852:   if (doing_eh (0))
                    853:     {
                    854:       emit_label (push_eh_entry (&ehstack));
                    855:     }
                    856: }
                    857:    
                    858: /* call this to end a block of unwind protection.  the finalization tree is
                    859:    the finalization which needs to be run in order to cleanly unwind through
                    860:    this level of protection. (ie: call this when a scope is exited)*/
                    861: void
                    862: end_protect (finalization)
                    863:      tree finalization;
                    864: {
                    865:   struct ehEntry *entry = pop_eh_entry (&ehstack);
                    866: 
                    867:   if (! doing_eh (0))
                    868:     return;
                    869: 
                    870:   emit_label (entry->end_label);
                    871: 
                    872:   entry->finalization = finalization;
                    873: 
                    874:   enqueue_eh_entry (&ehqueue, entry);
                    875: }
                    876: 
                    877: /* call this on start of a try block. */
                    878: void
                    879: expand_start_try_stmts ()
                    880: {
                    881:   if (doing_eh (1))
                    882:     {
                    883:       start_protect ();
                    884:     }
                    885: }
                    886: 
                    887: void
                    888: expand_end_try_stmts ()
                    889: {
                    890:   end_protect (integer_zero_node);
                    891: }
                    892: 
                    893: struct insn_save_node {
                    894:        rtx last;
                    895:        struct insn_save_node *chain;
                    896:  };
                    897: 
                    898: static struct insn_save_node *InsnSave = NULL;
                    899: 
                    900: 
                    901: /* Used to keep track of where the catch blocks start.  */
                    902: static void
                    903: push_last_insn ()
                    904: {
                    905:   struct insn_save_node *newnode = (struct insn_save_node*)
                    906:     xmalloc (sizeof (struct insn_save_node));
                    907: 
                    908:   newnode->last = get_last_insn ();
                    909:   newnode->chain = InsnSave;
                    910:   InsnSave = newnode;
                    911: }
                    912: 
                    913: /* Use to keep track of where the catch blocks start.  */
                    914: static rtx
                    915: pop_last_insn ()
                    916: {
                    917:   struct insn_save_node *tempnode;
                    918:   rtx temprtx;
                    919: 
                    920:   if (!InsnSave) return NULL_RTX;
                    921: 
                    922:   tempnode = InsnSave;
                    923:   temprtx = tempnode->last;
                    924:   InsnSave = InsnSave->chain;
                    925: 
                    926:   free (tempnode);
                    927: 
                    928:   return temprtx;
                    929: }
                    930: 
                    931: /* call this to start processing of all the catch blocks. */
                    932: void
                    933: expand_start_all_catch ()
                    934: {
                    935:   struct ehEntry *entry;
                    936:   rtx label;
                    937: 
                    938:   if (! doing_eh (1))
                    939:     return;
                    940: 
                    941:   emit_line_note (input_filename, lineno);
                    942:   label = gen_label_rtx ();
                    943:   /* The label for the exception handling block we will save.  */
                    944:   emit_label (label);
                    945:   
                    946:   push_label_entry (&caught_return_label_stack, label);
                    947: 
                    948:   /* Remember where we started. */
                    949:   push_last_insn ();
                    950: 
                    951:   emit_insn (gen_nop ());
                    952: 
                    953:   /* Will this help us not stomp on it? */
                    954:   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
                    955:   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
                    956: 
                    957:   while (1)
                    958:     {
                    959:       entry = dequeue_eh_entry (&ehqueue);
                    960:       emit_label (entry->exception_handler_label);
                    961: 
                    962:       expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
                    963: 
                    964:       /* When we get down to the matching entry, stop.  */
                    965:       if (entry->finalization == integer_zero_node)
                    966:        break;
                    967: 
                    968:       free (entry);
                    969:     }
                    970: 
                    971:   /* This goes when the below moves out of our way.  */
                    972: #if 1
                    973:   label = gen_label_rtx ();
                    974:   emit_jump (label);
                    975: #endif
                    976:   
                    977:   /* All this should be out of line, and saved back in the exception handler
                    978:      block area.  */
                    979: #if 1
                    980:   entry->start_label = entry->exception_handler_label;
                    981:   /* These are saved for the exception table.  */
                    982:   push_rtl_perm ();
                    983:   entry->end_label = gen_label_rtx ();
                    984:   entry->exception_handler_label = gen_label_rtx ();
                    985:   entry->finalization = TerminateFunctionCall;
                    986:   pop_rtl_from_perm ();
                    987:   emit_label (entry->end_label);
                    988: 
                    989:   enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
                    990: 
                    991:   /* After running the finalization, continue on out to the next
                    992:      cleanup, if we have nothing better to do.  */
                    993:   emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry->end_label));
                    994:   /* Will this help us not stomp on it? */
                    995:   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
                    996:   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
                    997:   emit_jump (throw_label);
                    998:   emit_label (entry->exception_handler_label);
                    999:   expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
                   1000:   emit_barrier ();
                   1001: #endif
                   1002:   emit_label (label);
                   1003: }
                   1004: 
                   1005: /* call this to end processing of all the catch blocks. */
                   1006: void
                   1007: expand_end_all_catch ()
                   1008: {
                   1009:   rtx catchstart, catchend, last;
                   1010:   rtx label;
                   1011: 
                   1012:   if (! doing_eh (1))
                   1013:     return;
                   1014: 
                   1015:   /* Find the start of the catch block.  */
                   1016:   last = pop_last_insn ();
                   1017:   catchstart = NEXT_INSN (last);
                   1018:   catchend = get_last_insn ();
                   1019: 
                   1020:   NEXT_INSN (last) = 0;
                   1021:   set_last_insn (last);
                   1022: 
                   1023:   /* this level of catch blocks is done, so set up the successful catch jump
                   1024:      label for the next layer of catch blocks. */
                   1025:   pop_label_entry (&caught_return_label_stack);
                   1026: 
                   1027:   push_except_stmts (&exceptstack, catchstart, catchend);
                   1028:   
                   1029:   /* Here we fall through into the continuation code.  */
                   1030: }
                   1031: 
                   1032: 
                   1033: /* this is called from expand_exception_blocks () to expand the toplevel
                   1034:    finalizations for a function. */
                   1035: void
                   1036: expand_leftover_cleanups ()
                   1037: {
                   1038:   struct ehEntry *entry;
                   1039:   rtx first_label = NULL_RTX;
                   1040: 
                   1041:   if (! doing_eh (0))
                   1042:     return;
                   1043: 
                   1044:   /* Will this help us not stomp on it? */
                   1045:   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
                   1046:   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
                   1047: 
                   1048:   while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
                   1049:     {
                   1050:       if (! first_label)
                   1051:        first_label = entry->exception_handler_label;
                   1052:       emit_label (entry->exception_handler_label);
                   1053: 
                   1054:       expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
                   1055: 
                   1056:       /* leftover try block, opps.  */
                   1057:       if (entry->finalization == integer_zero_node)
                   1058:        abort ();
                   1059: 
                   1060:       free (entry);
                   1061:     }
                   1062:   if (first_label)
                   1063:     {
                   1064:       rtx label;
                   1065:       struct ehEntry entry;
                   1066:       /* These are saved for the exception table.  */
                   1067:       push_rtl_perm ();
                   1068:       label = gen_label_rtx ();
                   1069:       entry.start_label = first_label;
                   1070:       entry.end_label = label;
                   1071:       entry.exception_handler_label = gen_label_rtx ();
                   1072:       entry.finalization = TerminateFunctionCall;
                   1073:       pop_rtl_from_perm ();
                   1074:       emit_label (label);
                   1075: 
                   1076:       enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
                   1077: 
                   1078:       /* After running the finalization, continue on out to the next
                   1079:         cleanup, if we have nothing better to do.  */
                   1080:       emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry.end_label));
                   1081:       /* Will this help us not stomp on it? */
                   1082:       emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
                   1083:       emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
                   1084:       emit_jump (throw_label);
                   1085:       emit_label (entry.exception_handler_label);
                   1086:       expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
                   1087:       emit_barrier ();
                   1088:     }
                   1089: }
                   1090: 
                   1091: /* call this to start a catch block. Typename is the typename, and identifier
                   1092:    is the variable to place the object in or NULL if the variable doesn't
                   1093:    matter.  If typename is NULL, that means its a "catch (...)" or catch
                   1094:    everything.  In that case we don't need to do any type checking.
                   1095:    (ie: it ends up as the "else" clause rather than an "else if" clause) */
                   1096: void
                   1097: expand_start_catch_block (declspecs, declarator)
                   1098:      tree declspecs, declarator;
                   1099: {
                   1100:   rtx false_label_rtx;
                   1101:   rtx protect_label_rtx;
                   1102:   tree type;
                   1103:   tree decl;
                   1104:   tree init;
                   1105: 
                   1106:   if (! doing_eh (1))
                   1107:     return;
                   1108: 
                   1109:   /* Create a binding level for the parm.  */
                   1110:   expand_start_bindings (0);
                   1111: 
                   1112:   if (declspecs)
                   1113:     {
                   1114:       tree init_type;
                   1115:       decl = grokdeclarator (declarator, declspecs, NORMAL, 1, NULL_TREE);
                   1116: 
                   1117:       /* Figure out the type that the initializer is. */
                   1118:       init_type = TREE_TYPE (decl);
                   1119:       if (TREE_CODE (init_type) != REFERENCE_TYPE)
                   1120:        init_type = build_reference_type (init_type);
                   1121: 
                   1122:       init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value)));
                   1123:       
                   1124:       /* Do we need the below two lines? */
                   1125:       /* Let `finish_decl' know that this initializer is ok.  */
                   1126:       DECL_INITIAL (decl) = init;
                   1127:       /* This needs to be preallocated under the try block,
                   1128:         in a union of all catch variables. */
                   1129:       pushdecl (decl);
                   1130:       type = TREE_TYPE (decl);
                   1131: 
                   1132:       /* peel back references, so they match. */
                   1133:       if (TREE_CODE (type) == REFERENCE_TYPE)
                   1134:        type = TREE_TYPE (type);
                   1135:     }
                   1136:   else
                   1137:     type = NULL_TREE;
                   1138: 
                   1139:   /* These are saved for the exception table.  */
                   1140:   push_rtl_perm ();
                   1141:   false_label_rtx = gen_label_rtx ();
                   1142:   protect_label_rtx = gen_label_rtx ();
                   1143:   pop_rtl_from_perm ();
                   1144:   push_label_entry (&false_label_stack, false_label_rtx);
                   1145:   push_label_entry (&false_label_stack, protect_label_rtx);
                   1146: 
                   1147:   if (type)
                   1148:     {
                   1149:       tree params;
                   1150:       char *typestring;
                   1151:       rtx call_rtx, return_value_rtx;
                   1152:       tree catch_match_fcall;
                   1153:       tree catchmatch_arg, argval;
                   1154: 
                   1155:       typestring = build_overload_name (type, 1, 1);
                   1156: 
                   1157:       params = tree_cons (NULL_TREE,
                   1158:                         combine_strings (build_string (strlen (typestring)+1, typestring)),
                   1159:                         tree_cons (NULL_TREE,
                   1160:                                    make_tree (ptr_type_node, saved_throw_type),
                   1161:                                    NULL_TREE));
                   1162:       catch_match_fcall = build_function_call (CatchMatch, params);
                   1163:       call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
                   1164: 
                   1165:       return_value_rtx =
                   1166:        hard_function_value (integer_type_node, catch_match_fcall);
                   1167: 
                   1168:       /* did the throw type match function return TRUE? */
                   1169:       emit_cmp_insn (return_value_rtx, const0_rtx, NE, NULL_RTX,
                   1170:                    GET_MODE (return_value_rtx), 0, 0);
                   1171: 
                   1172:       /* if it returned FALSE, jump over the catch block, else fall into it */
                   1173:       emit_jump_insn (gen_bne (false_label_rtx));
                   1174:       finish_decl (decl, init, NULL_TREE, 0);
                   1175:     }
                   1176:   else
                   1177:     {
                   1178:       /* Fall into the catch all section. */
                   1179:     }
                   1180: 
                   1181:   /* This is the starting of something to protect.  */
                   1182:   emit_label (protect_label_rtx);
                   1183: 
                   1184:   emit_line_note (input_filename, lineno);
                   1185: }
                   1186: 
                   1187: 
                   1188: /* Call this to end a catch block.  Its responsible for emitting the
                   1189:    code to handle jumping back to the correct place, and for emitting
                   1190:    the label to jump to if this catch block didn't match.  */
                   1191: void expand_end_catch_block ()
                   1192: {
                   1193:   if (doing_eh (1))
                   1194:     {
                   1195:       rtx start_protect_label_rtx;
                   1196:       rtx end_protect_label_rtx;
                   1197:       tree decls;
                   1198:       struct ehEntry entry;
                   1199: 
                   1200:       /* label we jump to if we caught the exception */
                   1201:       emit_jump (top_label_entry (&caught_return_label_stack));
                   1202: 
                   1203:       /* Code to throw out to outer context, if we get an throw from within
                   1204:         our catch handler. */
                   1205:       /* These are saved for the exception table.  */
                   1206:       push_rtl_perm ();
                   1207:       entry.exception_handler_label = gen_label_rtx ();
                   1208:       pop_rtl_from_perm ();
                   1209:       emit_label (entry.exception_handler_label);
                   1210:       emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
                   1211:                                         Pmode,
                   1212:                                         top_label_entry (&caught_return_label_stack)));
                   1213:       emit_jump (throw_label);
                   1214:       /* No associated finalization.  */
                   1215:       entry.finalization = NULL_TREE;
                   1216: 
                   1217:       /* Because we are reordered out of line, we have to protect this. */
                   1218:       /* label for the start of the protection region.  */
                   1219:       start_protect_label_rtx = pop_label_entry (&false_label_stack);
                   1220: 
                   1221:       /* Cleanup the EH paramater.  */
                   1222:       expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
                   1223:       
                   1224:       /* label we emit to jump to if this catch block didn't match. */
                   1225:       emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack));
                   1226: 
                   1227:       /* Because we are reordered out of line, we have to protect this. */
                   1228:       entry.start_label = start_protect_label_rtx;
                   1229:       entry.end_label = end_protect_label_rtx;
                   1230: 
                   1231:       /* These set up a call to throw the caught exception into the outer
                   1232:        context.  */
                   1233:       enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
                   1234:     }
                   1235: }
                   1236: 
                   1237: /* cheesyness to save some typing. returns the return value rtx */
                   1238: rtx
                   1239: do_function_call (func, params, return_type)
                   1240:      tree func, params, return_type;
                   1241: {
                   1242:   tree func_call;
                   1243:   func_call = build_function_call (func, params);
                   1244:   expand_call (func_call, NULL_RTX, 0);
                   1245:   if (return_type != NULL_TREE)
                   1246:     return hard_function_value (return_type, func_call);
                   1247:   return NULL_RTX;
                   1248: }
                   1249: 
                   1250: 
                   1251: /* is called from expand_excpetion_blocks () to generate the code in a function
                   1252:    to "throw" if anything in the function needs to preform a throw.
                   1253: 
                   1254:    expands "throw" as the following psuedo code:
                   1255: 
                   1256:        throw:
                   1257:                eh = find_first_exception_match (saved_pc);
                   1258:            if (!eh) goto gotta_rethrow_it;
                   1259:                goto eh;
                   1260: 
                   1261:        gotta_rethrow_it:
                   1262:                saved_pc = __builtin_return_address (0);
                   1263:                pop_to_previous_level ();
                   1264:                goto throw;
                   1265: 
                   1266:  */
                   1267: static void
                   1268: expand_builtin_throw ()
                   1269: {
                   1270:   tree fcall;
                   1271:   tree params;
                   1272:   rtx return_val_rtx;
                   1273:   rtx gotta_rethrow_it = gen_label_rtx ();
                   1274:   rtx gotta_call_terminate = gen_label_rtx ();
                   1275:   rtx unwind_and_throw = gen_label_rtx ();
                   1276:   rtx goto_unwind_and_throw = gen_label_rtx ();
                   1277: 
                   1278:   emit_label (throw_label);
                   1279: 
                   1280:   /* search for an exception handler for the saved_pc */
                   1281:   return_val_rtx = do_function_call (FirstExceptionMatch,
                   1282:                                     tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
                   1283:                                     ptr_type_node);
                   1284: 
                   1285:   /* did we find one? */
                   1286:   emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
                   1287:                 GET_MODE (return_val_rtx), 0, 0);
                   1288: 
                   1289:   /* if not, jump to gotta_rethrow_it */
                   1290:   emit_jump_insn (gen_beq (gotta_rethrow_it));
                   1291: 
                   1292:   /* we found it, so jump to it */
                   1293:   emit_indirect_jump (return_val_rtx);
                   1294: 
                   1295:   /* code to deal with unwinding and looking for it again */
                   1296:   emit_label (gotta_rethrow_it);
                   1297: 
                   1298:   /* call to  __builtin_return_address () */
                   1299:   params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
                   1300:   fcall = build_function_call (BuiltinReturnAddress, params);
                   1301:   return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
                   1302: 
                   1303:   /* did __builtin_return_address () return a valid address? */
                   1304:   emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
                   1305:                 GET_MODE (return_val_rtx), 0, 0);
                   1306: 
                   1307:   emit_jump_insn (gen_beq (gotta_call_terminate));
                   1308: 
                   1309:   /* yes it did */
                   1310:   emit_move_insn (saved_pc, return_val_rtx);
                   1311:   do_unwind (throw_label);
                   1312:   emit_jump (throw_label);
                   1313: 
                   1314:   /* no it didn't --> therefore we need to call terminate */
                   1315:   emit_label (gotta_call_terminate);
                   1316:   do_function_call (Terminate, NULL_TREE, NULL_TREE);
                   1317: }
                   1318: 
                   1319: 
                   1320: /* This is called to expand all the toplevel exception handling
                   1321:    finalization for a function.  It should only be called once per
                   1322:    function.  */
                   1323: void
                   1324: expand_exception_blocks ()
                   1325: {
                   1326:   rtx catchstart, catchend;
                   1327:   rtx last;
                   1328:   static rtx funcend;
                   1329: 
                   1330:   funcend = gen_label_rtx ();
                   1331:   emit_jump (funcend);
                   1332:   /* expand_null_return (); */
                   1333: 
                   1334:   while (pop_except_stmts (&exceptstack, &catchstart, &catchend)) {
                   1335:     last = get_last_insn ();
                   1336:     NEXT_INSN (last) = catchstart;
                   1337:     PREV_INSN (catchstart) = last;
                   1338:     NEXT_INSN (catchend) = 0;
                   1339:     set_last_insn (catchend);
                   1340:   }
                   1341: 
                   1342:   expand_leftover_cleanups ();
                   1343: 
                   1344:   {
                   1345:     static int have_done = 0;
                   1346:     if (! have_done && TREE_PUBLIC (current_function_decl)
                   1347:        && ! DECL_INLINE (current_function_decl))
                   1348:       {
                   1349:        have_done = 1;
                   1350:        expand_builtin_throw ();
                   1351:       }
                   1352:   }
                   1353:   emit_label (funcend);
                   1354: }
                   1355: 
                   1356: 
                   1357: /* call this to expand a throw statement.  This follows the following
                   1358:    algorithm:
                   1359: 
                   1360:        1. Allocate space to save the current PC onto the stack.
                   1361:        2. Generate and emit a label and save its address into the
                   1362:                newly allocate stack space since we can't save the pc directly.
                   1363:        3. If this is the first call to throw in this function:
                   1364:                generate a label for the throw block
                   1365:        4. jump to the throw block label.  */
                   1366: void
                   1367: expand_throw (exp)
                   1368:      tree exp;
                   1369: {
                   1370:   rtx label;
                   1371:   tree type;
                   1372: 
                   1373:   if (! doing_eh (1))
                   1374:     return;
                   1375: 
                   1376:   /* This is the label that represents where in the code we were, when
                   1377:      we got an exception.  This needs to be updated when we rethrow an
                   1378:      exception, so that the matching routine knows to search out.  */
                   1379:   label = gen_label_rtx ();
                   1380:   emit_label (label);
                   1381:   emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
                   1382: 
                   1383:   if (exp)
                   1384:     {
                   1385:       /* throw expression */
                   1386:       /* First, decay it. */
                   1387:       exp = default_conversion (exp);
                   1388:       type = TREE_TYPE (exp);
                   1389: 
                   1390:       {
                   1391:        char *typestring = build_overload_name (type, 1, 1);
                   1392:        tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
                   1393:        rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
                   1394:        rtx throw_value_rtx;
                   1395: 
                   1396:        emit_move_insn (saved_throw_type, throw_type_rtx);
                   1397:        exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, NULL_TREE);
                   1398:        if (exp == error_mark_node)
                   1399:          error ("  in thrown expression");
                   1400:        throw_value_rtx = expand_expr (build_unary_op (ADDR_EXPR, exp, 0), NULL_RTX, VOIDmode, 0);
                   1401:        emit_move_insn (saved_throw_value, throw_value_rtx);
                   1402:       }
                   1403:     }
                   1404:   else
                   1405:     {
                   1406:       /* rethrow current exception */
                   1407:       /* This part is easy, as we dont' have to do anything else.  */
                   1408:     }
                   1409: 
                   1410:   emit_jump (throw_label);
                   1411: }
                   1412: 
                   1413: /* end of: my-cp-except.c */
                   1414: #endif
                   1415: 
                   1416: 
                   1417: /* Output the exception table.
                   1418:  Return the number of handlers.  */
                   1419: int
                   1420: build_exception_table ()
                   1421: {
                   1422:   int count = 0;
                   1423: #ifdef TRY_NEW_EH
                   1424:   extern FILE *asm_out_file;
                   1425:   struct ehEntry *entry;
                   1426:   tree eh_node_decl;
                   1427: 
                   1428:   if (! doing_eh (0))
                   1429:     return 0;
                   1430: 
                   1431:  while (entry = dequeue_eh_entry (&eh_table_output_queue))
                   1432:    {
                   1433:      if (count == 0)
                   1434:        {
                   1435:         exception_section ();
                   1436: 
                   1437:         /* Beginning marker for table. */
                   1438:         ASM_OUTPUT_ALIGN (asm_out_file, 2);
                   1439:         ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
                   1440:         fprintf (asm_out_file, "        .word   0, 0, 0\n");
                   1441:        }
                   1442:      count++;
                   1443:      output_exception_table_entry (asm_out_file,
                   1444:                                   entry->start_label, entry->end_label,
                   1445:                                   entry->exception_handler_label);
                   1446:   }
                   1447: 
                   1448:   if (count)
                   1449:     {
                   1450:       /* Ending marker for table. */
                   1451:       ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
                   1452:       fprintf (asm_out_file, "        .word   -1, -1, -1\n");
                   1453:     }
                   1454: 
                   1455: #endif /* TRY_NEW_EH */
                   1456:   return count;
                   1457: }
                   1458: 
                   1459: void
                   1460: register_exception_table ()
                   1461: {
                   1462: #ifdef TRY_NEW_EH
                   1463:   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
                   1464:                     VOIDmode, 1,
                   1465:                     gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
                   1466:                     Pmode);
                   1467: #endif /* TRY_NEW_EH */
                   1468: }
                   1469: 
                   1470: /* Build a throw expression.  */
                   1471: tree
                   1472: build_throw (e)
                   1473:      tree e;
                   1474: {
                   1475:   e = build1 (THROW_EXPR, void_type_node, e);
                   1476:   TREE_SIDE_EFFECTS (e) = 1;
                   1477:   return e;
                   1478: }

unix.superglobalmegacorp.com

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