Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
9a0d1e1b
Commit
9a0d1e1b
authored
May 14, 1998
by
Andrew MacLeod
Committed by
Andrew Macleod
May 14, 1998
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First cut of changes to utilize the new exception handling model
From-SVN: r19746
parent
2129b081
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
960 additions
and
213 deletions
+960
-213
gcc/ChangeLog
+62
-0
gcc/cp/ChangeLog
+16
-0
gcc/cp/except.c
+48
-16
gcc/cp/exception.cc
+34
-0
gcc/cp/parse.y
+5
-1
gcc/cp/semantics.c
+8
-2
gcc/eh-common.h
+133
-0
gcc/except.c
+422
-140
gcc/except.h
+81
-1
gcc/final.c
+5
-0
gcc/flow.c
+35
-20
gcc/function.h
+1
-0
gcc/integrate.c
+42
-3
gcc/libgcc2.c
+68
-30
No files found.
gcc/ChangeLog
View file @
9a0d1e1b
Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
* eh-common.h: New file for basic EH data structures.
* except.h: Various prototypes and structures for NEW_EH_MODEL
* function.h (struct function): Add a struct eh_stack for the catch
clause stack.
* except.c (gen_exception_label): New function to generate an
exception label.
(push_eh_entry): Use gen_exception_label() and init 'label_used' field.
(push_entry): New function to push an existing entry onto a stack.
(receive_exception_label): New function to emit the code required
at the start of all catch blocks.
(struct func_eh_entry): New structure for maintaining handlers
associated with EH regions.
(new_eh_region_entry): New function to register an EH region.
(add_new_handler): New function to register a handler with a region.
(get_new_handler): Creates anew handler entry for registering.
(find_func_region): New function to convert a NOTE eh region number
to an Eh region index.
(get_first_handler): New function to get the first handler in a region.
(clear_function_eh_region): New function to release memory.
(duplicate_handlers): New function to duplicate a list of handlers.
(expand_eh_region_end): Create a new region entry node as well.
(expand_leftover_cleanups): Call receive_exception_label() and
register the cleanup as a handler to the current region.
(expand_start_catch): New function to start a catch clause.
(expand_end_catch): New function to end a catch clause.
(expand_start_all_catch): restructure to not do the equivilent of
what expand_start_catch() does now. Push the exception region being
handled onto the catch stack.
(output_exception_table_entry): Issue an entry for each handler
associated with a region.
(set_exception_lang_code): New function for setting the language code.
(set_exception_version_code): New function to set the version number.
(output_exception_table): Output version and language codes.
(find_exception_handler_labels): Find handler labels using new scheme.
(is_exception_handler_label): New function, returns 1 if label is
present as a handler in some exception region.
(check_exception_handler_labels): Use the new scheme.
(init_eh_for_function): Initialize the catch stack.
(save_eh_status): Save the catch stack.
(restore_eh_status): Restore the catch stack.
(scan_region): Don't remove unreferenced handler label. Flow does it.
(get_reg_for_handler): New function to get the eh_context pointer
passed by __throw.
(expand_builtin_eh_stub): Changes required for NEW_EH_MODEL only.
* final.c (final_scan_insn): With NEW_EH_MODEL, add EH table
entry when processing END region rather that START region.
* flow.c (find_basic_blocks_1): Find all potential handler regions
now that we don't automatically know what the labels might be.
Let scan_region() remove unreferenced EH BEGIN/END labels.
* integrate.c (get_label_from_map): Put inlined labels onto the
permanent obstack since we dont know which ones might be exception
labels.
(save_for_inline_copying): Make new copies of all the handlers.
(expand_inline_function): Make new copies of all the handlers.
* libgcc2.c: Remove local struct decls, and include eh-common.h.
(find_exception_handler): With NEW_EH_MODEL the first matching
region we find is the right one. Add eh_info as a new parameter.
(__throw): Pass eh_info to find_exception_handler. Set handler
and pass use different regs under NEW_EH_MODEL.
Thu May 14 12:58:21 1998 Jim Wilson <wilson@cygnus.com>
* i960.h (hard_regno_mode_ok): Changed to function from array of
...
...
gcc/cp/ChangeLog
View file @
9a0d1e1b
Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
* exception.cc: Include eh-common.h.
(struct cp_eh_info): add eh_info struct with NEW_EH_MODEL.
(__cplus_type_matcher): First stab at new C++ runtime type matcher.
(__cp_push_exception): Initialize eh_info struct as well.
* except.c: Remove local structs and include eh-common.h.
(init_exception_processing): Set language and version codes.
(call_eh_info): add presence of eh_info to runtime description of
struct cp_eh_info.
(expand_end_eh_spec): call start_catch_block() and end_catch_block().
* semantics.c (finish_try_block): call start_catch_block() and
end_catch_block().
* parse.y (function_try_block): call start_catch_block() and
end_catch_block().
Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
* typeck.c (original_type): New function.
...
...
gcc/cp/except.c
View file @
9a0d1e1b
...
...
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "defaults.h"
#include "toplev.h"
#include "eh-common.h"
rtx
expand_builtin_return_addr
PROTO
((
enum
built_in_function
,
int
,
rtx
));
...
...
@@ -66,14 +67,6 @@ static tree do_pop_exception PROTO((void));
#endif
#ifdef EXCEPT_SECTION_ASM_OP
typedef struct {
void *start_region;
void *end_region;
void *exception_handler;
} exception_table;
#endif /* EXCEPT_SECTION_ASM_OP */
#ifdef EXCEPT_SECTION_ASM_OP
/* on machines which support it, the exception table lives in another section,
but it needs a label so we can reference it... This sets up that
...
...
@@ -227,6 +220,11 @@ init_exception_processing ()
push_lang_context
(
lang_name_c
);
#ifdef NEW_EH_MODEL
set_exception_lang_code
(
EH_LANG_C_plus_plus
);
set_exception_version_code
(
1
);
#endif
CatchMatch
=
builtin_function
(
flag_rtti
?
"__throw_type_match_rtti"
...
...
@@ -269,7 +267,8 @@ call_eh_info ()
fn
=
IDENTIFIER_GLOBAL_VALUE
(
fn
);
else
{
tree
t
,
fields
[
6
];
tree
t1
,
t
,
fields
[
7
];
int
fo
=
0
;
/* Declare cp_eh_info * __cp_exception_info (void),
as defined in exception.cc. */
...
...
@@ -278,25 +277,56 @@ call_eh_info ()
/* struct cp_eh_info. This must match exception.cc. Note that this
type is not pushed anywhere. */
#ifdef NEW_EH_MODEL
t1
=
make_lang_type
(
RECORD_TYPE
);
fields
[
0
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"handler_label"
),
ptr_type_node
);
fields
[
1
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"dynamic_handler_chain"
),
ptr_type_node
);
fields
[
2
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"info"
),
ptr_type_node
);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type
(
t1
,
"eh_context"
,
fields
,
2
,
ptr_type_node
);
t1
=
build_pointer_type
(
t1
);
t1
=
make_lang_type
(
RECORD_TYPE
);
fields
[
0
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"match_function"
),
ptr_type_node
);
fields
[
1
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"coerced_value"
),
ptr_type_node
);
fields
[
2
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"language"
),
short_integer_type_node
);
fields
[
3
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"version"
),
short_integer_type_node
);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type
(
t1
,
"__eh_info"
,
fields
,
3
,
ptr_type_node
);
fo
=
1
;
#endif
t
=
make_lang_type
(
RECORD_TYPE
);
fields
[
0
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"value"
),
#ifdef NEW_EH_MODEL
fields
[
0
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"eh_info"
),
t1
);
#endif
fields
[
0
+
fo
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"value"
),
ptr_type_node
);
fields
[
1
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"type"
),
fields
[
1
+
fo
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"type"
),
ptr_type_node
);
fields
[
2
]
=
build_lang_field_decl
fields
[
2
+
fo
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"cleanup"
),
build_pointer_type
(
build_function_type
(
ptr_type_node
,
tree_cons
(
NULL_TREE
,
ptr_type_node
,
void_list_node
))));
fields
[
3
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"caught"
),
fields
[
3
+
fo
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"caught"
),
boolean_type_node
);
fields
[
4
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"next"
),
fields
[
4
+
fo
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"next"
),
build_pointer_type
(
t
));
fields
[
5
]
=
build_lang_field_decl
fields
[
5
+
fo
]
=
build_lang_field_decl
(
FIELD_DECL
,
get_identifier
(
"handlers"
),
long_integer_type_node
);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type
(
t
,
"cp_eh_info"
,
fields
,
5
,
ptr_type_node
);
finish_builtin_type
(
t
,
"cp_eh_info"
,
fields
,
5
+
fo
,
ptr_type_node
);
t
=
build_pointer_type
(
t
);
/* And now the function. */
...
...
@@ -681,6 +711,7 @@ expand_end_eh_spec (raises)
int
count
=
0
;
expand_start_all_catch
();
expand_start_catch
(
NULL
);
expand_start_catch_block
(
NULL_TREE
,
NULL_TREE
);
/* Build up an array of type_infos. */
...
...
@@ -733,6 +764,7 @@ expand_end_eh_spec (raises)
expand_expr
(
tmp
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_end_catch_block
();
expand_end_catch
();
expand_end_all_catch
();
}
...
...
gcc/cp/exception.cc
View file @
9a0d1e1b
...
...
@@ -30,6 +30,7 @@
#include "typeinfo"
#include "exception"
#include <stddef.h>
#include "eh-common.h"
/* Define terminate, unexpected, set_terminate, set_unexpected as
well as the default terminate func and default unexpected func. */
...
...
@@ -85,6 +86,9 @@ std::unexpected ()
struct
cp_eh_info
{
#ifdef NEW_EH_MODEL
__eh_info
eh_info
;
#endif
void
*
value
;
void
*
type
;
void
(
*
cleanup
)(
void
*
,
int
);
...
...
@@ -133,6 +137,29 @@ __eh_free (void *p)
free
(
p
);
}
#ifdef NEW_EH_MODEL
typedef
void
*
(
*
rtimetype
)
(
void
);
extern
"C"
void
*
__cplus_type_matcher
(
cp_eh_info
*
info
,
exception_table
*
matching_info
,
exception_descriptor
*
exception_table
)
{
void
*
ret
;
if
(
exception_table
->
lang
.
language
!=
EH_LANG_C_plus_plus
)
return
NULL
;
/* we don't worry about version info yet, there is only one version! */
void
*
match_type
=
((
rtimetype
)
(
matching_info
->
match_info
))
();
ret
=
__throw_type_match_rtti
(
match_type
,
info
->
type
,
info
->
value
);
return
ret
;
}
#endif
/* Compiler hook to push a new exception onto the stack.
Used by expand_throw(). */
...
...
@@ -147,6 +174,13 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
p
->
handlers
=
0
;
p
->
caught
=
false
;
#ifdef NEW_EH_MODEL
p
->
eh_info
.
match_function
=
__cplus_type_matcher
;
p
->
eh_info
.
language
=
EH_LANG_C_plus_plus
;
p
->
eh_info
.
version
=
1
;
p
->
eh_info
.
coerced_value
=
NULL
;
#endif
cp_eh_info
**
q
=
__get_eh_info
();
p
->
next
=
*
q
;
...
...
gcc/cp/parse.y
View file @
9a0d1e1b
...
...
@@ -3222,12 +3222,16 @@ function_try_block:
expand_start_early_try_stmts ();
}
ctor_initializer_opt compstmt
{ expand_start_all_catch (); }
{
expand_start_all_catch ();
expand_start_catch (NULL);
}
handler_seq
{
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
expand_end_all_catch ();
expand_end_catch ();
finish_function (lineno, (int)$3, nested);
}
;
...
...
gcc/cp/semantics.c
View file @
9a0d1e1b
...
...
@@ -587,7 +587,10 @@ finish_try_block (try_block)
if
(
processing_template_decl
)
RECHAIN_STMTS_FROM_LAST
(
try_block
,
TRY_STMTS
(
try_block
));
else
expand_start_all_catch
();
{
expand_start_all_catch
();
expand_start_catch
(
NULL
);
}
}
/* Finish a handler-sequence for a try-block, which may be given by
...
...
@@ -600,7 +603,10 @@ finish_handler_sequence (try_block)
if
(
processing_template_decl
)
RECHAIN_STMTS_FROM_CHAIN
(
try_block
,
TRY_HANDLERS
(
try_block
));
else
expand_end_all_catch
();
{
expand_end_catch
();
expand_end_all_catch
();
}
}
/* Begin a handler. Returns a HANDLER if appropriate. */
...
...
gcc/eh-common.h
0 → 100644
View file @
9a0d1e1b
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of GNU CC. */
/* This file contains the structures required for the language
independant exception handling model. Both the static compiler and
the runtime library share this file. */
/* The compiler flag NEW_EH_MODEL is used to determine whether the
compiler supports the new runtime typechecking mechanism or not. Under
the new model, runtime info is contained in the exception table, and
the __throw() library routine determines which handler to call based
on the results of a call to a matching function provided by the expcetion
thrower. Otherwise the old scheme of calling any handler which matches
an exception range is used, and the handler is responsible for all
checking of runtime conditions. If the handler wasn't suppose to
get the exception, it performs a re-throw. */
#include "gansidecl.h"
#ifndef NEW_EH_MODEL
struct
eh_context
{
void
**
dynamic_handler_chain
;
/* This is language dependent part of the eh context. */
void
*
info
;
};
#else
/* The handler_label field MUST be the first field in this structure. The
__throw() library routine expects uses __eh_stub() from except.c, which
simply dereferences the context pointer to get the handler */
struct
eh_context
{
void
*
handler_label
;
void
**
dynamic_handler_chain
;
/* This is language dependent part of the eh context. */
void
*
info
;
};
#endif
#ifndef EH_TABLE_LOOKUP
#ifndef NEW_EH_MODEL
typedef
struct
exception_table
{
void
*
start_region
;
void
*
end_region
;
void
*
exception_handler
;
}
exception_table
;
typedef
exception_table
exception_descriptor
;
#else
typedef
struct
exception_table
{
void
*
start_region
;
void
*
end_region
;
void
*
exception_handler
;
void
*
match_info
;
/* runtime type info */
}
exception_table
;
/* The language identifying portion of an exception table */
typedef
struct
exception_lang_info
{
short
language
;
short
version
;
}
exception_lang_info
;
/* Each function has an exception_descriptor which contains the
language info, and a table of exception ranges and handlers */
typedef
struct
exception_descriptor
{
exception_lang_info
lang
;
exception_table
table
[
1
];
}
exception_descriptor
;
/* A pointer to a matching function is initialized at runtime by the
specific language if run-time exceptions are supported.
The function takes 3 parameters
1 - runtime exception that has been thrown info. (__eh_info *)
2 - Match info pointer from the region being considered (void *)
3 - exception table region is in (exception descriptor *)
*/
typedef
void
*
(
*
__eh_matcher
)
PROTO
((
void
*
,
void
*
,
void
*
));
/* This is the runtime exception information. This forms the minimum required
information for an exception info pointer in an eh_context structure. */
typedef
struct
__eh_info
{
__eh_matcher
match_function
;
void
*
coerced_value
;
short
language
;
short
version
;
}
__eh_info
;
/* Convienient language codes for ID the originating language. Similar
to the codes in dwarf2.h. */
enum
exception_source_language
{
EH_LANG_C89
=
0x0001
,
EH_LANG_C
=
0x0002
,
EH_LANG_Ada83
=
0x0003
,
EH_LANG_C_plus_plus
=
0x0004
,
EH_LANG_Cobol74
=
0x0005
,
EH_LANG_Cobol85
=
0x0006
,
EH_LANG_Fortran77
=
0x0007
,
EH_LANG_Fortran90
=
0x0008
,
EH_LANG_Pascal83
=
0x0009
,
EH_LANG_Modula2
=
0x000a
,
EH_LANG_Java
=
0x000b
,
EH_LANG_Mips_Assembler
=
0x8001
};
#endif
#endif
/* EH_TABLE_LOOKUP */
gcc/except.c
View file @
9a0d1e1b
...
...
@@ -390,6 +390,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "defaults.h"
#include "eh-common.h"
#include "system.h"
#include "rtl.h"
#include "tree.h"
...
...
@@ -442,6 +443,12 @@ rtx current_function_ehc;
static
struct
eh_stack
ehstack
;
/* This stack is used to represent what the current eh region is
for the catch blocks beings processed */
static
struct
eh_stack
catchstack
;
/* A queue used for tracking which exception regions have closed but
whose handlers have not yet been expanded. Regions are emitted in
groups in an attempt to improve paging performance.
...
...
@@ -553,6 +560,20 @@ top_label_entry (stack)
return
(
*
stack
)
->
u
.
tlabel
;
}
/* get an exception label. These must be on the permanent obstack */
rtx
gen_exception_label
()
{
rtx
lab
;
push_obstacks_nochange
();
end_temporary_allocation
();
lab
=
gen_label_rtx
();
pop_obstacks
();
return
lab
;
}
/* Push a new eh_node entry onto STACK. */
static
void
...
...
@@ -563,9 +584,22 @@ push_eh_entry (stack)
struct
eh_entry
*
entry
=
(
struct
eh_entry
*
)
xmalloc
(
sizeof
(
struct
eh_entry
));
entry
->
outer_context
=
gen_label_rtx
();
entry
->
exception_handler_label
=
gen_label_rtx
();
entry
->
finalization
=
NULL_TREE
;
entry
->
label_used
=
0
;
entry
->
exception_handler_label
=
gen_exception_label
();
node
->
entry
=
entry
;
node
->
chain
=
stack
->
top
;
stack
->
top
=
node
;
}
/* push an existing entry onto a stack. */
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
));
node
->
entry
=
entry
;
node
->
chain
=
stack
->
top
;
stack
->
top
=
node
;
...
...
@@ -631,6 +665,185 @@ dequeue_eh_entry (queue)
return
tempentry
;
}
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
{
int
range_number
;
/* EH region number from EH NOTE insn's */
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)
/* Add a new eh_entry for this function, and base it off of the information
in the EH_ENTRY parameter. A NULL parameter is invalid. The number
returned is an number which uniquely identifies this exception range. */
int
new_eh_region_entry
(
note_eh_region
)
int
note_eh_region
;
{
if
(
current_func_eh_entry
==
num_func_eh_entries
)
{
if
(
num_func_eh_entries
==
0
)
{
function_eh_regions
=
(
struct
func_eh_entry
*
)
malloc
(
SIZE_FUNC_EH
(
50
));
num_func_eh_entries
=
50
;
}
else
{
num_func_eh_entries
=
num_func_eh_entries
*
3
/
2
;
function_eh_regions
=
(
struct
func_eh_entry
*
)
realloc
(
function_eh_regions
,
SIZE_FUNC_EH
(
num_func_eh_entries
));
}
}
function_eh_regions
[
current_func_eh_entry
].
range_number
=
note_eh_region
;
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
;
newhandler
->
next
=
NULL
;
last
=
function_eh_regions
[
region
].
handlers
;
if
(
last
==
NULL
)
function_eh_regions
[
region
].
handlers
=
newhandler
;
else
{
for
(
;
last
->
next
!=
NULL
;
last
=
last
->
next
)
last
->
next
=
newhandler
;
}
}
/* 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
;
ptr
=
(
struct
handler_info
*
)
malloc
(
sizeof
(
struct
handler_info
));
ptr
->
handler_label
=
handler
;
ptr
->
type_info
=
typeinfo
;
ptr
->
next
=
NULL
;
return
ptr
;
}
/* Find the index in function_eh_regions associated with a NOTE region. If
the region cannot be found, a -1 is returned. This should never happen! */
int
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
;
{
return
function_eh_regions
[
find_func_region
(
region
)].
handlers
;
}
/* 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
for an exception region. Return the new handler index. */
int
duplicate_handlers
(
old_note_eh_region
,
new_note_eh_region
)
int
old_note_eh_region
,
new_note_eh_region
;
{
struct
handler_info
*
ptr
,
*
new_ptr
;
int
new_region
,
region
;
region
=
find_func_region
(
old_note_eh_region
);
if
(
region
==
-
1
)
error
(
"Cannot duplicate non-existant exception region."
);
if
(
find_func_region
(
new_note_eh_region
)
!=
-
1
)
error
(
"Cannot duplicate EH region because new note region already exists"
);
new_region
=
new_eh_region_entry
(
new_note_eh_region
);
ptr
=
function_eh_regions
[
region
].
handlers
;
for
(
;
ptr
;
ptr
=
ptr
->
next
)
{
new_ptr
=
get_new_handler
(
ptr
->
handler_label
,
ptr
->
type_info
);
add_new_handler
(
new_region
,
new_ptr
);
}
return
new_region
;
}
/* Routine to see if exception handling is turned on.
DO_WARN is non-zero if we want to inform the user that exception
...
...
@@ -1118,6 +1331,9 @@ expand_eh_region_end (handler)
entry
->
finalization
=
handler
;
/* create region entry in final exception table */
new_eh_region_entry
(
NOTE_BLOCK_NUMBER
(
note
));
enqueue_eh_entry
(
&
ehqueue
,
entry
);
/* If we have already started ending the bindings, don't recurse.
...
...
@@ -1232,19 +1448,13 @@ expand_leftover_cleanups ()
abort
();
/* Output the label for the start of the exception handler. */
emit_label
(
entry
->
exception_handler_label
);
#ifdef HAVE_exception_receiver
if
(
!
exceptions_via_longjmp
)
if
(
HAVE_exception_receiver
)
emit_insn
(
gen_exception_receiver
());
#endif
receive_exception_label
(
entry
->
exception_handler_label
);
#ifdef HAVE_nonlocal_goto_receiver
if
(
!
exceptions_via_longjmp
)
if
(
HAVE_nonlocal_goto_receiver
)
emit_insn
(
gen_nonlocal_goto_receiver
());
#endif
/* 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 handler. */
expand_expr
(
entry
->
finalization
,
const0_rtx
,
VOIDmode
,
0
);
...
...
@@ -1270,6 +1480,37 @@ expand_start_try_stmts ()
expand_eh_region_start
();
}
/* Called to begin a catch clause. The parameter is the object which
will be passed to the runtime type check routine. */
void
expand_start_catch
(
rtime
)
tree
rtime
;
{
rtx
handler_label
=
catchstack
.
top
->
entry
->
exception_handler_label
;
int
insn_region_num
=
CODE_LABEL_NUMBER
(
handler_label
);
int
eh_region_entry
=
find_func_region
(
insn_region_num
);
/* If we've already issued this label, pick a new one */
if
(
catchstack
.
top
->
entry
->
label_used
==
0
)
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
));
}
/* End a catch clause by dequeuing the current region */
void
expand_end_catch
()
{
struct
eh_entry
*
entry
;
entry
=
pop_eh_entry
(
&
catchstack
);
free
(
entry
);
}
/* Generate RTL for the start of a group of catch clauses.
It is responsible for starting a new instruction sequence for the
...
...
@@ -1308,12 +1549,13 @@ expand_start_all_catch ()
the handlers in this handler-seq. */
start_sequence
();
while
(
1
)
entry
=
dequeue_eh_entry
(
&
ehqueue
);
for
(
;
entry
->
finalization
!=
integer_zero_node
;
entry
=
dequeue_eh_entry
(
&
ehqueue
))
{
rtx
prev
;
entry
=
dequeue_eh_entry
(
&
ehqueue
);
/* Emit the label for the exception handler for this region, and
/* 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;
...
...
@@ -1322,29 +1564,15 @@ expand_start_all_catch ()
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. */
emit_label
(
entry
->
exception_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
receive_exception_label
(
entry
->
exception_handler_label
);
/* When we get down to the matching entry for this try block, stop. */
if
(
entry
->
finalization
==
integer_zero_node
)
{
/* Don't forget to free this entry. */
free
(
entry
);
break
;
}
/* 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 handler. */
/* And now generate the insns for the
cleanup
handler. */
expand_expr
(
entry
->
finalization
,
const0_rtx
,
VOIDmode
,
0
);
prev
=
get_last_insn
();
...
...
@@ -1358,6 +1586,12 @@ expand_start_all_catch ()
free
(
entry
);
}
/* 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. */
push_entry
(
&
catchstack
,
entry
);
/* 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
...
...
@@ -1496,15 +1730,16 @@ protect_with_terminate (e)
handler for the region. This is added by add_eh_table_entry and
used by output_exception_table_entry. */
static
int
*
eh_table
;
static
int
eh_table_size
;
static
int
eh_table_max_size
;
static
int
*
eh_table
=
NULL
;
static
int
eh_table_size
=
0
;
static
int
eh_table_max_size
=
0
;
/* Note the need for an exception table entry for region N. If we
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.
(Or NOTE_INSN_EH_REGION_END sometimes)
N is the NOTE_BLOCK_NUMBER of the note, which comes from the code
label number of the exception handler for the region. */
...
...
@@ -1562,24 +1797,60 @@ output_exception_table_entry (file, n)
{
char
buf
[
256
];
rtx
sym
;
int
eh_entry
;
struct
handler_info
*
handler
;
handler
=
get_first_handler
(
n
);
ASM_GENERATE_INTERNAL_LABEL
(
buf
,
"LEHB"
,
n
);
sym
=
gen_rtx_SYMBOL_REF
(
Pmode
,
buf
);
assemble_integer
(
sym
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
for
(
;
handler
!=
NULL
;
handler
=
handler
->
next
)
{
ASM_GENERATE_INTERNAL_LABEL
(
buf
,
"LEHB"
,
n
);
sym
=
gen_rtx_SYMBOL_REF
(
Pmode
,
buf
);
assemble_integer
(
sym
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
ASM_GENERATE_INTERNAL_LABEL
(
buf
,
"LEHE"
,
n
);
sym
=
gen_rtx_SYMBOL_REF
(
Pmode
,
buf
);
assemble_integer
(
sym
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
ASM_GENERATE_INTERNAL_LABEL
(
buf
,
"LEHE"
,
n
);
sym
=
gen_rtx_SYMBOL_REF
(
Pmode
,
buf
);
assemble_integer
(
sym
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
assemble_integer
(
handler
->
handler_label
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
ASM_GENERATE_INTERNAL_LABEL
(
buf
,
"L"
,
n
);
sym
=
gen_rtx_SYMBOL_REF
(
Pmode
,
buf
);
assemble_integer
(
sym
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
#ifdef NEW_EH_MODEL
/* for now make sure the sizes match */
if
(
handler
->
type_info
==
NULL
)
assemble_integer
(
const0_rtx
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
else
output_constant
((
tree
)(
handler
->
type_info
),
POINTER_SIZE
/
BITS_PER_UNIT
);
#endif
putc
(
'\n'
,
file
);
/* blank line */
putc
(
'\n'
,
file
);
/* blank line */
}
}
/* Output the exception table if we have and need one. */
#ifdef NEW_EH_MODEL
static
short
language_code
=
0
;
static
short
version_code
=
0
;
/* This routine will set the language code for exceptions. */
void
set_exception_lang_code
(
code
)
short
code
;
{
language_code
=
code
;
}
/* This routine will set the language version code for exceptions. */
void
set_exception_version_code
(
code
)
short
code
;
{
version_code
=
code
;
}
#endif
void
output_exception_table
()
{
...
...
@@ -1595,15 +1866,31 @@ output_exception_table ()
assemble_align
(
GET_MODE_ALIGNMENT
(
ptr_mode
));
assemble_label
(
"__EXCEPTION_TABLE__"
);
#ifdef NEW_EH_MODEL
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
);
#endif
for
(
i
=
0
;
i
<
eh_table_size
;
++
i
)
output_exception_table_entry
(
asm_out_file
,
eh_table
[
i
]);
free
(
eh_table
);
clear_function_eh_region
();
/* Ending marker for table. */
assemble_integer
(
constm1_rtx
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
#ifndef NEW_EH_MODEL
/* for binary compatability, the old __throw checked the second
position for a -1, so we should output at least 2 -1's */
assemble_integer
(
constm1_rtx
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
assemble_integer
(
constm1_rtx
,
POINTER_SIZE
/
BITS_PER_UNIT
,
1
);
#endif
putc
(
'\n'
,
asm_out_file
);
/* blank line */
}
...
...
@@ -1662,9 +1949,6 @@ void
find_exception_handler_labels
()
{
rtx
insn
;
int
max_labelno
=
max_label_num
();
int
min_labelno
=
get_first_label_num
();
rtx
*
labels
;
exception_handler_labels
=
NULL_RTX
;
...
...
@@ -1672,53 +1956,42 @@ find_exception_handler_labels ()
if
(
!
doing_eh
(
0
))
return
;
/* Generate a handy reference to each label. */
/* We call xmalloc here instead of alloca; we did the latter in the past,
but found that it can sometimes end up being asked to allocate space
for more than 1 million labels. */
labels
=
(
rtx
*
)
xmalloc
((
max_labelno
-
min_labelno
)
*
sizeof
(
rtx
));
bzero
((
char
*
)
labels
,
(
max_labelno
-
min_labelno
)
*
sizeof
(
rtx
));
/* Arrange for labels to be indexed directly by CODE_LABEL_NUMBER. */
labels
-=
min_labelno
;
for
(
insn
=
get_insns
();
insn
;
insn
=
NEXT_INSN
(
insn
))
{
if
(
GET_CODE
(
insn
)
==
CODE_LABEL
)
if
(
CODE_LABEL_NUMBER
(
insn
)
>=
min_labelno
&&
CODE_LABEL_NUMBER
(
insn
)
<
max_labelno
)
labels
[
CODE_LABEL_NUMBER
(
insn
)]
=
insn
;
}
/* For each start of a region, add its label to the list. */
for
(
insn
=
get_insns
();
insn
;
insn
=
NEXT_INSN
(
insn
))
{
struct
handler_info
*
ptr
;
if
(
GET_CODE
(
insn
)
==
NOTE
&&
NOTE_LINE_NUMBER
(
insn
)
==
NOTE_INSN_EH_REGION_BEG
)
{
rtx
label
=
NULL_RTX
;
if
(
NOTE_BLOCK_NUMBER
(
insn
)
>=
min_labelno
&&
NOTE_BLOCK_NUMBER
(
insn
)
<
max_labelno
)
{
label
=
labels
[
NOTE_BLOCK_NUMBER
(
insn
)];
if
(
label
)
exception_handler_labels
=
gen_rtx_EXPR_LIST
(
VOIDmode
,
label
,
exception_handler_labels
);
else
warning
(
"didn't find handler for EH region %d"
,
NOTE_BLOCK_NUMBER
(
insn
));
}
else
warning
(
"mismatched EH region %d"
,
NOTE_BLOCK_NUMBER
(
insn
));
ptr
=
get_first_handler
(
NOTE_BLOCK_NUMBER
(
insn
));
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
);
}
}
}
}
/* Return a value of 1 if the parameter label number is an exception handler
label. Return 0 otherwise. */
free
(
labels
+
min_labelno
);
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
;
}
/* Perform sanity checking on the exception_handler_labels list.
...
...
@@ -1730,60 +2003,24 @@ find_exception_handler_labels ()
void
check_exception_handler_labels
()
{
rtx
insn
,
handler
;
rtx
insn
,
insn2
;
/* If we aren't doing exception handling, there isn't much to check. */
if
(
!
doing_eh
(
0
))
return
;
/* Ensure that the CODE_LABEL_NUMBER for the CODE_LABEL entry point
in each handler corresponds to the CODE_LABEL_NUMBER of the
handler. */
for
(
handler
=
exception_handler_labels
;
handler
;
handler
=
XEXP
(
handler
,
1
))
/* Make sure there is no more than 1 copy of a label */
for
(
insn
=
exception_handler_labels
;
insn
;
insn
=
XEXP
(
insn
,
1
))
{
for
(
insn
=
get_insns
();
insn
;
insn
=
NEXT_INSN
(
insn
))
{
if
(
GET_CODE
(
insn
)
==
CODE_LABEL
)
{
if
(
CODE_LABEL_NUMBER
(
insn
)
==
CODE_LABEL_NUMBER
(
XEXP
(
handler
,
0
)))
{
if
(
insn
!=
XEXP
(
handler
,
0
))
warning
(
"mismatched handler %d"
,
CODE_LABEL_NUMBER
(
insn
));
break
;
}
}
}
if
(
insn
==
NULL_RTX
)
warning
(
"handler not found %d"
,
CODE_LABEL_NUMBER
(
XEXP
(
handler
,
0
)));
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
));
}
/* Now go through and make sure that for each region there is a
corresponding label. */
for
(
insn
=
get_insns
();
insn
;
insn
=
NEXT_INSN
(
insn
))
{
if
(
GET_CODE
(
insn
)
==
NOTE
&&
(
NOTE_LINE_NUMBER
(
insn
)
==
NOTE_INSN_EH_REGION_BEG
||
NOTE_LINE_NUMBER
(
insn
)
==
NOTE_INSN_EH_REGION_END
))
{
for
(
handler
=
exception_handler_labels
;
handler
;
handler
=
XEXP
(
handler
,
1
))
{
if
(
CODE_LABEL_NUMBER
(
XEXP
(
handler
,
0
))
==
NOTE_BLOCK_NUMBER
(
insn
))
break
;
}
if
(
handler
==
NULL_RTX
&&
!
flag_syntax_only
)
warning
(
"region exists, no handler %d"
,
NOTE_BLOCK_NUMBER
(
insn
));
}
}
}
/* This group of functions initializes the exception handling data
...
...
@@ -1805,6 +2042,7 @@ void
init_eh_for_function
()
{
ehstack
.
top
=
0
;
catchstack
.
top
=
0
;
ehqueue
.
head
=
ehqueue
.
tail
=
0
;
catch_clauses
=
NULL_RTX
;
false_label_stack
=
0
;
...
...
@@ -1826,6 +2064,7 @@ save_eh_status (p)
abort
();
p
->
ehstack
=
ehstack
;
p
->
catchstack
=
catchstack
;
p
->
ehqueue
=
ehqueue
;
p
->
catch_clauses
=
catch_clauses
;
p
->
false_label_stack
=
false_label_stack
;
...
...
@@ -1853,6 +2092,7 @@ restore_eh_status (p)
catch_clauses
=
p
->
catch_clauses
;
ehqueue
=
p
->
ehqueue
;
ehstack
=
p
->
ehstack
;
catchstack
=
p
->
catchstack
;
current_function_ehc
=
p
->
ehc
;
}
...
...
@@ -1951,6 +2191,10 @@ scan_region (insn, n, delete_outer)
delete_insn
(
start
);
delete_insn
(
insn
);
/* We no longer removed labels here, since flow will now remove any
handler which cannot be called any more. */
#if 0
/* Only do this part if we have built the exception handler
labels. */
if (exception_handler_labels)
...
...
@@ -1984,6 +2228,7 @@ scan_region (insn, n, delete_outer)
prev = &XEXP (x, 1);
}
}
#endif
}
return
insn
;
}
...
...
@@ -2133,6 +2378,20 @@ eh_regs (r1, r2, outgoing)
*
r2
=
reg2
;
}
/* Retrieve the register which contains the pointer to the eh_context
structure set the __throw. */
rtx
get_reg_for_handler
()
{
rtx
reg1
;
reg1
=
FUNCTION_VALUE
(
build_pointer_type
(
void_type_node
),
current_function_decl
);
return
reg1
;
}
/* Emit inside of __throw a stub which adjusts the stack pointer and jumps
to the exception handler. __throw will set up the necessary values
and then return to the stub. */
...
...
@@ -2150,8 +2409,28 @@ expand_builtin_eh_stub ()
eh_regs
(
&
handler
,
&
offset
,
0
);
adjust_stack
(
offset
);
#ifdef NEW_EH_MODEL
/* Handler is in fact a pointer to the _eh_context structure, we need
to pick out the handler field (first element), and jump to there,
leaving the pointer to _eh_conext in the same hardware register. */
{
rtx
jump_to
,
temp
;
temp
=
gen_rtx_MEM
(
Pmode
,
handler
);
MEM_IN_STRUCT_P
(
temp
)
=
1
;
RTX_UNCHANGING_P
(
temp
)
=
1
;
emit_insn
(
gen_rtx_SET
(
Pmode
,
offset
,
temp
));
emit_insn
(
gen_rtx_USE
(
Pmode
,
handler
));
emit_indirect_jump
(
offset
);
}
#else
emit_indirect_jump
(
handler
);
#endif
emit_label
(
after_stub
);
return
gen_rtx_LABEL_REF
(
Pmode
,
stub_start
);
}
...
...
@@ -2213,7 +2492,8 @@ set_insn_eh_region (first, region_num)
/* Free the insn table, an make sure it cannot be used again. */
void
free_insn_eh_region
()
void
free_insn_eh_region
()
{
if
(
!
doing_eh
(
0
))
return
;
...
...
@@ -2229,7 +2509,8 @@ void free_insn_eh_region ()
this routine. If it is unavailable, passing a value of 0 will
cause this routine to calculate it as well. */
void
init_insn_eh_region
(
first
,
max_uid
)
void
init_insn_eh_region
(
first
,
max_uid
)
rtx
first
;
int
max_uid
;
{
...
...
@@ -2255,8 +2536,9 @@ void init_insn_eh_region (first, max_uid)
/* Check whether 2 instructions are within the same region. */
int
in_same_eh_region
(
insn1
,
insn2
)
rtx
insn1
,
insn2
;
int
in_same_eh_region
(
insn1
,
insn2
)
rtx
insn1
,
insn2
;
{
int
ret
,
uid1
,
uid2
;
...
...
gcc/except.h
View file @
9a0d1e1b
...
...
@@ -43,6 +43,10 @@ struct label_node {
EXCEPTION_HANDLER_LABEL is the label corresponding to the handler
for this region.
LABEL_USED indicates whether a CATCH block has already used this
label or not. New ones are needed for additional catch blocks if
it has.
FINALIZATION is the tree codes for the handler, or is NULL_TREE if
one hasn't been generated yet, or is integer_zero_node to mark the
end of a group of try blocks. */
...
...
@@ -50,8 +54,8 @@ struct label_node {
struct
eh_entry
{
rtx
outer_context
;
rtx
exception_handler_label
;
tree
finalization
;
int
label_used
;
};
/* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next
...
...
@@ -145,17 +149,89 @@ extern int doing_eh PROTO ((int));
/* Toplevel initialization for EH. */
#ifdef NEW_EH_MODEL
void
set_exception_lang_code
PROTO
((
short
));
void
set_exception_version_code
PROTO
((
short
));
#endif
/* A list of handlers asocciated with an exception region. HANDLER_LABEL
is the the label that control should be transfered to if the data
in TYPE_INFO matches an exception. a value of NULL_TREE for TYPE_INFO
means This is a cleanup, and must always be called. A value of
CATCH_ALL_TYPE works like a cleanup, but a call to the runtime matcher
is still performed to avoid being caught by a different language
exception. NEXT is a pointer to the next handler for this region.
NULL means there are no more. */
#define CATCH_ALL_TYPE (tree *) -1
typedef
struct
handler_info
{
rtx
handler_label
;
void
*
type_info
;
struct
handler_info
*
next
;
}
handler_info
;
/* Add a new eh_entry for this function, The parameter specifies what
exception region number NOTE insns use to delimit this range.
The integer returned is uniquely identifies this exception range
within an internal table. */
int
new_eh_region_entry
PROTO
((
int
));
/* 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
PROTO
((
int
,
struct
handler_info
*
));
/* Create a new handler structure initialized with the handler label and
typeinfo fields passed in. */
struct
handler_info
*
get_new_handler
PROTO
((
rtx
,
void
*
));
/* Make a duplicate of an exception region by copying all the handlers
for an exception region. Return the new handler index. */
int
duplicate_handlers
PROTO
((
int
,
int
));
/* Get a pointer to the first handler in an exception region's list. */
struct
handler_info
*
get_first_handler
PROTO
((
int
));
extern
void
init_eh
PROTO
((
void
));
/* Initialization for the per-function EH data. */
extern
void
init_eh_for_function
PROTO
((
void
));
/* Generate an exception label. Use instead of gen_label_rtx */
extern
rtx
gen_exception_label
PROTO
((
void
));
/* Adds an EH table entry for EH entry number N. Called from
final_scan_insn for NOTE_INSN_EH_REGION_BEG. */
extern
void
add_eh_table_entry
PROTO
((
int
n
));
/* Start a catch clause, triggered by runtime value paramter. */
#ifdef TREE_CODE
extern
void
expand_start_catch
PROTO
((
tree
));
#endif
/* End a catch clause. */
extern
void
expand_end_catch
PROTO
((
void
));
/* Returns a non-zero value if we need to output an exception table. */
extern
int
exception_table_p
PROTO
((
void
));
...
...
@@ -225,6 +301,10 @@ extern void end_eh_unwinder PROTO((void));
extern
void
find_exception_handler_labels
PROTO
((
void
));
/* Determine if an arbitrary label is an exception label */
extern
int
is_exception_handler_label
PROTO
((
int
));
/* Performs sanity checking on the check_exception_handler_labels
list. */
...
...
gcc/final.c
View file @
9a0d1e1b
...
...
@@ -1988,7 +1988,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
&&
!
exceptions_via_longjmp
)
{
ASM_OUTPUT_INTERNAL_LABEL
(
file
,
"LEHB"
,
NOTE_BLOCK_NUMBER
(
insn
));
#ifndef NEW_EH_MODEL
add_eh_table_entry
(
NOTE_BLOCK_NUMBER
(
insn
));
#endif
#ifdef ASM_OUTPUT_EH_REGION_BEG
ASM_OUTPUT_EH_REGION_BEG
(
file
,
NOTE_BLOCK_NUMBER
(
insn
));
#endif
...
...
@@ -1999,6 +2001,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
&&
!
exceptions_via_longjmp
)
{
ASM_OUTPUT_INTERNAL_LABEL
(
file
,
"LEHE"
,
NOTE_BLOCK_NUMBER
(
insn
));
#ifdef NEW_EH_MODEL
add_eh_table_entry
(
NOTE_BLOCK_NUMBER
(
insn
));
#endif
#ifdef ASM_OUTPUT_EH_REGION_END
ASM_OUTPUT_EH_REGION_END
(
file
,
NOTE_BLOCK_NUMBER
(
insn
));
#endif
...
...
gcc/flow.c
View file @
9a0d1e1b
...
...
@@ -396,7 +396,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
register
char
*
block_marked
=
(
char
*
)
alloca
(
n_basic_blocks
);
/* An array of CODE_LABELs, indexed by UID for the start of the active
EH handler for each insn in F. */
rtx
*
active_eh_handler
;
int
*
active_eh_region
;
int
*
nested_eh_region
;
/* List of label_refs to all labels whose addresses are taken
and used as data. */
rtx
label_value_list
;
...
...
@@ -406,7 +407,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
int
in_libcall_block
=
0
;
pass
=
1
;
active_eh_handler
=
(
rtx
*
)
alloca
((
max_uid_for_flow
+
1
)
*
sizeof
(
rtx
));
active_eh_region
=
(
int
*
)
alloca
((
max_uid_for_flow
+
1
)
*
sizeof
(
int
));
nested_eh_region
=
(
int
*
)
alloca
((
max_label_num
()
+
1
)
*
sizeof
(
int
));
restart
:
label_value_list
=
0
;
...
...
@@ -414,7 +416,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
bzero
(
block_live
,
n_basic_blocks
);
bzero
(
block_marked
,
n_basic_blocks
);
bzero
(
basic_block_computed_jump_target
,
n_basic_blocks
);
bzero
((
char
*
)
active_eh_handler
,
(
max_uid_for_flow
+
1
)
*
sizeof
(
rtx
));
bzero
((
char
*
)
active_eh_region
,
(
max_uid_for_flow
+
1
)
*
sizeof
(
int
));
bzero
((
char
*
)
nested_eh_region
,
(
max_label_num
()
+
1
)
*
sizeof
(
int
));
current_function_has_computed_jump
=
0
;
/* Initialize with just block 0 reachable and no blocks marked. */
...
...
@@ -482,20 +485,18 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
label_value_list
);
}
/* Keep a lifo list of the currently active exception
handler
s. */
/* Keep a lifo list of the currently active exception
note
s. */
if
(
GET_CODE
(
insn
)
==
NOTE
)
{
if
(
NOTE_LINE_NUMBER
(
insn
)
==
NOTE_INSN_EH_REGION_BEG
)
{
for
(
x
=
exception_handler_labels
;
x
;
x
=
XEXP
(
x
,
1
))
if
(
CODE_LABEL_NUMBER
(
XEXP
(
x
,
0
))
==
NOTE_BLOCK_NUMBER
(
insn
))
{
eh_note
=
gen_rtx_EXPR_LIST
(
VOIDmode
,
XEXP
(
x
,
0
),
eh_note
);
break
;
}
if
(
x
==
NULL_RTX
)
abort
();
if
(
eh_note
)
nested_eh_region
[
NOTE_BLOCK_NUMBER
(
insn
)]
=
NOTE_BLOCK_NUMBER
(
XEXP
(
eh_note
,
0
));
else
nested_eh_region
[
NOTE_BLOCK_NUMBER
(
insn
)]
=
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
);
...
...
@@ -509,8 +510,8 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
&&
(
asynchronous_exceptions
||
(
GET_CODE
(
insn
)
==
CALL_INSN
&&
!
in_libcall_block
)))
active_eh_
handler
[
INSN_UID
(
insn
)]
=
XEXP
(
eh_note
,
0
);
active_eh_
region
[
INSN_UID
(
insn
)]
=
NOTE_BLOCK_NUMBER
(
XEXP
(
eh_note
,
0
));
BLOCK_NUM
(
insn
)
=
i
;
if
(
code
!=
NOTE
)
...
...
@@ -655,11 +656,20 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
&&
!
find_reg_note
(
insn
,
REG_RETVAL
,
NULL_RTX
)))
{
if
(
active_eh_handler
[
INSN_UID
(
insn
)])
mark_label_ref
(
gen_rtx_LABEL_REF
(
VOIDmode
,
active_eh_handler
[
INSN_UID
(
insn
)]),
insn
,
0
);
if
(
active_eh_region
[
INSN_UID
(
insn
)])
{
int
region
;
handler_info
*
ptr
;
region
=
active_eh_region
[
INSN_UID
(
insn
)];
for
(
;
region
;
region
=
nested_eh_region
[
region
])
{
ptr
=
get_first_handler
(
region
);
for
(
;
ptr
;
ptr
=
ptr
->
next
)
mark_label_ref
(
gen_rtx_LABEL_REF
(
VOIDmode
,
ptr
->
handler_label
),
insn
,
0
);
}
}
if
(
!
asynchronous_exceptions
)
{
for
(
x
=
nonlocal_label_list
;
...
...
@@ -764,6 +774,10 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
/* Now we have to find the EH_BEG and EH_END notes
associated with this label and remove them. */
#if 0
/* Handlers and labels no longer needs to have the same values.
If there are no references, scan_region will remove any region
labels which are of no use. */
for (x = get_insns (); x; x = NEXT_INSN (x))
{
if (GET_CODE (x) == NOTE
...
...
@@ -778,6 +792,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
NOTE_SOURCE_FILE (x) = 0;
}
}
#endif
break
;
}
prev
=
&
XEXP
(
x
,
1
);
...
...
gcc/function.h
View file @
9a0d1e1b
...
...
@@ -133,6 +133,7 @@ struct function
/* For exception handling information. */
struct
eh_stack
ehstack
;
struct
eh_stack
catchstack
;
struct
eh_queue
ehqueue
;
rtx
catch_clauses
;
struct
label_node
*
false_label_stack
;
...
...
gcc/integrate.c
View file @
9a0d1e1b
...
...
@@ -95,7 +95,12 @@ get_label_from_map (map, i)
rtx
x
=
map
->
label_map
[
i
];
if
(
x
==
NULL_RTX
)
x
=
map
->
label_map
[
i
]
=
gen_label_rtx
();
{
push_obstacks_nochange
();
end_temporary_allocation
();
x
=
map
->
label_map
[
i
]
=
gen_label_rtx
();
pop_obstacks
();
}
return
x
;
}
...
...
@@ -658,10 +663,28 @@ save_for_inline_copying (fndecl)
if
(
NOTE_LINE_NUMBER
(
copy
)
==
NOTE_INSN_EH_REGION_BEG
||
NOTE_LINE_NUMBER
(
copy
)
==
NOTE_INSN_EH_REGION_END
)
{
int
new_region
=
CODE_LABEL_NUMBER
(
label_map
[
NOTE_BLOCK_NUMBER
(
copy
)]);
/* we have to duplicate the handlers for the original */
if
(
NOTE_LINE_NUMBER
(
copy
)
==
NOTE_INSN_EH_REGION_BEG
)
{
handler_info
*
ptr
,
*
temp
;
int
nr
;
nr
=
new_eh_region_entry
(
new_region
);
ptr
=
get_first_handler
(
NOTE_BLOCK_NUMBER
(
copy
));
for
(
;
ptr
;
ptr
=
ptr
->
next
)
{
temp
=
get_new_handler
(
label_map
[
CODE_LABEL_NUMBER
(
ptr
->
handler_label
)],
ptr
->
type_info
);
add_new_handler
(
nr
,
temp
);
}
}
/* We have to forward these both to match the new exception
region. */
NOTE_BLOCK_NUMBER
(
copy
)
=
CODE_LABEL_NUMBER
(
label_map
[
NOTE_BLOCK_NUMBER
(
copy
)]);
NOTE_BLOCK_NUMBER
(
copy
)
=
new_region
;
}
RTX_INTEGRATED_P
(
copy
)
=
RTX_INTEGRATED_P
(
insn
);
...
...
@@ -2038,6 +2061,22 @@ expand_inline_function (fndecl, parms, target, ignore, type,
rtx
label
=
get_label_from_map
(
map
,
NOTE_BLOCK_NUMBER
(
copy
));
/* we have to duplicate the handlers for the original */
if
(
NOTE_LINE_NUMBER
(
copy
)
==
NOTE_INSN_EH_REGION_BEG
)
{
handler_info
*
ptr
,
*
temp
;
int
nr
;
nr
=
new_eh_region_entry
(
CODE_LABEL_NUMBER
(
label
));
ptr
=
get_first_handler
(
NOTE_BLOCK_NUMBER
(
copy
));
for
(
;
ptr
;
ptr
=
ptr
->
next
)
{
temp
=
get_new_handler
(
get_label_from_map
(
map
,
CODE_LABEL_NUMBER
(
ptr
->
handler_label
)),
ptr
->
type_info
);
add_new_handler
(
nr
,
temp
);
}
}
/* We have to forward these both to match the new exception
region. */
NOTE_BLOCK_NUMBER
(
copy
)
=
CODE_LABEL_NUMBER
(
label
);
...
...
gcc/libgcc2.c
View file @
9a0d1e1b
...
...
@@ -3046,14 +3046,10 @@ __empty ()
{
}
/* EH context structure. */
struct
eh_context
{
void
**
dynamic_handler_chain
;
/* This is language dependent part of the eh context. */
void
*
info
;
};
/* Include definitions of EH context and table layout */
#include "eh-common.h"
/* This is a safeguard for dynamic handler chain. */
...
...
@@ -3361,11 +3357,6 @@ EH_TABLE_LOOKUP
#else
#ifdef DWARF2_UNWIND_INFO
typedef
struct
exception_table
{
void
*
start
;
void
*
end
;
void
*
exception_handler
;
}
exception_table
;
/* This routine takes a PC and a pointer to the exception region TABLE for
its translation unit, and returns the address of the exception handler
...
...
@@ -3376,31 +3367,68 @@ typedef struct exception_table {
an inner block. */
static
void
*
find_exception_handler
(
void
*
pc
,
exception_
table
*
table
)
find_exception_handler
(
void
*
pc
,
exception_
descriptor
*
table
,
void
*
eh_info
)
{
if
(
table
)
{
#ifdef NEW_EH_MODEL
/* The new model assumed the table is sorted inner-most out so the
first region we find which matches is the correct one */
int
pos
;
void
*
ret
;
exception_table
*
tab
=
&
(
table
->
table
[
0
]);
/* Subtract 1 from the PC to avoid hitting the next region */
pc
--
;
/* We can't do a binary search because the table is in inner-most
to outermost address ranges within functions */
for
(
pos
=
0
;
tab
[
pos
].
start_region
!=
(
void
*
)
-
1
;
pos
++
)
{
if
(
tab
[
pos
].
start_region
<=
pc
&&
tab
[
pos
].
end_region
>
pc
)
{
if
(
tab
[
pos
].
match_info
)
{
__eh_matcher
matcher
=
((
__eh_info
*
)
eh_info
)
->
match_function
;
/* match info but no matcher is NOT a match */
if
(
matcher
)
{
ret
=
(
*
matcher
)(
eh_info
,
tab
[
pos
].
match_info
,
table
);
if
(
ret
)
{
((
__eh_info
*
)
eh_info
)
->
coerced_value
=
ret
;
return
tab
[
pos
].
exception_handler
;
}
}
}
else
return
tab
[
pos
].
exception_handler
;
}
}
#else
int
pos
;
int
best
=
-
1
;
/* We can't do a binary search because the table isn't guaranteed
to be sorted from function to function. */
for
(
pos
=
0
;
table
[
pos
].
exception_handler
!=
(
void
*
)
-
1
;
++
pos
)
{
if
(
table
[
pos
].
start
<=
pc
&&
table
[
pos
].
end
>
pc
)
{
/* This can apply. Make sure it is at least as small as
the previous best. */
if
(
best
==
-
1
||
(
table
[
pos
].
end
<=
table
[
best
].
end
&&
table
[
pos
].
start
>=
table
[
best
].
start
))
best
=
pos
;
}
/* But it is sorted by starting PC within a function. */
else
if
(
best
>=
0
&&
table
[
pos
].
start
>
pc
)
break
;
}
to be sorted from function to function. */
for
(
pos
=
0
;
table
[
pos
].
start_region
!=
(
void
*
)
-
1
;
++
pos
)
{
if
(
table
[
pos
].
start_region
<=
pc
&&
table
[
pos
].
end_region
>
pc
)
{
/* This can apply. Make sure it is at least as small as
the previous best. */
if
(
best
==
-
1
||
(
table
[
pos
].
end_region
<=
table
[
best
].
end_region
&&
table
[
pos
].
start_region
>=
table
[
best
].
start_region
))
best
=
pos
;
}
/* But it is sorted by starting PC within a function. */
else
if
(
best
>=
0
&&
table
[
pos
].
start_region
>
pc
)
break
;
}
if
(
best
!=
-
1
)
return
table
[
best
].
exception_handler
;
return
table
[
best
].
exception_handler
;
#endif
}
return
(
void
*
)
0
;
...
...
@@ -3583,7 +3611,7 @@ label:
if
(
!
udata
)
break
;
handler
=
find_exception_handler
(
pc
,
udata
->
eh_ptr
);
handler
=
find_exception_handler
(
pc
,
udata
->
eh_ptr
,
eh
->
info
);
/* If we found one, we can stop searching. */
if
(
handler
)
...
...
@@ -3602,6 +3630,10 @@ label:
if
(
!
handler
)
__terminate
();
#ifdef NEW_EH_MODEL
eh
->
handler_label
=
handler
;
#endif
if
(
pc
==
saved_pc
)
/* We found a handler in the throw context, no need to unwind. */
udata
=
my_udata
;
...
...
@@ -3669,7 +3701,13 @@ label:
/* Set up the registers we use to communicate with the stub.
We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack. */
#ifdef NEW_EH_MODEL
__builtin_set_eh_regs
((
void
*
)
eh
,
#else
__builtin_set_eh_regs
(
handler
,
#endif
#ifdef STACK_GROWS_DOWNWARD
udata
->
cfa
-
my_udata
->
cfa
#else
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment