⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 except.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Handle exceptional things in C++.   Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.   Contributed by Michael Tiemann <tiemann@cygnus.com>   Rewritten by Mike Stump <mrs@cygnus.com>, based upon an   initial re-implementation courtesy Tad Hunt.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  *//* High-level class interface. */#include "config.h"#include "tree.h"#include "rtl.h"#include "cp-tree.h"#include "flags.h"#include "obstack.h"#include "expr.h"tree protect_list;extern void (*interim_eh_hook)	PROTO((tree));rtx expand_builtin_return_addr	PROTO((enum built_in_function, int, rtx));/* holds the fndecl for __builtin_return_address () */tree builtin_return_address_fndecl;tree throw_fndecl;static intdoing_eh (do_warn)     int do_warn;{  if (! flag_handle_exceptions)    {      static int warned = 0;      if (! warned && do_warn)	{	  error ("exception handling disabled, use -fhandle-exceptions to enable.");	  warned = 1;	}      return 0;    }  return 1;}/*NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closerto supporting exception handling as per ANSI C++ working draft.It is a complete rewrite of all the EH stuff that was here before	Shortcomings:		1. Throw specifications of functions still don't work.	Cool Things:		1. Destructors are called properly :-)		2. No overhead for the non-exception thrown case.		3. Fixing shortcoming 1 is simple.			-Tad Hunt	(tad@mail.csh.rit.edu)*//* A couple of backend routines from m88k.c *//* used to cache a call to __builtin_return_address () */static tree BuiltinReturnAddress;     #include <stdio.h>/* XXX - Tad: for EH *//* output an exception table entry */static voidoutput_exception_table_entry (file, start_label, end_label, eh_label)     FILE *file;     rtx start_label, end_label, eh_label;{  char label[100];  assemble_integer (start_label, GET_MODE_SIZE (Pmode), 1);  assemble_integer (end_label, GET_MODE_SIZE (Pmode), 1);  assemble_integer (eh_label, GET_MODE_SIZE (Pmode), 1);  putc ('\n', file);		/* blank line */}   static voideasy_expand_asm (str)     char *str;{  expand_asm (build_string (strlen (str)+1, str));}#if 0/* This is the startup, and finish stuff per exception table. *//* XXX - Tad: exception handling section */#ifndef EXCEPT_SECTION_ASM_OP#define EXCEPT_SECTION_ASM_OP	"section\t.gcc_except_table,\"a\",@progbits"#endif#ifdef EXCEPT_SECTION_ASM_OPtypedef struct {    void *start_protect;    void *end_protect;    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    label! */asm (EXCEPT_SECTION_ASM_OP);exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };asm (TEXT_SECTION_ASM_OP);#endif /* EXCEPT_SECTION_ASM_OP */#ifdef EXCEPT_SECTION_ASM_OP /* we need to know where the end of the exception table is... so this    is how we do it! */asm (EXCEPT_SECTION_ASM_OP);exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };asm (TEXT_SECTION_ASM_OP);#endif /* EXCEPT_SECTION_ASM_OP */#endifvoidexception_section (){#ifdef ASM_OUTPUT_SECTION_NAME  named_section (NULL_TREE, ".gcc_except_table");#else  if (flag_pic)    data_section ();  else#if defined(TARGET_POWERPC) /* are we on a __rs6000? */    data_section ();#else    readonly_data_section ();#endif#endif}/* from: my-cp-except.c *//* VI: ":set ts=4" */#if 0#include <stdio.h> */#include "config.h"#include "tree.h"#include "rtl.h"#include "cp-tree.h"#endif#include "decl.h"#if 0#include "flags.h"#endif#include "insn-flags.h"#include "obstack.h"#if 0#include "expr.h"#endif/* ======================================================================   Briefly the algorithm works like this:     When a constructor or start of a try block is encountered,     push_eh_entry (&eh_stack) is called.  Push_eh_entry () creates a     new entry in the unwind protection stack and returns a label to     output to start the protection for that block.     When a destructor or end try block is encountered, pop_eh_entry     (&eh_stack) is called.  Pop_eh_entry () returns the ehEntry it     created when push_eh_entry () was called.  The ehEntry structure     contains three things at this point.  The start protect label,     the end protect label, and the exception handler label.  The end     protect label should be output before the call to the destructor     (if any). If it was a destructor, then its parse tree is stored     in the finalization variable in the ehEntry structure.  Otherwise     the finalization variable is set to NULL to reflect the fact that     is the the end of a try block.  Next, this modified ehEntry node     is enqueued in the finalizations queue by calling     enqueue_eh_entry (&queue,entry).	+---------------------------------------------------------------+	|XXX: Will need modification to deal with partially		|	|			constructed arrays of objects		|	|								|	|	Basically, this consists of keeping track of how many	|	|	of the objects have been constructed already (this	|	|	should be in a register though, so that shouldn't be a	|	|	problem.						|	+---------------------------------------------------------------+     When a catch block is encountered, there is a lot of work to be     done.     Since we don't want to generate the catch block inline with the     regular flow of the function, we need to have some way of doing     so.  Luckily, we can use sequences to defer the catch sections.     When the start of a catch block is encountered, we start the     sequence.  After the catch block is generated, we end the     sequence.     Next we must insure that when the catch block is executed, all     finalizations for the matching try block have been completed.  If     any of those finalizations throw an exception, we must call     terminate according to the ARM (section r.15.6.1).  What this     means is that we need to dequeue and emit finalizations for each     entry in the ehQueue until we get to an entry with a NULL     finalization field.  For any of the finalization entries, if it     is not a call to terminate (), we must protect it by giving it     another start label, end label, and exception handler label,     setting its finalization tree to be a call to terminate (), and     enqueue'ing this new ehEntry to be output at an outer level.     Finally, after all that is done, we can get around to outputting     the catch block which basically wraps all the "catch (...) {...}"     statements in a big if/then/else construct that matches the     correct block to call.          ===================================================================== */extern rtx emit_insn		PROTO((rtx));extern rtx gen_nop		PROTO(());/* local globals for function calls   ====================================================================== *//* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and   "set_unexpected ()" after default_conversion. (lib-except.c)  */static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch, Throw;/* used to cache __find_first_exception_table_match ()   for throw (lib-except.c)  */static tree FirstExceptionMatch;/* used to cache a call to __unwind_function () (lib-except.c)  */static tree Unwind;/* holds a ready to emit call to "terminate ()".  */static tree TerminateFunctionCall;/* ====================================================================== *//* data structures for my various quick and dirty stacks and queues   Eventually, most of this should go away, because I think it can be   integrated with stuff already built into the compiler.  *//* =================================================================== */struct labelNode {  rtx label;  struct labelNode *chain;};/* this is the most important structure here.  Basically this is how I store   an exception table entry internally. */struct ehEntry {  rtx start_label;  rtx end_label;  rtx exception_handler_label;  tree finalization;  tree context;};struct ehNode {  struct ehEntry *entry;  struct ehNode *chain;};struct ehStack {  struct ehNode *top;};struct ehQueue {  struct ehNode *head;  struct ehNode *tail;};/* ========================================================================= *//* local globals - these local globals are for storing data necessary for   generating the exception table and code in the correct order.   ========================================================================= *//* Holds the pc for doing "throw" */tree saved_pc;/* Holds the type of the thing being thrown. */tree saved_throw_type;/* Holds the value being thrown.  */tree saved_throw_value;int throw_used;static rtx catch_clauses;static first_catch_label;static struct ehStack ehstack;static struct ehQueue ehqueue;static struct ehQueue eh_table_output_queue;static struct labelNode *false_label_stack = NULL;static struct labelNode *caught_return_label_stack = NULL;/* ========================================================================= *//* function prototypes */static struct ehEntry *pop_eh_entry	PROTO((struct ehStack *stack));static void enqueue_eh_entry		PROTO((struct ehQueue *queue, struct ehEntry *entry));static rtx push_eh_entry		PROTO((struct ehStack *stack));static struct ehEntry *dequeue_eh_entry	PROTO((struct ehQueue *queue));static void new_eh_queue		PROTO((struct ehQueue *queue));static void new_eh_stack		PROTO((struct ehStack *stack));static void push_label_entry		PROTO((struct labelNode **labelstack, rtx label));static rtx pop_label_entry		PROTO((struct labelNode **labelstack));static rtx top_label_entry		PROTO((struct labelNode **labelstack));static struct ehEntry *copy_eh_entry	PROTO((struct ehEntry *entry));/* All my cheesy stack/queue/misc data structure handling routines   ========================================================================= */static voidpush_label_entry (labelstack, label)     struct labelNode **labelstack;     rtx label;{  struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));  newnode->label = label;  newnode->chain = *labelstack;  *labelstack = newnode;}static rtxpop_label_entry (labelstack)     struct labelNode **labelstack;{  rtx label;  struct labelNode *tempnode;  if (! *labelstack) return NULL_RTX;  tempnode = *labelstack;  label = tempnode->label;  *labelstack = (*labelstack)->chain;  free (tempnode);  return label;}static rtxtop_label_entry (labelstack)     struct labelNode **labelstack;{  if (! *labelstack) return NULL_RTX;  return (*labelstack)->label;}/* Push to permanent obstack for rtl generation.   One level only!  */static struct obstack *saved_rtl_obstack;voidpush_rtl_perm (){  extern struct obstack permanent_obstack;  extern struct obstack *rtl_obstack;    saved_rtl_obstack = rtl_obstack;  rtl_obstack = &permanent_obstack;}/* Pop back to normal rtl handling.  */static voidpop_rtl_from_perm (){  extern struct obstack permanent_obstack;  extern struct obstack *rtl_obstack;    rtl_obstack = saved_rtl_obstack;}static rtxpush_eh_entry (stack)     struct ehStack *stack;{  struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));  struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));  if (stack == NULL) {    free (node);    free (entry);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -