1996-09-14 20:47:01 -04:00
|
|
|
|
/* Implements exception handling.
|
2000-02-25 23:04:48 -07:00
|
|
|
|
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
|
|
|
|
1999, 2000 Free Software Foundation, Inc.
|
1996-07-23 20:20:04 +00:00
|
|
|
|
Contributed by Mike Stump <mrs@cygnus.com>.
|
|
|
|
|
|
|
|
|
|
This file is part of GNU CC.
|
|
|
|
|
|
|
|
|
|
GNU CC is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
|
|
GNU CC is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with GNU CC; see the file COPYING. If not, write to
|
|
|
|
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
|
|
|
|
Boston, MA 02111-1307, USA. */
|
|
|
|
|
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* An exception is an event that can be signaled from within a
|
|
|
|
|
function. This event can then be "caught" or "trapped" by the
|
|
|
|
|
callers of this function. This potentially allows program flow to
|
1997-12-06 17:31:01 -07:00
|
|
|
|
be transferred to any arbitrary code associated with a function call
|
1996-09-14 20:47:01 -04:00
|
|
|
|
several levels up the stack.
|
|
|
|
|
|
|
|
|
|
The intended use for this mechanism is for signaling "exceptional
|
|
|
|
|
events" in an out-of-band fashion, hence its name. The C++ language
|
|
|
|
|
(and many other OO-styled or functional languages) practically
|
|
|
|
|
requires such a mechanism, as otherwise it becomes very difficult
|
|
|
|
|
or even impossible to signal failure conditions in complex
|
|
|
|
|
situations. The traditional C++ example is when an error occurs in
|
|
|
|
|
the process of constructing an object; without such a mechanism, it
|
|
|
|
|
is impossible to signal that the error occurs without adding global
|
|
|
|
|
state variables and error checks around every object construction.
|
|
|
|
|
|
|
|
|
|
The act of causing this event to occur is referred to as "throwing
|
|
|
|
|
an exception". (Alternate terms include "raising an exception" or
|
|
|
|
|
"signaling an exception".) The term "throw" is used because control
|
|
|
|
|
is returned to the callers of the function that is signaling the
|
|
|
|
|
exception, and thus there is the concept of "throwing" the
|
|
|
|
|
exception up the call stack.
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
There are two major codegen options for exception handling. The
|
|
|
|
|
flag -fsjlj-exceptions can be used to select the setjmp/longjmp
|
1997-11-02 14:19:36 -07:00
|
|
|
|
approach, which is the default. -fno-sjlj-exceptions can be used to
|
1997-04-23 20:11:52 +00:00
|
|
|
|
get the PC range table approach. While this is a compile time
|
|
|
|
|
flag, an entire application must be compiled with the same codegen
|
|
|
|
|
option. The first is a PC range table approach, the second is a
|
|
|
|
|
setjmp/longjmp based scheme. We will first discuss the PC range
|
|
|
|
|
table approach, after that, we will discuss the setjmp/longjmp
|
|
|
|
|
based approach.
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
It is appropriate to speak of the "context of a throw". This
|
|
|
|
|
context refers to the address where the exception is thrown from,
|
|
|
|
|
and is used to determine which exception region will handle the
|
|
|
|
|
exception.
|
|
|
|
|
|
|
|
|
|
Regions of code within a function can be marked such that if it
|
|
|
|
|
contains the context of a throw, control will be passed to a
|
|
|
|
|
designated "exception handler". These areas are known as "exception
|
|
|
|
|
regions". Exception regions cannot overlap, but they can be nested
|
|
|
|
|
to any arbitrary depth. Also, exception regions cannot cross
|
|
|
|
|
function boundaries.
|
|
|
|
|
|
1996-10-29 01:25:27 +00:00
|
|
|
|
Exception handlers can either be specified by the user (which we
|
|
|
|
|
will call a "user-defined handler") or generated by the compiler
|
|
|
|
|
(which we will designate as a "cleanup"). Cleanups are used to
|
|
|
|
|
perform tasks such as destruction of objects allocated on the
|
|
|
|
|
stack.
|
|
|
|
|
|
1997-12-06 17:31:01 -07:00
|
|
|
|
In the current implementation, cleanups are handled by allocating an
|
1996-10-29 01:25:27 +00:00
|
|
|
|
exception region for the area that the cleanup is designated for,
|
|
|
|
|
and the handler for the region performs the cleanup and then
|
|
|
|
|
rethrows the exception to the outer exception region. From the
|
|
|
|
|
standpoint of the current implementation, there is little
|
|
|
|
|
distinction made between a cleanup and a user-defined handler, and
|
|
|
|
|
the phrase "exception handler" can be used to refer to either one
|
|
|
|
|
equally well. (The section "Future Directions" below discusses how
|
|
|
|
|
this will change).
|
|
|
|
|
|
|
|
|
|
Each object file that is compiled with exception handling contains
|
|
|
|
|
a static array of exception handlers named __EXCEPTION_TABLE__.
|
|
|
|
|
Each entry contains the starting and ending addresses of the
|
|
|
|
|
exception region, and the address of the handler designated for
|
|
|
|
|
that region.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
If the target does not use the DWARF 2 frame unwind information, at
|
|
|
|
|
program startup each object file invokes a function named
|
1996-09-14 20:47:01 -04:00
|
|
|
|
__register_exceptions with the address of its local
|
1997-09-15 22:07:50 -04:00
|
|
|
|
__EXCEPTION_TABLE__. __register_exceptions is defined in libgcc2.c, and
|
|
|
|
|
is responsible for recording all of the exception regions into one list
|
|
|
|
|
(which is kept in a static variable named exception_table_list).
|
|
|
|
|
|
|
|
|
|
On targets that support crtstuff.c, the unwind information
|
|
|
|
|
is stored in a section named .eh_frame and the information for the
|
|
|
|
|
entire shared object or program is registered with a call to
|
1997-12-15 00:05:04 -07:00
|
|
|
|
__register_frame_info. On other targets, the information for each
|
1997-10-18 21:10:32 +00:00
|
|
|
|
translation unit is registered from the file generated by collect2.
|
1997-12-15 00:05:04 -07:00
|
|
|
|
__register_frame_info is defined in frame.c, and is responsible for
|
1997-09-15 22:07:50 -04:00
|
|
|
|
recording all of the unwind regions into one list (which is kept in a
|
|
|
|
|
static variable named unwind_table_list).
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
The function __throw is actually responsible for doing the
|
1997-09-15 22:07:50 -04:00
|
|
|
|
throw. On machines that have unwind info support, __throw is generated
|
|
|
|
|
by code in libgcc2.c, otherwise __throw is generated on a
|
1996-09-14 20:47:01 -04:00
|
|
|
|
per-object-file basis for each source file compiled with
|
1998-05-06 15:09:07 -06:00
|
|
|
|
-fexceptions by the C++ frontend. Before __throw is invoked,
|
1997-09-15 22:07:50 -04:00
|
|
|
|
the current context of the throw needs to be placed in the global
|
|
|
|
|
variable __eh_pc.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
__throw attempts to find the appropriate exception handler for the
|
1996-09-14 20:47:01 -04:00
|
|
|
|
PC value stored in __eh_pc by calling __find_first_exception_table_match
|
1996-10-29 01:25:27 +00:00
|
|
|
|
(which is defined in libgcc2.c). If __find_first_exception_table_match
|
1997-09-15 22:07:50 -04:00
|
|
|
|
finds a relevant handler, __throw transfers control directly to it.
|
|
|
|
|
|
|
|
|
|
If a handler for the context being thrown from can't be found, __throw
|
|
|
|
|
walks (see Walking the stack below) the stack up the dynamic call chain to
|
|
|
|
|
continue searching for an appropriate exception handler based upon the
|
|
|
|
|
caller of the function it last sought a exception handler for. It stops
|
|
|
|
|
then either an exception handler is found, or when the top of the
|
|
|
|
|
call chain is reached.
|
|
|
|
|
|
|
|
|
|
If no handler is found, an external library function named
|
|
|
|
|
__terminate is called. If a handler is found, then we restart
|
|
|
|
|
our search for a handler at the end of the call chain, and repeat
|
|
|
|
|
the search process, but instead of just walking up the call chain,
|
|
|
|
|
we unwind the call chain as we walk up it.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
Internal implementation details:
|
|
|
|
|
|
|
|
|
|
To associate a user-defined handler with a block of statements, the
|
1997-04-23 20:11:52 +00:00
|
|
|
|
function expand_start_try_stmts is used to mark the start of the
|
1996-09-14 20:47:01 -04:00
|
|
|
|
block of statements with which the handler is to be associated
|
1996-10-29 01:25:27 +00:00
|
|
|
|
(which is known as a "try block"). All statements that appear
|
|
|
|
|
afterwards will be associated with the try block.
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
A call to expand_start_all_catch marks the end of the try block,
|
1996-10-29 01:25:27 +00:00
|
|
|
|
and also marks the start of the "catch block" (the user-defined
|
|
|
|
|
handler) associated with the try block.
|
|
|
|
|
|
|
|
|
|
This user-defined handler will be invoked for *every* exception
|
|
|
|
|
thrown with the context of the try block. It is up to the handler
|
|
|
|
|
to decide whether or not it wishes to handle any given exception,
|
|
|
|
|
as there is currently no mechanism in this implementation for doing
|
|
|
|
|
this. (There are plans for conditionally processing an exception
|
|
|
|
|
based on its "type", which will provide a language-independent
|
|
|
|
|
mechanism).
|
|
|
|
|
|
|
|
|
|
If the handler chooses not to process the exception (perhaps by
|
|
|
|
|
looking at an "exception type" or some other additional data
|
|
|
|
|
supplied with the exception), it can fall through to the end of the
|
1997-04-23 20:11:52 +00:00
|
|
|
|
handler. expand_end_all_catch and expand_leftover_cleanups
|
1996-10-29 01:25:27 +00:00
|
|
|
|
add additional code to the end of each handler to take care of
|
|
|
|
|
rethrowing to the outer exception handler.
|
|
|
|
|
|
|
|
|
|
The handler also has the option to continue with "normal flow of
|
|
|
|
|
code", or in other words to resume executing at the statement
|
|
|
|
|
immediately after the end of the exception region. The variable
|
|
|
|
|
caught_return_label_stack contains a stack of labels, and jumping
|
1997-04-23 20:11:52 +00:00
|
|
|
|
to the topmost entry's label via expand_goto will resume normal
|
1996-10-29 01:25:27 +00:00
|
|
|
|
flow to the statement immediately after the end of the exception
|
|
|
|
|
region. If the handler falls through to the end, the exception will
|
|
|
|
|
be rethrown to the outer exception region.
|
|
|
|
|
|
|
|
|
|
The instructions for the catch block are kept as a separate
|
|
|
|
|
sequence, and will be emitted at the end of the function along with
|
1997-04-23 20:11:52 +00:00
|
|
|
|
the handlers specified via expand_eh_region_end. The end of the
|
|
|
|
|
catch block is marked with expand_end_all_catch.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
Any data associated with the exception must currently be handled by
|
|
|
|
|
some external mechanism maintained in the frontend. For example,
|
|
|
|
|
the C++ exception mechanism passes an arbitrary value along with
|
|
|
|
|
the exception, and this is handled in the C++ frontend by using a
|
1996-10-29 01:25:27 +00:00
|
|
|
|
global variable to hold the value. (This will be changing in the
|
|
|
|
|
future.)
|
|
|
|
|
|
|
|
|
|
The mechanism in C++ for handling data associated with the
|
|
|
|
|
exception is clearly not thread-safe. For a thread-based
|
|
|
|
|
environment, another mechanism must be used (possibly using a
|
|
|
|
|
per-thread allocation mechanism if the size of the area that needs
|
|
|
|
|
to be allocated isn't known at compile time.)
|
|
|
|
|
|
|
|
|
|
Internally-generated exception regions (cleanups) are marked by
|
1997-04-23 20:11:52 +00:00
|
|
|
|
calling expand_eh_region_start to mark the start of the region,
|
1996-10-29 01:25:27 +00:00
|
|
|
|
and expand_eh_region_end (handler) is used to both designate the
|
|
|
|
|
end of the region and to associate a specified handler/cleanup with
|
|
|
|
|
the region. The rtl code in HANDLER will be invoked whenever an
|
|
|
|
|
exception occurs in the region between the calls to
|
|
|
|
|
expand_eh_region_start and expand_eh_region_end. After HANDLER is
|
|
|
|
|
executed, additional code is emitted to handle rethrowing the
|
|
|
|
|
exception to the outer exception handler. The code for HANDLER will
|
|
|
|
|
be emitted at the end of the function.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
TARGET_EXPRs can also be used to designate exception regions. A
|
|
|
|
|
TARGET_EXPR gives an unwind-protect style interface commonly used
|
|
|
|
|
in functional languages such as LISP. The associated expression is
|
1996-10-29 01:25:27 +00:00
|
|
|
|
evaluated, and whether or not it (or any of the functions that it
|
|
|
|
|
calls) throws an exception, the protect expression is always
|
|
|
|
|
invoked. This implementation takes care of the details of
|
|
|
|
|
associating an exception table entry with the expression and
|
|
|
|
|
generating the necessary code (it actually emits the protect
|
|
|
|
|
expression twice, once for normal flow and once for the exception
|
|
|
|
|
case). As for the other handlers, the code for the exception case
|
|
|
|
|
will be emitted at the end of the function.
|
|
|
|
|
|
|
|
|
|
Cleanups can also be specified by using add_partial_entry (handler)
|
1997-04-23 20:11:52 +00:00
|
|
|
|
and end_protect_partials. add_partial_entry creates the start of
|
1996-10-29 01:25:27 +00:00
|
|
|
|
a new exception region; HANDLER will be invoked if an exception is
|
|
|
|
|
thrown with the context of the region between the calls to
|
|
|
|
|
add_partial_entry and end_protect_partials. end_protect_partials is
|
|
|
|
|
used to mark the end of these regions. add_partial_entry can be
|
|
|
|
|
called as many times as needed before calling end_protect_partials.
|
|
|
|
|
However, end_protect_partials should only be invoked once for each
|
1997-04-23 20:11:52 +00:00
|
|
|
|
group of calls to add_partial_entry as the entries are queued
|
1996-10-29 01:25:27 +00:00
|
|
|
|
and all of the outstanding entries are processed simultaneously
|
|
|
|
|
when end_protect_partials is invoked. Similarly to the other
|
|
|
|
|
handlers, the code for HANDLER will be emitted at the end of the
|
|
|
|
|
function.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
The generated RTL for an exception region includes
|
|
|
|
|
NOTE_INSN_EH_REGION_BEG and NOTE_INSN_EH_REGION_END notes that mark
|
|
|
|
|
the start and end of the exception region. A unique label is also
|
1996-10-29 01:25:27 +00:00
|
|
|
|
generated at the start of the exception region, which is available
|
|
|
|
|
by looking at the ehstack variable. The topmost entry corresponds
|
|
|
|
|
to the current region.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
In the current implementation, an exception can only be thrown from
|
|
|
|
|
a function call (since the mechanism used to actually throw an
|
|
|
|
|
exception involves calling __throw). If an exception region is
|
|
|
|
|
created but no function calls occur within that region, the region
|
1996-10-29 01:25:27 +00:00
|
|
|
|
can be safely optimized away (along with its exception handlers)
|
1997-04-23 20:11:52 +00:00
|
|
|
|
since no exceptions can ever be caught in that region. This
|
|
|
|
|
optimization is performed unless -fasynchronous-exceptions is
|
|
|
|
|
given. If the user wishes to throw from a signal handler, or other
|
|
|
|
|
asynchronous place, -fasynchronous-exceptions should be used when
|
|
|
|
|
compiling for maximally correct code, at the cost of additional
|
|
|
|
|
exception regions. Using -fasynchronous-exceptions only produces
|
|
|
|
|
code that is reasonably safe in such situations, but a correct
|
|
|
|
|
program cannot rely upon this working. It can be used in failsafe
|
|
|
|
|
code, where trying to continue on, and proceeding with potentially
|
|
|
|
|
incorrect results is better than halting the program.
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
Walking the stack:
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
The stack is walked by starting with a pointer to the current
|
|
|
|
|
frame, and finding the pointer to the callers frame. The unwind info
|
|
|
|
|
tells __throw how to find it.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
Unwinding the stack:
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
When we use the term unwinding the stack, we mean undoing the
|
|
|
|
|
effects of the function prologue in a controlled fashion so that we
|
|
|
|
|
still have the flow of control. Otherwise, we could just return
|
|
|
|
|
(jump to the normal end of function epilogue).
|
|
|
|
|
|
|
|
|
|
This is done in __throw in libgcc2.c when we know that a handler exists
|
|
|
|
|
in a frame higher up the call stack than its immediate caller.
|
|
|
|
|
|
|
|
|
|
To unwind, we find the unwind data associated with the frame, if any.
|
|
|
|
|
If we don't find any, we call the library routine __terminate. If we do
|
|
|
|
|
find it, we use the information to copy the saved register values from
|
|
|
|
|
that frame into the register save area in the frame for __throw, return
|
|
|
|
|
into a stub which updates the stack pointer, and jump to the handler.
|
|
|
|
|
The normal function epilogue for __throw handles restoring the saved
|
|
|
|
|
values into registers.
|
|
|
|
|
|
|
|
|
|
When unwinding, we use this method if we know it will
|
|
|
|
|
work (if DWARF2_UNWIND_INFO is defined). Otherwise, we know that
|
|
|
|
|
an inline unwinder will have been emitted for any function that
|
|
|
|
|
__unwind_function cannot unwind. The inline unwinder appears as a
|
|
|
|
|
normal exception handler for the entire function, for any function
|
|
|
|
|
that we know cannot be unwound by __unwind_function. We inform the
|
|
|
|
|
compiler of whether a function can be unwound with
|
|
|
|
|
__unwind_function by having DOESNT_NEED_UNWINDER evaluate to true
|
|
|
|
|
when the unwinder isn't needed. __unwind_function is used as an
|
|
|
|
|
action of last resort. If no other method can be used for
|
|
|
|
|
unwinding, __unwind_function is used. If it cannot unwind, it
|
1997-12-06 17:31:01 -07:00
|
|
|
|
should call __terminate.
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
|
|
|
|
By default, if the target-specific backend doesn't supply a definition
|
|
|
|
|
for __unwind_function and doesn't support DWARF2_UNWIND_INFO, inlined
|
|
|
|
|
unwinders will be used instead. The main tradeoff here is in text space
|
|
|
|
|
utilization. Obviously, if inline unwinders have to be generated
|
|
|
|
|
repeatedly, this uses much more space than if a single routine is used.
|
1996-10-29 01:25:27 +00:00
|
|
|
|
|
|
|
|
|
However, it is simply not possible on some platforms to write a
|
|
|
|
|
generalized routine for doing stack unwinding without having some
|
1997-09-15 22:07:50 -04:00
|
|
|
|
form of additional data associated with each function. The current
|
|
|
|
|
implementation can encode this data in the form of additional
|
|
|
|
|
machine instructions or as static data in tabular form. The later
|
|
|
|
|
is called the unwind data.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
The backend macro DOESNT_NEED_UNWINDER is used to conditionalize whether
|
|
|
|
|
or not per-function unwinders are needed. If DOESNT_NEED_UNWINDER is
|
|
|
|
|
defined and has a non-zero value, a per-function unwinder is not emitted
|
|
|
|
|
for the current function. If the static unwind data is supported, then
|
|
|
|
|
a per-function unwinder is not emitted.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
On some platforms it is possible that neither __unwind_function
|
1996-09-14 20:47:01 -04:00
|
|
|
|
nor inlined unwinders are available. For these platforms it is not
|
1997-04-23 20:11:52 +00:00
|
|
|
|
possible to throw through a function call, and abort will be
|
1996-10-29 01:25:27 +00:00
|
|
|
|
invoked instead of performing the throw.
|
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
The reason the unwind data may be needed is that on some platforms
|
|
|
|
|
the order and types of data stored on the stack can vary depending
|
|
|
|
|
on the type of function, its arguments and returned values, and the
|
|
|
|
|
compilation options used (optimization versus non-optimization,
|
|
|
|
|
-fomit-frame-pointer, processor variations, etc).
|
|
|
|
|
|
|
|
|
|
Unfortunately, this also means that throwing through functions that
|
|
|
|
|
aren't compiled with exception handling support will still not be
|
|
|
|
|
possible on some platforms. This problem is currently being
|
|
|
|
|
investigated, but no solutions have been found that do not imply
|
|
|
|
|
some unacceptable performance penalties.
|
|
|
|
|
|
1996-10-29 01:25:27 +00:00
|
|
|
|
Future directions:
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
Currently __throw makes no differentiation between cleanups and
|
1996-10-29 01:25:27 +00:00
|
|
|
|
user-defined exception regions. While this makes the implementation
|
|
|
|
|
simple, it also implies that it is impossible to determine if a
|
|
|
|
|
user-defined exception handler exists for a given exception without
|
|
|
|
|
completely unwinding the stack in the process. This is undesirable
|
|
|
|
|
from the standpoint of debugging, as ideally it would be possible
|
|
|
|
|
to trap unhandled exceptions in the debugger before the process of
|
|
|
|
|
unwinding has even started.
|
|
|
|
|
|
|
|
|
|
This problem can be solved by marking user-defined handlers in a
|
|
|
|
|
special way (probably by adding additional bits to exception_table_list).
|
1997-04-23 20:11:52 +00:00
|
|
|
|
A two-pass scheme could then be used by __throw to iterate
|
1996-10-29 01:25:27 +00:00
|
|
|
|
through the table. The first pass would search for a relevant
|
|
|
|
|
user-defined handler for the current context of the throw, and if
|
|
|
|
|
one is found, the second pass would then invoke all needed cleanups
|
|
|
|
|
before jumping to the user-defined handler.
|
|
|
|
|
|
|
|
|
|
Many languages (including C++ and Ada) make execution of a
|
|
|
|
|
user-defined handler conditional on the "type" of the exception
|
|
|
|
|
thrown. (The type of the exception is actually the type of the data
|
|
|
|
|
that is thrown with the exception.) It will thus be necessary for
|
1997-04-23 20:11:52 +00:00
|
|
|
|
__throw to be able to determine if a given user-defined
|
1996-10-29 01:25:27 +00:00
|
|
|
|
exception handler will actually be executed, given the type of
|
|
|
|
|
exception.
|
|
|
|
|
|
|
|
|
|
One scheme is to add additional information to exception_table_list
|
1997-04-23 20:11:52 +00:00
|
|
|
|
as to the types of exceptions accepted by each handler. __throw
|
1996-10-29 01:25:27 +00:00
|
|
|
|
can do the type comparisons and then determine if the handler is
|
|
|
|
|
actually going to be executed.
|
|
|
|
|
|
|
|
|
|
There is currently no significant level of debugging support
|
1997-04-23 20:11:52 +00:00
|
|
|
|
available, other than to place a breakpoint on __throw. While
|
1996-10-29 01:25:27 +00:00
|
|
|
|
this is sufficient in most cases, it would be helpful to be able to
|
|
|
|
|
know where a given exception was going to be thrown to before it is
|
|
|
|
|
actually thrown, and to be able to choose between stopping before
|
|
|
|
|
every exception region (including cleanups), or just user-defined
|
|
|
|
|
exception regions. This should be possible to do in the two-pass
|
1997-04-23 20:11:52 +00:00
|
|
|
|
scheme by adding additional labels to __throw for appropriate
|
1996-10-29 01:25:27 +00:00
|
|
|
|
breakpoints, and additional debugger commands could be added to
|
|
|
|
|
query various state variables to determine what actions are to be
|
|
|
|
|
performed next.
|
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
Another major problem that is being worked on is the issue with stack
|
|
|
|
|
unwinding on various platforms. Currently the only platforms that have
|
|
|
|
|
support for the generation of a generic unwinder are the SPARC and MIPS.
|
|
|
|
|
All other ports require per-function unwinders, which produce large
|
|
|
|
|
amounts of code bloat.
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
For setjmp/longjmp based exception handling, some of the details
|
|
|
|
|
are as above, but there are some additional details. This section
|
|
|
|
|
discusses the details.
|
|
|
|
|
|
|
|
|
|
We don't use NOTE_INSN_EH_REGION_{BEG,END} pairs. We don't
|
|
|
|
|
optimize EH regions yet. We don't have to worry about machine
|
|
|
|
|
specific issues with unwinding the stack, as we rely upon longjmp
|
|
|
|
|
for all the machine specific details. There is no variable context
|
|
|
|
|
of a throw, just the one implied by the dynamic handler stack
|
|
|
|
|
pointed to by the dynamic handler chain. There is no exception
|
1997-12-06 17:31:01 -07:00
|
|
|
|
table, and no calls to __register_exceptions. __sjthrow is used
|
1997-04-23 20:11:52 +00:00
|
|
|
|
instead of __throw, and it works by using the dynamic handler
|
|
|
|
|
chain, and longjmp. -fasynchronous-exceptions has no effect, as
|
|
|
|
|
the elimination of trivial exception regions is not yet performed.
|
|
|
|
|
|
|
|
|
|
A frontend can set protect_cleanup_actions_with_terminate when all
|
|
|
|
|
the cleanup actions should be protected with an EH region that
|
|
|
|
|
calls terminate when an unhandled exception is throw. C++ does
|
|
|
|
|
this, Ada does not. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
1997-09-15 22:07:50 -04:00
|
|
|
|
#include "defaults.h"
|
1998-05-14 13:39:15 +00:00
|
|
|
|
#include "eh-common.h"
|
Major cutover to using system.h:
* Makefile.in (alias.o, bitmap.o, c-aux-info.o, c-common.o,
c-decl.o, c-iterate.o, c-lang.o, c-lex.o, c-pragma.o, c-typeck.o,
caller-save.o, calls.o, collect2.o, combine.o, cse.o, dbxout.o,
dwarf2out.o, dwarfout.o, emit-rtl.o, except.o, explow.o, expmed.o,
expr.o, final.o, flow.o, function.o, getpwd.o, global.o,
integrate.o, jump.o, local-alloc.o, loop.o, optabs.o, pexecute.o,
prefix.o, print-rtl.o, print-tree.o, profile.o, real.o, recog.o,
reg-stack.o, regclass.o, regmove.o, reload.o, reload1.o, reorg.o,
rtl.o, rtlanal.o, sdbout.o, stmt.o, stor-layout.o, stupid.o,
tlink.o, toplev.o, tree.o, unroll.o, varasm.o, xcoffout.o): Depend
on system.h.
* alias.c, bitmap.c, c-aux-info.c, c-common.c, c-decl.c,
c-iterate.c, c-lang.c, c-lex.c, c-pragma.c, c-typeck.c,
caller-save.c, calls.c, collect2.c, combine.c, cse.c, dbxout.c,
dwarf2out.c, dwarfout.c, emit-rtl.c, except.c, explow.c, expmed.c,
expr.c, final.c, flow.c, function.c, gcc.c, getpwd.c, global.c,
integrate.c, jump.c, local-alloc.c, loop.c, optabs.c, pexecute.c,
prefix.c, print-rtl.c, print-tree.c, profile.c, real.c, recog.c,
reg-stack.c, regclass.c, regmove.c, reload.c, reload1.c, reorg.c,
rtl.c, rtlanal.c, sched.c, sdbout.c, stmt.c, stor-layout.c,
stupid.c, tlink.c, toplev.c, tree.c, unroll.c, varasm.c,
xcoffout.c: Include system.h. Organize include ordering so
that stdarg/varargs comes before other system headers. Remove
spurious casts of functions assured of a prototype in system.h.
From-SVN: r18726
1998-03-20 14:58:42 +00:00
|
|
|
|
#include "system.h"
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#include "rtl.h"
|
|
|
|
|
#include "tree.h"
|
|
|
|
|
#include "flags.h"
|
|
|
|
|
#include "except.h"
|
|
|
|
|
#include "function.h"
|
|
|
|
|
#include "insn-flags.h"
|
|
|
|
|
#include "expr.h"
|
|
|
|
|
#include "insn-codes.h"
|
|
|
|
|
#include "regs.h"
|
|
|
|
|
#include "hard-reg-set.h"
|
|
|
|
|
#include "insn-config.h"
|
|
|
|
|
#include "recog.h"
|
|
|
|
|
#include "output.h"
|
toplev.h: New file.
Wed May 6 06:35:38 1998 Robert Lipe <robertl@dgii.com>
* toplev.h: New file. Protypes for functions in toplev.c.
* tree.h, rtl.h: Deleted protos for functions in toplev.c.
* c-common.c, c-convert.c, c-decl.c, c-iterate.c, c-lex.c,
c-parse.in, c-parse.y, c-pragma.c, c-typeck.c, calls.c,
convert.c, dwarf2out.c, except.c, expr.c, final.c, fold-const.c,
function.c, hash.c, profile.c, real.c, reg-stack.c, regclass.c,
reload.c, reload1.c, stmt.c, stor-layout.c, tlink.c, tree.c,
varasm.c: include it.
From-SVN: r19564
1998-05-06 04:54:01 +00:00
|
|
|
|
#include "toplev.h"
|
1999-07-01 17:52:55 -06:00
|
|
|
|
#include "intl.h"
|
1998-12-08 14:04:03 +00:00
|
|
|
|
#include "obstack.h"
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
#include "ggc.h"
|
calls.c: Include tm_p.h later, so everything we need is defined.
* calls.c: Include tm_p.h later, so everything we need is defined.
* expr.c: Likewise.
* function.c: Likewise.
* except.c: Include tm_p.h.
* sparc.c: Likewise.
(dwarf2out_cfi_label): Don't prototype.
(check_return_regs, epilogue_renumber,
ultra_cmove_results_ready_p, ultra_fpmode_conflict_exists,
ultra_find_type, ultra_build_types_avail, ultra_flush_pipeline,
ultra_rescan_pipeline_state, set_extends, ultra_code_from_mask,
ultra_schedule_insn): Add static prototype.
(data_segment_operand, text_segment_operand): Call itself with the
proper number of arguments.
(sparc_flat_save_restore, sparc_v8plus_shift): Constify a char*.
* sparc.h: Move all declarations to sparc-protos.h.
(SELECT_RTX_SECTION): Pass a missing MODE argument to
symbolic_operand.
* sparc/sysv4.h (SELECT_RTX_SECTION): Likewise.
* config/svr4.h (text_section, ctors_section, dtors_section): Add
Prototypes.
(ASM_OUTPUT_SECTION_NAME, UNIQUE_SECTION,
ASM_FINISH_DECLARE_OBJECT, ASM_OUTPUT_LIMITED_STRING,
ASM_OUTPUT_ASCII): Constify a char*.
* sparc-protos.h: New file for sparc prototypes.
cp:
* expr.c: Include tm_p.h.
From-SVN: r30122
1999-10-21 16:58:33 +00:00
|
|
|
|
#include "tm_p.h"
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* One to use setjmp/longjmp method of generating code for exception
|
|
|
|
|
handling. */
|
|
|
|
|
|
1997-10-18 21:10:32 +00:00
|
|
|
|
int exceptions_via_longjmp = 2;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* One to enable asynchronous exception support. */
|
|
|
|
|
|
|
|
|
|
int asynchronous_exceptions = 0;
|
|
|
|
|
|
|
|
|
|
/* One to protect cleanup actions with a handler that calls
|
|
|
|
|
__terminate, zero otherwise. */
|
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
int protect_cleanup_actions_with_terminate;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* A list of labels used for exception handlers. Created by
|
1996-07-23 20:20:04 +00:00
|
|
|
|
find_exception_handler_labels for the optimization passes. */
|
|
|
|
|
|
|
|
|
|
rtx exception_handler_labels;
|
|
|
|
|
|
1997-12-06 17:31:01 -07:00
|
|
|
|
/* Keeps track of the label used as the context of a throw to rethrow an
|
|
|
|
|
exception to the outer exception region. */
|
|
|
|
|
|
|
|
|
|
struct label_node *outer_context_label_stack = NULL;
|
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Pseudos used to hold exception return data in the interim between
|
|
|
|
|
__builtin_eh_return and the end of the function. */
|
|
|
|
|
|
|
|
|
|
static rtx eh_return_context;
|
|
|
|
|
static rtx eh_return_stack_adjust;
|
|
|
|
|
static rtx eh_return_handler;
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
/* This is used for targets which can call rethrow with an offset instead
|
|
|
|
|
of an address. This is subtracted from the rethrow label we are
|
|
|
|
|
interested in. */
|
|
|
|
|
|
|
|
|
|
static rtx first_rethrow_symbol = NULL_RTX;
|
|
|
|
|
static rtx final_rethrow = NULL_RTX;
|
|
|
|
|
static rtx last_rethrow_symbol = NULL_RTX;
|
|
|
|
|
|
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Prototypes for local functions. */
|
|
|
|
|
|
2000-01-14 17:14:43 +00:00
|
|
|
|
static void push_eh_entry PARAMS ((struct eh_stack *));
|
|
|
|
|
static struct eh_entry * pop_eh_entry PARAMS ((struct eh_stack *));
|
|
|
|
|
static void enqueue_eh_entry PARAMS ((struct eh_queue *, struct eh_entry *));
|
|
|
|
|
static struct eh_entry * dequeue_eh_entry PARAMS ((struct eh_queue *));
|
|
|
|
|
static rtx call_get_eh_context PARAMS ((void));
|
|
|
|
|
static void start_dynamic_cleanup PARAMS ((tree, tree));
|
|
|
|
|
static void start_dynamic_handler PARAMS ((void));
|
|
|
|
|
static void expand_rethrow PARAMS ((rtx));
|
|
|
|
|
static void output_exception_table_entry PARAMS ((FILE *, int));
|
|
|
|
|
static int can_throw PARAMS ((rtx));
|
|
|
|
|
static rtx scan_region PARAMS ((rtx, int, int *));
|
|
|
|
|
static void eh_regs PARAMS ((rtx *, rtx *, rtx *, int));
|
|
|
|
|
static void set_insn_eh_region PARAMS ((rtx *, int));
|
1998-06-19 23:45:30 +00:00
|
|
|
|
#ifdef DONT_USE_BUILTIN_SETJMP
|
2000-01-14 17:14:43 +00:00
|
|
|
|
static void jumpif_rtx PARAMS ((rtx, rtx));
|
1998-06-19 23:45:30 +00:00
|
|
|
|
#endif
|
2000-05-20 19:45:36 +00:00
|
|
|
|
static void find_exception_handler_labels_1 PARAMS ((rtx));
|
2000-01-14 17:14:43 +00:00
|
|
|
|
static void mark_eh_node PARAMS ((struct eh_node *));
|
|
|
|
|
static void mark_eh_stack PARAMS ((struct eh_stack *));
|
|
|
|
|
static void mark_eh_queue PARAMS ((struct eh_queue *));
|
|
|
|
|
static void mark_tree_label_node PARAMS ((struct label_node *));
|
|
|
|
|
static void mark_func_eh_entry PARAMS ((void *));
|
|
|
|
|
static rtx create_rethrow_ref PARAMS ((int));
|
|
|
|
|
static void push_entry PARAMS ((struct eh_stack *, struct eh_entry*));
|
|
|
|
|
static void receive_exception_label PARAMS ((rtx));
|
|
|
|
|
static int new_eh_region_entry PARAMS ((int, rtx));
|
|
|
|
|
static int find_func_region PARAMS ((int));
|
|
|
|
|
static int find_func_region_from_symbol PARAMS ((rtx));
|
|
|
|
|
static void clear_function_eh_region PARAMS ((void));
|
|
|
|
|
static void process_nestinfo PARAMS ((int, eh_nesting_info *, int *));
|
|
|
|
|
rtx expand_builtin_return_addr PARAMS ((enum built_in_function, int, rtx));
|
|
|
|
|
static void emit_cleanup_handler PARAMS ((struct eh_entry *));
|
|
|
|
|
static int eh_region_from_symbol PARAMS ((rtx));
|
1999-11-18 17:50:56 +00:00
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* Various support routines to manipulate the various data structures
|
|
|
|
|
used by the exception handling code. */
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
extern struct obstack permanent_obstack;
|
|
|
|
|
|
|
|
|
|
/* Generate a SYMBOL_REF for rethrow to use */
|
2000-03-08 16:30:17 -05:00
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
static rtx
|
|
|
|
|
create_rethrow_ref (region_num)
|
|
|
|
|
int region_num;
|
|
|
|
|
{
|
|
|
|
|
rtx def;
|
|
|
|
|
char *ptr;
|
|
|
|
|
char buf[60];
|
|
|
|
|
|
|
|
|
|
push_obstacks_nochange ();
|
|
|
|
|
end_temporary_allocation ();
|
|
|
|
|
|
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", region_num);
|
1999-09-09 00:07:41 -07:00
|
|
|
|
ptr = ggc_alloc_string (buf, -1);
|
1998-12-08 14:04:03 +00:00
|
|
|
|
def = gen_rtx_SYMBOL_REF (Pmode, ptr);
|
|
|
|
|
SYMBOL_REF_NEED_ADJUST (def) = 1;
|
|
|
|
|
|
|
|
|
|
pop_obstacks ();
|
|
|
|
|
return def;
|
|
|
|
|
}
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
/* Push a label entry onto the given STACK. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
push_label_entry (stack, rlabel, tlabel)
|
|
|
|
|
struct label_node **stack;
|
|
|
|
|
rtx rlabel;
|
|
|
|
|
tree tlabel;
|
|
|
|
|
{
|
|
|
|
|
struct label_node *newnode
|
|
|
|
|
= (struct label_node *) xmalloc (sizeof (struct label_node));
|
|
|
|
|
|
|
|
|
|
if (rlabel)
|
|
|
|
|
newnode->u.rlabel = rlabel;
|
|
|
|
|
else
|
|
|
|
|
newnode->u.tlabel = tlabel;
|
|
|
|
|
newnode->chain = *stack;
|
|
|
|
|
*stack = newnode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pop a label entry from the given STACK. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
pop_label_entry (stack)
|
|
|
|
|
struct label_node **stack;
|
|
|
|
|
{
|
|
|
|
|
rtx label;
|
|
|
|
|
struct label_node *tempnode;
|
|
|
|
|
|
|
|
|
|
if (! *stack)
|
|
|
|
|
return NULL_RTX;
|
|
|
|
|
|
|
|
|
|
tempnode = *stack;
|
|
|
|
|
label = tempnode->u.rlabel;
|
|
|
|
|
*stack = (*stack)->chain;
|
|
|
|
|
free (tempnode);
|
|
|
|
|
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the top element of the given STACK. */
|
|
|
|
|
|
|
|
|
|
tree
|
|
|
|
|
top_label_entry (stack)
|
|
|
|
|
struct label_node **stack;
|
|
|
|
|
{
|
|
|
|
|
if (! *stack)
|
|
|
|
|
return NULL_TREE;
|
|
|
|
|
|
|
|
|
|
return (*stack)->u.tlabel;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* Get an exception label. */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
gen_exception_label ()
|
|
|
|
|
{
|
|
|
|
|
rtx lab;
|
|
|
|
|
lab = gen_label_rtx ();
|
|
|
|
|
return lab;
|
|
|
|
|
}
|
|
|
|
|
|
1997-05-29 18:42:07 +00:00
|
|
|
|
/* Push a new eh_node entry onto STACK. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-05-29 18:42:07 +00:00
|
|
|
|
static void
|
1996-07-23 20:20:04 +00:00
|
|
|
|
push_eh_entry (stack)
|
|
|
|
|
struct eh_stack *stack;
|
|
|
|
|
{
|
|
|
|
|
struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
|
|
|
|
|
struct eh_entry *entry = (struct eh_entry *) xmalloc (sizeof (struct eh_entry));
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
rtx rlab = gen_exception_label ();
|
1996-07-23 20:20:04 +00:00
|
|
|
|
entry->finalization = NULL_TREE;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
entry->label_used = 0;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
entry->exception_handler_label = rlab;
|
1998-09-15 11:20:52 +00:00
|
|
|
|
entry->false_label = NULL_RTX;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (! flag_new_exceptions)
|
|
|
|
|
entry->outer_context = gen_label_rtx ();
|
|
|
|
|
else
|
|
|
|
|
entry->outer_context = create_rethrow_ref (CODE_LABEL_NUMBER (rlab));
|
|
|
|
|
entry->rethrow_label = entry->outer_context;
|
1999-11-18 17:50:56 +00:00
|
|
|
|
entry->goto_entry_p = 0;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
node->entry = entry;
|
|
|
|
|
node->chain = stack->top;
|
|
|
|
|
stack->top = node;
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* Push an existing entry onto a stack. */
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
static void
|
|
|
|
|
push_entry (stack, entry)
|
|
|
|
|
struct eh_stack *stack;
|
|
|
|
|
struct eh_entry *entry;
|
|
|
|
|
{
|
|
|
|
|
struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
|
1996-07-23 20:20:04 +00:00
|
|
|
|
node->entry = entry;
|
|
|
|
|
node->chain = stack->top;
|
|
|
|
|
stack->top = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pop an entry from the given STACK. */
|
|
|
|
|
|
|
|
|
|
static struct eh_entry *
|
|
|
|
|
pop_eh_entry (stack)
|
|
|
|
|
struct eh_stack *stack;
|
|
|
|
|
{
|
|
|
|
|
struct eh_node *tempnode;
|
|
|
|
|
struct eh_entry *tempentry;
|
|
|
|
|
|
|
|
|
|
tempnode = stack->top;
|
|
|
|
|
tempentry = tempnode->entry;
|
|
|
|
|
stack->top = stack->top->chain;
|
|
|
|
|
free (tempnode);
|
|
|
|
|
|
|
|
|
|
return tempentry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Enqueue an ENTRY onto the given QUEUE. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
enqueue_eh_entry (queue, entry)
|
|
|
|
|
struct eh_queue *queue;
|
|
|
|
|
struct eh_entry *entry;
|
|
|
|
|
{
|
|
|
|
|
struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
|
|
|
|
|
|
|
|
|
|
node->entry = entry;
|
|
|
|
|
node->chain = NULL;
|
|
|
|
|
|
|
|
|
|
if (queue->head == NULL)
|
1999-11-25 19:21:27 +00:00
|
|
|
|
queue->head = node;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
else
|
1999-11-25 19:21:27 +00:00
|
|
|
|
queue->tail->chain = node;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
queue->tail = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Dequeue an entry from the given QUEUE. */
|
|
|
|
|
|
|
|
|
|
static struct eh_entry *
|
|
|
|
|
dequeue_eh_entry (queue)
|
|
|
|
|
struct eh_queue *queue;
|
|
|
|
|
{
|
|
|
|
|
struct eh_node *tempnode;
|
|
|
|
|
struct eh_entry *tempentry;
|
|
|
|
|
|
|
|
|
|
if (queue->head == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
tempnode = queue->head;
|
|
|
|
|
queue->head = queue->head->chain;
|
|
|
|
|
|
|
|
|
|
tempentry = tempnode->entry;
|
|
|
|
|
free (tempnode);
|
|
|
|
|
|
|
|
|
|
return tempentry;
|
|
|
|
|
}
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
receive_exception_label (handler_label)
|
|
|
|
|
rtx handler_label;
|
|
|
|
|
{
|
|
|
|
|
emit_label (handler_label);
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_exception_receiver
|
|
|
|
|
if (! exceptions_via_longjmp)
|
|
|
|
|
if (HAVE_exception_receiver)
|
|
|
|
|
emit_insn (gen_exception_receiver ());
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_nonlocal_goto_receiver
|
|
|
|
|
if (! exceptions_via_longjmp)
|
|
|
|
|
if (HAVE_nonlocal_goto_receiver)
|
|
|
|
|
emit_insn (gen_nonlocal_goto_receiver ());
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct func_eh_entry
|
|
|
|
|
{
|
1999-08-10 16:19:16 +00:00
|
|
|
|
int range_number; /* EH region number from EH NOTE insn's. */
|
|
|
|
|
rtx rethrow_label; /* Label for rethrow. */
|
2000-03-08 16:30:17 -05:00
|
|
|
|
int rethrow_ref; /* Is rethrow_label referenced? */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
struct handler_info *handlers;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* table of function eh regions */
|
|
|
|
|
static struct func_eh_entry *function_eh_regions = NULL;
|
|
|
|
|
static int num_func_eh_entries = 0;
|
|
|
|
|
static int current_func_eh_entry = 0;
|
|
|
|
|
|
|
|
|
|
#define SIZE_FUNC_EH(X) (sizeof (struct func_eh_entry) * X)
|
|
|
|
|
|
1999-11-18 17:50:56 +00:00
|
|
|
|
/* Add a new eh_entry for this function. The number returned is an
|
|
|
|
|
number which uniquely identifies this exception range. */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
static int
|
|
|
|
|
new_eh_region_entry (note_eh_region, rethrow)
|
1998-05-14 13:39:15 +00:00
|
|
|
|
int note_eh_region;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
rtx rethrow;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
{
|
|
|
|
|
if (current_func_eh_entry == num_func_eh_entries)
|
|
|
|
|
{
|
|
|
|
|
if (num_func_eh_entries == 0)
|
|
|
|
|
{
|
|
|
|
|
function_eh_regions =
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
(struct func_eh_entry *) xmalloc (SIZE_FUNC_EH (50));
|
1998-05-14 13:39:15 +00:00
|
|
|
|
num_func_eh_entries = 50;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
num_func_eh_entries = num_func_eh_entries * 3 / 2;
|
|
|
|
|
function_eh_regions = (struct func_eh_entry *)
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
xrealloc (function_eh_regions, SIZE_FUNC_EH (num_func_eh_entries));
|
1998-05-14 13:39:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function_eh_regions[current_func_eh_entry].range_number = note_eh_region;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (rethrow == NULL_RTX)
|
|
|
|
|
function_eh_regions[current_func_eh_entry].rethrow_label =
|
|
|
|
|
create_rethrow_ref (note_eh_region);
|
|
|
|
|
else
|
|
|
|
|
function_eh_regions[current_func_eh_entry].rethrow_label = rethrow;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
function_eh_regions[current_func_eh_entry].handlers = NULL;
|
|
|
|
|
|
|
|
|
|
return current_func_eh_entry++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add new handler information to an exception range. The first parameter
|
|
|
|
|
specifies the range number (returned from new_eh_entry()). The second
|
|
|
|
|
parameter specifies the handler. By default the handler is inserted at
|
|
|
|
|
the end of the list. A handler list may contain only ONE NULL_TREE
|
|
|
|
|
typeinfo entry. Regardless where it is positioned, a NULL_TREE entry
|
|
|
|
|
is always output as the LAST handler in the exception table for a region. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
add_new_handler (region, newhandler)
|
|
|
|
|
int region;
|
|
|
|
|
struct handler_info *newhandler;
|
|
|
|
|
{
|
|
|
|
|
struct handler_info *last;
|
|
|
|
|
|
1999-11-18 17:50:56 +00:00
|
|
|
|
/* If find_func_region returns -1, callers might attempt to pass us
|
|
|
|
|
this region number. If that happens, something has gone wrong;
|
|
|
|
|
-1 is never a valid region. */
|
|
|
|
|
if (region == -1)
|
|
|
|
|
abort ();
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
newhandler->next = NULL;
|
|
|
|
|
last = function_eh_regions[region].handlers;
|
|
|
|
|
if (last == NULL)
|
|
|
|
|
function_eh_regions[region].handlers = newhandler;
|
|
|
|
|
else
|
|
|
|
|
{
|
1998-11-29 23:01:19 +00:00
|
|
|
|
for ( ; ; last = last->next)
|
|
|
|
|
{
|
|
|
|
|
if (last->type_info == CATCH_ALL_TYPE)
|
|
|
|
|
pedwarn ("additional handler after ...");
|
|
|
|
|
if (last->next == NULL)
|
|
|
|
|
break;
|
|
|
|
|
}
|
1998-06-17 13:29:22 +00:00
|
|
|
|
last->next = newhandler;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-28 07:32:33 +00:00
|
|
|
|
/* Remove a handler label. The handler label is being deleted, so all
|
|
|
|
|
regions which reference this handler should have it removed from their
|
|
|
|
|
list of possible handlers. Any region which has the final handler
|
|
|
|
|
removed can be deleted. */
|
|
|
|
|
|
|
|
|
|
void remove_handler (removing_label)
|
|
|
|
|
rtx removing_label;
|
|
|
|
|
{
|
|
|
|
|
struct handler_info *handler, *last;
|
|
|
|
|
int x;
|
|
|
|
|
for (x = 0 ; x < current_func_eh_entry; ++x)
|
|
|
|
|
{
|
|
|
|
|
last = NULL;
|
|
|
|
|
handler = function_eh_regions[x].handlers;
|
|
|
|
|
for ( ; handler; last = handler, handler = handler->next)
|
|
|
|
|
if (handler->handler_label == removing_label)
|
|
|
|
|
{
|
|
|
|
|
if (last)
|
|
|
|
|
{
|
|
|
|
|
last->next = handler->next;
|
|
|
|
|
handler = last;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
function_eh_regions[x].handlers = handler->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-06-25 14:11:54 +00:00
|
|
|
|
/* This function will return a malloc'd pointer to an array of
|
|
|
|
|
void pointer representing the runtime match values that
|
|
|
|
|
currently exist in all regions. */
|
|
|
|
|
|
|
|
|
|
int
|
1998-06-29 17:36:07 +00:00
|
|
|
|
find_all_handler_type_matches (array)
|
|
|
|
|
void ***array;
|
1998-06-25 14:11:54 +00:00
|
|
|
|
{
|
|
|
|
|
struct handler_info *handler, *last;
|
|
|
|
|
int x,y;
|
|
|
|
|
void *val;
|
|
|
|
|
void **ptr;
|
|
|
|
|
int max_ptr;
|
|
|
|
|
int n_ptr = 0;
|
|
|
|
|
|
|
|
|
|
*array = NULL;
|
|
|
|
|
|
|
|
|
|
if (!doing_eh (0) || ! flag_new_exceptions)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
max_ptr = 100;
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
ptr = (void **) xmalloc (max_ptr * sizeof (void *));
|
1998-06-25 14:11:54 +00:00
|
|
|
|
|
|
|
|
|
for (x = 0 ; x < current_func_eh_entry; x++)
|
|
|
|
|
{
|
|
|
|
|
last = NULL;
|
|
|
|
|
handler = function_eh_regions[x].handlers;
|
|
|
|
|
for ( ; handler; last = handler, handler = handler->next)
|
|
|
|
|
{
|
|
|
|
|
val = handler->type_info;
|
|
|
|
|
if (val != NULL && val != CATCH_ALL_TYPE)
|
|
|
|
|
{
|
|
|
|
|
/* See if this match value has already been found. */
|
|
|
|
|
for (y = 0; y < n_ptr; y++)
|
|
|
|
|
if (ptr[y] == val)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* If we break early, we already found this value. */
|
|
|
|
|
if (y < n_ptr)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* Do we need to allocate more space? */
|
|
|
|
|
if (n_ptr >= max_ptr)
|
|
|
|
|
{
|
|
|
|
|
max_ptr += max_ptr / 2;
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
ptr = (void **) xrealloc (ptr, max_ptr * sizeof (void *));
|
1998-06-25 14:11:54 +00:00
|
|
|
|
}
|
|
|
|
|
ptr[n_ptr] = val;
|
|
|
|
|
n_ptr++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-09-09 00:17:20 -07:00
|
|
|
|
|
|
|
|
|
if (n_ptr == 0)
|
|
|
|
|
{
|
|
|
|
|
free (ptr);
|
|
|
|
|
ptr = NULL;
|
|
|
|
|
}
|
1998-06-25 14:11:54 +00:00
|
|
|
|
*array = ptr;
|
|
|
|
|
return n_ptr;
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* Create a new handler structure initialized with the handler label and
|
|
|
|
|
typeinfo fields passed in. */
|
|
|
|
|
|
|
|
|
|
struct handler_info *
|
|
|
|
|
get_new_handler (handler, typeinfo)
|
|
|
|
|
rtx handler;
|
|
|
|
|
void *typeinfo;
|
|
|
|
|
{
|
|
|
|
|
struct handler_info* ptr;
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
ptr = (struct handler_info *) xmalloc (sizeof (struct handler_info));
|
1998-05-14 13:39:15 +00:00
|
|
|
|
ptr->handler_label = handler;
|
1998-12-09 06:15:20 +00:00
|
|
|
|
ptr->handler_number = CODE_LABEL_NUMBER (handler);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
ptr->type_info = typeinfo;
|
|
|
|
|
ptr->next = NULL;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Find the index in function_eh_regions associated with a NOTE region. If
|
1999-11-18 17:50:56 +00:00
|
|
|
|
the region cannot be found, a -1 is returned. */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
cpplib.c (if_directive_nameo): Add static prototype.
* cpplib.c (if_directive_nameo): Add static prototype.
* cse.c (cse_insn): Remove unused variable `p'.
* except.c (create_rethrow_ref, push_entry,
receive_exception_label, new_eh_region_entry, find_func_region,
clear_function_eh_region, process_nestinfo): Add static prototypes.
(get_reg_for_handler): Hide definition.
(process_nestinfo): Initialize variable `extra_handlers'.
* expr.h (expand_builtin_longjmp): Add extern prototype.
* final.c (final_addr_vec_align, align_fuzz): Add static prototypes.
* function.c (prepare_function_start): Likewise.
(pop_function_context_from): Mark parameter `context' with
ATTRIBUTE_UNUSED.
(push_temp_slots_for_block, flush_addressof): Hide definition.
* gcov.c (init_arc, reverse_arcs, create_program_flow_graph,
solve_program_flow_graph, calculate_branch_probs,
function_summary, main, fancy_abort): Add prototypes.
* gen-protos.c (add_hash, parse_fn_proto, main): Likewise.
(add_hash): Constify a char*.
* ggc-common.c (ggc_mark_rtx_ptr, ggc_mark_tree_ptr,
ggc_mark_tree_varray_ptr, ggc_mark_tree_hash_table_ptr,
ggc_mark_string_ptr, ggc_mark_tree_hash_table_entry): Add prototypes.
* integrate.c (expand_inline_function_eh_labelmap): Likewise.
* lists.c (free_list, zap_lists): Likewise.
From-SVN: r29783
1999-10-03 16:28:33 +00:00
|
|
|
|
static int
|
1998-05-14 13:39:15 +00:00
|
|
|
|
find_func_region (insn_region)
|
|
|
|
|
int insn_region;
|
|
|
|
|
{
|
|
|
|
|
int x;
|
|
|
|
|
for (x = 0; x < current_func_eh_entry; x++)
|
|
|
|
|
if (function_eh_regions[x].range_number == insn_region)
|
|
|
|
|
return x;
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get a pointer to the first handler in an exception region's list. */
|
|
|
|
|
|
|
|
|
|
struct handler_info *
|
|
|
|
|
get_first_handler (region)
|
|
|
|
|
int region;
|
|
|
|
|
{
|
1999-11-25 19:21:27 +00:00
|
|
|
|
int r = find_func_region (region);
|
|
|
|
|
if (r == -1)
|
|
|
|
|
abort ();
|
|
|
|
|
return function_eh_regions[r].handlers;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clean out the function_eh_region table and free all memory */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
clear_function_eh_region ()
|
|
|
|
|
{
|
|
|
|
|
int x;
|
|
|
|
|
struct handler_info *ptr, *next;
|
|
|
|
|
for (x = 0; x < current_func_eh_entry; x++)
|
|
|
|
|
for (ptr = function_eh_regions[x].handlers; ptr != NULL; ptr = next)
|
|
|
|
|
{
|
|
|
|
|
next = ptr->next;
|
|
|
|
|
free (ptr);
|
|
|
|
|
}
|
|
|
|
|
free (function_eh_regions);
|
|
|
|
|
num_func_eh_entries = 0;
|
|
|
|
|
current_func_eh_entry = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make a duplicate of an exception region by copying all the handlers
|
1998-12-08 14:04:03 +00:00
|
|
|
|
for an exception region. Return the new handler index. The final
|
|
|
|
|
parameter is a routine which maps old labels to new ones. */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
int
|
1998-12-08 14:04:03 +00:00
|
|
|
|
duplicate_eh_handlers (old_note_eh_region, new_note_eh_region, map)
|
1998-05-14 13:39:15 +00:00
|
|
|
|
int old_note_eh_region, new_note_eh_region;
|
1998-12-09 07:27:21 +00:00
|
|
|
|
rtx (*map) PARAMS ((rtx));
|
1998-05-14 13:39:15 +00:00
|
|
|
|
{
|
|
|
|
|
struct handler_info *ptr, *new_ptr;
|
|
|
|
|
int new_region, region;
|
|
|
|
|
|
|
|
|
|
region = find_func_region (old_note_eh_region);
|
|
|
|
|
if (region == -1)
|
1998-12-08 14:04:03 +00:00
|
|
|
|
fatal ("Cannot duplicate non-existant exception region.");
|
|
|
|
|
|
|
|
|
|
/* duplicate_eh_handlers may have been called during a symbol remap. */
|
|
|
|
|
new_region = find_func_region (new_note_eh_region);
|
|
|
|
|
if (new_region != -1)
|
|
|
|
|
return (new_region);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
new_region = new_eh_region_entry (new_note_eh_region, NULL_RTX);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
ptr = function_eh_regions[region].handlers;
|
|
|
|
|
|
|
|
|
|
for ( ; ptr; ptr = ptr->next)
|
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
new_ptr = get_new_handler (map (ptr->handler_label), ptr->type_info);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
add_new_handler (new_region, new_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new_region;
|
|
|
|
|
}
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
|
|
|
|
|
/* Given a rethrow symbol, find the EH region number this is for. */
|
2000-03-08 16:30:17 -05:00
|
|
|
|
|
1999-11-18 17:50:56 +00:00
|
|
|
|
static int
|
1998-12-08 14:04:03 +00:00
|
|
|
|
eh_region_from_symbol (sym)
|
|
|
|
|
rtx sym;
|
|
|
|
|
{
|
|
|
|
|
int x;
|
|
|
|
|
if (sym == last_rethrow_symbol)
|
|
|
|
|
return 1;
|
|
|
|
|
for (x = 0; x < current_func_eh_entry; x++)
|
|
|
|
|
if (function_eh_regions[x].rethrow_label == sym)
|
|
|
|
|
return function_eh_regions[x].range_number;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-18 17:50:56 +00:00
|
|
|
|
/* Like find_func_region, but using the rethrow symbol for the region
|
|
|
|
|
rather than the region number itself. */
|
2000-03-08 16:30:17 -05:00
|
|
|
|
|
1999-11-18 17:50:56 +00:00
|
|
|
|
static int
|
|
|
|
|
find_func_region_from_symbol (sym)
|
|
|
|
|
rtx sym;
|
|
|
|
|
{
|
|
|
|
|
return find_func_region (eh_region_from_symbol (sym));
|
|
|
|
|
}
|
1998-12-08 14:04:03 +00:00
|
|
|
|
|
|
|
|
|
/* When inlining/unrolling, we have to map the symbols passed to
|
|
|
|
|
__rethrow as well. This performs the remap. If a symbol isn't foiund,
|
|
|
|
|
the original one is returned. This is not an efficient routine,
|
|
|
|
|
so don't call it on everything!! */
|
2000-03-08 16:30:17 -05:00
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
rtx
|
|
|
|
|
rethrow_symbol_map (sym, map)
|
|
|
|
|
rtx sym;
|
1998-12-09 07:27:21 +00:00
|
|
|
|
rtx (*map) PARAMS ((rtx));
|
1998-12-08 14:04:03 +00:00
|
|
|
|
{
|
|
|
|
|
int x, y;
|
2000-03-08 16:30:17 -05:00
|
|
|
|
|
|
|
|
|
if (! flag_new_exceptions)
|
|
|
|
|
return sym;
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
for (x = 0; x < current_func_eh_entry; x++)
|
|
|
|
|
if (function_eh_regions[x].rethrow_label == sym)
|
|
|
|
|
{
|
|
|
|
|
/* We've found the original region, now lets determine which region
|
|
|
|
|
this now maps to. */
|
|
|
|
|
rtx l1 = function_eh_regions[x].handlers->handler_label;
|
|
|
|
|
rtx l2 = map (l1);
|
|
|
|
|
y = CODE_LABEL_NUMBER (l2); /* This is the new region number */
|
|
|
|
|
x = find_func_region (y); /* Get the new permanent region */
|
|
|
|
|
if (x == -1) /* Hmm, Doesn't exist yet */
|
|
|
|
|
{
|
|
|
|
|
x = duplicate_eh_handlers (CODE_LABEL_NUMBER (l1), y, map);
|
|
|
|
|
/* Since we're mapping it, it must be used. */
|
1999-08-10 16:19:16 +00:00
|
|
|
|
function_eh_regions[x].rethrow_ref = 1;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
}
|
|
|
|
|
return function_eh_regions[x].rethrow_label;
|
|
|
|
|
}
|
|
|
|
|
return sym;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* Returns nonzero if the rethrow label for REGION is referenced
|
|
|
|
|
somewhere (i.e. we rethrow out of REGION or some other region
|
|
|
|
|
masquerading as REGION). */
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
int
|
|
|
|
|
rethrow_used (region)
|
|
|
|
|
int region;
|
|
|
|
|
{
|
|
|
|
|
if (flag_new_exceptions)
|
|
|
|
|
{
|
1999-08-10 16:19:16 +00:00
|
|
|
|
int ret = function_eh_regions[find_func_region (region)].rethrow_ref;
|
|
|
|
|
return ret;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1998-05-06 15:09:07 -06:00
|
|
|
|
/* Routine to see if exception handling is turned on.
|
1996-07-23 20:20:04 +00:00
|
|
|
|
DO_WARN is non-zero if we want to inform the user that exception
|
1996-09-14 20:47:01 -04:00
|
|
|
|
handling is turned off.
|
|
|
|
|
|
|
|
|
|
This is used to ensure that -fexceptions has been specified if the
|
1997-02-07 01:17:32 +00:00
|
|
|
|
compiler tries to use any exception-specific functions. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
doing_eh (do_warn)
|
|
|
|
|
int do_warn;
|
|
|
|
|
{
|
|
|
|
|
if (! flag_exceptions)
|
|
|
|
|
{
|
|
|
|
|
static int warned = 0;
|
|
|
|
|
if (! warned && do_warn)
|
|
|
|
|
{
|
|
|
|
|
error ("exception handling disabled, use -fexceptions to enable");
|
|
|
|
|
warned = 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Given a return address in ADDR, determine the address we should use
|
1997-02-07 01:17:32 +00:00
|
|
|
|
to find the corresponding EH region. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
eh_outer_context (addr)
|
|
|
|
|
rtx addr;
|
|
|
|
|
{
|
|
|
|
|
/* First mask out any unwanted bits. */
|
|
|
|
|
#ifdef MASK_RETURN_ADDR
|
1997-09-15 22:07:50 -04:00
|
|
|
|
expand_and (addr, MASK_RETURN_ADDR, addr);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
/* Then adjust to find the real return address. */
|
|
|
|
|
#if defined (RETURN_ADDR_OFFSET)
|
|
|
|
|
addr = plus_constant (addr, RETURN_ADDR_OFFSET);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* Start a new exception region for a region of code that has a
|
|
|
|
|
cleanup action and push the HANDLER for the region onto
|
|
|
|
|
protect_list. All of the regions created with add_partial_entry
|
|
|
|
|
will be ended when end_protect_partials is invoked. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
add_partial_entry (handler)
|
|
|
|
|
tree handler;
|
|
|
|
|
{
|
|
|
|
|
expand_eh_region_start ();
|
|
|
|
|
|
1997-02-07 01:17:32 +00:00
|
|
|
|
/* Make sure the entry is on the correct obstack. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
push_obstacks_nochange ();
|
|
|
|
|
resume_temporary_allocation ();
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* Because this is a cleanup action, we may have to protect the handler
|
|
|
|
|
with __terminate. */
|
|
|
|
|
handler = protect_with_terminate (handler);
|
|
|
|
|
|
1999-11-25 19:21:27 +00:00
|
|
|
|
/* For backwards compatibility, we allow callers to omit calls to
|
|
|
|
|
begin_protect_partials for the outermost region. So, we must
|
|
|
|
|
explicitly do so here. */
|
|
|
|
|
if (!protect_list)
|
|
|
|
|
begin_protect_partials ();
|
|
|
|
|
|
|
|
|
|
/* Add this entry to the front of the list. */
|
|
|
|
|
TREE_VALUE (protect_list)
|
|
|
|
|
= tree_cons (NULL_TREE, handler, TREE_VALUE (protect_list));
|
1996-09-14 20:47:01 -04:00
|
|
|
|
pop_obstacks ();
|
|
|
|
|
}
|
|
|
|
|
|
1997-12-12 09:23:52 +00:00
|
|
|
|
/* Emit code to get EH context to current function. */
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
static rtx
|
1997-12-12 07:35:04 +00:00
|
|
|
|
call_get_eh_context ()
|
1997-04-23 20:11:52 +00:00
|
|
|
|
{
|
1997-11-25 04:30:38 -05:00
|
|
|
|
static tree fn;
|
|
|
|
|
tree expr;
|
|
|
|
|
|
|
|
|
|
if (fn == NULL_TREE)
|
|
|
|
|
{
|
|
|
|
|
tree fntype;
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
fn = get_identifier ("__get_eh_context");
|
1997-11-25 04:30:38 -05:00
|
|
|
|
push_obstacks_nochange ();
|
|
|
|
|
end_temporary_allocation ();
|
|
|
|
|
fntype = build_pointer_type (build_pointer_type
|
|
|
|
|
(build_pointer_type (void_type_node)));
|
|
|
|
|
fntype = build_function_type (fntype, NULL_TREE);
|
|
|
|
|
fn = build_decl (FUNCTION_DECL, fn, fntype);
|
|
|
|
|
DECL_EXTERNAL (fn) = 1;
|
|
|
|
|
TREE_PUBLIC (fn) = 1;
|
|
|
|
|
DECL_ARTIFICIAL (fn) = 1;
|
|
|
|
|
TREE_READONLY (fn) = 1;
|
|
|
|
|
make_decl_rtl (fn, NULL_PTR, 1);
|
|
|
|
|
assemble_external (fn);
|
|
|
|
|
pop_obstacks ();
|
1999-09-09 16:24:08 +00:00
|
|
|
|
|
|
|
|
|
ggc_add_tree_root (&fn, 1);
|
1997-11-25 04:30:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
|
|
|
|
|
expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
|
|
|
|
|
expr, NULL_TREE, NULL_TREE);
|
|
|
|
|
TREE_SIDE_EFFECTS (expr) = 1;
|
|
|
|
|
|
1997-12-12 09:23:52 +00:00
|
|
|
|
return copy_to_reg (expand_expr (expr, NULL_RTX, VOIDmode, 0));
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get a reference to the EH context.
|
|
|
|
|
We will only generate a register for the current function EH context here,
|
|
|
|
|
and emit a USE insn to mark that this is a EH context register.
|
|
|
|
|
|
|
|
|
|
Later, emit_eh_context will emit needed call to __get_eh_context
|
|
|
|
|
in libgcc2, and copy the value to the register we have generated. */
|
|
|
|
|
|
|
|
|
|
rtx
|
1997-12-12 07:35:04 +00:00
|
|
|
|
get_eh_context ()
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
{
|
|
|
|
|
if (current_function_ehc == 0)
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
|
|
|
|
|
current_function_ehc = gen_reg_rtx (Pmode);
|
|
|
|
|
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
insn = gen_rtx_USE (GET_MODE (current_function_ehc),
|
|
|
|
|
current_function_ehc);
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
insn = emit_insn_before (insn, get_first_nonparm_insn ());
|
|
|
|
|
|
|
|
|
|
REG_NOTES (insn)
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
= gen_rtx_EXPR_LIST (REG_EH_CONTEXT, current_function_ehc,
|
|
|
|
|
REG_NOTES (insn));
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
}
|
|
|
|
|
return current_function_ehc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get a reference to the dynamic handler chain. It points to the
|
|
|
|
|
pointer to the next element in the dynamic handler chain. It ends
|
|
|
|
|
when there are no more elements in the dynamic handler chain, when
|
|
|
|
|
the value is &top_elt from libgcc2.c. Immediately after the
|
|
|
|
|
pointer, is an area suitable for setjmp/longjmp when
|
|
|
|
|
DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
|
|
|
|
|
__builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
|
|
|
|
|
isn't defined. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
get_dynamic_handler_chain ()
|
|
|
|
|
{
|
|
|
|
|
rtx ehc, dhc, result;
|
|
|
|
|
|
1997-12-12 07:35:04 +00:00
|
|
|
|
ehc = get_eh_context ();
|
1998-06-17 13:05:54 +00:00
|
|
|
|
|
|
|
|
|
/* This is the offset of dynamic_handler_chain in the eh_context struct
|
|
|
|
|
declared in eh-common.h. If its location is change, change this offset */
|
1998-06-23 07:10:29 +00:00
|
|
|
|
dhc = plus_constant (ehc, POINTER_SIZE / BITS_PER_UNIT);
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
|
|
|
|
|
result = copy_to_reg (dhc);
|
|
|
|
|
|
|
|
|
|
/* We don't want a copy of the dcc, but rather, the single dcc. */
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
return gen_rtx_MEM (Pmode, result);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get a reference to the dynamic cleanup chain. It points to the
|
|
|
|
|
pointer to the next element in the dynamic cleanup chain.
|
|
|
|
|
Immediately after the pointer, are two Pmode variables, one for a
|
|
|
|
|
pointer to a function that performs the cleanup action, and the
|
|
|
|
|
second, the argument to pass to that function. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
get_dynamic_cleanup_chain ()
|
|
|
|
|
{
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
rtx dhc, dcc, result;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
dhc = get_dynamic_handler_chain ();
|
1998-06-23 07:10:29 +00:00
|
|
|
|
dcc = plus_constant (dhc, POINTER_SIZE / BITS_PER_UNIT);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
result = copy_to_reg (dcc);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* We don't want a copy of the dcc, but rather, the single dcc. */
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
return gen_rtx_MEM (Pmode, result);
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-06-19 23:45:30 +00:00
|
|
|
|
#ifdef DONT_USE_BUILTIN_SETJMP
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* Generate code to evaluate X and jump to LABEL if the value is nonzero.
|
|
|
|
|
LABEL is an rtx of code CODE_LABEL, in this function. */
|
|
|
|
|
|
1998-06-19 22:47:40 +00:00
|
|
|
|
static void
|
1997-04-23 20:11:52 +00:00
|
|
|
|
jumpif_rtx (x, label)
|
|
|
|
|
rtx x;
|
|
|
|
|
rtx label;
|
|
|
|
|
{
|
|
|
|
|
jumpif (make_tree (type_for_mode (GET_MODE (x), 0), x), label);
|
|
|
|
|
}
|
1998-06-19 23:45:30 +00:00
|
|
|
|
#endif
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* Start a dynamic cleanup on the EH runtime dynamic cleanup stack.
|
|
|
|
|
We just need to create an element for the cleanup list, and push it
|
|
|
|
|
into the chain.
|
|
|
|
|
|
|
|
|
|
A dynamic cleanup is a cleanup action implied by the presence of an
|
|
|
|
|
element on the EH runtime dynamic cleanup stack that is to be
|
|
|
|
|
performed when an exception is thrown. The cleanup action is
|
|
|
|
|
performed by __sjthrow when an exception is thrown. Only certain
|
|
|
|
|
actions can be optimized into dynamic cleanup actions. For the
|
|
|
|
|
restrictions on what actions can be performed using this routine,
|
|
|
|
|
see expand_eh_region_start_tree. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
start_dynamic_cleanup (func, arg)
|
|
|
|
|
tree func;
|
|
|
|
|
tree arg;
|
|
|
|
|
{
|
1998-02-11 00:35:13 +00:00
|
|
|
|
rtx dcc;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
rtx new_func, new_arg;
|
|
|
|
|
rtx x, buf;
|
|
|
|
|
int size;
|
|
|
|
|
|
|
|
|
|
/* We allocate enough room for a pointer to the function, and
|
|
|
|
|
one argument. */
|
|
|
|
|
size = 2;
|
|
|
|
|
|
|
|
|
|
/* XXX, FIXME: The stack space allocated this way is too long lived,
|
|
|
|
|
but there is no allocation routine that allocates at the level of
|
|
|
|
|
the last binding contour. */
|
|
|
|
|
buf = assign_stack_local (BLKmode,
|
|
|
|
|
GET_MODE_SIZE (Pmode)*(size+1),
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
buf = change_address (buf, Pmode, NULL_RTX);
|
|
|
|
|
|
|
|
|
|
/* Store dcc into the first word of the newly allocated buffer. */
|
|
|
|
|
|
|
|
|
|
dcc = get_dynamic_cleanup_chain ();
|
|
|
|
|
emit_move_insn (buf, dcc);
|
|
|
|
|
|
|
|
|
|
/* Store func and arg into the cleanup list element. */
|
|
|
|
|
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
new_func = gen_rtx_MEM (Pmode, plus_constant (XEXP (buf, 0),
|
|
|
|
|
GET_MODE_SIZE (Pmode)));
|
|
|
|
|
new_arg = gen_rtx_MEM (Pmode, plus_constant (XEXP (buf, 0),
|
|
|
|
|
GET_MODE_SIZE (Pmode)*2));
|
1997-04-23 20:11:52 +00:00
|
|
|
|
x = expand_expr (func, new_func, Pmode, 0);
|
|
|
|
|
if (x != new_func)
|
|
|
|
|
emit_move_insn (new_func, x);
|
|
|
|
|
|
|
|
|
|
x = expand_expr (arg, new_arg, Pmode, 0);
|
|
|
|
|
if (x != new_arg)
|
|
|
|
|
emit_move_insn (new_arg, x);
|
|
|
|
|
|
|
|
|
|
/* Update the cleanup chain. */
|
|
|
|
|
|
1999-07-26 18:53:02 -07:00
|
|
|
|
x = force_operand (XEXP (buf, 0), dcc);
|
|
|
|
|
if (x != dcc)
|
|
|
|
|
emit_move_insn (dcc, x);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Emit RTL to start a dynamic handler on the EH runtime dynamic
|
|
|
|
|
handler stack. This should only be used by expand_eh_region_start
|
|
|
|
|
or expand_eh_region_start_tree. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
start_dynamic_handler ()
|
|
|
|
|
{
|
|
|
|
|
rtx dhc, dcc;
|
1997-05-07 22:50:11 +00:00
|
|
|
|
rtx x, arg, buf;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
int size;
|
|
|
|
|
|
1997-05-07 22:50:11 +00:00
|
|
|
|
#ifndef DONT_USE_BUILTIN_SETJMP
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* The number of Pmode words for the setjmp buffer, when using the
|
1999-09-10 20:28:12 +00:00
|
|
|
|
builtin setjmp/longjmp, see expand_builtin, case BUILT_IN_LONGJMP. */
|
|
|
|
|
/* We use 2 words here before calling expand_builtin_setjmp.
|
|
|
|
|
expand_builtin_setjmp uses 2 words, and then calls emit_stack_save.
|
|
|
|
|
emit_stack_save needs space of size STACK_SAVEAREA_MODE (SAVE_NONLOCAL).
|
|
|
|
|
Subtract one, because the assign_stack_local call below adds 1. */
|
|
|
|
|
size = (2 + 2 + (GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL))
|
|
|
|
|
/ GET_MODE_SIZE (Pmode))
|
|
|
|
|
- 1);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
#else
|
|
|
|
|
#ifdef JMP_BUF_SIZE
|
|
|
|
|
size = JMP_BUF_SIZE;
|
|
|
|
|
#else
|
|
|
|
|
/* Should be large enough for most systems, if it is not,
|
|
|
|
|
JMP_BUF_SIZE should be defined with the proper value. It will
|
|
|
|
|
also tend to be larger than necessary for most systems, a more
|
|
|
|
|
optimal port will define JMP_BUF_SIZE. */
|
|
|
|
|
size = FIRST_PSEUDO_REGISTER+2;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
/* XXX, FIXME: The stack space allocated this way is too long lived,
|
|
|
|
|
but there is no allocation routine that allocates at the level of
|
|
|
|
|
the last binding contour. */
|
|
|
|
|
arg = assign_stack_local (BLKmode,
|
|
|
|
|
GET_MODE_SIZE (Pmode)*(size+1),
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
arg = change_address (arg, Pmode, NULL_RTX);
|
|
|
|
|
|
|
|
|
|
/* Store dhc into the first word of the newly allocated buffer. */
|
|
|
|
|
|
|
|
|
|
dhc = get_dynamic_handler_chain ();
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
dcc = gen_rtx_MEM (Pmode, plus_constant (XEXP (arg, 0),
|
|
|
|
|
GET_MODE_SIZE (Pmode)));
|
1997-04-23 20:11:52 +00:00
|
|
|
|
emit_move_insn (arg, dhc);
|
|
|
|
|
|
|
|
|
|
/* Zero out the start of the cleanup chain. */
|
|
|
|
|
emit_move_insn (dcc, const0_rtx);
|
|
|
|
|
|
|
|
|
|
/* The jmpbuf starts two words into the area allocated. */
|
1997-05-07 22:50:11 +00:00
|
|
|
|
buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
1997-05-07 22:50:11 +00:00
|
|
|
|
#ifdef DONT_USE_BUILTIN_SETJMP
|
2000-02-20 07:43:00 +01:00
|
|
|
|
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1,
|
|
|
|
|
TYPE_MODE (integer_type_node), 1,
|
1997-05-07 22:50:11 +00:00
|
|
|
|
buf, Pmode);
|
1998-02-02 11:28:57 -08:00
|
|
|
|
/* If we come back here for a catch, transfer control to the handler. */
|
|
|
|
|
jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
|
1997-05-07 22:50:11 +00:00
|
|
|
|
#else
|
1998-02-02 11:28:57 -08:00
|
|
|
|
{
|
|
|
|
|
/* A label to continue execution for the no exception case. */
|
|
|
|
|
rtx noex = gen_label_rtx();
|
|
|
|
|
x = expand_builtin_setjmp (buf, NULL_RTX, noex,
|
|
|
|
|
ehstack.top->entry->exception_handler_label);
|
|
|
|
|
emit_label (noex);
|
|
|
|
|
}
|
1997-05-07 22:50:11 +00:00
|
|
|
|
#endif
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* We are committed to this, so update the handler chain. */
|
|
|
|
|
|
1999-03-29 07:07:37 -08:00
|
|
|
|
emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));
|
1997-04-23 20:11:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Start an exception handling region for the given cleanup action.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
All instructions emitted after this point are considered to be part
|
1997-04-23 20:11:52 +00:00
|
|
|
|
of the region until expand_eh_region_end is invoked. CLEANUP is
|
|
|
|
|
the cleanup action to perform. The return value is true if the
|
|
|
|
|
exception region was optimized away. If that case,
|
|
|
|
|
expand_eh_region_end does not need to be called for this cleanup,
|
|
|
|
|
nor should it be.
|
|
|
|
|
|
|
|
|
|
This routine notices one particular common case in C++ code
|
|
|
|
|
generation, and optimizes it so as to not need the exception
|
|
|
|
|
region. It works by creating a dynamic cleanup action, instead of
|
1998-05-06 15:09:07 -06:00
|
|
|
|
a using an exception region. */
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
int
|
1997-04-29 20:03:15 +00:00
|
|
|
|
expand_eh_region_start_tree (decl, cleanup)
|
|
|
|
|
tree decl;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
tree cleanup;
|
|
|
|
|
{
|
|
|
|
|
/* This is the old code. */
|
|
|
|
|
if (! doing_eh (0))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* The optimization only applies to actions protected with
|
|
|
|
|
terminate, and only applies if we are using the setjmp/longjmp
|
|
|
|
|
codegen method. */
|
|
|
|
|
if (exceptions_via_longjmp
|
|
|
|
|
&& protect_cleanup_actions_with_terminate)
|
|
|
|
|
{
|
|
|
|
|
tree func, arg;
|
|
|
|
|
tree args;
|
|
|
|
|
|
|
|
|
|
/* Ignore any UNSAVE_EXPR. */
|
|
|
|
|
if (TREE_CODE (cleanup) == UNSAVE_EXPR)
|
|
|
|
|
cleanup = TREE_OPERAND (cleanup, 0);
|
|
|
|
|
|
|
|
|
|
/* Further, it only applies if the action is a call, if there
|
|
|
|
|
are 2 arguments, and if the second argument is 2. */
|
|
|
|
|
|
|
|
|
|
if (TREE_CODE (cleanup) == CALL_EXPR
|
|
|
|
|
&& (args = TREE_OPERAND (cleanup, 1))
|
|
|
|
|
&& (func = TREE_OPERAND (cleanup, 0))
|
|
|
|
|
&& (arg = TREE_VALUE (args))
|
|
|
|
|
&& (args = TREE_CHAIN (args))
|
|
|
|
|
|
|
|
|
|
/* is the second argument 2? */
|
|
|
|
|
&& TREE_CODE (TREE_VALUE (args)) == INTEGER_CST
|
tree.h (INT_CST_LT, [...]): Remove unneeded casts.
* tree.h (INT_CST_LT, INT_CST_LT_UNSIGNED): Remove unneeded casts.
(struct tree_int_cst): int_cst_low is now unsigned HOST_WIDE_INT.
(attribute_hash_list, type_hash_canon): hashcode is now unsigned.
(type_hash_lookup, type_hash_add, type_hash_list): Likewise.
(min_precision): Result is unsignd.
(add_double, neg_double, mul_double): Low word is unsigned.
(lshift_double, rshift_double, lrotate_double): Likewise.
(rrotate_double, div_and_round_double): Likewise.
(tree_floor_log2, compare_tree_int): New functions.
(preserve_rtl_expr_temps): New declaration.
* c-common.c (declare_hidden_char_array): Use compare_tree_int.
(decl_attributes): Use tree_log2 to find alignment.
Check for TREE_INT_CST_HIGH for format args.
(min_precision): Now unsigned.
Use tree_floor_log2.
(truthvalue_conversion): Delete long-disabled code.
* c-decl.c (finish_struct): Clean up tests on field width.
(finish_function): Use compare_tree_int.
* c-pragma.c (handle_pragma_token): Use tree_log2 for alignment.
* c-typeck.c (comptypes): Use tree_int_cst_equal.
(default_conversion, digest_init): Use compare_tree_int.
(build_binary_op): Use integer_all_onesp and compare_tree_int.
Fix type errors in forming masks.
* calls.c (initialize_argument_information): Use compare_tree_int.
* dbxout.c (dbxout_type): Cast TREE_INT_CST_LOW to HOST_WIDE_INT.
* except.c (expand_eh_region_start_tree): Use compare_tree_int.
* expr.c (is_zeros_p, case INTEGER_CST): Use integer_zerop.
(store_field): Use compare_tree_int.
(expand_expr, case CONSTRUCTOR): Use TYPE_SIZE_UNIT.
(expand_expr, case ARRAY_REF): Use compare_tree_int.
(do_jump, case BIT_AND_EXPR): Use tree_floor_log2.
(do_store_flag): Use compare_tree_int.
* fold-const.c (encode, decode): Low part is always unsigned.
(force_fit_type, add_double, neg_double, mul_double): Likewise.
(lshift_double, rshift_double, lrotate_double): Likewise.
(rrotate_double, div_and_round_double, int_const_binop): Likewise.
(fold_convert): Use compare_tree_int.
(operand_equal_p, case INTEGER_CST): Use tree_int_cst_equal.
(invert_truthvalue, case INTEGER_CST): Likewise.
(fold): Use compare_tree_int; add casts for unsigned TREE_INT_CST_LOW.
* mkdeps.c (deps_dummy_targets): Make I unsigned.
* rtl.h (add_double, neg_double, mul_double): Low words are unsigned.
(lshift_double, rshift_double, lrotate_double, rrotate_double):
Likewise.
* stmt.c (expand_decl): Use compare_tree_int and mode_for_size_tree.
(expand_end_case): Use compare_tree_int.
(estimate_case_costs): Cast TREE_INT_CST_LOW to HOST_WIDE_INT.
* stor-layout.c (mode_for_size_tree): Use compare_tree_int.
(layout_decl): Likewise.
(layout_record, layout_union): Make sizes unsigned.
(layout_type, case VOID_TYPE): TYPE_SIZE must be bitsizetype.
(layout_type, case QUAL_UNION_TYPE): Use compare_tree_int.
* tree.c (struct type_hash): hashcode is unsigned.
(build_type_attribute_variant, type_hash_list): Likewise.
(type_hash_lookup, type_hash_add, type_hash_canon): Likewise.
(attribute_hash_list, build_array_type, build_method_type): Likewise.
(build_complex_type): Likewise.
(real_value_from_int_cst): Remove unneeded casts.
(integer_all_onesp): Add casts.
(tree_floor_log2, compare_tree_int): New functions.
(build_index_type): Use tree_int_cst_sgn.
* varasm.c (assemble_variable): Use compare_tree_int.
* ch/actions.c (chill_convert_for_assignment): INDEX is unsigned
HOST_WIDE_INT.
* ch/ch-tree.h (DECL_NESTING_LEVEL): Use TREE_INT_CST_HIGH
since unsigned.
* ch/except.c (chill_handle_on_labels): ALTERNATIVE is unsigned.
Use compare_tree_int.
(expand_goto_except_cleanup): Likewise.
* cp/class.c (dfs_modify_vtables): I is now unsigned.
(check_bitfield_decl): Use tree_int_cst_sgn and compare_tree_int.
(build_base_field): Add casts of TREE_INT_CST_LOW to HOST_WIDE_INT.
* cp/error.c (dump_expr): Cast TREE_INT_CST_HIGH to unsigned.
* cp/init.c (build_vec_init): Cast TREE_INT_CST_LOW to HOST_WIDE_INT.
* cp/method.c (build_overload_int): Cast TREE_INT_CST_HIGH to unsigned.
* cp/typeck.c (build_binary_op, case TRUNC_DIV_EXPR):
Call integer_all_onesp.
* cp/typeck2.c (process_init_constructor): Use compare_tree_int.
* f/com.c (ffecom_f2c_set_lio_code_): Use compare_tree_int.
(ffecom_sym_transform_, ffecom_transform_common_): Likewise.
(ffecom_transform_equiv_): Likewise.
* java/decl.c (emit_init_test_initialization): Mark KEY as unused.
* java/expr.c (build_newarray): Cast TREE_INT_CST_LOW to HOST_WIDE_INT.
(build_anewarray): Likewise.
* java/parse.y (patch_newarray): Likewise.
* java/parse.c: Regenerated.
From-SVN: r32383
2000-03-07 11:41:32 +00:00
|
|
|
|
&& compare_tree_int (TREE_VALUE (args), 2) == 0
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* Make sure there are no other arguments. */
|
|
|
|
|
&& TREE_CHAIN (args) == NULL_TREE)
|
|
|
|
|
{
|
|
|
|
|
/* Arrange for returns and gotos to pop the entry we make on the
|
|
|
|
|
dynamic cleanup stack. */
|
1997-04-29 20:03:15 +00:00
|
|
|
|
expand_dcc_cleanup (decl);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
start_dynamic_cleanup (func, arg);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-04-29 20:03:15 +00:00
|
|
|
|
expand_eh_region_start_for_decl (decl);
|
1997-12-03 20:04:31 +00:00
|
|
|
|
ehstack.top->entry->finalization = cleanup;
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1997-04-29 20:03:15 +00:00
|
|
|
|
/* Just like expand_eh_region_start, except if a cleanup action is
|
|
|
|
|
entered on the cleanup chain, the TREE_PURPOSE of the element put
|
|
|
|
|
on the chain is DECL. DECL should be the associated VAR_DECL, if
|
|
|
|
|
any, otherwise it should be NULL_TREE. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
1997-04-29 20:03:15 +00:00
|
|
|
|
expand_eh_region_start_for_decl (decl)
|
|
|
|
|
tree decl;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
{
|
|
|
|
|
rtx note;
|
|
|
|
|
|
|
|
|
|
/* This is the old code. */
|
|
|
|
|
if (! doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
1999-08-09 08:52:48 +00:00
|
|
|
|
/* We need a new block to record the start and end of the
|
|
|
|
|
dynamic handler chain. We also want to prevent jumping into
|
|
|
|
|
a try block. */
|
1999-09-17 22:01:23 +00:00
|
|
|
|
expand_start_bindings (2);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
1999-08-09 08:52:48 +00:00
|
|
|
|
/* But we don't need or want a new temporary level. */
|
|
|
|
|
pop_temp_slots ();
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
1999-08-09 08:52:48 +00:00
|
|
|
|
/* Mark this block as created by expand_eh_region_start. This
|
|
|
|
|
is so that we can pop the block with expand_end_bindings
|
|
|
|
|
automatically. */
|
|
|
|
|
mark_block_as_eh_region ();
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
1999-08-09 08:52:48 +00:00
|
|
|
|
if (exceptions_via_longjmp)
|
|
|
|
|
{
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* Arrange for returns and gotos to pop the entry we make on the
|
|
|
|
|
dynamic handler stack. */
|
1997-04-29 20:03:15 +00:00
|
|
|
|
expand_dhc_cleanup (decl);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-05-29 18:42:07 +00:00
|
|
|
|
push_eh_entry (&ehstack);
|
1997-11-02 04:43:34 +00:00
|
|
|
|
note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_BEG);
|
1999-09-14 23:51:34 +00:00
|
|
|
|
NOTE_EH_HANDLER (note)
|
1997-11-02 04:43:34 +00:00
|
|
|
|
= CODE_LABEL_NUMBER (ehstack.top->entry->exception_handler_label);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
if (exceptions_via_longjmp)
|
|
|
|
|
start_dynamic_handler ();
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-04-29 20:03:15 +00:00
|
|
|
|
/* Start an exception handling region. All instructions emitted after
|
|
|
|
|
this point are considered to be part of the region until
|
|
|
|
|
expand_eh_region_end is invoked. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_eh_region_start ()
|
|
|
|
|
{
|
|
|
|
|
expand_eh_region_start_for_decl (NULL_TREE);
|
|
|
|
|
}
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* End an exception handling region. The information about the region
|
|
|
|
|
is found on the top of ehstack.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
HANDLER is either the cleanup for the exception region, or if we're
|
|
|
|
|
marking the end of a try block, HANDLER is integer_zero_node.
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
HANDLER will be transformed to rtl when expand_leftover_cleanups
|
1997-02-07 01:17:32 +00:00
|
|
|
|
is invoked. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_eh_region_end (handler)
|
|
|
|
|
tree handler;
|
|
|
|
|
{
|
|
|
|
|
struct eh_entry *entry;
|
1999-11-18 17:50:56 +00:00
|
|
|
|
struct eh_node *node;
|
1997-11-02 04:43:34 +00:00
|
|
|
|
rtx note;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
int ret, r;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
if (! doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
entry = pop_eh_entry (&ehstack);
|
|
|
|
|
|
1997-11-02 04:43:34 +00:00
|
|
|
|
note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_END);
|
1999-09-14 23:51:34 +00:00
|
|
|
|
ret = NOTE_EH_HANDLER (note)
|
1997-11-02 04:43:34 +00:00
|
|
|
|
= CODE_LABEL_NUMBER (entry->exception_handler_label);
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (exceptions_via_longjmp == 0 && ! flag_new_exceptions
|
1997-12-04 09:41:38 +00:00
|
|
|
|
/* We share outer_context between regions; only emit it once. */
|
|
|
|
|
&& INSN_UID (entry->outer_context) == 0)
|
1997-04-23 20:11:52 +00:00
|
|
|
|
{
|
1997-05-29 18:42:07 +00:00
|
|
|
|
rtx label;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-05-29 18:42:07 +00:00
|
|
|
|
label = gen_label_rtx ();
|
|
|
|
|
emit_jump (label);
|
|
|
|
|
|
|
|
|
|
/* Emit a label marking the end of this exception region that
|
|
|
|
|
is used for rethrowing into the outer context. */
|
|
|
|
|
emit_label (entry->outer_context);
|
1997-12-04 09:41:38 +00:00
|
|
|
|
expand_internal_throw ();
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-05-29 18:42:07 +00:00
|
|
|
|
emit_label (label);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
entry->finalization = handler;
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* create region entry in final exception table */
|
1999-09-14 23:51:34 +00:00
|
|
|
|
r = new_eh_region_entry (NOTE_EH_HANDLER (note), entry->rethrow_label);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
1999-12-12 18:32:36 +00:00
|
|
|
|
enqueue_eh_entry (ehqueue, entry);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1999-08-09 08:52:48 +00:00
|
|
|
|
/* If we have already started ending the bindings, don't recurse. */
|
1997-04-23 20:11:52 +00:00
|
|
|
|
if (is_eh_region ())
|
|
|
|
|
{
|
|
|
|
|
/* Because we don't need or want a new temporary level and
|
|
|
|
|
because we didn't create one in expand_eh_region_start,
|
|
|
|
|
create a fake one now to avoid removing one in
|
|
|
|
|
expand_end_bindings. */
|
|
|
|
|
push_temp_slots ();
|
|
|
|
|
|
|
|
|
|
mark_block_as_not_eh_region ();
|
|
|
|
|
|
|
|
|
|
expand_end_bindings (NULL_TREE, 0, 0);
|
|
|
|
|
}
|
1999-11-18 17:50:56 +00:00
|
|
|
|
|
|
|
|
|
/* Go through the goto handlers in the queue, emitting their
|
|
|
|
|
handlers if we now have enough information to do so. */
|
1999-12-12 18:32:36 +00:00
|
|
|
|
for (node = ehqueue->head; node; node = node->chain)
|
1999-11-18 17:50:56 +00:00
|
|
|
|
if (node->entry->goto_entry_p
|
|
|
|
|
&& node->entry->outer_context == entry->rethrow_label)
|
|
|
|
|
emit_cleanup_handler (node->entry);
|
|
|
|
|
|
|
|
|
|
/* We can't emit handlers for goto entries until their scopes are
|
|
|
|
|
complete because we don't know where they need to rethrow to,
|
|
|
|
|
yet. */
|
|
|
|
|
if (entry->finalization != integer_zero_node
|
|
|
|
|
&& (!entry->goto_entry_p
|
|
|
|
|
|| find_func_region_from_symbol (entry->outer_context) != -1))
|
|
|
|
|
emit_cleanup_handler (entry);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-12-03 20:04:31 +00:00
|
|
|
|
/* End the EH region for a goto fixup. We only need them in the region-based
|
|
|
|
|
EH scheme. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_fixup_region_start ()
|
|
|
|
|
{
|
|
|
|
|
if (! doing_eh (0) || exceptions_via_longjmp)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
expand_eh_region_start ();
|
1999-11-18 17:50:56 +00:00
|
|
|
|
/* Mark this entry as the entry for a goto. */
|
|
|
|
|
ehstack.top->entry->goto_entry_p = 1;
|
1997-12-03 20:04:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* End the EH region for a goto fixup. CLEANUP is the cleanup we just
|
|
|
|
|
expanded; to avoid running it twice if it throws, we look through the
|
|
|
|
|
ehqueue for a matching region and rethrow from its outer_context. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_fixup_region_end (cleanup)
|
|
|
|
|
tree cleanup;
|
|
|
|
|
{
|
|
|
|
|
struct eh_node *node;
|
1998-11-05 05:34:01 +00:00
|
|
|
|
int dont_issue;
|
1997-12-03 20:04:31 +00:00
|
|
|
|
|
|
|
|
|
if (! doing_eh (0) || exceptions_via_longjmp)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (node = ehstack.top; node && node->entry->finalization != cleanup; )
|
|
|
|
|
node = node->chain;
|
|
|
|
|
if (node == 0)
|
1999-12-12 18:32:36 +00:00
|
|
|
|
for (node = ehqueue->head; node && node->entry->finalization != cleanup; )
|
1997-12-03 20:04:31 +00:00
|
|
|
|
node = node->chain;
|
|
|
|
|
if (node == 0)
|
|
|
|
|
abort ();
|
|
|
|
|
|
1998-11-05 05:34:01 +00:00
|
|
|
|
/* If the outer context label has not been issued yet, we don't want
|
|
|
|
|
to issue it as a part of this region, unless this is the
|
|
|
|
|
correct region for the outer context. If we did, then the label for
|
|
|
|
|
the outer context will be WITHIN the begin/end labels,
|
|
|
|
|
and we could get an infinte loop when it tried to rethrow, or just
|
|
|
|
|
generally incorrect execution following a throw. */
|
|
|
|
|
|
1999-09-02 06:08:25 +00:00
|
|
|
|
if (flag_new_exceptions)
|
|
|
|
|
dont_issue = 0;
|
|
|
|
|
else
|
|
|
|
|
dont_issue = ((INSN_UID (node->entry->outer_context) == 0)
|
|
|
|
|
&& (ehstack.top->entry != node->entry));
|
1998-11-05 05:34:01 +00:00
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
ehstack.top->entry->outer_context = node->entry->outer_context;
|
1997-12-03 20:04:31 +00:00
|
|
|
|
|
1998-11-05 05:34:01 +00:00
|
|
|
|
/* Since we are rethrowing to the OUTER region, we know we don't need
|
|
|
|
|
a jump around sequence for this region, so we'll pretend the outer
|
|
|
|
|
context label has been issued by setting INSN_UID to 1, then clearing
|
|
|
|
|
it again afterwards. */
|
|
|
|
|
|
|
|
|
|
if (dont_issue)
|
|
|
|
|
INSN_UID (node->entry->outer_context) = 1;
|
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
/* Just rethrow. size_zero_node is just a NOP. */
|
|
|
|
|
expand_eh_region_end (size_zero_node);
|
1998-11-05 05:34:01 +00:00
|
|
|
|
|
|
|
|
|
if (dont_issue)
|
|
|
|
|
INSN_UID (node->entry->outer_context) = 0;
|
1997-12-03 20:04:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* If we are using the setjmp/longjmp EH codegen method, we emit a
|
2000-03-09 14:01:47 -05:00
|
|
|
|
call to __sjthrow. Otherwise, we emit a call to __throw. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
void
|
1996-07-23 20:20:04 +00:00
|
|
|
|
emit_throw ()
|
|
|
|
|
{
|
1997-04-23 20:11:52 +00:00
|
|
|
|
if (exceptions_via_longjmp)
|
|
|
|
|
{
|
|
|
|
|
emit_library_call (sjthrow_libfunc, 0, VOIDmode, 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#ifdef JUMP_TO_THROW
|
1997-04-23 20:11:52 +00:00
|
|
|
|
emit_indirect_jump (throw_libfunc);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#else
|
1997-04-23 20:11:52 +00:00
|
|
|
|
emit_library_call (throw_libfunc, 0, VOIDmode, 0);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#endif
|
1997-04-23 20:11:52 +00:00
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
emit_barrier ();
|
|
|
|
|
}
|
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
/* Throw the current exception. If appropriate, this is done by jumping
|
|
|
|
|
to the next handler. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
1997-12-04 09:41:38 +00:00
|
|
|
|
expand_internal_throw ()
|
1996-07-23 20:20:04 +00:00
|
|
|
|
{
|
1997-12-04 09:41:38 +00:00
|
|
|
|
emit_throw ();
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Called from expand_exception_blocks and expand_end_catch_block to
|
1997-04-23 20:11:52 +00:00
|
|
|
|
emit any pending handlers/cleanups queued from expand_eh_region_end. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_leftover_cleanups ()
|
|
|
|
|
{
|
|
|
|
|
struct eh_entry *entry;
|
|
|
|
|
|
1999-12-12 18:32:36 +00:00
|
|
|
|
for (entry = dequeue_eh_entry (ehqueue);
|
1999-11-18 17:50:56 +00:00
|
|
|
|
entry;
|
1999-12-12 18:32:36 +00:00
|
|
|
|
entry = dequeue_eh_entry (ehqueue))
|
1996-07-23 20:20:04 +00:00
|
|
|
|
{
|
1999-11-25 19:21:27 +00:00
|
|
|
|
/* A leftover try block. Shouldn't be one here. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
if (entry->finalization == integer_zero_node)
|
|
|
|
|
abort ();
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
free (entry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-02-07 01:17:32 +00:00
|
|
|
|
/* Called at the start of a block of try statements. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
void
|
|
|
|
|
expand_start_try_stmts ()
|
|
|
|
|
{
|
|
|
|
|
if (! doing_eh (1))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
expand_eh_region_start ();
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* Called to begin a catch clause. The parameter is the object which
|
|
|
|
|
will be passed to the runtime type check routine. */
|
|
|
|
|
void
|
1998-06-09 13:28:26 +00:00
|
|
|
|
start_catch_handler (rtime)
|
1998-05-14 13:39:15 +00:00
|
|
|
|
tree rtime;
|
|
|
|
|
{
|
1998-06-24 06:56:37 +00:00
|
|
|
|
rtx handler_label;
|
|
|
|
|
int insn_region_num;
|
|
|
|
|
int eh_region_entry;
|
|
|
|
|
|
|
|
|
|
if (! doing_eh (1))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
handler_label = catchstack.top->entry->exception_handler_label;
|
|
|
|
|
insn_region_num = CODE_LABEL_NUMBER (handler_label);
|
|
|
|
|
eh_region_entry = find_func_region (insn_region_num);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
/* If we've already issued this label, pick a new one */
|
1998-05-19 09:05:27 +00:00
|
|
|
|
if (catchstack.top->entry->label_used)
|
1998-05-14 13:39:15 +00:00
|
|
|
|
handler_label = gen_exception_label ();
|
|
|
|
|
else
|
|
|
|
|
catchstack.top->entry->label_used = 1;
|
|
|
|
|
|
|
|
|
|
receive_exception_label (handler_label);
|
|
|
|
|
|
|
|
|
|
add_new_handler (eh_region_entry, get_new_handler (handler_label, rtime));
|
1998-09-15 11:20:52 +00:00
|
|
|
|
|
|
|
|
|
if (flag_new_exceptions && ! exceptions_via_longjmp)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Under the old mechanism, as well as setjmp/longjmp, we need to
|
|
|
|
|
issue code to compare 'rtime' to the value in eh_info, via the
|
|
|
|
|
matching function in eh_info. If its is false, we branch around
|
|
|
|
|
the handler we are about to issue. */
|
|
|
|
|
|
|
|
|
|
if (rtime != NULL_TREE && rtime != CATCH_ALL_TYPE)
|
|
|
|
|
{
|
|
|
|
|
rtx call_rtx, rtime_address;
|
|
|
|
|
|
|
|
|
|
if (catchstack.top->entry->false_label != NULL_RTX)
|
system.h: Don't redefine abort or trim_filename.
1999-08-25 22:10 -0700 Zack Weinberg <zack@bitmover.com>
* system.h: Don't redefine abort or trim_filename.
* rtl.h: Define abort to fancy_abort (__FILE__, __LINE__, 0)
or fancy_abort (__FILE__, __LINE__, __FUNCTION__) depending on
whether or not __FUNCTION__ is available.
* tree.h: Duplicate rtl.h's definition of abort, for files
that don't include rtl.h. Delete all code to perform type
checking with a compiler other than GCC.
* varray.h: Delete all code to perform type checking with a
compiler other than GCC. Make VARRAY_CHECK() always evaluate
its arguments exactly once, using a statement expression.
Adjust the VARRAY_<type> accessor macros to match.
* toplev.h (fatal_insn, fatal_insn_not_found): Kill.
(_fatal_insn, _fatal_insn_not_found): New fns, take info on
caller's location. Define fatal_insn and fatal_insn_not_found
as macros that use _fatal_insn and _fatal_insn_not_found.
(fancy_abort, trim_filename): Kill prototypes.
* rtl.c (trim_filename): Move here from toplev.c.
(fancy_abort): New function.
(DIR_SEPARATOR): Provide default definition.
* tree.c (tree_check_failed, tree_class_check_failed): Go
through fancy_abort.
(tree_check, tree_class_check, cst_or_constructor_check,
expr_check): Delete.
* varray.c (varray_check_failed): New function.
* toplev.c (fatal_insn, fatal_insn_not_found): Replace with
_fatal_insn and _fatal_insn_not_found. Go through
fancy_abort.
(trim_filename, fancy_abort): Delete.
* builtins.c (expand_builtin_args_info): Report ICE with abort.
* except.c (start_catch_handler): Report ICE with error/abort
combo.
* final.c (output_operand_lossage): Likewise.
* flow.c (verify_flow_info): Likewise.
* gcc.c: Prototype fatal.
* gengenrtl.c: Undef abort after including rtl.h not system.h.
* genattr.c, genattrtab.c, genemit.c, genextract.c,
genflags.c, genopinit.c, genoutput.c, genpeep.c, genrecog.c:
Don't define fancy_abort.
From-SVN: r28889
1999-08-26 05:18:44 +00:00
|
|
|
|
{
|
|
|
|
|
error ("Never issued previous false_label");
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
1998-09-15 11:20:52 +00:00
|
|
|
|
catchstack.top->entry->false_label = gen_exception_label ();
|
|
|
|
|
|
|
|
|
|
rtime_address = expand_expr (rtime, NULL_RTX, Pmode, EXPAND_INITIALIZER);
|
1999-04-15 19:54:09 +00:00
|
|
|
|
#ifdef POINTERS_EXTEND_UNSIGNED
|
|
|
|
|
rtime_address = convert_memory_address (Pmode, rtime_address);
|
|
|
|
|
#endif
|
1998-09-15 11:20:52 +00:00
|
|
|
|
rtime_address = force_reg (Pmode, rtime_address);
|
|
|
|
|
|
|
|
|
|
/* Now issue the call, and branch around handler if needed */
|
1998-09-21 14:23:16 +00:00
|
|
|
|
call_rtx = emit_library_call_value (eh_rtime_match_libfunc, NULL_RTX,
|
2000-02-20 07:43:00 +01:00
|
|
|
|
0, TYPE_MODE (integer_type_node),
|
|
|
|
|
1, rtime_address, Pmode);
|
1998-09-15 11:20:52 +00:00
|
|
|
|
|
|
|
|
|
/* Did the function return true? */
|
1999-02-14 20:08:39 +00:00
|
|
|
|
emit_cmp_and_jump_insns (call_rtx, const0_rtx, EQ, NULL_RTX,
|
|
|
|
|
GET_MODE (call_rtx), 0, 0,
|
|
|
|
|
catchstack.top->entry->false_label);
|
1998-09-15 11:20:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Called to end a catch clause. If we aren't using the new exception
|
|
|
|
|
model tabel mechanism, we need to issue the branch-around label
|
|
|
|
|
for the end of the catch block. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
end_catch_handler ()
|
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (! doing_eh (1))
|
1998-09-15 11:20:52 +00:00
|
|
|
|
return;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
|
|
|
|
|
if (flag_new_exceptions && ! exceptions_via_longjmp)
|
|
|
|
|
{
|
|
|
|
|
emit_barrier ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
1998-09-15 11:20:52 +00:00
|
|
|
|
|
|
|
|
|
/* A NULL label implies the catch clause was a catch all or cleanup */
|
|
|
|
|
if (catchstack.top->entry->false_label == NULL_RTX)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
emit_label (catchstack.top->entry->false_label);
|
|
|
|
|
catchstack.top->entry->false_label = NULL_RTX;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-12 18:32:36 +00:00
|
|
|
|
/* Save away the current ehqueue. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
push_ehqueue ()
|
|
|
|
|
{
|
|
|
|
|
struct eh_queue *q;
|
2000-01-04 23:55:02 -07:00
|
|
|
|
q = (struct eh_queue *) xcalloc (1, sizeof (struct eh_queue));
|
1999-12-12 18:32:36 +00:00
|
|
|
|
q->next = ehqueue;
|
|
|
|
|
ehqueue = q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore a previously pushed ehqueue. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
pop_ehqueue ()
|
|
|
|
|
{
|
|
|
|
|
struct eh_queue *q;
|
|
|
|
|
expand_leftover_cleanups ();
|
|
|
|
|
q = ehqueue->next;
|
|
|
|
|
free (ehqueue);
|
|
|
|
|
ehqueue = q;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-18 17:50:56 +00:00
|
|
|
|
/* Emit the handler specified by ENTRY. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_cleanup_handler (entry)
|
|
|
|
|
struct eh_entry *entry;
|
|
|
|
|
{
|
|
|
|
|
rtx prev;
|
|
|
|
|
rtx handler_insns;
|
1999-11-25 19:21:27 +00:00
|
|
|
|
|
|
|
|
|
/* Since the cleanup could itself contain try-catch blocks, we
|
|
|
|
|
squirrel away the current queue and replace it when we are done
|
|
|
|
|
with this function. */
|
1999-12-12 18:32:36 +00:00
|
|
|
|
push_ehqueue ();
|
1999-11-18 17:50:56 +00:00
|
|
|
|
|
|
|
|
|
/* Put these handler instructions in a sequence. */
|
|
|
|
|
do_pending_stack_adjust ();
|
|
|
|
|
start_sequence ();
|
|
|
|
|
|
|
|
|
|
/* Emit the label for the cleanup handler for this region, and
|
|
|
|
|
expand the code for the handler.
|
|
|
|
|
|
|
|
|
|
Note that a catch region is handled as a side-effect here; for a
|
|
|
|
|
try block, entry->finalization will contain integer_zero_node, so
|
|
|
|
|
no code will be generated in the expand_expr call below. But, the
|
|
|
|
|
label for the handler will still be emitted, so any code emitted
|
|
|
|
|
after this point will end up being the handler. */
|
|
|
|
|
|
|
|
|
|
receive_exception_label (entry->exception_handler_label);
|
|
|
|
|
|
|
|
|
|
/* register a handler for this cleanup region */
|
|
|
|
|
add_new_handler (find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)),
|
|
|
|
|
get_new_handler (entry->exception_handler_label, NULL));
|
|
|
|
|
|
|
|
|
|
/* And now generate the insns for the cleanup handler. */
|
|
|
|
|
expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
|
|
|
|
|
|
|
|
|
|
prev = get_last_insn ();
|
|
|
|
|
if (prev == NULL || GET_CODE (prev) != BARRIER)
|
|
|
|
|
/* Code to throw out to outer context when we fall off end of the
|
|
|
|
|
handler. We can't do this here for catch blocks, so it's done
|
|
|
|
|
in expand_end_all_catch instead. */
|
|
|
|
|
expand_rethrow (entry->outer_context);
|
|
|
|
|
|
|
|
|
|
/* Finish this sequence. */
|
|
|
|
|
do_pending_stack_adjust ();
|
|
|
|
|
handler_insns = get_insns ();
|
|
|
|
|
end_sequence ();
|
|
|
|
|
|
|
|
|
|
/* And add it to the CATCH_CLAUSES. */
|
2000-03-19 18:25:27 +00:00
|
|
|
|
push_to_full_sequence (catch_clauses, catch_clauses_last);
|
1999-11-18 17:50:56 +00:00
|
|
|
|
emit_insns (handler_insns);
|
2000-03-19 18:25:27 +00:00
|
|
|
|
end_full_sequence (&catch_clauses, &catch_clauses_last);
|
1999-11-25 19:21:27 +00:00
|
|
|
|
|
|
|
|
|
/* Now we've left the handler. */
|
1999-12-12 18:32:36 +00:00
|
|
|
|
pop_ehqueue ();
|
1999-11-18 17:50:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Generate RTL for the start of a group of catch clauses.
|
|
|
|
|
|
|
|
|
|
It is responsible for starting a new instruction sequence for the
|
|
|
|
|
instructions in the catch block, and expanding the handlers for the
|
|
|
|
|
internally-generated exception regions nested within the try block
|
1997-02-07 01:17:32 +00:00
|
|
|
|
corresponding to this catch block. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_start_all_catch ()
|
|
|
|
|
{
|
|
|
|
|
struct eh_entry *entry;
|
|
|
|
|
tree label;
|
1997-12-04 09:41:38 +00:00
|
|
|
|
rtx outer_context;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
if (! doing_eh (1))
|
|
|
|
|
return;
|
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
outer_context = ehstack.top->entry->outer_context;
|
1997-11-21 20:20:41 +00:00
|
|
|
|
|
1997-02-07 01:17:32 +00:00
|
|
|
|
/* End the try block. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
expand_eh_region_end (integer_zero_node);
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
emit_line_note (input_filename, lineno);
|
|
|
|
|
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* The label for the exception handling block that we will save.
|
1997-12-06 17:31:01 -07:00
|
|
|
|
This is Lresume in the documentation. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
expand_label (label);
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Push the label that points to where normal flow is resumed onto
|
1997-02-07 01:17:32 +00:00
|
|
|
|
the top of the label stack. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
push_label_entry (&caught_return_label_stack, NULL_RTX, label);
|
|
|
|
|
|
|
|
|
|
/* Start a new sequence for all the catch blocks. We will add this
|
1996-09-14 20:47:01 -04:00
|
|
|
|
to the global sequence catch_clauses when we have completed all
|
1996-07-23 20:20:04 +00:00
|
|
|
|
the handlers in this handler-seq. */
|
|
|
|
|
start_sequence ();
|
|
|
|
|
|
1999-11-25 19:21:27 +00:00
|
|
|
|
/* Throw away entries in the queue that we won't need anymore. We
|
|
|
|
|
need entries for regions that have ended but to which there might
|
|
|
|
|
still be gotos pending. */
|
1999-12-12 18:32:36 +00:00
|
|
|
|
for (entry = dequeue_eh_entry (ehqueue);
|
1999-11-18 17:50:56 +00:00
|
|
|
|
entry->finalization != integer_zero_node;
|
1999-12-12 18:32:36 +00:00
|
|
|
|
entry = dequeue_eh_entry (ehqueue))
|
1999-11-18 17:50:56 +00:00
|
|
|
|
free (entry);
|
1997-12-04 09:41:38 +00:00
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* At this point, all the cleanups are done, and the ehqueue now has
|
|
|
|
|
the current exception region at its head. We dequeue it, and put it
|
|
|
|
|
on the catch stack. */
|
1999-11-18 17:50:56 +00:00
|
|
|
|
push_entry (&catchstack, entry);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
/* If we are not doing setjmp/longjmp EH, because we are reordered
|
|
|
|
|
out of line, we arrange to rethrow in the outer context. We need to
|
|
|
|
|
do this because we are not physically within the region, if any, that
|
|
|
|
|
logically contains this catch block. */
|
|
|
|
|
if (! exceptions_via_longjmp)
|
|
|
|
|
{
|
|
|
|
|
expand_eh_region_start ();
|
|
|
|
|
ehstack.top->entry->outer_context = outer_context;
|
|
|
|
|
}
|
1998-06-23 07:10:29 +00:00
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Finish up the catch block. At this point all the insns for the
|
|
|
|
|
catch clauses have already been generated, so we only have to add
|
|
|
|
|
them to the catch_clauses list. We also want to make sure that if
|
|
|
|
|
we fall off the end of the catch clauses that we rethrow to the
|
1997-02-07 01:17:32 +00:00
|
|
|
|
outer EH region. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_end_all_catch ()
|
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
rtx new_catch_clause;
|
1998-06-09 13:28:26 +00:00
|
|
|
|
struct eh_entry *entry;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
if (! doing_eh (1))
|
|
|
|
|
return;
|
|
|
|
|
|
1998-06-09 13:28:26 +00:00
|
|
|
|
/* Dequeue the current catch clause region. */
|
|
|
|
|
entry = pop_eh_entry (&catchstack);
|
|
|
|
|
free (entry);
|
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
if (! exceptions_via_longjmp)
|
1997-12-04 19:52:49 +00:00
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
rtx outer_context = ehstack.top->entry->outer_context;
|
1997-12-04 19:52:49 +00:00
|
|
|
|
|
|
|
|
|
/* Finish the rethrow region. size_zero_node is just a NOP. */
|
|
|
|
|
expand_eh_region_end (size_zero_node);
|
1998-12-08 14:04:03 +00:00
|
|
|
|
/* New exceptions handling models will never have a fall through
|
|
|
|
|
of a catch clause */
|
|
|
|
|
if (!flag_new_exceptions)
|
|
|
|
|
expand_rethrow (outer_context);
|
1997-12-04 19:52:49 +00:00
|
|
|
|
}
|
1998-12-08 14:04:03 +00:00
|
|
|
|
else
|
|
|
|
|
expand_rethrow (NULL_RTX);
|
1997-12-04 19:52:49 +00:00
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
/* Code to throw out to outer context, if we fall off end of catch
|
|
|
|
|
handlers. This is rethrow (Lresume, same id, same obj) in the
|
|
|
|
|
documentation. We use Lresume because we know that it will throw
|
|
|
|
|
to the correct context.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
In other words, if the catch handler doesn't exit or return, we
|
|
|
|
|
do a "throw" (using the address of Lresume as the point being
|
|
|
|
|
thrown from) so that the outer EH region can then try to process
|
|
|
|
|
the exception. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* Now we have the complete catch sequence. */
|
|
|
|
|
new_catch_clause = get_insns ();
|
|
|
|
|
end_sequence ();
|
|
|
|
|
|
|
|
|
|
/* This level of catch blocks is done, so set up the successful
|
|
|
|
|
catch jump label for the next layer of catch blocks. */
|
|
|
|
|
pop_label_entry (&caught_return_label_stack);
|
1997-12-06 17:31:01 -07:00
|
|
|
|
pop_label_entry (&outer_context_label_stack);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* Add the new sequence of catches to the main one for this function. */
|
2000-03-19 18:25:27 +00:00
|
|
|
|
push_to_full_sequence (catch_clauses, catch_clauses_last);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
emit_insns (new_catch_clause);
|
2000-03-19 18:25:27 +00:00
|
|
|
|
end_full_sequence (&catch_clauses, &catch_clauses_last);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* Here we fall through into the continuation code. */
|
|
|
|
|
}
|
|
|
|
|
|
1997-12-04 09:41:38 +00:00
|
|
|
|
/* Rethrow from the outer context LABEL. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
expand_rethrow (label)
|
|
|
|
|
rtx label;
|
|
|
|
|
{
|
|
|
|
|
if (exceptions_via_longjmp)
|
|
|
|
|
emit_throw ();
|
|
|
|
|
else
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (flag_new_exceptions)
|
|
|
|
|
{
|
1999-09-02 10:29:25 -07:00
|
|
|
|
rtx insn;
|
1999-08-10 16:19:16 +00:00
|
|
|
|
int region;
|
|
|
|
|
if (label == NULL_RTX)
|
|
|
|
|
label = last_rethrow_symbol;
|
|
|
|
|
emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
|
|
|
|
|
region = find_func_region (eh_region_from_symbol (label));
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* If the region is -1, it doesn't exist yet. We shouldn't be
|
1999-11-18 17:50:56 +00:00
|
|
|
|
trying to rethrow there yet. */
|
|
|
|
|
if (region == -1)
|
|
|
|
|
abort ();
|
1999-08-10 16:19:16 +00:00
|
|
|
|
function_eh_regions[region].rethrow_ref = 1;
|
1999-02-25 15:45:42 -08:00
|
|
|
|
|
|
|
|
|
/* Search backwards for the actual call insn. */
|
1999-08-10 16:19:16 +00:00
|
|
|
|
insn = get_last_insn ();
|
1999-02-25 15:45:42 -08:00
|
|
|
|
while (GET_CODE (insn) != CALL_INSN)
|
|
|
|
|
insn = PREV_INSN (insn);
|
|
|
|
|
delete_insns_since (insn);
|
1999-08-10 16:19:16 +00:00
|
|
|
|
|
|
|
|
|
/* Mark the label/symbol on the call. */
|
|
|
|
|
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, label,
|
1999-02-25 15:45:42 -08:00
|
|
|
|
REG_NOTES (insn));
|
1999-08-10 16:19:16 +00:00
|
|
|
|
emit_barrier ();
|
1998-12-08 14:04:03 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
emit_jump (label);
|
1997-12-04 09:41:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-11-25 19:21:27 +00:00
|
|
|
|
/* Begin a region that will contain entries created with
|
|
|
|
|
add_partial_entry. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
begin_protect_partials ()
|
|
|
|
|
{
|
|
|
|
|
/* Put the entry on the function obstack. */
|
|
|
|
|
push_obstacks_nochange ();
|
|
|
|
|
resume_temporary_allocation ();
|
|
|
|
|
|
|
|
|
|
/* Push room for a new list. */
|
|
|
|
|
protect_list = tree_cons (NULL_TREE, NULL_TREE, protect_list);
|
|
|
|
|
|
|
|
|
|
/* We're done with the function obstack now. */
|
|
|
|
|
pop_obstacks ();
|
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* End all the pending exception regions on protect_list. The handlers
|
1997-04-23 20:11:52 +00:00
|
|
|
|
will be emitted when expand_leftover_cleanups is invoked. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
end_protect_partials ()
|
|
|
|
|
{
|
1999-11-25 19:21:27 +00:00
|
|
|
|
tree t;
|
|
|
|
|
|
|
|
|
|
/* For backwards compatibility, we allow callers to omit the call to
|
|
|
|
|
begin_protect_partials for the outermost region. So,
|
|
|
|
|
PROTECT_LIST may be NULL. */
|
|
|
|
|
if (!protect_list)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* End all the exception regions. */
|
|
|
|
|
for (t = TREE_VALUE (protect_list); t; t = TREE_CHAIN (t))
|
|
|
|
|
expand_eh_region_end (TREE_VALUE (t));
|
|
|
|
|
|
|
|
|
|
/* Pop the topmost entry. */
|
|
|
|
|
protect_list = TREE_CHAIN (protect_list);
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
/* Arrange for __terminate to be called if there is an unhandled throw
|
|
|
|
|
from within E. */
|
|
|
|
|
|
|
|
|
|
tree
|
|
|
|
|
protect_with_terminate (e)
|
|
|
|
|
tree e;
|
|
|
|
|
{
|
|
|
|
|
/* We only need to do this when using setjmp/longjmp EH and the
|
|
|
|
|
language requires it, as otherwise we protect all of the handlers
|
|
|
|
|
at once, if we need to. */
|
|
|
|
|
if (exceptions_via_longjmp && protect_cleanup_actions_with_terminate)
|
|
|
|
|
{
|
|
|
|
|
tree handler, result;
|
|
|
|
|
|
|
|
|
|
/* All cleanups must be on the function_obstack. */
|
|
|
|
|
push_obstacks_nochange ();
|
|
|
|
|
resume_temporary_allocation ();
|
|
|
|
|
|
|
|
|
|
handler = make_node (RTL_EXPR);
|
|
|
|
|
TREE_TYPE (handler) = void_type_node;
|
|
|
|
|
RTL_EXPR_RTL (handler) = const0_rtx;
|
|
|
|
|
TREE_SIDE_EFFECTS (handler) = 1;
|
2000-03-05 19:34:29 +00:00
|
|
|
|
start_sequence_for_rtl_expr (handler);
|
1997-04-23 20:11:52 +00:00
|
|
|
|
|
|
|
|
|
emit_library_call (terminate_libfunc, 0, VOIDmode, 0);
|
|
|
|
|
emit_barrier ();
|
|
|
|
|
|
|
|
|
|
RTL_EXPR_SEQUENCE (handler) = get_insns ();
|
|
|
|
|
end_sequence ();
|
|
|
|
|
|
|
|
|
|
result = build (TRY_CATCH_EXPR, TREE_TYPE (e), e, handler);
|
|
|
|
|
TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
|
|
|
|
|
TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
|
|
|
|
|
TREE_READONLY (result) = TREE_READONLY (e);
|
|
|
|
|
|
|
|
|
|
pop_obstacks ();
|
|
|
|
|
|
|
|
|
|
e = result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return e;
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* The exception table that we build that is used for looking up and
|
1996-09-14 20:47:01 -04:00
|
|
|
|
dispatching exceptions, the current number of entries, and its
|
|
|
|
|
maximum size before we have to extend it.
|
|
|
|
|
|
|
|
|
|
The number in eh_table is the code label number of the exception
|
1997-04-23 20:11:52 +00:00
|
|
|
|
handler for the region. This is added by add_eh_table_entry and
|
|
|
|
|
used by output_exception_table_entry. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
static int *eh_table = NULL;
|
|
|
|
|
static int eh_table_size = 0;
|
|
|
|
|
static int eh_table_max_size = 0;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* Note the need for an exception table entry for region N. If we
|
1996-09-14 20:47:01 -04:00
|
|
|
|
don't need to output an explicit exception table, avoid all of the
|
|
|
|
|
extra work.
|
|
|
|
|
|
|
|
|
|
Called from final_scan_insn when a NOTE_INSN_EH_REGION_BEG is seen.
|
1998-05-14 13:39:15 +00:00
|
|
|
|
(Or NOTE_INSN_EH_REGION_END sometimes)
|
1999-09-14 23:51:34 +00:00
|
|
|
|
N is the NOTE_EH_HANDLER of the note, which comes from the code
|
1997-02-07 01:17:32 +00:00
|
|
|
|
label number of the exception handler for the region. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
add_eh_table_entry (n)
|
|
|
|
|
int n;
|
|
|
|
|
{
|
|
|
|
|
#ifndef OMIT_EH_TABLE
|
|
|
|
|
if (eh_table_size >= eh_table_max_size)
|
|
|
|
|
{
|
|
|
|
|
if (eh_table)
|
|
|
|
|
{
|
|
|
|
|
eh_table_max_size += eh_table_max_size>>1;
|
|
|
|
|
|
|
|
|
|
if (eh_table_max_size < 0)
|
|
|
|
|
abort ();
|
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
eh_table = (int *) xrealloc (eh_table,
|
|
|
|
|
eh_table_max_size * sizeof (int));
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
eh_table_max_size = 252;
|
|
|
|
|
eh_table = (int *) xmalloc (eh_table_max_size * sizeof (int));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
eh_table[eh_table_size++] = n;
|
2000-03-29 08:22:21 +00:00
|
|
|
|
|
|
|
|
|
if (flag_new_exceptions)
|
|
|
|
|
{
|
|
|
|
|
/* We will output the exception table late in the compilation. That
|
|
|
|
|
references type_info objects which should have already been output
|
|
|
|
|
by that time. We explicitly mark those objects as being
|
|
|
|
|
referenced now so we know to emit them. */
|
|
|
|
|
struct handler_info *handler = get_first_handler (n);
|
|
|
|
|
|
|
|
|
|
for (; handler; handler = handler->next)
|
|
|
|
|
if (handler->type_info && handler->type_info != CATCH_ALL_TYPE)
|
|
|
|
|
{
|
|
|
|
|
tree tinfo = (tree)handler->type_info;
|
|
|
|
|
|
|
|
|
|
tinfo = TREE_OPERAND (tinfo, 0);
|
|
|
|
|
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Return a non-zero value if we need to output an exception table.
|
|
|
|
|
|
|
|
|
|
On some platforms, we don't have to output a table explicitly.
|
|
|
|
|
This routine doesn't mean we don't have one. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
exception_table_p ()
|
|
|
|
|
{
|
|
|
|
|
if (eh_table)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-06 15:09:07 -06:00
|
|
|
|
/* Output the entry of the exception table corresponding to the
|
1996-09-14 20:47:01 -04:00
|
|
|
|
exception region numbered N to file FILE.
|
|
|
|
|
|
|
|
|
|
N is the code label number corresponding to the handler of the
|
1997-02-07 01:17:32 +00:00
|
|
|
|
region. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
output_exception_table_entry (file, n)
|
|
|
|
|
FILE *file;
|
|
|
|
|
int n;
|
|
|
|
|
{
|
|
|
|
|
char buf[256];
|
|
|
|
|
rtx sym;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
struct handler_info *handler = get_first_handler (n);
|
|
|
|
|
int index = find_func_region (n);
|
|
|
|
|
rtx rethrow;
|
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* Form and emit the rethrow label, if needed */
|
|
|
|
|
if (flag_new_exceptions
|
|
|
|
|
&& (handler || function_eh_regions[index].rethrow_ref))
|
|
|
|
|
rethrow = function_eh_regions[index].rethrow_label;
|
|
|
|
|
else
|
|
|
|
|
rethrow = NULL_RTX;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
for ( ; handler != NULL || rethrow != NULL_RTX; handler = handler->next)
|
1998-05-14 13:39:15 +00:00
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
/* rethrow label should indicate the LAST entry for a region */
|
|
|
|
|
if (rethrow != NULL_RTX && (handler == NULL || handler->next == NULL))
|
|
|
|
|
{
|
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", n);
|
|
|
|
|
assemble_label(buf);
|
|
|
|
|
rethrow = NULL_RTX;
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
|
|
|
|
|
sym = gen_rtx_SYMBOL_REF (Pmode, buf);
|
|
|
|
|
assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LEHE", n);
|
|
|
|
|
sym = gen_rtx_SYMBOL_REF (Pmode, buf);
|
|
|
|
|
assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (handler == NULL)
|
|
|
|
|
assemble_integer (GEN_INT (0), POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
else
|
1998-12-09 06:15:20 +00:00
|
|
|
|
{
|
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "L", handler->handler_number);
|
|
|
|
|
sym = gen_rtx_SYMBOL_REF (Pmode, buf);
|
|
|
|
|
assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1998-06-08 12:43:28 +00:00
|
|
|
|
if (flag_new_exceptions)
|
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (handler == NULL || handler->type_info == NULL)
|
1998-06-08 12:43:28 +00:00
|
|
|
|
assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
else
|
1998-06-25 14:11:54 +00:00
|
|
|
|
if (handler->type_info == CATCH_ALL_TYPE)
|
|
|
|
|
assemble_integer (GEN_INT (CATCH_ALL_TYPE),
|
|
|
|
|
POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
else
|
|
|
|
|
output_constant ((tree)(handler->type_info),
|
1998-05-14 13:39:15 +00:00
|
|
|
|
POINTER_SIZE / BITS_PER_UNIT);
|
1998-06-08 12:43:28 +00:00
|
|
|
|
}
|
1998-05-14 13:39:15 +00:00
|
|
|
|
putc ('\n', file); /* blank line */
|
1998-09-15 11:20:52 +00:00
|
|
|
|
/* We only output the first label under the old scheme */
|
1998-12-08 14:04:03 +00:00
|
|
|
|
if (! flag_new_exceptions || handler == NULL)
|
1998-09-15 11:20:52 +00:00
|
|
|
|
break;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-02-07 01:17:32 +00:00
|
|
|
|
/* Output the exception table if we have and need one. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
static short language_code = 0;
|
|
|
|
|
static short version_code = 0;
|
|
|
|
|
|
|
|
|
|
/* This routine will set the language code for exceptions. */
|
1998-08-17 09:08:32 +00:00
|
|
|
|
void
|
|
|
|
|
set_exception_lang_code (code)
|
|
|
|
|
int code;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
{
|
|
|
|
|
language_code = code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This routine will set the language version code for exceptions. */
|
1998-08-17 09:08:32 +00:00
|
|
|
|
void
|
|
|
|
|
set_exception_version_code (code)
|
1998-12-04 01:26:15 +00:00
|
|
|
|
int code;
|
1998-05-14 13:39:15 +00:00
|
|
|
|
{
|
|
|
|
|
version_code = code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
void
|
|
|
|
|
output_exception_table ()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
1998-12-08 14:04:03 +00:00
|
|
|
|
char buf[256];
|
1996-07-23 20:20:04 +00:00
|
|
|
|
extern FILE *asm_out_file;
|
|
|
|
|
|
1997-09-15 22:07:50 -04:00
|
|
|
|
if (! doing_eh (0) || ! eh_table)
|
1996-07-23 20:20:04 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
exception_section ();
|
|
|
|
|
|
|
|
|
|
/* Beginning marker for table. */
|
|
|
|
|
assemble_align (GET_MODE_ALIGNMENT (ptr_mode));
|
|
|
|
|
assemble_label ("__EXCEPTION_TABLE__");
|
|
|
|
|
|
1998-06-08 12:43:28 +00:00
|
|
|
|
if (flag_new_exceptions)
|
|
|
|
|
{
|
|
|
|
|
assemble_integer (GEN_INT (NEW_EH_RUNTIME),
|
|
|
|
|
POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
assemble_integer (GEN_INT (language_code), 2 , 1);
|
|
|
|
|
assemble_integer (GEN_INT (version_code), 2 , 1);
|
|
|
|
|
|
|
|
|
|
/* Add enough padding to make sure table aligns on a pointer boundry. */
|
|
|
|
|
i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4;
|
|
|
|
|
for ( ; i < 0; i = i + GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT)
|
|
|
|
|
;
|
|
|
|
|
if (i != 0)
|
|
|
|
|
assemble_integer (const0_rtx, i , 1);
|
1998-12-08 14:04:03 +00:00
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* Generate the label for offset calculations on rethrows. */
|
1998-12-08 14:04:03 +00:00
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", 0);
|
|
|
|
|
assemble_label(buf);
|
1998-06-08 12:43:28 +00:00
|
|
|
|
}
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
for (i = 0; i < eh_table_size; ++i)
|
|
|
|
|
output_exception_table_entry (asm_out_file, eh_table[i]);
|
|
|
|
|
|
|
|
|
|
free (eh_table);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
clear_function_eh_region ();
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* Ending marker for table. */
|
1998-12-08 14:04:03 +00:00
|
|
|
|
/* Generate the label for end of table. */
|
|
|
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", CODE_LABEL_NUMBER (final_rethrow));
|
|
|
|
|
assemble_label(buf);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
|
1998-06-08 12:43:28 +00:00
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* For binary compatibility, the old __throw checked the second
|
1998-05-14 13:39:15 +00:00
|
|
|
|
position for a -1, so we should output at least 2 -1's */
|
1998-06-08 12:43:28 +00:00
|
|
|
|
if (! flag_new_exceptions)
|
|
|
|
|
assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
putc ('\n', asm_out_file); /* blank line */
|
|
|
|
|
}
|
|
|
|
|
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
/* Emit code to get EH context.
|
|
|
|
|
|
|
|
|
|
We have to scan thru the code to find possible EH context registers.
|
|
|
|
|
Inlined functions may use it too, and thus we'll have to be able
|
|
|
|
|
to change them too.
|
|
|
|
|
|
|
|
|
|
This is done only if using exceptions_via_longjmp. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
emit_eh_context ()
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
rtx ehc = 0;
|
|
|
|
|
|
|
|
|
|
if (! doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
|
|
|
|
if (GET_CODE (insn) == INSN
|
|
|
|
|
&& GET_CODE (PATTERN (insn)) == USE)
|
|
|
|
|
{
|
|
|
|
|
rtx reg = find_reg_note (insn, REG_EH_CONTEXT, 0);
|
|
|
|
|
if (reg)
|
|
|
|
|
{
|
|
|
|
|
rtx insns;
|
|
|
|
|
|
1997-12-12 09:23:52 +00:00
|
|
|
|
start_sequence ();
|
|
|
|
|
|
1997-12-14 22:58:03 -05:00
|
|
|
|
/* If this is the first use insn, emit the call here. This
|
|
|
|
|
will always be at the top of our function, because if
|
|
|
|
|
expand_inline_function notices a REG_EH_CONTEXT note, it
|
|
|
|
|
adds a use insn to this function as well. */
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
if (ehc == 0)
|
1997-12-12 07:35:04 +00:00
|
|
|
|
ehc = call_get_eh_context ();
|
[multiple changes]
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads.
* integrate.c (expand_inline_function): If the inline fn uses eh
context, make sure that the current fn has one.
* toplev.c (rest_of_compilation): Call emit_eh_context.
* except.c (use_eh_context): New fn.
(get_eh_context_once): New fn.
(call_get_eh_context): New fn.
(emit_eh_context): New fn.
(get_eh_context): Call either get_eh_context_once or
call_get_eh_context, depending on what we have.
(get_dynamic_handler_chain): Call get_eh_context_once.
* except.h: Prototypes for fns above.
* optabs.c (get_eh_context_libfunc): Removed.
(init_optabs): Don't initialize it.
* expr.h (get_eh_context_libfunc): Removed.
* rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
* config/pa/pa.h (CPP_SPEC): Support for -threads.
* config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
* config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
New multilib for -threads.
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc-thr.h: New file.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c: Include libgcc-thr.h.
(new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_specific, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
(longjmp): Move the declaration inside
#ifdef DONT_USE_BUILTIN_SETJMP.
* frame.c: Include libgcc-thr.h.
(object_mutex): Mutex to protect the object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
* except.h (get_eh_context): Declare.
* except.c (current_function_ehc): Define.
(current_function_dhc, current_function_dcc): Removed.
(get_eh_context): New function.
(get_dynamic_handler_chain): Use get_eh_context.
(get_saved_pc_ref): Ditto.
(get_dynamic_cleanup_chain): Removed references to
current_function_dcc.
(save_eh_status, restore_eh_status): Save and restore
current_function_ehc instead.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
* function.h (struct function): Replaced dhc and dcc with ehc.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
cp/:
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
From-SVN: r17052
1997-12-12 04:53:20 +00:00
|
|
|
|
|
|
|
|
|
emit_move_insn (XEXP (reg, 0), ehc);
|
|
|
|
|
insns = get_insns ();
|
|
|
|
|
end_sequence ();
|
|
|
|
|
|
|
|
|
|
emit_insns_before (insns, insn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-11 16:20:31 +02:00
|
|
|
|
/* Scan the insn chain F and build a list of handler labels. The
|
|
|
|
|
resulting list is placed in the global variable exception_handler_labels. */
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
2000-05-11 16:20:31 +02:00
|
|
|
|
static void
|
|
|
|
|
find_exception_handler_labels_1 (f)
|
|
|
|
|
rtx f;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* For each start of a region, add its label to the list. */
|
|
|
|
|
|
2000-05-11 16:20:31 +02:00
|
|
|
|
for (insn = f; insn; insn = NEXT_INSN (insn))
|
1996-07-23 20:20:04 +00:00
|
|
|
|
{
|
1998-05-14 13:39:15 +00:00
|
|
|
|
struct handler_info* ptr;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
if (GET_CODE (insn) == NOTE
|
|
|
|
|
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
|
|
|
|
|
{
|
1999-09-14 23:51:34 +00:00
|
|
|
|
ptr = get_first_handler (NOTE_EH_HANDLER (insn));
|
1998-05-14 13:39:15 +00:00
|
|
|
|
for ( ; ptr; ptr = ptr->next)
|
|
|
|
|
{
|
|
|
|
|
/* make sure label isn't in the list already */
|
|
|
|
|
rtx x;
|
|
|
|
|
for (x = exception_handler_labels; x; x = XEXP (x, 1))
|
|
|
|
|
if (XEXP (x, 0) == ptr->handler_label)
|
|
|
|
|
break;
|
|
|
|
|
if (! x)
|
|
|
|
|
exception_handler_labels = gen_rtx_EXPR_LIST (VOIDmode,
|
|
|
|
|
ptr->handler_label, exception_handler_labels);
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
2000-05-11 16:20:31 +02:00
|
|
|
|
else if (GET_CODE (insn) == CALL_INSN
|
|
|
|
|
&& GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
|
|
|
|
|
{
|
|
|
|
|
find_exception_handler_labels_1 (XEXP (PATTERN (insn), 0));
|
|
|
|
|
find_exception_handler_labels_1 (XEXP (PATTERN (insn), 1));
|
|
|
|
|
find_exception_handler_labels_1 (XEXP (PATTERN (insn), 2));
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
1998-05-14 13:39:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-05-11 16:20:31 +02:00
|
|
|
|
/* Scan the current insns and build a list of handler labels. The
|
|
|
|
|
resulting list is placed in the global variable exception_handler_labels.
|
|
|
|
|
|
|
|
|
|
It is called after the last exception handling region is added to
|
|
|
|
|
the current function (when the rtl is almost all built for the
|
|
|
|
|
current function) and before the jump optimization pass. */
|
|
|
|
|
void
|
|
|
|
|
find_exception_handler_labels ()
|
|
|
|
|
{
|
|
|
|
|
exception_handler_labels = NULL_RTX;
|
|
|
|
|
|
|
|
|
|
/* If we aren't doing exception handling, there isn't much to check. */
|
|
|
|
|
if (! doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
find_exception_handler_labels_1 (get_insns ());
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* Return a value of 1 if the parameter label number is an exception handler
|
|
|
|
|
label. Return 0 otherwise. */
|
1997-09-30 18:25:09 +00:00
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
int
|
|
|
|
|
is_exception_handler_label (lab)
|
|
|
|
|
int lab;
|
|
|
|
|
{
|
|
|
|
|
rtx x;
|
|
|
|
|
for (x = exception_handler_labels ; x ; x = XEXP (x, 1))
|
|
|
|
|
if (lab == CODE_LABEL_NUMBER (XEXP (x, 0)))
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Perform sanity checking on the exception_handler_labels list.
|
|
|
|
|
|
|
|
|
|
Can be called after find_exception_handler_labels is called to
|
|
|
|
|
build the list of exception handlers for the current function and
|
|
|
|
|
before we finish processing the current function. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
check_exception_handler_labels ()
|
|
|
|
|
{
|
1998-05-14 13:39:15 +00:00
|
|
|
|
rtx insn, insn2;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* If we aren't doing exception handling, there isn't much to check. */
|
|
|
|
|
if (! doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* Make sure there is no more than 1 copy of a label */
|
|
|
|
|
for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
|
1996-07-23 20:20:04 +00:00
|
|
|
|
{
|
1998-05-14 13:39:15 +00:00
|
|
|
|
int count = 0;
|
|
|
|
|
for (insn2 = exception_handler_labels; insn2; insn2 = XEXP (insn2, 1))
|
|
|
|
|
if (XEXP (insn, 0) == XEXP (insn2, 0))
|
|
|
|
|
count++;
|
|
|
|
|
if (count != 1)
|
|
|
|
|
warning ("Counted %d copies of EH region %d in list.\n", count,
|
|
|
|
|
CODE_LABEL_NUMBER (insn));
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
|
|
|
|
|
/* Mark the children of NODE for GC. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mark_eh_node (node)
|
|
|
|
|
struct eh_node *node;
|
|
|
|
|
{
|
|
|
|
|
while (node)
|
|
|
|
|
{
|
|
|
|
|
if (node->entry)
|
|
|
|
|
{
|
|
|
|
|
ggc_mark_rtx (node->entry->outer_context);
|
|
|
|
|
ggc_mark_rtx (node->entry->exception_handler_label);
|
|
|
|
|
ggc_mark_tree (node->entry->finalization);
|
1999-09-07 15:20:58 +00:00
|
|
|
|
ggc_mark_rtx (node->entry->false_label);
|
|
|
|
|
ggc_mark_rtx (node->entry->rethrow_label);
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
}
|
|
|
|
|
node = node ->chain;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mark S for GC. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mark_eh_stack (s)
|
|
|
|
|
struct eh_stack *s;
|
|
|
|
|
{
|
|
|
|
|
if (s)
|
|
|
|
|
mark_eh_node (s->top);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mark Q for GC. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mark_eh_queue (q)
|
|
|
|
|
struct eh_queue *q;
|
|
|
|
|
{
|
1999-12-12 18:32:36 +00:00
|
|
|
|
while (q)
|
|
|
|
|
{
|
|
|
|
|
mark_eh_node (q->head);
|
|
|
|
|
q = q->next;
|
|
|
|
|
}
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mark NODE for GC. A label_node contains a union containing either
|
|
|
|
|
a tree or an rtx. This label_node will contain a tree. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mark_tree_label_node (node)
|
|
|
|
|
struct label_node *node;
|
|
|
|
|
{
|
|
|
|
|
while (node)
|
|
|
|
|
{
|
|
|
|
|
ggc_mark_tree (node->u.tlabel);
|
|
|
|
|
node = node->chain;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mark EH for GC. */
|
|
|
|
|
|
|
|
|
|
void
|
1999-09-15 18:12:25 -07:00
|
|
|
|
mark_eh_status (eh)
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
struct eh_status *eh;
|
|
|
|
|
{
|
1999-09-15 18:12:25 -07:00
|
|
|
|
if (eh == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
mark_eh_stack (&eh->x_ehstack);
|
1999-09-07 10:10:01 +00:00
|
|
|
|
mark_eh_stack (&eh->x_catchstack);
|
1999-12-12 18:32:36 +00:00
|
|
|
|
mark_eh_queue (eh->x_ehqueue);
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
ggc_mark_rtx (eh->x_catch_clauses);
|
|
|
|
|
|
|
|
|
|
lang_mark_false_label_stack (eh->x_false_label_stack);
|
|
|
|
|
mark_tree_label_node (eh->x_caught_return_label_stack);
|
|
|
|
|
|
|
|
|
|
ggc_mark_tree (eh->x_protect_list);
|
|
|
|
|
ggc_mark_rtx (eh->ehc);
|
1999-09-07 10:10:01 +00:00
|
|
|
|
ggc_mark_rtx (eh->x_eh_return_stub_label);
|
Makefile.in (tree.o): Depend on ggc.h.
* Makefile.in (tree.o): Depend on ggc.h.
(varasm.o): Likewise.
(function.o): Likewise.
(stmt.o): Likewise.
(except.o): Likewise.
(optabs.o): Likewise.
(emit-rtl.o): Likewise.
* emit-rtl.c: Include ggc.h.
(sequence_element_free_list): Remove, and all references.
(mark_sequence): New functions.
(mark_emit_state): New function.
* except.c: Include ggc.h.
(mark_eh_node, mark_eh_stack, mark_eh_queue): New functions.
(mark_tree_label_node): New functions.
(mark_eh_state): New function.
* function.c: Include ggc.h.
(mark_temp_slot, mark_function_chain): New functions.
(mark_function_state): New function.
(init_function_once): New function.
* function.h (init_function_once): New function.
* ggc-callbacks.c (lang_mark_false_label_stack): New function.
* ggc.h (label_node): Declare.
(eh_status, emit_status, stmt_status, varasm_status): Likewise.
(lang_mark_false_label_stack): New function.
(mark_temp_slot): Remove declaration.
(mark_function_chain): Likewise.
(mark_eh_state): Adjust prototype.
(mark_stmt_state, mark_emit_state, mark_varasm_state, mark_optab):
Likewise.
* optabs.c: Include ggc.h.
(mark_optab): New function.
(init_optabs): Add gc roots.
* stmt.c: Include ggc.h.
(mark_cond_nesting, mark_loop_nesting): New functions.
(mark_block_nesting, mark_case_nesting, mark_goto_fixup): Likewise.
(mark_stmt_state): New function.
* toplev.c (compile_file): Call init_function_once.
* tree.c: Include ggc.h.
(type_hash): Move declaration earlier in file.
(TYPE_HASH_SIZE, type_hash_table): Likewise.
(init_obstacks): Add gc roots.
(mark_type_hash): New function.
* varasm.c: Include ggc.h.
(mark_pool_constant): New function.
(mark_varasm_state): New function.
Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>
From-SVN: r29119
1999-09-04 19:41:35 -07:00
|
|
|
|
}
|
|
|
|
|
|
1999-09-07 15:20:58 +00:00
|
|
|
|
/* Mark ARG (which is really a struct func_eh_entry**) for GC. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mark_func_eh_entry (arg)
|
|
|
|
|
void *arg;
|
|
|
|
|
{
|
|
|
|
|
struct func_eh_entry *fee;
|
|
|
|
|
struct handler_info *h;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
fee = *((struct func_eh_entry **) arg);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < current_func_eh_entry; ++i)
|
|
|
|
|
{
|
|
|
|
|
ggc_mark_rtx (fee->rethrow_label);
|
|
|
|
|
for (h = fee->handlers; h; h = h->next)
|
|
|
|
|
{
|
|
|
|
|
ggc_mark_rtx (h->handler_label);
|
|
|
|
|
if (h->type_info != CATCH_ALL_TYPE)
|
|
|
|
|
ggc_mark_tree ((tree) h->type_info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Skip to the next entry in the array. */
|
|
|
|
|
++fee;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
/* This group of functions initializes the exception handling data
|
|
|
|
|
structures at the start of the compilation, initializes the data
|
1996-09-14 20:47:01 -04:00
|
|
|
|
structures at the start of a function, and saves and restores the
|
1996-07-23 20:20:04 +00:00
|
|
|
|
exception handling data structures for the start/end of a nested
|
|
|
|
|
function. */
|
|
|
|
|
|
|
|
|
|
/* Toplevel initialization for EH things. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_eh ()
|
|
|
|
|
{
|
1998-12-08 14:04:03 +00:00
|
|
|
|
first_rethrow_symbol = create_rethrow_ref (0);
|
|
|
|
|
final_rethrow = gen_exception_label ();
|
|
|
|
|
last_rethrow_symbol = create_rethrow_ref (CODE_LABEL_NUMBER (final_rethrow));
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1999-09-07 15:20:58 +00:00
|
|
|
|
ggc_add_rtx_root (&exception_handler_labels, 1);
|
|
|
|
|
ggc_add_rtx_root (&eh_return_context, 1);
|
|
|
|
|
ggc_add_rtx_root (&eh_return_stack_adjust, 1);
|
|
|
|
|
ggc_add_rtx_root (&eh_return_handler, 1);
|
|
|
|
|
ggc_add_rtx_root (&first_rethrow_symbol, 1);
|
|
|
|
|
ggc_add_rtx_root (&final_rethrow, 1);
|
|
|
|
|
ggc_add_rtx_root (&last_rethrow_symbol, 1);
|
|
|
|
|
ggc_add_root (&function_eh_regions, 1, sizeof (function_eh_regions),
|
|
|
|
|
mark_func_eh_entry);
|
|
|
|
|
}
|
|
|
|
|
|
1997-02-07 01:17:32 +00:00
|
|
|
|
/* Initialize the per-function EH information. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_eh_for_function ()
|
|
|
|
|
{
|
1999-12-20 13:18:17 +00:00
|
|
|
|
cfun->eh = (struct eh_status *) xcalloc (1, sizeof (struct eh_status));
|
1999-12-12 18:32:36 +00:00
|
|
|
|
ehqueue = (struct eh_queue *) xcalloc (1, sizeof (struct eh_queue));
|
1999-11-25 20:06:25 +00:00
|
|
|
|
eh_return_context = NULL_RTX;
|
|
|
|
|
eh_return_stack_adjust = NULL_RTX;
|
|
|
|
|
eh_return_handler = NULL_RTX;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
1999-09-15 18:12:25 -07:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
free_eh_status (f)
|
|
|
|
|
struct function *f;
|
|
|
|
|
{
|
1999-12-12 18:32:36 +00:00
|
|
|
|
free (f->eh->x_ehqueue);
|
1999-09-15 18:12:25 -07:00
|
|
|
|
free (f->eh);
|
|
|
|
|
f->eh = NULL;
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
/* This section is for the exception handling specific optimization
|
|
|
|
|
pass. First are the internal routines, and then the main
|
|
|
|
|
optimization pass. */
|
|
|
|
|
|
|
|
|
|
/* Determine if the given INSN can throw an exception. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
can_throw (insn)
|
|
|
|
|
rtx insn;
|
|
|
|
|
{
|
2000-03-09 14:01:47 -05:00
|
|
|
|
if (GET_CODE (insn) == INSN
|
|
|
|
|
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
|
|
|
|
|
insn = XVECEXP (PATTERN (insn), 0, 0);
|
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
/* Calls can always potentially throw exceptions, unless they have
|
|
|
|
|
a REG_EH_REGION note with a value of 0 or less. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
if (GET_CODE (insn) == CALL_INSN)
|
1999-08-10 16:19:16 +00:00
|
|
|
|
{
|
|
|
|
|
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
|
2000-03-10 11:21:06 -08:00
|
|
|
|
if (!note || INTVAL (XEXP (note, 0)) > 0)
|
1999-08-10 16:19:16 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
1997-04-23 20:11:52 +00:00
|
|
|
|
if (asynchronous_exceptions)
|
|
|
|
|
{
|
|
|
|
|
/* If we wanted asynchronous exceptions, then everything but NOTEs
|
|
|
|
|
and CODE_LABELs could throw. */
|
|
|
|
|
if (GET_CODE (insn) != NOTE && GET_CODE (insn) != CODE_LABEL)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-09 14:01:47 -05:00
|
|
|
|
/* Return nonzero if nothing in this function can throw. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nothrow_function_p ()
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
|
2000-03-09 20:37:06 +00:00
|
|
|
|
if (! flag_exceptions)
|
|
|
|
|
return 1;
|
|
|
|
|
|
2000-03-09 14:01:47 -05:00
|
|
|
|
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
|
|
|
|
if (can_throw (insn))
|
|
|
|
|
return 0;
|
|
|
|
|
for (insn = current_function_epilogue_delay_list; insn;
|
|
|
|
|
insn = XEXP (insn, 1))
|
|
|
|
|
if (can_throw (insn))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Scan a exception region looking for the matching end and then
|
|
|
|
|
remove it if possible. INSN is the start of the region, N is the
|
|
|
|
|
region number, and DELETE_OUTER is to note if anything in this
|
|
|
|
|
region can throw.
|
|
|
|
|
|
|
|
|
|
Regions are removed if they cannot possibly catch an exception.
|
1997-04-23 20:11:52 +00:00
|
|
|
|
This is determined by invoking can_throw on each insn within the
|
1996-09-14 20:47:01 -04:00
|
|
|
|
region; if can_throw returns true for any of the instructions, the
|
|
|
|
|
region can catch an exception, since there is an insn within the
|
|
|
|
|
region that is capable of throwing an exception.
|
|
|
|
|
|
|
|
|
|
Returns the NOTE_INSN_EH_REGION_END corresponding to this region, or
|
1997-04-23 20:11:52 +00:00
|
|
|
|
calls abort if it can't find one.
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
|
|
|
|
Can abort if INSN is not a NOTE_INSN_EH_REGION_BEGIN, or if N doesn't
|
1997-02-07 01:17:32 +00:00
|
|
|
|
correspond to the region number, or if DELETE_OUTER is NULL. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
static rtx
|
|
|
|
|
scan_region (insn, n, delete_outer)
|
|
|
|
|
rtx insn;
|
|
|
|
|
int n;
|
|
|
|
|
int *delete_outer;
|
|
|
|
|
{
|
|
|
|
|
rtx start = insn;
|
|
|
|
|
|
|
|
|
|
/* Assume we can delete the region. */
|
|
|
|
|
int delete = 1;
|
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* Can't delete something which is rethrown from. */
|
1999-08-10 16:19:16 +00:00
|
|
|
|
if (rethrow_used (n))
|
1998-12-08 14:04:03 +00:00
|
|
|
|
delete = 0;
|
|
|
|
|
|
1997-11-12 17:07:46 +00:00
|
|
|
|
if (insn == NULL_RTX
|
|
|
|
|
|| GET_CODE (insn) != NOTE
|
|
|
|
|
|| NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
|
1999-09-14 23:51:34 +00:00
|
|
|
|
|| NOTE_EH_HANDLER (insn) != n
|
1997-11-12 17:07:46 +00:00
|
|
|
|
|| delete_outer == NULL)
|
|
|
|
|
abort ();
|
1996-09-14 20:47:01 -04:00
|
|
|
|
|
1996-07-23 20:20:04 +00:00
|
|
|
|
insn = NEXT_INSN (insn);
|
|
|
|
|
|
|
|
|
|
/* Look for the matching end. */
|
|
|
|
|
while (! (GET_CODE (insn) == NOTE
|
|
|
|
|
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
|
|
|
|
|
{
|
|
|
|
|
/* If anything can throw, we can't remove the region. */
|
|
|
|
|
if (delete && can_throw (insn))
|
|
|
|
|
{
|
|
|
|
|
delete = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Watch out for and handle nested regions. */
|
|
|
|
|
if (GET_CODE (insn) == NOTE
|
|
|
|
|
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
|
|
|
|
|
{
|
1999-09-14 23:51:34 +00:00
|
|
|
|
insn = scan_region (insn, NOTE_EH_HANDLER (insn), &delete);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
insn = NEXT_INSN (insn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The _BEG/_END NOTEs must match and nest. */
|
1999-09-14 23:51:34 +00:00
|
|
|
|
if (NOTE_EH_HANDLER (insn) != n)
|
1996-07-23 20:20:04 +00:00
|
|
|
|
abort ();
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* If anything in this exception region can throw, we can throw. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
if (! delete)
|
|
|
|
|
*delete_outer = 0;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Delete the start and end of the region. */
|
|
|
|
|
delete_insn (start);
|
|
|
|
|
delete_insn (insn);
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
/* We no longer removed labels here, since flow will now remove any
|
|
|
|
|
handler which cannot be called any more. */
|
|
|
|
|
|
|
|
|
|
#if 0
|
1996-07-23 20:20:04 +00:00
|
|
|
|
/* Only do this part if we have built the exception handler
|
|
|
|
|
labels. */
|
|
|
|
|
if (exception_handler_labels)
|
|
|
|
|
{
|
|
|
|
|
rtx x, *prev = &exception_handler_labels;
|
|
|
|
|
|
|
|
|
|
/* Find it in the list of handlers. */
|
|
|
|
|
for (x = exception_handler_labels; x; x = XEXP (x, 1))
|
|
|
|
|
{
|
|
|
|
|
rtx label = XEXP (x, 0);
|
|
|
|
|
if (CODE_LABEL_NUMBER (label) == n)
|
|
|
|
|
{
|
|
|
|
|
/* If we are the last reference to the handler,
|
|
|
|
|
delete it. */
|
|
|
|
|
if (--LABEL_NUSES (label) == 0)
|
|
|
|
|
delete_insn (label);
|
|
|
|
|
|
|
|
|
|
if (optimize)
|
|
|
|
|
{
|
|
|
|
|
/* Remove it from the list of exception handler
|
|
|
|
|
labels, if we are optimizing. If we are not, then
|
|
|
|
|
leave it in the list, as we are not really going to
|
|
|
|
|
remove the region. */
|
|
|
|
|
*prev = XEXP (x, 1);
|
|
|
|
|
XEXP (x, 1) = 0;
|
|
|
|
|
XEXP (x, 0) = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
prev = &XEXP (x, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-05-14 13:39:15 +00:00
|
|
|
|
#endif
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
return insn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Perform various interesting optimizations for exception handling
|
|
|
|
|
code.
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
We look for empty exception regions and make them go (away). The
|
|
|
|
|
jump optimization code will remove the handler if nothing else uses
|
1997-02-07 01:17:32 +00:00
|
|
|
|
it. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
exception_optimize ()
|
|
|
|
|
{
|
1998-02-11 00:35:13 +00:00
|
|
|
|
rtx insn;
|
1996-07-23 20:20:04 +00:00
|
|
|
|
int n;
|
|
|
|
|
|
1996-09-14 20:47:01 -04:00
|
|
|
|
/* Remove empty regions. */
|
1996-07-23 20:20:04 +00:00
|
|
|
|
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (insn) == NOTE
|
|
|
|
|
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
|
|
|
|
|
{
|
1997-04-23 20:11:52 +00:00
|
|
|
|
/* Since scan_region will return the NOTE_INSN_EH_REGION_END
|
1996-09-14 20:47:01 -04:00
|
|
|
|
insn, we will indirectly skip through all the insns
|
|
|
|
|
inbetween. We are also guaranteed that the value of insn
|
1997-04-23 20:11:52 +00:00
|
|
|
|
returned will be valid, as otherwise scan_region won't
|
1997-02-07 01:17:32 +00:00
|
|
|
|
return. */
|
1999-09-14 23:51:34 +00:00
|
|
|
|
insn = scan_region (insn, NOTE_EH_HANDLER (insn), &n);
|
1996-07-23 20:20:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-08-10 16:19:16 +00:00
|
|
|
|
|
2000-03-08 16:30:17 -05:00
|
|
|
|
/* This function determines whether the rethrow labels for any of the
|
|
|
|
|
exception regions in the current function are used or not, and set
|
|
|
|
|
the reference flag according. */
|
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
void
|
|
|
|
|
update_rethrow_references ()
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
int x, region;
|
|
|
|
|
int *saw_region, *saw_rethrow;
|
|
|
|
|
|
|
|
|
|
if (!flag_new_exceptions)
|
|
|
|
|
return;
|
|
|
|
|
|
1999-11-08 04:56:18 +00:00
|
|
|
|
saw_region = (int *) xcalloc (current_func_eh_entry, sizeof (int));
|
|
|
|
|
saw_rethrow = (int *) xcalloc (current_func_eh_entry, sizeof (int));
|
1999-08-10 16:19:16 +00:00
|
|
|
|
|
|
|
|
|
/* Determine what regions exist, and whether there are any rethrows
|
2000-03-08 16:30:17 -05:00
|
|
|
|
from those regions or not. */
|
1999-08-10 16:19:16 +00:00
|
|
|
|
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
|
|
|
|
if (GET_CODE (insn) == CALL_INSN)
|
|
|
|
|
{
|
|
|
|
|
rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
|
|
|
|
|
if (note)
|
|
|
|
|
{
|
|
|
|
|
region = eh_region_from_symbol (XEXP (note, 0));
|
|
|
|
|
region = find_func_region (region);
|
|
|
|
|
saw_rethrow[region] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if (GET_CODE (insn) == NOTE)
|
|
|
|
|
{
|
|
|
|
|
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
|
|
|
|
|
{
|
1999-09-14 23:51:34 +00:00
|
|
|
|
region = find_func_region (NOTE_EH_HANDLER (insn));
|
1999-08-10 16:19:16 +00:00
|
|
|
|
saw_region[region] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* For any regions we did see, set the referenced flag. */
|
|
|
|
|
for (x = 0; x < current_func_eh_entry; x++)
|
|
|
|
|
if (saw_region[x])
|
|
|
|
|
function_eh_regions[x].rethrow_ref = saw_rethrow[x];
|
1999-11-08 04:56:18 +00:00
|
|
|
|
|
|
|
|
|
/* Clean up. */
|
|
|
|
|
free (saw_region);
|
|
|
|
|
free (saw_rethrow);
|
1999-08-10 16:19:16 +00:00
|
|
|
|
}
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
|
|
|
|
/* Various hooks for the DWARF 2 __throw routine. */
|
|
|
|
|
|
|
|
|
|
/* Do any necessary initialization to access arbitrary stack frames.
|
|
|
|
|
On the SPARC, this means flushing the register windows. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
expand_builtin_unwind_init ()
|
|
|
|
|
{
|
|
|
|
|
/* Set this so all the registers get saved in our frame; we need to be
|
|
|
|
|
able to copy the saved values for any registers from frames we unwind. */
|
|
|
|
|
current_function_has_nonlocal_label = 1;
|
|
|
|
|
|
|
|
|
|
#ifdef SETUP_FRAME_ADDRESSES
|
|
|
|
|
SETUP_FRAME_ADDRESSES ();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given a value extracted from the return address register or stack slot,
|
|
|
|
|
return the actual address encoded in that value. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
expand_builtin_extract_return_addr (addr_tree)
|
|
|
|
|
tree addr_tree;
|
|
|
|
|
{
|
|
|
|
|
rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
|
|
|
|
|
return eh_outer_context (addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given an actual address in addr_tree, do any necessary encoding
|
|
|
|
|
and return the value to be stored in the return address register or
|
|
|
|
|
stack slot so the epilogue will return to that address. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
expand_builtin_frob_return_addr (addr_tree)
|
|
|
|
|
tree addr_tree;
|
|
|
|
|
{
|
|
|
|
|
rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
|
|
|
|
|
#ifdef RETURN_ADDR_OFFSET
|
|
|
|
|
addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
|
|
|
|
|
#endif
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Choose three registers for communication between the main body of
|
|
|
|
|
__throw and the epilogue (or eh stub) and the exception handler.
|
|
|
|
|
We must do this with hard registers because the epilogue itself
|
|
|
|
|
will be generated after reload, at which point we may not reference
|
|
|
|
|
pseudos at all.
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
The first passes the exception context to the handler. For this
|
|
|
|
|
we use the return value register for a void*.
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
2000-03-23 00:29:55 +00:00
|
|
|
|
The second holds the stack pointer value to be restored. For this
|
|
|
|
|
we use the static chain register if it exists, is different from
|
|
|
|
|
the previous, and is call-clobbered; otherwise some arbitrary
|
|
|
|
|
call-clobbered register.
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
The third holds the address of the handler itself. Here we use
|
|
|
|
|
some arbitrary call-clobbered register. */
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
|
|
|
|
static void
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
eh_regs (pcontext, psp, pra, outgoing)
|
|
|
|
|
rtx *pcontext, *psp, *pra;
|
2000-01-18 22:45:16 +00:00
|
|
|
|
int outgoing ATTRIBUTE_UNUSED;
|
1997-09-15 22:07:50 -04:00
|
|
|
|
{
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rtx rcontext, rsp, rra;
|
* Rework fields used to describe positions of bitfields and
modify sizes to be unsigned and use HOST_WIDE_INT.
* alias.c (reg_known_value_size): Now unsigned.
* c-typeck.c (build_unary_op, case ADDR_EXPR): Use byte_position.
(really_start_incremental_init): Use bitsize_zero_node.
(push_init_level, pop_init_level, output_init_element): Likewise.
Use bitsize_unit_node and bitsize_one_node.
(output_pending_init_elements, process_init_element): Likewise.
* combine.c (combine_max_regno, reg_sign_bit_copies): Now unsigned.
(make_extraction): Position and length HOST_WIDE_INT and unsigned
HOST_WIDE_INT, respectively.
(get_pos_from_mask): Passed in value is unsigned HOST_WIDE_INT.
(num_sign_bit_copies): Returns unsigned.
BITWIDTH now unsigned; rework arithmetic.
Remove recursive call from arg to MAX.
(combine_instructions, init_reg_last_arrays): NREGS now unsigned.
(setup_incoming_promotions, can_combine_p, try_combine, simplify_set):
REGNO now unsigned.
(set_nonzero_bit_and_sign_copies): NUM now unsigned.
(find_split_point, expand_compound_operation, make_extraction): LEN
now unsigned HOST_WIDE_INT, POS now HOST_WIDE_INT.
(make_field_assignment): Likewise.
(combine_simplify_rtx): Add cast.
(expand_compound_operation): MODEWIDTH now unsigned; rework arithmetic.
(force_to_mode): WIDTH now unsigned; add cast.
(if_then_else_cond): SIZE now unsigned.
(nonzero_bits): MODE_WIDTH, RESULT_WIDTH, and WIDTH now unsigned.
(extended_count): Now returns unsigned.
(simplify_shift_const): COUNT unsigned; arg is now INPUT_COUNT.
Add SIGNED_COUNT variable; MODE_WORDS and FIRST_COUNT now unsigned.
(simplify_comparison): MODE_WIDTH now unsigned.
(update_table_tick): REGNO and ENDREGNO now unsigned; new var R.
(mark_used_regs_combine): Likewise; rework arithmetic.
(record_value_for_reg): REGNO, ENDREGNO, and I now unsigned.
(record_dead_and_set_regs, reg_dead_at_p, distribute_notes): Likewise.
(record_promoted_value): REGNO now unsigned.
(get_last_value_validate): REGNO, ENDREGNO, and J now unsigned.
(get_last_value): REGNO now unsigned.
(use_crosses_set_p): REGNO and ENDREGNO now unsigned.
(reg_dead_regno, reg_dead_endregno): Now unsigned.
(remove_death): Arg REGNO now unsigned.
(move_deaths): REGNO, DEADREGNO, DEADEND, OUREND, and I now unsigned.
(reg_bitfield_target_p): REGNO, REGNO, ENDREGNO, and ENDTREGNO
now unsigned.
* convert.c (convert_to_integer): INPREC and OUTPREC now unsigned.
* cse.c (struct qty_table_elem): FIRST_REG and LAST_REG now unsigned.
(struct cse_reg_info): REGNO now unsigned.
(cached_regno): Now unsigned.
(REGNO_QTY_VALID_P): Add cast.
(make_new_qty, make_regs_eqv, delete_reg_eqiv): Regno args unsigned.
(remove_invalid_regs): Likewise.
(remove_invalid_subreg_refs): Likewise; arg WORD also unsigned
as are variables END and I.
(get_cse_reg_info, insert): Likewise.
(mention_regs, invalidate_for_call): REGNO, ENDREGNO, and I unsigned.
(canon_hash): Likewise.
(insert_regs, lookup_for_remove): REGNO now unsigned.
(invalidate): REGNO, ENDREGNO, TREGNO, and TENDREGNO now unsigned.
New variable RN.
* dbxout.c (dbxout_parms, dbxout_reg_parms): Don't check for REGNO < 0.
* dwarf2out.c (dwarf2ou_frame_debug_expr): Remove cast.
* emit-rtl.c (subreg_realpart_p): Add cast.
(operand_subword): Arg I is now unsigned as is var PARTWORDS.
(operand_subword_force): Arg I is now unsigned.
* except.c (eh_regs): Variable I is now unsigned.
* explow.c (hard_function_value): BYTES is unsigned HOST_WIDE_INT.
* expmed.c (store_fixed_bit_field): Position is HOST_WIDE_INT;
length is unsigned HOST_WIDE_INT; likewise for internal variables.
(store_split_bit_field, extract_fixed_bit_field): Likewise.
(extract_split_bit_field, store_bit_field, extract_bit_field):
Likewise.
* expr.c (store_constructor_fields, store_constructor, store_field):
Positions are HOST_WIDE_INT and lengths are unsigned HOST_WIDE_INT.
(expand_assignment, expand_expr, expand_expr_unaligned): Likewise.
(do_jump): Likewise.
(move_by_pieces, move_by_pieces_ninsns, clear_by_pieces):
MAX_SIZE is now unsigned.
(emit_group_load): BYTEPOS is HOST_WIDE_INT; BYTELEN is unsigned.
(emit_group_store): Likewise.
(emit_move_insn): I now unsigned.
(store_constructor): Use host_integerp, tree_low_cst, and
bitsize_unit_node.
(get_inner_reference): Return bitpos and bitsize as HOST_WIDE_INT.
Rework all calculations to use trees and new fields.
* expr.h (promoted_input_arg): Regno now unsigned.
(store_bit_field, extract_bit_field): Adjust types of pos and size.
(mark_seen_cases): Arg is HOST_WIDE_INT.
* flow.c (verify_wide_reg_1): REGNO now unsigned.
* fold-const.c (decode_field_reference): Size and pos HOST_WIDE_INT;
precisions and alignments are unsigned.
(optimize_bit_field_compare, fold_truthop): Likewise.
(int_const_binop): Adjust threshold for size_int_type_wide call.
(fold_convert): Likewise.
(size_int_type_wide): Make table larger and fix thinko that only
had half of table used.
(all_ones_mask_p, fold): Precisions are unsigned.
* function.c (put_reg_info_stack): REGNO is unsigned.
(instantiate_decl): Size is HOST_WIDE_INT.
(instantiate_virtual_regs): I is unsigned.
(assign_parms): REGNO, REGNOI, and REGNOR are unsigned.
(promoted_input_arg): REGNO is unsigned.
* function.h (struct function): x_max_parm_reg is now unsigned.
* gcse.c (max_gcse_regno): Now unsigned.
(struct null_pointer_info): min_reg and max_reg now unsigned.
(lookup_set, next_set): REGNO arg now unsigned.
(compute_hash_table): REGNO and I now unsigned.
(handle_avail_expr): regnum_for_replacing now unsigned.
(cprop_insn): REGNO now unsigned.
(delete_null_pointer_checks_1): BLOCK_REG now pointer to unsigned.
* ggc-common.c (ggc_mark_tree_children, case FIELD_DECL): New case.
* global.c (set_preference): SRC_REGNO, DEST_REGNO, and I now unsigned.
* hard-reg-set.h (reg_class_size): Now unsigned.
* integrate.c (mark_stores): LAST_REG and I now unsigned; new UREGNO.
* jump.c (mark_modified_reg): I now unsigned; add cast.
(rtx_equal_for_thread_p): Add cast.
* loop.c (max_reg_before_loop): Now unsigned.
(struct_movable): REGNO now unsigned.
(try_copy_prop): REGNO arg unsigned.
(regs_match_p): XN and YN now unsigned.
(consec_sets_invariant_p, maybe_eliminate_biv): REGNO now unsigned.
(strength_reduce): Likewise; NREGS also unsigned.
(first_increment_giv, last_increment_giv unsigned): Now unsigned.
* loop.h (struct iv_class): REGNO now unsigned.
(max_reg_before_loop, first_increment_giv, last_increment_giv):
Now unsigned.
* machmode.h (mode_size, mode_unit_size): Now unsigned.
(mode_for_size, smallest_mode_for_size): Pass size as unsigned.
* optabs.c (expand_binop): I and NWORDS now unsigned.
(expand_unop): I now unsigned.
* print-tree.c (print_node): Don't print DECL_FIELD_BITPOS, but do
print DECL_FIELD_OFFSET and DECL_FIELD_BIT_OFFSET.
* real.c (significand_size): Now returns unsigned.
* real.h (significand_size): Likewise.
* regclass.c (reg_class_size): Now unsigned.
(choose_hard_reg_mode): Both operands now unsigned.
(record_reg_classes): REGNO and NR now unsigned.
(reg_scan): NREGS now unsigned.
(reg_scan_update): old_max_regno now unsigned.
(reg_scan_mark_refs): Arg MIN_REGNO and var REGNO now unsigned.
* reload.c (find_valid_class): BEST_SIZE now unsigned.
(find_dummy_reload): REGNO, NWORDS, and I now unsigned.
(hard_reg_set_here_p): Args BEG_REGNO and END_REGNO now unsigned.
Likewise for variable R.
(refers_to_regno_for_reload_p): Args REGNO and END_REGNO now unsigned,
as are variables INNER_REGNO and INNER_ENDREGNO; add new variable R.
(find_equiv_reg): Add casts.
(regno_clobbered_p): Arg REGNO now unsigned.
* reload.h (struct reload): NREGS now unsigned.
(refers_to_regno_for_reload_p): Regno args are unsigned.
(regno_clobbered_p): Likewise.
* reload1.c (reg_max_ref_width, spill_stack_slot_width): Now unsigned.
(compute_use_by_pseudos): REGNO now unsigned.
(find_reg): I and J now unsigned, new variable K, and change loop
variables accordingly; THIS_NREGS now unsigned.
(alter_reg): INHERENT_SIZE and TOTAL_SIZE now unsigned.
(spill_hard_reg): REGNO arg now unsigned; add casts.
(forget_old_reloads_1): REGNO, NR, and I now unsigned.
(mark_reload_reg_in_use): Arg REGNO and vars NREGS and I now unsigned.
(clear_reload_reg_in_use): Arg REGNO and vars NREGS, START_REGNO,
END_REGNO, CONFLICT_START, and CONFLICT_END now unsigned.
(reload_reg_free_p, reload_reg_reaches_end_p): Arg REGNO now unsigned.
(choose_reload_regs): MAX_GROUP_SIZE now unsigned.
(emit_reload_insns): REGNO now unsigned.
(reload_cse_move2add): Add cast.
(move2add_note_store): REGNO and I now unsigned; new variable ENDREGNO
and rework loop.
* resource.c (mark_referenced_resources, mark_set_resources): New
variable R; REGNO and LAST_REGNO now unsigned.
(mark_target_live_regs): J and REGNO now unsigned.
* rtl.c (mode_size, mode_unit_size): Now unsigned.
* rtl.h (union rtunion_def): New field rtuint.
(XCUINT): New macro.
(ADDRESSOF_REGNO, REGNO, SUBREG_WORD): New XCUINT.
(operand_subword, operand_subword_force): Word number is unsigned.
(choose_hard_reg_mode): Operands are unsigned.
(refers_to-regno_p, dead_or_set_regno_p): Regno arg is unsigned.
(find_regno_note, find_regno_fusage, replace_regs): Likewise.
(regno_use_in, combine_instructions, remove_death): Likewise.
(reg_scan, reg_scan_update): Likewise.
(extended_count): Return is unsigned.
* rtlanal.c (refers_to_regno_p): Args REGNO and ENDREGNO and vars I,
INNER_REGNO, and INNER_ENDREGNO now unsigned; new variable X_REGNO.
(reg_overlap_mentioned_p): REGNO and ENDREGNO now unsigned.
(reg_set_last_first_regno, reg_set_last_last_regno): Now unsigned.
(reg_reg_last_1): FIRS and LAST now unsigned.
(dead_or_set_p): REGNO, LAST_REGNO, and I now unsigned.
(dead_or_set_regno_p): Arg TEST_REGNO and vars REGNO and ENDREGNO
now unsigned.
(find_regno_note, regno_use_in): Arg REGNO now unsigned.
(find_regno_fusage): Likewise; also var REGNOTE now unsigned.
(find_reg_fusage): Variables REGNO, END_REGNO, and I now unsigned.
(replace_regs): Arg NREGS now unsigned.
* sdbout.c (sdbout_parms, sdbout_reg_parms): Don't check REGNO < 0.
* simplify-rtx.c (simplify_unary_operation): WIDTH now unsigned.
(simplify_binary_operation): Likewise.
(cselib_invalidate_regno): Arg REGNO and variables ENDREGNO, I, and
THIS_LAST now unsigned.
(cselib_record_set): Add cast.
* ssa.c (ssa_max_reg_num): Now unsigned.
(rename_block): REGNO now unsigned.
* stmt.c (expand_return): Bit positions unsigned HOST_WIDE_INT;
sizes now unsigned.
(all_cases_count): Just return -1 not -2.
COUNT, MINVAL, and LASTVAL now HOST_WIDE_INT.
Rework tests to use trees whenever possible.
Use host_integerp and tree_low_cst.
(mark_seen_cases): COUNT arg now HOST_WIDE_INT;
Likewise variable NEXT_NODE_OFFSET; XLO now unsigned.
(check_for_full_enumeration_handing): BYTES_NEEDED, I to HOST_WIDE_INT.
* stor-layout.c (mode_for_size): SIZE arg now unsigned.
(smallest_mode_for_size): Likewise.
(layout_decl): Simplify handing of a specified DECL_SIZE_UNIT.
KNOWN_ALIGN is now an alignment, so simplify code.
Don't turn off DECL_BIT_FIELD if field is BLKmode, but not type.
(start_record_layout): Renamed from new_record_layout_info.
Update to new fields.
(debug_rli, normalize_rli, rli_size_unit_so_far, rli_size_so_far):
New functions.
(place_union_field): Renamed from layout_union_field.
Update to use new fields in rli.
(place_field): Renamed from layout_field.
Major rewrite to use new fields in rli; pass alignment to layout_decl.
(finalize_record_size): Rework to use new fields in rli and handle
union.
(compute_record_mode): Rework to simplify and to use new DECL fields.
(finalize_type_size): Make rounding more consistent.
(finish_union_layout): Deleted.
(layout_type, case VOID_TYPE): Don't set TYPE_SIZE_UNIT either.
(layout_type, case RECORD_TYPE): Call new function names.
(initialize_sizetypes): Set TYPE_IS_SIZETYPE.
(set_sizetype): Set TYPE_IS_SIZETYPE earlier.
(get_best_mode): UNIT is now unsigned; remove casts.
* tree.c (bit_position): Compute from new fields.
(byte_position, int_byte_position): New functions.
(print_type_hash_statistics): Cast to remove warning.
(build_range_type): Use host_integerp and tree_low_cst to try to hash.
(build_index_type): Likewise; make subtype of sizetype.
(build_index_2_type): Pass sizetype to build_range_type.
(build_common_tree_nodes): Use size_int and bitsize_int to
initialize nodes; add bitsize_{zero,one,unit}_node.
* tree.h (DECL_FIELD_CONTEXT): Use FIELD_DECL_CHECK.
(DECL_BIT_FIELD_TYPE, DECL_QUALIFIER, DECL_FCONTEXT): Likewise.
(DECL_PACKED, DECL_BIT_FIELD): Likewise.
(DECL_FIELD_BITPOS): Deleted.
(DECL_FIELD_OFFSET, DECL_FIELD_BIT_OFFSET): New fields.
(DECL_RESULT, DECL_SAVED_INSNS): Use FUNCTION_DECL_CHECK.
(DECL_FRAME_SIZE, DECL_FUNCTION_CODE, DECL_NO_STATIC_CHAIN): Likewise.
(DECL_INLINE, DECL_BUILT_IN_NONANSI, DECL_IS_MALLOC): Likewise.
(DECL_BUILT_IN_CLASS, DECL_STATIC_CONSTRUCTOR): Likewise.
(DECL_STATIC_DESTRUCTOR, DECL_NO_CHECK_MEMORY_USAGE): Likewise.
(DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT, DECL_NO_LIMIT_STACK) Likewise.
(DECL_ORIGINAL_TYPE, TYPE_DECL_SUPPRESS_DEBUG): Use TYPE_DECL_CHECK.
(DECL_ARG_TYPE_AS_WRITEN, DECL_ARG_TYPE): Use PARM_DECL_CHECK.
(DECL_INCOMING_RTL, DECL_TRANSPARENT_UNION): Likewise.
(DECL_ALIGN): Adjust to new field in union.
(DECL_OFFSET_ALIGN): New field.
(DECL_ERROR_ISSUED, DECL_TOO_LATE): Use LABEL_DECL_CHECK.
(DECL_IN_TEXT_SECTION): Use VAR_DECL_CHECK.
(union tree_decl): Add struct for both aligns.
(enum tree_index): Add TI_BITSIZE_{ZERO,ONE,UNIT}.
(bitsize_zero_node, bitsize_one_node, bitsize_unit_node): Added.
(struct record_layout_info): Rework fields to have offset
alignment and byte and bit position.
(start_record_layout, place_field): Renamed from old names.
(rli_size_so_far, rli_size_unit_so_far, normalize_rli): New decls.
(byte_position, int_byte_position): Likewise.
(get_inner_reference): Change types of position and length.
* unroll.c (unroll_loop): New variable R; use for some loops.
MAX_LOCAL_REGNUM and MAXREGNUM now unsigned.
(calculate_giv_inc): Arg REGNO now unsigned.
(copy_loop_body): REGNO and SRC_REGNO now unsigned.
* varasm.c (assemble_variable): Clean up handling of size using
host_integerp and tree_low_cst.
(decode_addr_const): Use byte, not bit, position.
(output_constructor): bitpos and offsets are HOST_WIDE_INT;
use tree_low_cst and int_bit_position.
* objc/objc-act.c (build_ivar_list_initializer): Use byte_position.
* ch/actions.c (check_missing_cases): BYTES_NEEDED is HOST_WIDE_INT.
* ch/typeck.c (expand_constant_to_buffer): Use int_byte_position.
(extract_constant_from_buffer): Likewise.
* cp/class.c (build_vbase_pointer_fields): layout_field now
place_field.
(get_vfield_offset): Use byte_position.
(set_rtti_entry): Set OFFSET to ssizetype zero.
(get_binfo_offset_as_int): Deleted.
(dfs_record_base_offsets): Use tree_low_cst.
(dfs_search_base_offsets): Likewise.
(layout_nonempty_base_or_field): Reflect changes in RLI format
and call byte_position.
(layout_empty_base): Convert offset to ssizetype.
(build_base_field): use rli_size_unit_so_far.
(dfs_propagate_binfo_offsets): Do computation in proper type.
(layout_virtual_bases): Pass ssizetype to propagate_binfo_offsets.
(layout_class_type): Reflect changes in RLI names and fields.
(finish_struct_1): Set DECL_FIELD_OFFSET.
* cp/dump.c (dequeue_and_dump): Call bit_position.
* cp/expr.c (cplus_expand_constant): Use byte_position.
* cp/rtti.c (expand_class_desc): Use bitsize_one_node.
* cp/typeck.c (build_component_addr): Use byte_position and don't
special case for zero offset.
* f/com.c (ffecom_tree_canonize_ptr_): Use bitsize_zero_node.
(ffecom_tree_canonize_ref_): Likewise.
* java/class.c (make_field_value): Use byte_position.
* java/expr.c (JAVA_ARRAY_LENGTH_OFFSET): Use byte_position.
(java_array_data_offset): Likewise.
* java/java-tree.h (MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Add case to
bzero call.
From-SVN: r32742
2000-03-25 18:34:13 +00:00
|
|
|
|
unsigned int i;
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
|
|
|
|
#ifdef FUNCTION_OUTGOING_VALUE
|
|
|
|
|
if (outgoing)
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rcontext = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
|
|
|
|
|
current_function_decl);
|
1997-09-15 22:07:50 -04:00
|
|
|
|
else
|
|
|
|
|
#endif
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rcontext = FUNCTION_VALUE (build_pointer_type (void_type_node),
|
|
|
|
|
current_function_decl);
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
|
|
|
|
#ifdef STATIC_CHAIN_REGNUM
|
|
|
|
|
if (outgoing)
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rsp = static_chain_incoming_rtx;
|
1997-09-15 22:07:50 -04:00
|
|
|
|
else
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rsp = static_chain_rtx;
|
2000-03-23 00:29:55 +00:00
|
|
|
|
if (REGNO (rsp) == REGNO (rcontext)
|
|
|
|
|
|| ! call_used_regs [REGNO (rsp)])
|
1997-09-15 22:07:50 -04:00
|
|
|
|
#endif /* STATIC_CHAIN_REGNUM */
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rsp = NULL_RTX;
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
if (rsp == NULL_RTX)
|
1997-09-15 22:07:50 -04:00
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (rcontext))
|
|
|
|
|
break;
|
|
|
|
|
if (i == FIRST_PSEUDO_REGISTER)
|
|
|
|
|
abort();
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rsp = gen_rtx_REG (Pmode, i);
|
1997-09-15 22:07:50 -04:00
|
|
|
|
}
|
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
|
|
|
|
|
if (call_used_regs[i] && ! fixed_regs[i]
|
|
|
|
|
&& i != REGNO (rcontext) && i != REGNO (rsp))
|
|
|
|
|
break;
|
|
|
|
|
if (i == FIRST_PSEUDO_REGISTER)
|
|
|
|
|
abort();
|
|
|
|
|
|
|
|
|
|
rra = gen_rtx_REG (Pmode, i);
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
*pcontext = rcontext;
|
|
|
|
|
*psp = rsp;
|
|
|
|
|
*pra = rra;
|
|
|
|
|
}
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
|
|
|
|
/* Retrieve the register which contains the pointer to the eh_context
|
|
|
|
|
structure set the __throw. */
|
|
|
|
|
|
cpplib.c (if_directive_nameo): Add static prototype.
* cpplib.c (if_directive_nameo): Add static prototype.
* cse.c (cse_insn): Remove unused variable `p'.
* except.c (create_rethrow_ref, push_entry,
receive_exception_label, new_eh_region_entry, find_func_region,
clear_function_eh_region, process_nestinfo): Add static prototypes.
(get_reg_for_handler): Hide definition.
(process_nestinfo): Initialize variable `extra_handlers'.
* expr.h (expand_builtin_longjmp): Add extern prototype.
* final.c (final_addr_vec_align, align_fuzz): Add static prototypes.
* function.c (prepare_function_start): Likewise.
(pop_function_context_from): Mark parameter `context' with
ATTRIBUTE_UNUSED.
(push_temp_slots_for_block, flush_addressof): Hide definition.
* gcov.c (init_arc, reverse_arcs, create_program_flow_graph,
solve_program_flow_graph, calculate_branch_probs,
function_summary, main, fancy_abort): Add prototypes.
* gen-protos.c (add_hash, parse_fn_proto, main): Likewise.
(add_hash): Constify a char*.
* ggc-common.c (ggc_mark_rtx_ptr, ggc_mark_tree_ptr,
ggc_mark_tree_varray_ptr, ggc_mark_tree_hash_table_ptr,
ggc_mark_string_ptr, ggc_mark_tree_hash_table_entry): Add prototypes.
* integrate.c (expand_inline_function_eh_labelmap): Likewise.
* lists.c (free_list, zap_lists): Likewise.
From-SVN: r29783
1999-10-03 16:28:33 +00:00
|
|
|
|
#if 0
|
1998-05-14 13:39:15 +00:00
|
|
|
|
rtx
|
|
|
|
|
get_reg_for_handler ()
|
|
|
|
|
{
|
|
|
|
|
rtx reg1;
|
|
|
|
|
reg1 = FUNCTION_VALUE (build_pointer_type (void_type_node),
|
|
|
|
|
current_function_decl);
|
|
|
|
|
return reg1;
|
|
|
|
|
}
|
cpplib.c (if_directive_nameo): Add static prototype.
* cpplib.c (if_directive_nameo): Add static prototype.
* cse.c (cse_insn): Remove unused variable `p'.
* except.c (create_rethrow_ref, push_entry,
receive_exception_label, new_eh_region_entry, find_func_region,
clear_function_eh_region, process_nestinfo): Add static prototypes.
(get_reg_for_handler): Hide definition.
(process_nestinfo): Initialize variable `extra_handlers'.
* expr.h (expand_builtin_longjmp): Add extern prototype.
* final.c (final_addr_vec_align, align_fuzz): Add static prototypes.
* function.c (prepare_function_start): Likewise.
(pop_function_context_from): Mark parameter `context' with
ATTRIBUTE_UNUSED.
(push_temp_slots_for_block, flush_addressof): Hide definition.
* gcov.c (init_arc, reverse_arcs, create_program_flow_graph,
solve_program_flow_graph, calculate_branch_probs,
function_summary, main, fancy_abort): Add prototypes.
* gen-protos.c (add_hash, parse_fn_proto, main): Likewise.
(add_hash): Constify a char*.
* ggc-common.c (ggc_mark_rtx_ptr, ggc_mark_tree_ptr,
ggc_mark_tree_varray_ptr, ggc_mark_tree_hash_table_ptr,
ggc_mark_string_ptr, ggc_mark_tree_hash_table_entry): Add prototypes.
* integrate.c (expand_inline_function_eh_labelmap): Likewise.
* lists.c (free_list, zap_lists): Likewise.
From-SVN: r29783
1999-10-03 16:28:33 +00:00
|
|
|
|
#endif
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Set up the epilogue with the magic bits we'll need to return to the
|
|
|
|
|
exception handler. */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
void
|
|
|
|
|
expand_builtin_eh_return (context, stack, handler)
|
|
|
|
|
tree context, stack, handler;
|
1998-06-08 12:43:28 +00:00
|
|
|
|
{
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
if (eh_return_context)
|
|
|
|
|
error("Duplicate call to __builtin_eh_return");
|
1998-06-08 12:43:28 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
eh_return_context
|
|
|
|
|
= copy_to_reg (expand_expr (context, NULL_RTX, VOIDmode, 0));
|
|
|
|
|
eh_return_stack_adjust
|
|
|
|
|
= copy_to_reg (expand_expr (stack, NULL_RTX, VOIDmode, 0));
|
|
|
|
|
eh_return_handler
|
|
|
|
|
= copy_to_reg (expand_expr (handler, NULL_RTX, VOIDmode, 0));
|
1998-06-08 12:43:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
void
|
|
|
|
|
expand_eh_return ()
|
1997-09-15 22:07:50 -04:00
|
|
|
|
{
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
rtx reg1, reg2, reg3;
|
|
|
|
|
rtx stub_start, after_stub;
|
|
|
|
|
rtx ra, tmp;
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
if (!eh_return_context)
|
|
|
|
|
return;
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
1999-07-01 17:52:55 -06:00
|
|
|
|
current_function_cannot_inline = N_("function uses __builtin_eh_return");
|
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
eh_regs (®1, ®2, ®3, 1);
|
1999-04-15 19:52:18 +00:00
|
|
|
|
#ifdef POINTERS_EXTEND_UNSIGNED
|
|
|
|
|
eh_return_context = convert_memory_address (Pmode, eh_return_context);
|
|
|
|
|
eh_return_stack_adjust =
|
|
|
|
|
convert_memory_address (Pmode, eh_return_stack_adjust);
|
|
|
|
|
eh_return_handler = convert_memory_address (Pmode, eh_return_handler);
|
|
|
|
|
#endif
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
emit_move_insn (reg1, eh_return_context);
|
|
|
|
|
emit_move_insn (reg2, eh_return_stack_adjust);
|
|
|
|
|
emit_move_insn (reg3, eh_return_handler);
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Talk directly to the target's epilogue code when possible. */
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
#ifdef HAVE_eh_epilogue
|
|
|
|
|
if (HAVE_eh_epilogue)
|
|
|
|
|
{
|
|
|
|
|
emit_insn (gen_eh_epilogue (reg1, reg2, reg3));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
1998-05-14 13:39:15 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Otherwise, use the same stub technique we had before. */
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
eh_return_stub_label = stub_start = gen_label_rtx ();
|
|
|
|
|
after_stub = gen_label_rtx ();
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Set the return address to the stub label. */
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
|
|
|
|
|
0, hard_frame_pointer_rtx);
|
|
|
|
|
if (GET_CODE (ra) == REG && REGNO (ra) >= FIRST_PSEUDO_REGISTER)
|
|
|
|
|
abort();
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
tmp = memory_address (Pmode, gen_rtx_LABEL_REF (Pmode, stub_start));
|
|
|
|
|
#ifdef RETURN_ADDR_OFFSET
|
|
|
|
|
tmp = plus_constant (tmp, -RETURN_ADDR_OFFSET);
|
|
|
|
|
#endif
|
1998-11-11 13:48:34 +00:00
|
|
|
|
tmp = force_operand (tmp, ra);
|
|
|
|
|
if (tmp != ra)
|
|
|
|
|
emit_move_insn (ra, tmp);
|
1997-09-15 22:07:50 -04:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Indicate that the registers are in fact used. */
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-14 15:10:50 -08:00
|
|
|
|
emit_insn (gen_rtx_USE (VOIDmode, reg1));
|
|
|
|
|
emit_insn (gen_rtx_USE (VOIDmode, reg2));
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
emit_insn (gen_rtx_USE (VOIDmode, reg3));
|
|
|
|
|
if (GET_CODE (ra) == REG)
|
|
|
|
|
emit_insn (gen_rtx_USE (VOIDmode, ra));
|
1998-03-16 12:51:39 +00:00
|
|
|
|
|
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
(BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
(BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
(BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
* c-decl.c (init_decl_processing): Update accordingly.
* expr.c (expand_builtin): Likewise.
* cp/decl.c (init_decl_processing): Likewise.
* rtl.h (global_rtl): Add cfa entry.
(virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
(LAST_VIRTUAL_REGISTER): Update.
* emit-rtl.c (global_rtl): Add cfa entry.
(init_emit): Initialize it.
* function.c (cfa_offset): New.
(instantiate_virtual_regs): Initialize it.
(instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
(expand_function_end): Call expand_eh_return.
* tm.texi (ARG_POINTER_CFA_OFFSET): New.
* except.c (current_function_eh_stub_label): Kill.
(current_function_eh_old_stub_label): Likwise; update all references.
(expand_builtin_set_return_addr_reg): Kill.
(expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
(expand_builtin_set_eh_regs): Kill.
(eh_regs): Produce a third reg for the actual handler address.
(eh_return_context, eh_return_stack_adjust): New.
(eh_return_handler, eh_return_stub_label): New.
(init_eh_for_function): Initialize them.
(expand_builtin_eh_return, expand_eh_return): New.
* except.h: Update prototypes.
* flow.c (find_basic_blocks_1): Update references to the stub label.
* function.h (struct function): Kill stub label elements.
* libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
register number is one that would be in the previous window.
Provide a dummy definition for non-windowed targets.
(get_reg_addr): New function.
(get_reg, put_reg, copy_reg): Use it.
(__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
* alpha.c (alpha_eh_epilogue_sp_ofs): New.
(alpha_init_expanders): Initialize it.
(alpha_expand_epilogue): Use it.
* alpha.h: Declare it.
* alpha.md (eh_epilogue): New.
* m68h.h (ARG_POINTER_CFA_OFFSET): New.
* sparc.h (ARG_POINTER_CFA_OFFSET): New.
From-SVN: r22436
1998-09-15 12:19:12 -07:00
|
|
|
|
/* Generate the stub. */
|
|
|
|
|
|
|
|
|
|
emit_jump (after_stub);
|
|
|
|
|
emit_label (stub_start);
|
|
|
|
|
|
|
|
|
|
eh_regs (®1, ®2, ®3, 0);
|
|
|
|
|
adjust_stack (reg2);
|
|
|
|
|
emit_indirect_jump (reg3);
|
|
|
|
|
|
|
|
|
|
emit_label (after_stub);
|
|
|
|
|
}
|
1998-03-16 12:51:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This contains the code required to verify whether arbitrary instructions
|
|
|
|
|
are in the same exception region. */
|
|
|
|
|
|
|
|
|
|
static int *insn_eh_region = (int *)0;
|
|
|
|
|
static int maximum_uid;
|
|
|
|
|
|
1998-04-16 22:57:50 +00:00
|
|
|
|
static void
|
|
|
|
|
set_insn_eh_region (first, region_num)
|
1998-03-16 12:51:39 +00:00
|
|
|
|
rtx *first;
|
|
|
|
|
int region_num;
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
int rnum;
|
|
|
|
|
|
|
|
|
|
for (insn = *first; insn; insn = NEXT_INSN (insn))
|
|
|
|
|
{
|
1999-09-14 23:51:34 +00:00
|
|
|
|
if ((GET_CODE (insn) == NOTE)
|
|
|
|
|
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG))
|
1998-03-16 12:51:39 +00:00
|
|
|
|
{
|
1999-09-14 23:51:34 +00:00
|
|
|
|
rnum = NOTE_EH_HANDLER (insn);
|
1998-03-16 12:51:39 +00:00
|
|
|
|
insn_eh_region[INSN_UID (insn)] = rnum;
|
|
|
|
|
insn = NEXT_INSN (insn);
|
|
|
|
|
set_insn_eh_region (&insn, rnum);
|
|
|
|
|
/* Upon return, insn points to the EH_REGION_END of nested region */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
insn_eh_region[INSN_UID (insn)] = region_num;
|
|
|
|
|
if ((GET_CODE (insn) == NOTE) &&
|
|
|
|
|
(NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*first = insn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Free the insn table, an make sure it cannot be used again. */
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
void
|
|
|
|
|
free_insn_eh_region ()
|
1998-03-16 12:51:39 +00:00
|
|
|
|
{
|
|
|
|
|
if (!doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (insn_eh_region)
|
|
|
|
|
{
|
|
|
|
|
free (insn_eh_region);
|
|
|
|
|
insn_eh_region = (int *)0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initialize the table. max_uid must be calculated and handed into
|
|
|
|
|
this routine. If it is unavailable, passing a value of 0 will
|
|
|
|
|
cause this routine to calculate it as well. */
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
void
|
|
|
|
|
init_insn_eh_region (first, max_uid)
|
1998-03-16 12:51:39 +00:00
|
|
|
|
rtx first;
|
|
|
|
|
int max_uid;
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
|
|
|
|
|
if (!doing_eh (0))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (insn_eh_region)
|
|
|
|
|
free_insn_eh_region();
|
|
|
|
|
|
|
|
|
|
if (max_uid == 0)
|
|
|
|
|
for (insn = first; insn; insn = NEXT_INSN (insn))
|
|
|
|
|
if (INSN_UID (insn) > max_uid) /* find largest UID */
|
|
|
|
|
max_uid = INSN_UID (insn);
|
|
|
|
|
|
|
|
|
|
maximum_uid = max_uid;
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
insn_eh_region = (int *) xmalloc ((max_uid + 1) * sizeof (int));
|
1998-03-16 12:51:39 +00:00
|
|
|
|
insn = first;
|
|
|
|
|
set_insn_eh_region (&insn, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check whether 2 instructions are within the same region. */
|
|
|
|
|
|
1998-05-14 13:39:15 +00:00
|
|
|
|
int
|
|
|
|
|
in_same_eh_region (insn1, insn2)
|
|
|
|
|
rtx insn1, insn2;
|
1998-03-16 12:51:39 +00:00
|
|
|
|
{
|
|
|
|
|
int ret, uid1, uid2;
|
|
|
|
|
|
|
|
|
|
/* If no exceptions, instructions are always in same region. */
|
|
|
|
|
if (!doing_eh (0))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
/* If the table isn't allocated, assume the worst. */
|
|
|
|
|
if (!insn_eh_region)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
uid1 = INSN_UID (insn1);
|
|
|
|
|
uid2 = INSN_UID (insn2);
|
|
|
|
|
|
|
|
|
|
/* if instructions have been allocated beyond the end, either
|
|
|
|
|
the table is out of date, or this is a late addition, or
|
|
|
|
|
something... Assume the worst. */
|
|
|
|
|
if (uid1 > maximum_uid || uid2 > maximum_uid)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
ret = (insn_eh_region[uid1] == insn_eh_region[uid2]);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
1999-08-10 16:19:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This function will initialize the handler list for a specified block.
|
|
|
|
|
It may recursively call itself if the outer block hasn't been processed
|
|
|
|
|
yet. At some point in the future we can trim out handlers which we
|
|
|
|
|
know cannot be called. (ie, if a block has an INT type handler,
|
|
|
|
|
control will never be passed to an outer INT type handler). */
|
2000-03-09 20:37:06 +00:00
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
static void
|
|
|
|
|
process_nestinfo (block, info, nested_eh_region)
|
|
|
|
|
int block;
|
|
|
|
|
eh_nesting_info *info;
|
|
|
|
|
int *nested_eh_region;
|
|
|
|
|
{
|
|
|
|
|
handler_info *ptr, *last_ptr = NULL;
|
|
|
|
|
int x, y, count = 0;
|
|
|
|
|
int extra = 0;
|
cpplib.c (if_directive_nameo): Add static prototype.
* cpplib.c (if_directive_nameo): Add static prototype.
* cse.c (cse_insn): Remove unused variable `p'.
* except.c (create_rethrow_ref, push_entry,
receive_exception_label, new_eh_region_entry, find_func_region,
clear_function_eh_region, process_nestinfo): Add static prototypes.
(get_reg_for_handler): Hide definition.
(process_nestinfo): Initialize variable `extra_handlers'.
* expr.h (expand_builtin_longjmp): Add extern prototype.
* final.c (final_addr_vec_align, align_fuzz): Add static prototypes.
* function.c (prepare_function_start): Likewise.
(pop_function_context_from): Mark parameter `context' with
ATTRIBUTE_UNUSED.
(push_temp_slots_for_block, flush_addressof): Hide definition.
* gcov.c (init_arc, reverse_arcs, create_program_flow_graph,
solve_program_flow_graph, calculate_branch_probs,
function_summary, main, fancy_abort): Add prototypes.
* gen-protos.c (add_hash, parse_fn_proto, main): Likewise.
(add_hash): Constify a char*.
* ggc-common.c (ggc_mark_rtx_ptr, ggc_mark_tree_ptr,
ggc_mark_tree_varray_ptr, ggc_mark_tree_hash_table_ptr,
ggc_mark_string_ptr, ggc_mark_tree_hash_table_entry): Add prototypes.
* integrate.c (expand_inline_function_eh_labelmap): Likewise.
* lists.c (free_list, zap_lists): Likewise.
From-SVN: r29783
1999-10-03 16:28:33 +00:00
|
|
|
|
handler_info **extra_handlers = 0;
|
1999-08-10 16:19:16 +00:00
|
|
|
|
int index = info->region_index[block];
|
|
|
|
|
|
|
|
|
|
/* If we've already processed this block, simply return. */
|
|
|
|
|
if (info->num_handlers[index] > 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (ptr = get_first_handler (block); ptr; last_ptr = ptr, ptr = ptr->next)
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
/* pick up any information from the next outer region. It will already
|
|
|
|
|
contain a summary of itself and all outer regions to it. */
|
|
|
|
|
|
|
|
|
|
if (nested_eh_region [block] != 0)
|
|
|
|
|
{
|
|
|
|
|
int nested_index = info->region_index[nested_eh_region[block]];
|
|
|
|
|
process_nestinfo (nested_eh_region[block], info, nested_eh_region);
|
|
|
|
|
extra = info->num_handlers[nested_index];
|
|
|
|
|
extra_handlers = info->handlers[nested_index];
|
|
|
|
|
info->outer_index[index] = nested_index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the last handler is either a CATCH_ALL or a cleanup, then we
|
|
|
|
|
won't use the outer ones since we know control will not go past the
|
|
|
|
|
catch-all or cleanup. */
|
|
|
|
|
|
|
|
|
|
if (last_ptr != NULL && (last_ptr->type_info == NULL
|
|
|
|
|
|| last_ptr->type_info == CATCH_ALL_TYPE))
|
|
|
|
|
extra = 0;
|
|
|
|
|
|
|
|
|
|
info->num_handlers[index] = count + extra;
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
info->handlers[index] = (handler_info **) xmalloc ((count + extra)
|
1999-08-10 16:19:16 +00:00
|
|
|
|
* sizeof (handler_info **));
|
|
|
|
|
|
|
|
|
|
/* First put all our handlers into the list. */
|
|
|
|
|
ptr = get_first_handler (block);
|
|
|
|
|
for (x = 0; x < count; x++)
|
|
|
|
|
{
|
|
|
|
|
info->handlers[index][x] = ptr;
|
|
|
|
|
ptr = ptr->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now add all the outer region handlers, if they aren't they same as
|
|
|
|
|
one of the types in the current block. We won't worry about
|
|
|
|
|
derived types yet, we'll just look for the exact type. */
|
|
|
|
|
for (y =0, x = 0; x < extra ; x++)
|
|
|
|
|
{
|
|
|
|
|
int i, ok;
|
|
|
|
|
ok = 1;
|
|
|
|
|
/* Check to see if we have a type duplication. */
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
if (info->handlers[index][i]->type_info == extra_handlers[x]->type_info)
|
|
|
|
|
{
|
|
|
|
|
ok = 0;
|
|
|
|
|
/* Record one less handler. */
|
|
|
|
|
(info->num_handlers[index])--;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (ok)
|
|
|
|
|
{
|
|
|
|
|
info->handlers[index][y + count] = extra_handlers[x];
|
|
|
|
|
y++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This function will allocate and initialize an eh_nesting_info structure.
|
|
|
|
|
It returns a pointer to the completed data structure. If there are
|
|
|
|
|
no exception regions, a NULL value is returned. */
|
2000-03-09 20:37:06 +00:00
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
eh_nesting_info *
|
|
|
|
|
init_eh_nesting_info ()
|
|
|
|
|
{
|
|
|
|
|
int *nested_eh_region;
|
|
|
|
|
int region_count = 0;
|
|
|
|
|
rtx eh_note = NULL_RTX;
|
|
|
|
|
eh_nesting_info *info;
|
|
|
|
|
rtx insn;
|
|
|
|
|
int x;
|
|
|
|
|
|
2000-03-09 20:37:06 +00:00
|
|
|
|
if (! flag_exceptions)
|
|
|
|
|
return 0;
|
|
|
|
|
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
info = (eh_nesting_info *) xmalloc (sizeof (eh_nesting_info));
|
|
|
|
|
info->region_index = (int *) xcalloc ((max_label_num () + 1), sizeof (int));
|
1999-11-08 04:56:18 +00:00
|
|
|
|
nested_eh_region = (int *) xcalloc (max_label_num () + 1, sizeof (int));
|
1998-03-16 12:51:39 +00:00
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
/* Create the nested_eh_region list. If indexed with a block number, it
|
|
|
|
|
returns the block number of the next outermost region, if any.
|
|
|
|
|
We can count the number of regions and initialize the region_index
|
|
|
|
|
vector at the same time. */
|
|
|
|
|
for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (insn) == NOTE)
|
|
|
|
|
{
|
|
|
|
|
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
|
|
|
|
|
{
|
1999-09-14 23:51:34 +00:00
|
|
|
|
int block = NOTE_EH_HANDLER (insn);
|
1999-08-10 16:19:16 +00:00
|
|
|
|
region_count++;
|
|
|
|
|
info->region_index[block] = region_count;
|
|
|
|
|
if (eh_note)
|
|
|
|
|
nested_eh_region [block] =
|
1999-09-14 23:51:34 +00:00
|
|
|
|
NOTE_EH_HANDLER (XEXP (eh_note, 0));
|
1999-08-10 16:19:16 +00:00
|
|
|
|
else
|
|
|
|
|
nested_eh_region [block] = 0;
|
|
|
|
|
eh_note = gen_rtx_EXPR_LIST (VOIDmode, insn, eh_note);
|
|
|
|
|
}
|
|
|
|
|
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
|
|
|
|
|
eh_note = XEXP (eh_note, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If there are no regions, wrap it up now. */
|
|
|
|
|
if (region_count == 0)
|
|
|
|
|
{
|
|
|
|
|
free (info->region_index);
|
|
|
|
|
free (info);
|
1999-11-08 04:56:18 +00:00
|
|
|
|
free (nested_eh_region);
|
1999-08-10 16:19:16 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
region_count++;
|
c-aux-info.c (concat): Don't define.
* c-aux-info.c (concat): Don't define.
* cccp.c (my_strerror): Likewise. All callers changed to use
xstrerror instead.
(do_include): Call xstrdup, not xmalloc/strcpy.
(grow_outbuf): Don't check if xrealloc returns NULL, it can't.
(xmalloc, xrealloc, xcalloc, xstrdup): Don't define.
* collect2.c (my_strsignal): Likewise. All callers changed to use
strsignal instead.
(locatelib): Call xstrdup, not xmalloc/strcpy.
* 1750a.h (ASM_OUTPUT_INTERNAL_LABEL): Call xmalloc, not malloc.
* dsp16xx.c (override_options): Call xstrdup, not xmalloc/strcpy.
* i370.h (ASM_DECLARE_FUNCTION_NAME): Call xmalloc, not malloc.
* mips.c (build_mips16_call_stub): Call xstrdup, not xmalloc/strcpy.
* cppinit.c (cpp_options_init): Call xcalloc, not xmalloc/bzero.
* dwarfout.c (dwarfout_init): Call concat, not xmalloc/strcpy/...
* except.c (new_eh_region_entry): Call xmalloc/xrealloc, not
malloc/realloc.
(find_all_handler_type_matches): Likewise. Don't check return
value.
(get_new_handler, init_insn_eh_region, process_nestinfo): Call
xmalloc, not malloc.
(init_eh_nesting_info): Likewise. Call xcalloc, not xmalloc/bzero.
* gcc.c (xstrerror, xmalloc, xrealloc): Don't define.
(init_spec): Call xcalloc, not xmalloc/bzero.
(set_spec): Call xstrdup, not save_string.
(record_temp_file): Call xstrdup, not xmalloc/strcpy.
(find_a_file): Call xstrdup, not xmalloc/strcpy.
(process_command): Call xstrdup, not save_string.
(main): Call xcalloc, not xmalloc/bzero.
* gcov.c (xmalloc): Don't define.
(create_program_flow_graph): Call xcalloc, not xmalloc/bzero.
(scan_for_source_files): Call xstrdup, not xmalloc/strcpy.
(output_data): Call xcalloc, not xmalloc/bzero.
* haifa-sched.c (schedule_insns): Call xcalloc, not xmalloc/bzero.
* mips-tdump.c (xmalloc): Don't define.
(print_symbol): Call xmalloc, not malloc.
(read_tfile): Call xcalloc, not calloc.
* mips-tfile.c (xfree, my_strsignal, xmalloc, xcalloc, xrealloc):
Don't define. All callers of xfree/my_strsignal changed to use
free/strsignal instead.
(allocate_cluster): Call xcalloc, not calloc.
* objc/objc-act.c (lang_init): Call concat, not xmalloc/strcpy/...
Fix memory leak, free allocated memory.
* prefix.c (translate_name): Call xstrdup, not save_string.
(update_path): Likewise.
* profile.c (branch_prob): Call xstrdup, not xmalloc/strcpy.
* protoize.c (xstrerror, xmalloc, xrealloc, xfree, savestring2):
Don't define. Callers of xfree/savestring2 changed to use
free/concat instead.
* reload1.c (reload): Call xcalloc, not xmalloc/bzero.
(init_elim_table): Likewise.
* resource.c (init_resource_info): Likewise.
* stupid.c (stupid_life_analysis): Likewise.
* toplev.c (xmalloc, xcalloc, xrealloc, xstrdup): Don't define.
(open_dump_file): Call concat, not xmalloc/strcpy/...
(clean_dump_file): Likewise.
(compile_file): Call xstrdup, not xmalloc/strcpy.
From-SVN: r29148
1999-09-07 02:36:41 +00:00
|
|
|
|
info->handlers = (handler_info ***) xcalloc (region_count,
|
|
|
|
|
sizeof (handler_info ***));
|
|
|
|
|
info->num_handlers = (int *) xcalloc (region_count, sizeof (int));
|
|
|
|
|
info->outer_index = (int *) xcalloc (region_count, sizeof (int));
|
1999-08-10 16:19:16 +00:00
|
|
|
|
|
|
|
|
|
/* Now initialize the handler lists for all exception blocks. */
|
|
|
|
|
for (x = 0; x <= max_label_num (); x++)
|
|
|
|
|
{
|
|
|
|
|
if (info->region_index[x] != 0)
|
|
|
|
|
process_nestinfo (x, info, nested_eh_region);
|
|
|
|
|
}
|
|
|
|
|
info->region_count = region_count;
|
1999-11-08 04:56:18 +00:00
|
|
|
|
|
|
|
|
|
/* Clean up. */
|
|
|
|
|
free (nested_eh_region);
|
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This function is used to retreive the vector of handlers which
|
|
|
|
|
can be reached by a given insn in a given exception region.
|
|
|
|
|
BLOCK is the exception block the insn is in.
|
|
|
|
|
INFO is the eh_nesting_info structure.
|
|
|
|
|
INSN is the (optional) insn within the block. If insn is not NULL_RTX,
|
|
|
|
|
it may contain reg notes which modify its throwing behavior, and
|
|
|
|
|
these will be obeyed. If NULL_RTX is passed, then we simply return the
|
|
|
|
|
handlers for block.
|
|
|
|
|
HANDLERS is the address of a pointer to a vector of handler_info pointers.
|
|
|
|
|
Upon return, this will have the handlers which can be reached by block.
|
|
|
|
|
This function returns the number of elements in the handlers vector. */
|
2000-03-09 20:37:06 +00:00
|
|
|
|
|
1999-08-10 16:19:16 +00:00
|
|
|
|
int
|
|
|
|
|
reachable_handlers (block, info, insn, handlers)
|
|
|
|
|
int block;
|
|
|
|
|
eh_nesting_info *info;
|
|
|
|
|
rtx insn ;
|
|
|
|
|
handler_info ***handlers;
|
|
|
|
|
{
|
|
|
|
|
int index = 0;
|
|
|
|
|
*handlers = NULL;
|
|
|
|
|
|
|
|
|
|
if (info == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (block > 0)
|
|
|
|
|
index = info->region_index[block];
|
|
|
|
|
|
|
|
|
|
if (insn && GET_CODE (insn) == CALL_INSN)
|
|
|
|
|
{
|
|
|
|
|
/* RETHROWs specify a region number from which we are going to rethrow.
|
2000-03-08 16:30:17 -05:00
|
|
|
|
This means we won't pass control to handlers in the specified
|
1999-08-10 16:19:16 +00:00
|
|
|
|
region, but rather any region OUTSIDE the specified region.
|
|
|
|
|
We accomplish this by setting block to the outer_index of the
|
|
|
|
|
specified region. */
|
|
|
|
|
rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
|
|
|
|
|
if (note)
|
|
|
|
|
{
|
|
|
|
|
index = eh_region_from_symbol (XEXP (note, 0));
|
|
|
|
|
index = info->region_index[index];
|
|
|
|
|
if (index)
|
|
|
|
|
index = info->outer_index[index];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If there is no rethrow, we look for a REG_EH_REGION, and
|
|
|
|
|
we'll throw from that block. A value of 0 or less
|
|
|
|
|
indicates that this insn cannot throw. */
|
|
|
|
|
note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
|
|
|
|
|
if (note)
|
|
|
|
|
{
|
2000-03-10 11:21:06 -08:00
|
|
|
|
int b = INTVAL (XEXP (note, 0));
|
1999-08-10 16:19:16 +00:00
|
|
|
|
if (b <= 0)
|
|
|
|
|
index = 0;
|
|
|
|
|
else
|
|
|
|
|
index = info->region_index[b];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* If we reach this point, and index is 0, there is no throw. */
|
|
|
|
|
if (index == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
*handlers = info->handlers[index];
|
|
|
|
|
return info->num_handlers[index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This function will free all memory associated with the eh_nesting info. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
free_eh_nesting_info (info)
|
|
|
|
|
eh_nesting_info *info;
|
|
|
|
|
{
|
|
|
|
|
int x;
|
|
|
|
|
if (info != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (info->region_index)
|
|
|
|
|
free (info->region_index);
|
|
|
|
|
if (info->num_handlers)
|
|
|
|
|
free (info->num_handlers);
|
|
|
|
|
if (info->outer_index)
|
|
|
|
|
free (info->outer_index);
|
|
|
|
|
if (info->handlers)
|
|
|
|
|
{
|
|
|
|
|
for (x = 0; x < info->region_count; x++)
|
|
|
|
|
if (info->handlers[x])
|
|
|
|
|
free (info->handlers[x]);
|
|
|
|
|
free (info->handlers);
|
|
|
|
|
}
|
1999-10-29 09:49:23 +00:00
|
|
|
|
free (info);
|
1999-08-10 16:19:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|