]> gcc.gnu.org Git - gcc.git/blob - gcc/except.c
Manson: Doc +
[gcc.git] / gcc / except.c
1 /* Implements exception handling.
2 Copyright (C) 1989, 92-95, 1996 Free Software Foundation, Inc.
3 Contributed by Mike Stump <mrs@cygnus.com>.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22
23 /* An exception is an event that can be signaled from within a
24 function. This event can then be "caught" or "trapped" by the
25 callers of this function. This potentially allows program flow to
26 be transferred to any arbitrary code assocated with a function call
27 several levels up the stack.
28
29 The intended use for this mechanism is for signaling "exceptional
30 events" in an out-of-band fashion, hence its name. The C++ language
31 (and many other OO-styled or functional languages) practically
32 requires such a mechanism, as otherwise it becomes very difficult
33 or even impossible to signal failure conditions in complex
34 situations. The traditional C++ example is when an error occurs in
35 the process of constructing an object; without such a mechanism, it
36 is impossible to signal that the error occurs without adding global
37 state variables and error checks around every object construction.
38
39 The act of causing this event to occur is referred to as "throwing
40 an exception". (Alternate terms include "raising an exception" or
41 "signaling an exception".) The term "throw" is used because control
42 is returned to the callers of the function that is signaling the
43 exception, and thus there is the concept of "throwing" the
44 exception up the call stack.
45
46 It is appropriate to speak of the "context of a throw". This
47 context refers to the address where the exception is thrown from,
48 and is used to determine which exception region will handle the
49 exception.
50
51 Regions of code within a function can be marked such that if it
52 contains the context of a throw, control will be passed to a
53 designated "exception handler". These areas are known as "exception
54 regions". Exception regions cannot overlap, but they can be nested
55 to any arbitrary depth. Also, exception regions cannot cross
56 function boundaries.
57
58 Each object file that is compiled with exception handling contains a
59 static array of exception handlers named __EXCEPTION_TABLE__. Each entry
60 contains the starting and ending addresses of the exception region,
61 and the address of the handler designated for that region.
62
63 At program startup each object file invokes a function named
64 __register_exceptions with the address of its local
65 __EXCEPTION_TABLE__. __register_exceptions is defined in libgcc2.c,
66 and is responsible for recording all of the exception regions into
67 one list (which is kept in a static variable named exception_table_list).
68
69 The function __throw () is actually responsible for doing the
70 throw. In the C++ frontend, __throw () is generated on a
71 per-object-file basis for each source file compiled with
72 -fexceptions.
73
74 __throw () attempts to find the appropriate exception handler for the
75 PC value stored in __eh_pc by calling __find_first_exception_table_match
76 (which is defined in libgcc2.c). If an appropriate handler is
77 found, __throw jumps directly to it.
78
79 If a handler for the address being thrown from can't be found,
80 __throw is responsible for unwinding the stack, determining the
81 address of the caller of the current function (which will be used
82 as the new context to throw from), and then searching for a handler
83 for the new context. __throw may also call abort () if it is unable
84 to unwind the stack, and can also call an external library function
85 named __terminate if it reaches the top of the stack without
86 finding an appropriate handler.
87
88 Note that some of the regions and handlers are implicitly
89 generated. The handlers for these regions perform necessary
90 cleanups (in C++ these cleanups are responsible for invoking
91 necessary object destructors) before rethrowing the exception to
92 the outer exception region.
93
94 Internal implementation details:
95
96 The start of an exception region is indicated by calling
97 expand_eh_region_start (). expand_eh_region_end (handler) is
98 subsequently invoked to end the region and to associate a handler
99 with the region. This is used to create a region that has an
100 associated cleanup routine for performing tasks like object
101 destruction.
102
103 To associate a user-defined handler with a block of statements, the
104 function expand_start_try_stmts () is used to mark the start of the
105 block of statements with which the handler is to be associated
106 (which is usually known as a "try block"). All statements that
107 appear afterwards will be associated with the try block.
108
109 A call to expand_start_all_catch () will mark the end of the try
110 block, and also marks the start of the "catch block" associated
111 with the try block. This catch block will only be invoked if an
112 exception is thrown through the try block. The instructions for the
113 catch block are kept as a separate sequence, and will be emitted at
114 the end of the function along with the handlers specified via
115 expand_eh_region_end (). The end of the catch block is marked with
116 expand_end_all_catch ().
117
118 Any data associated with the exception must currently be handled by
119 some external mechanism maintained in the frontend. For example,
120 the C++ exception mechanism passes an arbitrary value along with
121 the exception, and this is handled in the C++ frontend by using a
122 global variable to hold the value.
123
124 Internally-generated exception regions are marked by calling
125 expand_eh_region_start () to mark the start of the region, and
126 expand_eh_region_end () is used to both designate the end of the
127 region and to associate a handler/cleanup with the region. These
128 functions generate the appropriate RTL sequences to mark the start
129 and end of the exception regions and ensure that an appropriate
130 exception region entry will be added to the exception region table.
131 expand_eh_region_end () also queues the provided handler to be
132 emitted at the end of the current function.
133
134 TARGET_EXPRs can also be used to designate exception regions. A
135 TARGET_EXPR gives an unwind-protect style interface commonly used
136 in functional languages such as LISP. The associated expression is
137 evaluated, and if it (or any of the functions that it calls) throws
138 an exception it is caught by the associated cleanup. The backend
139 also takes care of the details of associating an exception table
140 entry with the expression and generating the necessary code.
141
142 The generated RTL for an exception region includes
143 NOTE_INSN_EH_REGION_BEG and NOTE_INSN_EH_REGION_END notes that mark
144 the start and end of the exception region. A unique label is also
145 generated at the start of the exception region.
146
147 In the current implementation, an exception can only be thrown from
148 a function call (since the mechanism used to actually throw an
149 exception involves calling __throw). If an exception region is
150 created but no function calls occur within that region, the region
151 can be safely optimized away since no exceptions can ever be caught
152 in that region.
153
154 Unwinding the stack:
155
156 The details of unwinding the stack to the next frame can be rather
157 complex. While in many cases a generic __unwind_function () routine
158 can be used by the generated exception handling code to do this, it
159 is often necessary to generate inline code to do the unwinding.
160
161 Whether or not these inlined unwinders are necessary is
162 target-specific.
163
164 By default, if the target-specific backend doesn't supply a
165 definition for __unwind_function (), inlined unwinders will be used
166 instead. The main tradeoff here is in text space utilization.
167 Obviously, if inline unwinders have to be generated repeatedly,
168 this uses more space than if a single routine is used.
169
170 The backend macro DOESNT_NEED_UNWINDER is used to conditionalize
171 whether or not per-function unwinders are needed. If DOESNT_NEED_UNWINDER
172 is defined and has a non-zero value, a per-function unwinder is
173 not emitted for the current function.
174
175 On some platforms it is possible that neither __unwind_function ()
176 nor inlined unwinders are available. For these platforms it is not
177 possible to throw through a function call, and abort () will be
178 invoked instead of performing the throw. */
179
180
181 #include "config.h"
182 #include <stdio.h>
183 #include "rtl.h"
184 #include "tree.h"
185 #include "flags.h"
186 #include "except.h"
187 #include "function.h"
188 #include "insn-flags.h"
189 #include "expr.h"
190 #include "insn-codes.h"
191 #include "regs.h"
192 #include "hard-reg-set.h"
193 #include "insn-config.h"
194 #include "recog.h"
195 #include "output.h"
196 #include "assert.h"
197
198 /* A list of labels used for exception handlers. Created by
199 find_exception_handler_labels for the optimization passes. */
200
201 rtx exception_handler_labels;
202
203 /* Nonzero means that __throw was invoked.
204
205 This is used by the C++ frontend to know if code needs to be emitted
206 for __throw or not. */
207
208 int throw_used;
209
210 /* A stack used for keeping track of the currectly active exception
211 handling region. As each exception region is started, an entry
212 describing the region is pushed onto this stack. The current
213 region can be found by looking at the top of the stack, and as we
214 exit regions, the corresponding entries are popped.
215
216 Entries cannot overlap; they must be nested. So there is only one
217 entry at most that corresponds to the current instruction, and that
218 is the entry on the top of the stack. */
219
220 struct eh_stack ehstack;
221
222 /* A queue used for tracking which exception regions have closed but
223 whose handlers have not yet been expanded. Regions are emitted in
224 groups in an attempt to improve paging performance.
225
226 As we exit a region, we enqueue a new entry. The entries are then
227 dequeued during expand_leftover_cleanups () and expand_start_all_catch (),
228
229 We should redo things so that we either take RTL for the handler,
230 or we expand the handler expressed as a tree immediately at region
231 end time. */
232
233 struct eh_queue ehqueue;
234
235 /* Insns for all of the exception handlers for the current function.
236 They are currently emitted by the frontend code. */
237
238 rtx catch_clauses;
239
240 /* A TREE_CHAINed list of handlers for regions that are not yet
241 closed. The TREE_VALUE of each entry contains the handler for the
242 corresponding entry on the ehstack. */
243
244 static tree protect_list;
245
246 /* Stacks to keep track of various labels. */
247
248 /* Keeps track of the label to resume to should one want to resume
249 normal control flow out of a handler (instead of, say, returning to
250 the caller of the current function or exiting the program). Also
251 used as the context of a throw to rethrow an exception to the outer
252 exception region. */
253
254 struct label_node *caught_return_label_stack = NULL;
255
256 /* A random data area for the front end's own use. */
257
258 struct label_node *false_label_stack = NULL;
259
260 /* The rtx and the tree for the saved PC value. */
261
262 rtx eh_saved_pc_rtx;
263 tree eh_saved_pc;
264
265 rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
266 \f
267 /* Various support routines to manipulate the various data structures
268 used by the exception handling code. */
269
270 /* Push a label entry onto the given STACK. */
271
272 void
273 push_label_entry (stack, rlabel, tlabel)
274 struct label_node **stack;
275 rtx rlabel;
276 tree tlabel;
277 {
278 struct label_node *newnode
279 = (struct label_node *) xmalloc (sizeof (struct label_node));
280
281 if (rlabel)
282 newnode->u.rlabel = rlabel;
283 else
284 newnode->u.tlabel = tlabel;
285 newnode->chain = *stack;
286 *stack = newnode;
287 }
288
289 /* Pop a label entry from the given STACK. */
290
291 rtx
292 pop_label_entry (stack)
293 struct label_node **stack;
294 {
295 rtx label;
296 struct label_node *tempnode;
297
298 if (! *stack)
299 return NULL_RTX;
300
301 tempnode = *stack;
302 label = tempnode->u.rlabel;
303 *stack = (*stack)->chain;
304 free (tempnode);
305
306 return label;
307 }
308
309 /* Return the top element of the given STACK. */
310
311 tree
312 top_label_entry (stack)
313 struct label_node **stack;
314 {
315 if (! *stack)
316 return NULL_TREE;
317
318 return (*stack)->u.tlabel;
319 }
320
321 /* Make a copy of ENTRY using xmalloc to allocate the space. */
322
323 static struct eh_entry *
324 copy_eh_entry (entry)
325 struct eh_entry *entry;
326 {
327 struct eh_entry *newentry;
328
329 newentry = (struct eh_entry *) xmalloc (sizeof (struct eh_entry));
330 bcopy ((char *) entry, (char *) newentry, sizeof (struct eh_entry));
331
332 return newentry;
333 }
334
335 /* Push a new eh_node entry onto STACK, and return the start label for
336 the entry. */
337
338 static rtx
339 push_eh_entry (stack)
340 struct eh_stack *stack;
341 {
342 struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
343 struct eh_entry *entry = (struct eh_entry *) xmalloc (sizeof (struct eh_entry));
344
345 entry->start_label = gen_label_rtx ();
346 entry->end_label = gen_label_rtx ();
347 entry->exception_handler_label = gen_label_rtx ();
348 entry->finalization = NULL_TREE;
349
350 node->entry = entry;
351 node->chain = stack->top;
352 stack->top = node;
353
354 return entry->start_label;
355 }
356
357 /* Pop an entry from the given STACK. */
358
359 static struct eh_entry *
360 pop_eh_entry (stack)
361 struct eh_stack *stack;
362 {
363 struct eh_node *tempnode;
364 struct eh_entry *tempentry;
365
366 tempnode = stack->top;
367 tempentry = tempnode->entry;
368 stack->top = stack->top->chain;
369 free (tempnode);
370
371 return tempentry;
372 }
373
374 /* Enqueue an ENTRY onto the given QUEUE. */
375
376 static void
377 enqueue_eh_entry (queue, entry)
378 struct eh_queue *queue;
379 struct eh_entry *entry;
380 {
381 struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
382
383 node->entry = entry;
384 node->chain = NULL;
385
386 if (queue->head == NULL)
387 {
388 queue->head = node;
389 }
390 else
391 {
392 queue->tail->chain = node;
393 }
394 queue->tail = node;
395 }
396
397 /* Dequeue an entry from the given QUEUE. */
398
399 static struct eh_entry *
400 dequeue_eh_entry (queue)
401 struct eh_queue *queue;
402 {
403 struct eh_node *tempnode;
404 struct eh_entry *tempentry;
405
406 if (queue->head == NULL)
407 return NULL;
408
409 tempnode = queue->head;
410 queue->head = queue->head->chain;
411
412 tempentry = tempnode->entry;
413 free (tempnode);
414
415 return tempentry;
416 }
417 \f
418 /* Routine to see if exception exception handling is turned on.
419 DO_WARN is non-zero if we want to inform the user that exception
420 handling is turned off.
421
422 This is used to ensure that -fexceptions has been specified if the
423 compiler tries to use any exception-specific functions. */
424
425 int
426 doing_eh (do_warn)
427 int do_warn;
428 {
429 if (! flag_exceptions)
430 {
431 static int warned = 0;
432 if (! warned && do_warn)
433 {
434 error ("exception handling disabled, use -fexceptions to enable");
435 warned = 1;
436 }
437 return 0;
438 }
439 return 1;
440 }
441
442 /* Given a return address in ADDR, determine the address we should use
443 to find the corresponding EH region. */
444
445 rtx
446 eh_outer_context (addr)
447 rtx addr;
448 {
449 /* First mask out any unwanted bits. */
450 #ifdef MASK_RETURN_ADDR
451 emit_insn (gen_rtx (SET, Pmode,
452 addr,
453 gen_rtx (AND, Pmode,
454 addr, MASK_RETURN_ADDR)));
455 #endif
456
457 /* Then subtract out enough to get into the appropriate region. If
458 this is defined, assume we don't need to subtract anything as it
459 is already within the correct region. */
460 #if ! defined (RETURN_ADDR_OFFSET)
461 addr = plus_constant (addr, -1);
462 #endif
463
464 return addr;
465 }
466
467 /* Start a new exception region and push the HANDLER for the region
468 onto protect_list. All of the regions created with add_partial_entry
469 will be ended when end_protect_partials () is invoked. */
470
471 void
472 add_partial_entry (handler)
473 tree handler;
474 {
475 expand_eh_region_start ();
476
477 /* Make sure the entry is on the correct obstack. */
478 push_obstacks_nochange ();
479 resume_temporary_allocation ();
480 protect_list = tree_cons (NULL_TREE, handler, protect_list);
481 pop_obstacks ();
482 }
483
484 /* Output a note marking the start of an exception handling region.
485 All instructions emitted after this point are considered to be part
486 of the region until expand_eh_region_end () is invoked. */
487
488 void
489 expand_eh_region_start ()
490 {
491 rtx note;
492
493 /* This is the old code. */
494 if (! doing_eh (0))
495 return;
496
497 #if 0
498 /* Maybe do this to prevent jumping in and so on... */
499 pushlevel (0);
500 #endif
501
502 note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_BEG);
503 emit_label (push_eh_entry (&ehstack));
504 NOTE_BLOCK_NUMBER (note)
505 = CODE_LABEL_NUMBER (ehstack.top->entry->exception_handler_label);
506 }
507
508 /* Output a note marking the end of the exception handling region on
509 the top of ehstack.
510
511 HANDLER is either the cleanup for the exception region, or if we're
512 marking the end of a try block, HANDLER is integer_zero_node.
513
514 HANDLER will be transformed to rtl when expand_leftover_cleanups ()
515 is invoked. */
516
517 void
518 expand_eh_region_end (handler)
519 tree handler;
520 {
521 rtx note;
522
523 struct eh_entry *entry;
524
525 if (! doing_eh (0))
526 return;
527
528 entry = pop_eh_entry (&ehstack);
529
530 note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_END);
531 NOTE_BLOCK_NUMBER (note) = CODE_LABEL_NUMBER (entry->exception_handler_label);
532
533 /* Emit a label marking the end of this exception region. */
534 emit_label (entry->end_label);
535
536 /* Put in something that takes up space, as otherwise the end
537 address for this EH region could have the exact same address as
538 its outer region. This would cause us to miss the fact that
539 resuming exception handling with this PC value would be inside
540 the outer region. */
541 emit_insn (gen_nop ());
542
543 entry->finalization = handler;
544
545 enqueue_eh_entry (&ehqueue, entry);
546
547 #if 0
548 /* Maybe do this to prevent jumping in and so on... */
549 poplevel (1, 0, 0);
550 #endif
551 }
552
553 /* Emit a call to __throw and note that we threw something, so we know
554 we need to generate the necessary code for __throw.
555
556 Before invoking throw, the __eh_pc variable must have been set up
557 to contain the PC being thrown from. This address is used by
558 __throw () to determine which exception region (if any) is
559 responsible for handling the exception. */
560
561 static void
562 emit_throw ()
563 {
564 #ifdef JUMP_TO_THROW
565 emit_indirect_jump (throw_libfunc);
566 #else
567 SYMBOL_REF_USED (throw_libfunc) = 1;
568 emit_library_call (throw_libfunc, 0, VOIDmode, 0);
569 #endif
570 throw_used = 1;
571 emit_barrier ();
572 }
573
574 /* An internal throw with an indirect CONTEXT we want to throw from.
575 CONTEXT evaluates to the context of the throw. */
576
577 static void
578 expand_internal_throw_indirect (context)
579 rtx context;
580 {
581 assemble_external (eh_saved_pc);
582 emit_move_insn (eh_saved_pc_rtx, context);
583 emit_throw ();
584 }
585
586 /* An internal throw with a direct CONTEXT we want to throw from.
587 CONTEXT must be a label; its address will be used as the context of
588 the throw. */
589
590 void
591 expand_internal_throw (context)
592 rtx context;
593 {
594 expand_internal_throw_indirect (gen_rtx (LABEL_REF, Pmode, context));
595 }
596
597 /* Called from expand_exception_blocks and expand_end_catch_block to
598 emit any pending handlers/cleanups queued from expand_eh_region_end (). */
599
600 void
601 expand_leftover_cleanups ()
602 {
603 struct eh_entry *entry;
604
605 while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
606 {
607 rtx prev;
608
609 /* A leftover try block. Shouldn't be one here. */
610 if (entry->finalization == integer_zero_node)
611 abort ();
612
613 /* Output the label for the start of the exception handler. */
614 emit_label (entry->exception_handler_label);
615
616 /* And now generate the insns for the handler. */
617 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
618
619 prev = get_last_insn ();
620 if (! (prev && GET_CODE (prev) == BARRIER))
621 {
622 /* The below can be optimized away, and we could just fall into the
623 next EH handler, if we are certain they are nested. */
624 /* Emit code to throw to the outer context if we fall off
625 the end of the handler. */
626 expand_internal_throw (entry->end_label);
627 }
628
629 free (entry);
630 }
631 }
632
633 /* Called at the start of a block of try statements. */
634 void
635 expand_start_try_stmts ()
636 {
637 if (! doing_eh (1))
638 return;
639
640 expand_eh_region_start ();
641 }
642
643 /* Generate RTL for the start of a group of catch clauses.
644
645 It is responsible for starting a new instruction sequence for the
646 instructions in the catch block, and expanding the handlers for the
647 internally-generated exception regions nested within the try block
648 corresponding to this catch block. */
649
650 void
651 expand_start_all_catch ()
652 {
653 struct eh_entry *entry;
654 tree label;
655
656 if (! doing_eh (1))
657 return;
658
659 /* End the try block. */
660 expand_eh_region_end (integer_zero_node);
661
662 emit_line_note (input_filename, lineno);
663 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
664
665 /* The label for the exception handling block that we will save.
666 This is Lresume in the documention. */
667 expand_label (label);
668
669 /* Put in something that takes up space, as otherwise the end
670 address for the EH region could have the exact same address as
671 the outer region, causing us to miss the fact that resuming
672 exception handling with this PC value would be inside the outer
673 region. */
674 emit_insn (gen_nop ());
675
676 /* Push the label that points to where normal flow is resumed onto
677 the top of the label stack. */
678 push_label_entry (&caught_return_label_stack, NULL_RTX, label);
679
680 /* Start a new sequence for all the catch blocks. We will add this
681 to the global sequence catch_clauses when we have completed all
682 the handlers in this handler-seq. */
683 start_sequence ();
684
685 while (1)
686 {
687 rtx prev;
688
689 entry = dequeue_eh_entry (&ehqueue);
690 /* Emit the label for the exception handler for this region, and
691 expand the code for the handler.
692
693 Note that a catch region is handled as a side-effect here;
694 for a try block, entry->finalization will contain
695 integer_zero_node, so no code will be generated in the
696 expand_expr call below. But, the label for the handler will
697 still be emitted, so any code emitted after this point will
698 end up being the handler. */
699 emit_label (entry->exception_handler_label);
700 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
701
702 /* When we get down to the matching entry for this try block, stop. */
703 if (entry->finalization == integer_zero_node)
704 {
705 /* Don't forget to free this entry. */
706 free (entry);
707 break;
708 }
709
710 prev = get_last_insn ();
711 if (prev == NULL || GET_CODE (prev) != BARRIER)
712 {
713 /* Code to throw out to outer context when we fall off end
714 of the handler. We can't do this here for catch blocks,
715 so it's done in expand_end_all_catch () instead.
716
717 The below can be optimized away (and we could just fall
718 into the next EH handler) if we are certain they are
719 nested. */
720
721 expand_internal_throw (entry->end_label);
722 }
723 free (entry);
724 }
725 }
726
727 /* Finish up the catch block. At this point all the insns for the
728 catch clauses have already been generated, so we only have to add
729 them to the catch_clauses list. We also want to make sure that if
730 we fall off the end of the catch clauses that we rethrow to the
731 outer EH region. */
732
733 void
734 expand_end_all_catch ()
735 {
736 rtx new_catch_clause;
737
738 if (! doing_eh (1))
739 return;
740
741 /* Code to throw out to outer context, if we fall off end of catch
742 handlers. This is rethrow (Lresume, same id, same obj) in the
743 documentation. We use Lresume because we know that it will throw
744 to the correct context.
745
746 In other words, if the catch handler doesn't exit or return, we
747 do a "throw" (using the address of Lresume as the point being
748 thrown from) so that the outer EH region can then try to process
749 the exception. */
750
751 expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack)));
752
753 /* Now we have the complete catch sequence. */
754 new_catch_clause = get_insns ();
755 end_sequence ();
756
757 /* This level of catch blocks is done, so set up the successful
758 catch jump label for the next layer of catch blocks. */
759 pop_label_entry (&caught_return_label_stack);
760
761 /* Add the new sequence of catches to the main one for this function. */
762 push_to_sequence (catch_clauses);
763 emit_insns (new_catch_clause);
764 catch_clauses = get_insns ();
765 end_sequence ();
766
767 /* Here we fall through into the continuation code. */
768 }
769
770 /* End all the pending exception regions on protect_list. The handlers
771 will be emitted when expand_leftover_cleanups () is invoked. */
772
773 void
774 end_protect_partials ()
775 {
776 while (protect_list)
777 {
778 expand_eh_region_end (TREE_VALUE (protect_list));
779 protect_list = TREE_CHAIN (protect_list);
780 }
781 }
782 \f
783 /* The exception table that we build that is used for looking up and
784 dispatching exceptions, the current number of entries, and its
785 maximum size before we have to extend it.
786
787 The number in eh_table is the code label number of the exception
788 handler for the region. This is added by add_eh_table_entry () and
789 used by output_exception_table_entry (). */
790
791 static int *eh_table;
792 static int eh_table_size;
793 static int eh_table_max_size;
794
795 /* Note the need for an exception table entry for region N. If we
796 don't need to output an explicit exception table, avoid all of the
797 extra work.
798
799 Called from final_scan_insn when a NOTE_INSN_EH_REGION_BEG is seen.
800 N is the NOTE_BLOCK_NUMBER of the note, which comes from the code
801 label number of the exception handler for the region. */
802
803 void
804 add_eh_table_entry (n)
805 int n;
806 {
807 #ifndef OMIT_EH_TABLE
808 if (eh_table_size >= eh_table_max_size)
809 {
810 if (eh_table)
811 {
812 eh_table_max_size += eh_table_max_size>>1;
813
814 if (eh_table_max_size < 0)
815 abort ();
816
817 if ((eh_table = (int *) realloc (eh_table,
818 eh_table_max_size * sizeof (int)))
819 == 0)
820 fatal ("virtual memory exhausted");
821 }
822 else
823 {
824 eh_table_max_size = 252;
825 eh_table = (int *) xmalloc (eh_table_max_size * sizeof (int));
826 }
827 }
828 eh_table[eh_table_size++] = n;
829 #endif
830 }
831
832 /* Return a non-zero value if we need to output an exception table.
833
834 On some platforms, we don't have to output a table explicitly.
835 This routine doesn't mean we don't have one. */
836
837 int
838 exception_table_p ()
839 {
840 if (eh_table)
841 return 1;
842
843 return 0;
844 }
845
846 /* Output the entry of the exception table corresponding to to the
847 exception region numbered N to file FILE.
848
849 N is the code label number corresponding to the handler of the
850 region. */
851
852 static void
853 output_exception_table_entry (file, n)
854 FILE *file;
855 int n;
856 {
857 char buf[256];
858 rtx sym;
859
860 ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
861 sym = gen_rtx (SYMBOL_REF, Pmode, buf);
862 assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
863
864 ASM_GENERATE_INTERNAL_LABEL (buf, "LEHE", n);
865 sym = gen_rtx (SYMBOL_REF, Pmode, buf);
866 assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
867
868 ASM_GENERATE_INTERNAL_LABEL (buf, "L", n);
869 sym = gen_rtx (SYMBOL_REF, Pmode, buf);
870 assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
871
872 putc ('\n', file); /* blank line */
873 }
874
875 /* Output the exception table if we have and need one. */
876
877 void
878 output_exception_table ()
879 {
880 int i;
881 extern FILE *asm_out_file;
882
883 if (! doing_eh (0))
884 return;
885
886 exception_section ();
887
888 /* Beginning marker for table. */
889 assemble_align (GET_MODE_ALIGNMENT (ptr_mode));
890 assemble_label ("__EXCEPTION_TABLE__");
891
892 assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
893 assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
894 assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
895 putc ('\n', asm_out_file); /* blank line */
896
897 for (i = 0; i < eh_table_size; ++i)
898 output_exception_table_entry (asm_out_file, eh_table[i]);
899
900 free (eh_table);
901
902 /* Ending marker for table. */
903 assemble_label ("__EXCEPTION_END__");
904 assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
905 assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
906 assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
907 putc ('\n', asm_out_file); /* blank line */
908 }
909
910 /* Generate code to initialize the exception table at program startup
911 time. */
912
913 void
914 register_exception_table ()
915 {
916 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
917 VOIDmode, 1,
918 gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
919 Pmode);
920 }
921 \f
922 /* Emit the RTL for the start of the per-function unwinder for the
923 current function. See emit_unwinder () for further information.
924
925 DOESNT_NEED_UNWINDER is a target-specific macro that determines if
926 the current function actually needs a per-function unwinder or not.
927 By default, all functions need one. */
928
929 void
930 start_eh_unwinder ()
931 {
932 #ifdef DOESNT_NEED_UNWINDER
933 if (DOESNT_NEED_UNWINDER)
934 return;
935 #endif
936
937 expand_eh_region_start ();
938 }
939
940 /* Emit insns for the end of the per-function unwinder for the
941 current function. */
942
943 void
944 end_eh_unwinder ()
945 {
946 tree expr;
947 rtx return_val_rtx, ret_val, label, end, insns;
948
949 if (! doing_eh (0))
950 return;
951
952 #ifdef DOESNT_NEED_UNWINDER
953 if (DOESNT_NEED_UNWINDER)
954 return;
955 #endif
956
957 assemble_external (eh_saved_pc);
958
959 expr = make_node (RTL_EXPR);
960 TREE_TYPE (expr) = void_type_node;
961 RTL_EXPR_RTL (expr) = const0_rtx;
962 TREE_SIDE_EFFECTS (expr) = 1;
963 start_sequence_for_rtl_expr (expr);
964
965 /* ret_val will contain the address of the code where the call
966 to the current function occurred. */
967 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
968 0, hard_frame_pointer_rtx);
969 return_val_rtx = copy_to_reg (ret_val);
970
971 /* Get the address we need to use to determine what exception
972 handler should be invoked, and store it in __eh_pc. */
973 return_val_rtx = eh_outer_context (return_val_rtx);
974 emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
975
976 /* Either set things up so we do a return directly to __throw, or
977 we return here instead. */
978 #ifdef JUMP_TO_THROW
979 emit_move_insn (ret_val, throw_libfunc);
980 #else
981 label = gen_label_rtx ();
982 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, label));
983 #endif
984
985 #ifdef RETURN_ADDR_OFFSET
986 return_val_rtx = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
987 if (return_val_rtx != ret_val)
988 emit_move_insn (ret_val, return_val_rtx);
989 #endif
990
991 end = gen_label_rtx ();
992 emit_jump (end);
993
994 RTL_EXPR_SEQUENCE (expr) = get_insns ();
995 end_sequence ();
996 expand_eh_region_end (expr);
997
998 emit_jump (end);
999
1000 #ifndef JUMP_TO_THROW
1001 emit_label (label);
1002 emit_throw ();
1003 #endif
1004
1005 expand_leftover_cleanups ();
1006
1007 emit_label (end);
1008 }
1009
1010 /* If necessary, emit insns for the per function unwinder for the
1011 current function. Called after all the code that needs unwind
1012 protection is output.
1013
1014 The unwinder takes care of catching any exceptions that have not
1015 been previously caught within the function, unwinding the stack to
1016 the next frame, and rethrowing using the address of the current
1017 function's caller as the context of the throw.
1018
1019 On some platforms __throw can do this by itself (or with the help
1020 of __unwind_function) so the per-function unwinder is
1021 unnecessary.
1022
1023 We cannot place the unwinder into the function until after we know
1024 we are done inlining, as we don't want to have more than one
1025 unwinder per non-inlined function. */
1026
1027 void
1028 emit_unwinder ()
1029 {
1030 rtx insns, insn;
1031
1032 start_sequence ();
1033 start_eh_unwinder ();
1034 insns = get_insns ();
1035 end_sequence ();
1036
1037 /* We place the start of the exception region associated with the
1038 per function unwinder at the top of the function. */
1039 if (insns)
1040 emit_insns_after (insns, get_insns ());
1041
1042 start_sequence ();
1043 end_eh_unwinder ();
1044 insns = get_insns ();
1045 end_sequence ();
1046
1047 /* And we place the end of the exception region before the USE and
1048 CLOBBER insns that may come at the end of the function. */
1049 if (insns == 0)
1050 return;
1051
1052 insn = get_last_insn ();
1053 while (GET_CODE (insn) == NOTE
1054 || (GET_CODE (insn) == INSN
1055 && (GET_CODE (PATTERN (insn)) == USE
1056 || GET_CODE (PATTERN (insn)) == CLOBBER)))
1057 insn = PREV_INSN (insn);
1058
1059 if (GET_CODE (insn) == CODE_LABEL
1060 && GET_CODE (PREV_INSN (insn)) == BARRIER)
1061 {
1062 insn = PREV_INSN (insn);
1063 }
1064 else
1065 {
1066 rtx label = gen_label_rtx ();
1067 emit_label_after (label, insn);
1068 insn = emit_jump_insn_after (gen_jump (label), insn);
1069 insn = emit_barrier_after (insn);
1070 }
1071
1072 emit_insns_after (insns, insn);
1073 }
1074
1075 /* Scan the current insns and build a list of handler labels. The
1076 resulting list is placed in the global variable exception_handler_labels.
1077
1078 It is called after the last exception handling region is added to
1079 the current function (when the rtl is almost all built for the
1080 current function) and before the jump optimization pass. */
1081
1082 void
1083 find_exception_handler_labels ()
1084 {
1085 rtx insn;
1086 int max_labelno = max_label_num ();
1087 int min_labelno = get_first_label_num ();
1088 rtx *labels;
1089
1090 exception_handler_labels = NULL_RTX;
1091
1092 /* If we aren't doing exception handling, there isn't much to check. */
1093 if (! doing_eh (0))
1094 return;
1095
1096 /* Generate a handy reference to each label. */
1097
1098 labels = (rtx *) alloca ((max_labelno - min_labelno) * sizeof (rtx));
1099
1100 /* Eeeeeeew. */
1101 labels -= min_labelno;
1102
1103 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1104 {
1105 if (GET_CODE (insn) == CODE_LABEL)
1106 if (CODE_LABEL_NUMBER (insn) >= min_labelno
1107 && CODE_LABEL_NUMBER (insn) < max_labelno)
1108 labels[CODE_LABEL_NUMBER (insn)] = insn;
1109 }
1110
1111 /* For each start of a region, add its label to the list. */
1112
1113 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1114 {
1115 if (GET_CODE (insn) == NOTE
1116 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
1117 {
1118 rtx label = NULL_RTX;
1119
1120 if (NOTE_BLOCK_NUMBER (insn) >= min_labelno
1121 && NOTE_BLOCK_NUMBER (insn) < max_labelno)
1122 {
1123 label = labels[NOTE_BLOCK_NUMBER (insn)];
1124
1125 if (label)
1126 exception_handler_labels
1127 = gen_rtx (EXPR_LIST, VOIDmode,
1128 label, exception_handler_labels);
1129 else
1130 warning ("didn't find handler for EH region %d",
1131 NOTE_BLOCK_NUMBER (insn));
1132 }
1133 else
1134 warning ("mismatched EH region %d", NOTE_BLOCK_NUMBER (insn));
1135 }
1136 }
1137 }
1138
1139 /* Perform sanity checking on the exception_handler_labels list.
1140
1141 Can be called after find_exception_handler_labels is called to
1142 build the list of exception handlers for the current function and
1143 before we finish processing the current function. */
1144
1145 void
1146 check_exception_handler_labels ()
1147 {
1148 rtx insn, handler;
1149
1150 /* If we aren't doing exception handling, there isn't much to check. */
1151 if (! doing_eh (0))
1152 return;
1153
1154 /* Ensure that the CODE_LABEL_NUMBER for the CODE_LABEL entry point
1155 in each handler corresponds to the CODE_LABEL_NUMBER of the
1156 handler. */
1157
1158 for (handler = exception_handler_labels;
1159 handler;
1160 handler = XEXP (handler, 1))
1161 {
1162 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1163 {
1164 if (GET_CODE (insn) == CODE_LABEL)
1165 {
1166 if (CODE_LABEL_NUMBER (insn)
1167 == CODE_LABEL_NUMBER (XEXP (handler, 0)))
1168 {
1169 if (insn != XEXP (handler, 0))
1170 warning ("mismatched handler %d",
1171 CODE_LABEL_NUMBER (insn));
1172 break;
1173 }
1174 }
1175 }
1176 if (insn == NULL_RTX)
1177 warning ("handler not found %d",
1178 CODE_LABEL_NUMBER (XEXP (handler, 0)));
1179 }
1180
1181 /* Now go through and make sure that for each region there is a
1182 corresponding label. */
1183 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1184 {
1185 if (GET_CODE (insn) == NOTE
1186 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG ||
1187 NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
1188 {
1189 for (handler = exception_handler_labels;
1190 handler;
1191 handler = XEXP (handler, 1))
1192 {
1193 if (CODE_LABEL_NUMBER (XEXP (handler, 0))
1194 == NOTE_BLOCK_NUMBER (insn))
1195 break;
1196 }
1197 if (handler == NULL_RTX)
1198 warning ("region exists, no handler %d",
1199 NOTE_BLOCK_NUMBER (insn));
1200 }
1201 }
1202 }
1203 \f
1204 /* This group of functions initializes the exception handling data
1205 structures at the start of the compilation, initializes the data
1206 structures at the start of a function, and saves and restores the
1207 exception handling data structures for the start/end of a nested
1208 function. */
1209
1210 /* Toplevel initialization for EH things. */
1211
1212 void
1213 init_eh ()
1214 {
1215 /* Generate rtl to reference the variable in which the PC of the
1216 current context is saved. */
1217 tree type = build_pointer_type (make_node (VOID_TYPE));
1218
1219 eh_saved_pc = build_decl (VAR_DECL, get_identifier ("__eh_pc"), type);
1220 DECL_EXTERNAL (eh_saved_pc) = 1;
1221 TREE_PUBLIC (eh_saved_pc) = 1;
1222 make_decl_rtl (eh_saved_pc, NULL_PTR, 1);
1223 eh_saved_pc_rtx = DECL_RTL (eh_saved_pc);
1224 }
1225
1226 /* Initialize the per-function EH information. */
1227
1228 void
1229 init_eh_for_function ()
1230 {
1231 ehstack.top = 0;
1232 ehqueue.head = ehqueue.tail = 0;
1233 catch_clauses = NULL_RTX;
1234 false_label_stack = 0;
1235 caught_return_label_stack = 0;
1236 protect_list = NULL_TREE;
1237 }
1238
1239 /* Save some of the per-function EH info into the save area denoted by
1240 P.
1241
1242 This is currently called from save_stmt_status (). */
1243
1244 void
1245 save_eh_status (p)
1246 struct function *p;
1247 {
1248 assert (p != NULL);
1249
1250 p->ehstack = ehstack;
1251 p->ehqueue = ehqueue;
1252 p->catch_clauses = catch_clauses;
1253 p->false_label_stack = false_label_stack;
1254 p->caught_return_label_stack = caught_return_label_stack;
1255 p->protect_list = protect_list;
1256
1257 init_eh ();
1258 }
1259
1260 /* Restore the per-function EH info saved into the area denoted by P.
1261
1262 This is currently called from restore_stmt_status. */
1263
1264 void
1265 restore_eh_status (p)
1266 struct function *p;
1267 {
1268 assert (p != NULL);
1269
1270 protect_list = p->protect_list;
1271 caught_return_label_stack = p->caught_return_label_stack;
1272 false_label_stack = p->false_label_stack;
1273 catch_clauses = p->catch_clauses;
1274 ehqueue = p->ehqueue;
1275 ehstack = p->ehstack;
1276 }
1277 \f
1278 /* This section is for the exception handling specific optimization
1279 pass. First are the internal routines, and then the main
1280 optimization pass. */
1281
1282 /* Determine if the given INSN can throw an exception. */
1283
1284 static int
1285 can_throw (insn)
1286 rtx insn;
1287 {
1288 /* Calls can always potentially throw exceptions. */
1289 if (GET_CODE (insn) == CALL_INSN)
1290 return 1;
1291
1292 #ifdef ASYNCH_EXCEPTIONS
1293 /* If we wanted asynchronous exceptions, then everything but NOTEs
1294 and CODE_LABELs could throw. */
1295 if (GET_CODE (insn) != NOTE && GET_CODE (insn) != CODE_LABEL)
1296 return 1;
1297 #endif
1298
1299 return 0;
1300 }
1301
1302 /* Scan a exception region looking for the matching end and then
1303 remove it if possible. INSN is the start of the region, N is the
1304 region number, and DELETE_OUTER is to note if anything in this
1305 region can throw.
1306
1307 Regions are removed if they cannot possibly catch an exception.
1308 This is determined by invoking can_throw () on each insn within the
1309 region; if can_throw returns true for any of the instructions, the
1310 region can catch an exception, since there is an insn within the
1311 region that is capable of throwing an exception.
1312
1313 Returns the NOTE_INSN_EH_REGION_END corresponding to this region, or
1314 calls abort () if it can't find one.
1315
1316 Can abort if INSN is not a NOTE_INSN_EH_REGION_BEGIN, or if N doesn't
1317 correspond to the region number, or if DELETE_OUTER is NULL. */
1318
1319 static rtx
1320 scan_region (insn, n, delete_outer)
1321 rtx insn;
1322 int n;
1323 int *delete_outer;
1324 {
1325 rtx start = insn;
1326
1327 /* Assume we can delete the region. */
1328 int delete = 1;
1329
1330 assert (insn != NULL_RTX
1331 && GET_CODE (insn) == NOTE
1332 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
1333 && NOTE_BLOCK_NUMBER (insn) == n
1334 && delete_outer != NULL);
1335
1336 insn = NEXT_INSN (insn);
1337
1338 /* Look for the matching end. */
1339 while (! (GET_CODE (insn) == NOTE
1340 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
1341 {
1342 /* If anything can throw, we can't remove the region. */
1343 if (delete && can_throw (insn))
1344 {
1345 delete = 0;
1346 }
1347
1348 /* Watch out for and handle nested regions. */
1349 if (GET_CODE (insn) == NOTE
1350 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
1351 {
1352 insn = scan_region (insn, NOTE_BLOCK_NUMBER (insn), &delete);
1353 }
1354
1355 insn = NEXT_INSN (insn);
1356 }
1357
1358 /* The _BEG/_END NOTEs must match and nest. */
1359 if (NOTE_BLOCK_NUMBER (insn) != n)
1360 abort ();
1361
1362 /* If anything in this exception region can throw, we can throw. */
1363 if (! delete)
1364 *delete_outer = 0;
1365 else
1366 {
1367 /* Delete the start and end of the region. */
1368 delete_insn (start);
1369 delete_insn (insn);
1370
1371 /* Only do this part if we have built the exception handler
1372 labels. */
1373 if (exception_handler_labels)
1374 {
1375 rtx x, *prev = &exception_handler_labels;
1376
1377 /* Find it in the list of handlers. */
1378 for (x = exception_handler_labels; x; x = XEXP (x, 1))
1379 {
1380 rtx label = XEXP (x, 0);
1381 if (CODE_LABEL_NUMBER (label) == n)
1382 {
1383 /* If we are the last reference to the handler,
1384 delete it. */
1385 if (--LABEL_NUSES (label) == 0)
1386 delete_insn (label);
1387
1388 if (optimize)
1389 {
1390 /* Remove it from the list of exception handler
1391 labels, if we are optimizing. If we are not, then
1392 leave it in the list, as we are not really going to
1393 remove the region. */
1394 *prev = XEXP (x, 1);
1395 XEXP (x, 1) = 0;
1396 XEXP (x, 0) = 0;
1397 }
1398
1399 break;
1400 }
1401 prev = &XEXP (x, 1);
1402 }
1403 }
1404 }
1405 return insn;
1406 }
1407
1408 /* Perform various interesting optimizations for exception handling
1409 code.
1410
1411 We look for empty exception regions and make them go (away). The
1412 jump optimization code will remove the handler if nothing else uses
1413 it. */
1414
1415 void
1416 exception_optimize ()
1417 {
1418 rtx insn, regions = NULL_RTX;
1419 int n;
1420
1421 /* Remove empty regions. */
1422 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1423 {
1424 if (GET_CODE (insn) == NOTE
1425 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
1426 {
1427 /* Since scan_region () will return the NOTE_INSN_EH_REGION_END
1428 insn, we will indirectly skip through all the insns
1429 inbetween. We are also guaranteed that the value of insn
1430 returned will be valid, as otherwise scan_region () won't
1431 return. */
1432 insn = scan_region (insn, NOTE_BLOCK_NUMBER (insn), &n);
1433 }
1434 }
1435 }
This page took 0.096611 seconds and 6 git commands to generate.