OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc1/] [gcc/] [java/] [except.c] - Diff between revs 287 and 338

Only display areas with differences | Details | Blame | View Log

Rev 287 Rev 338
/* Handle exceptions for GNU compiler for the Java(TM) language.
/* Handle exceptions for GNU compiler for the Java(TM) language.
   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
   2007, 2008, 2009 Free Software Foundation, Inc.
   2007, 2008, 2009 Free Software Foundation, Inc.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
any later version.
 
 
GCC is distributed in the hope that it will be useful,
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.
<http://www.gnu.org/licenses/>.
 
 
Java and all Java-based marks are trademarks or registered trademarks
Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "tree.h"
#include "tree.h"
#include "real.h"
#include "real.h"
#include "rtl.h"
#include "rtl.h"
#include "java-tree.h"
#include "java-tree.h"
#include "javaop.h"
#include "javaop.h"
#include "java-opcodes.h"
#include "java-opcodes.h"
#include "jcf.h"
#include "jcf.h"
#include "function.h"
#include "function.h"
#include "except.h"
#include "except.h"
#include "java-except.h"
#include "java-except.h"
#include "toplev.h"
#include "toplev.h"
#include "tree-iterator.h"
#include "tree-iterator.h"
 
 
 
 
static void expand_start_java_handler (struct eh_range *);
static void expand_start_java_handler (struct eh_range *);
static struct eh_range *find_handler_in_range (int, struct eh_range *,
static struct eh_range *find_handler_in_range (int, struct eh_range *,
                                               struct eh_range *);
                                               struct eh_range *);
static void check_start_handlers (struct eh_range *, int);
static void check_start_handlers (struct eh_range *, int);
static void free_eh_ranges (struct eh_range *range);
static void free_eh_ranges (struct eh_range *range);
 
 
struct eh_range *current_method_handlers;
struct eh_range *current_method_handlers;
 
 
struct eh_range *current_try_block = NULL;
struct eh_range *current_try_block = NULL;
 
 
/* These variables are used to speed up find_handler. */
/* These variables are used to speed up find_handler. */
 
 
static int cache_range_start, cache_range_end;
static int cache_range_start, cache_range_end;
static struct eh_range *cache_range;
static struct eh_range *cache_range;
static struct eh_range *cache_next_child;
static struct eh_range *cache_next_child;
 
 
/* A dummy range that represents the entire method. */
/* A dummy range that represents the entire method. */
 
 
struct eh_range whole_range;
struct eh_range whole_range;
 
 
/* Check the invariants of the structure we're using to contain
/* Check the invariants of the structure we're using to contain
   exception regions.  Either returns true or fails an assertion
   exception regions.  Either returns true or fails an assertion
   check.  */
   check.  */
 
 
bool
bool
sanity_check_exception_range (struct eh_range *range)
sanity_check_exception_range (struct eh_range *range)
{
{
  struct eh_range *ptr = range->first_child;
  struct eh_range *ptr = range->first_child;
  for (; ptr; ptr = ptr->next_sibling)
  for (; ptr; ptr = ptr->next_sibling)
    {
    {
      gcc_assert (ptr->outer == range
      gcc_assert (ptr->outer == range
                  && ptr->end_pc > ptr->start_pc);
                  && ptr->end_pc > ptr->start_pc);
      if (ptr->next_sibling)
      if (ptr->next_sibling)
        gcc_assert (ptr->next_sibling->start_pc >= ptr->end_pc);
        gcc_assert (ptr->next_sibling->start_pc >= ptr->end_pc);
      gcc_assert (ptr->start_pc >= ptr->outer->start_pc
      gcc_assert (ptr->start_pc >= ptr->outer->start_pc
                  && ptr->end_pc <=  ptr->outer->end_pc);
                  && ptr->end_pc <=  ptr->outer->end_pc);
      (void) sanity_check_exception_range (ptr);
      (void) sanity_check_exception_range (ptr);
    }
    }
  return true;
  return true;
}
}
 
 
#if defined(DEBUG_JAVA_BINDING_LEVELS)
#if defined(DEBUG_JAVA_BINDING_LEVELS)
extern int is_class_level;
extern int is_class_level;
extern int current_pc;
extern int current_pc;
extern int binding_depth;
extern int binding_depth;
extern void indent (void);
extern void indent (void);
static void
static void
print_ranges (struct eh_range *range)
print_ranges (struct eh_range *range)
{
{
  if (! range)
  if (! range)
    return;
    return;
 
 
  struct eh_range *child = range->first_child;
  struct eh_range *child = range->first_child;
 
 
  indent ();
  indent ();
  fprintf (stderr, "handler pc %d --> %d ", range->start_pc, range->end_pc);
  fprintf (stderr, "handler pc %d --> %d ", range->start_pc, range->end_pc);
 
 
  tree handler = range->handlers;
  tree handler = range->handlers;
  for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
  for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
    {
    {
      tree type = TREE_PURPOSE (handler);
      tree type = TREE_PURPOSE (handler);
      if (type == NULL)
      if (type == NULL)
        type = throwable_type_node;
        type = throwable_type_node;
      fprintf (stderr, " type=%s ", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
      fprintf (stderr, " type=%s ", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
    }
    }
  fprintf (stderr, "\n");
  fprintf (stderr, "\n");
 
 
  int saved = binding_depth;
  int saved = binding_depth;
  binding_depth++;
  binding_depth++;
  print_ranges (child);
  print_ranges (child);
  binding_depth = saved;
  binding_depth = saved;
 
 
  print_ranges (range->next_sibling);
  print_ranges (range->next_sibling);
}
}
#endif
#endif
 
 
/* Search for the most specific eh_range containing PC.
/* Search for the most specific eh_range containing PC.
   Assume PC is within RANGE.
   Assume PC is within RANGE.
   CHILD is a list of children of RANGE such that any
   CHILD is a list of children of RANGE such that any
   previous children have end_pc values that are too low. */
   previous children have end_pc values that are too low. */
 
 
static struct eh_range *
static struct eh_range *
find_handler_in_range (int pc, struct eh_range *range, struct eh_range *child)
find_handler_in_range (int pc, struct eh_range *range, struct eh_range *child)
{
{
  for (; child != NULL;  child = child->next_sibling)
  for (; child != NULL;  child = child->next_sibling)
    {
    {
      if (pc < child->start_pc)
      if (pc < child->start_pc)
        break;
        break;
      if (pc < child->end_pc)
      if (pc < child->end_pc)
        return find_handler_in_range (pc, child, child->first_child);
        return find_handler_in_range (pc, child, child->first_child);
    }
    }
  cache_range = range;
  cache_range = range;
  cache_range_start = pc;
  cache_range_start = pc;
  cache_next_child = child;
  cache_next_child = child;
  cache_range_end = child == NULL ? range->end_pc : child->start_pc;
  cache_range_end = child == NULL ? range->end_pc : child->start_pc;
  return range;
  return range;
}
}
 
 
/* Find the inner-most handler that contains PC. */
/* Find the inner-most handler that contains PC. */
 
 
struct eh_range *
struct eh_range *
find_handler (int pc)
find_handler (int pc)
{
{
  struct eh_range *h;
  struct eh_range *h;
  if (pc >= cache_range_start)
  if (pc >= cache_range_start)
    {
    {
      h = cache_range;
      h = cache_range;
      if (pc < cache_range_end)
      if (pc < cache_range_end)
        return h;
        return h;
      while (pc >= h->end_pc)
      while (pc >= h->end_pc)
        {
        {
          cache_next_child = h->next_sibling;
          cache_next_child = h->next_sibling;
          h = h->outer;
          h = h->outer;
        }
        }
    }
    }
  else
  else
    {
    {
      h = &whole_range;
      h = &whole_range;
      cache_next_child = h->first_child;
      cache_next_child = h->first_child;
    }
    }
  return find_handler_in_range (pc, h, cache_next_child);
  return find_handler_in_range (pc, h, cache_next_child);
}
}
 
 
static void
static void
free_eh_ranges (struct eh_range *range)
free_eh_ranges (struct eh_range *range)
{
{
  while (range)
  while (range)
    {
    {
      struct eh_range *next = range->next_sibling;
      struct eh_range *next = range->next_sibling;
      free_eh_ranges (range->first_child);
      free_eh_ranges (range->first_child);
      if (range != &whole_range)
      if (range != &whole_range)
        free (range);
        free (range);
      range = next;
      range = next;
    }
    }
}
}
 
 
/* Called to re-initialize the exception machinery for a new method. */
/* Called to re-initialize the exception machinery for a new method. */
 
 
void
void
method_init_exceptions (void)
method_init_exceptions (void)
{
{
  free_eh_ranges (&whole_range);
  free_eh_ranges (&whole_range);
  whole_range.start_pc = 0;
  whole_range.start_pc = 0;
  whole_range.end_pc = DECL_CODE_LENGTH (current_function_decl) + 1;
  whole_range.end_pc = DECL_CODE_LENGTH (current_function_decl) + 1;
  whole_range.outer = NULL;
  whole_range.outer = NULL;
  whole_range.first_child = NULL;
  whole_range.first_child = NULL;
  whole_range.next_sibling = NULL;
  whole_range.next_sibling = NULL;
  cache_range_start = 0xFFFFFF;
  cache_range_start = 0xFFFFFF;
}
}
 
 
/* Split an exception range into two at PC.  The sub-ranges that
/* Split an exception range into two at PC.  The sub-ranges that
   belong to the range are split and distributed between the two new
   belong to the range are split and distributed between the two new
   ranges.  */
   ranges.  */
 
 
static void
static void
split_range (struct eh_range *range, int pc)
split_range (struct eh_range *range, int pc)
{
{
  struct eh_range *ptr;
  struct eh_range *ptr;
  struct eh_range **first_child, **second_child;
  struct eh_range **first_child, **second_child;
  struct eh_range *h;
  struct eh_range *h;
 
 
  /* First, split all the sub-ranges.  */
  /* First, split all the sub-ranges.  */
  for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
  for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
    {
    {
      if (pc > ptr->start_pc
      if (pc > ptr->start_pc
          && pc < ptr->end_pc)
          && pc < ptr->end_pc)
        {
        {
          split_range (ptr, pc);
          split_range (ptr, pc);
        }
        }
    }
    }
 
 
  /* Create a new range.  */
  /* Create a new range.  */
  h = XNEW (struct eh_range);
  h = XNEW (struct eh_range);
 
 
  h->start_pc = pc;
  h->start_pc = pc;
  h->end_pc = range->end_pc;
  h->end_pc = range->end_pc;
  h->next_sibling = range->next_sibling;
  h->next_sibling = range->next_sibling;
  range->next_sibling = h;
  range->next_sibling = h;
  range->end_pc = pc;
  range->end_pc = pc;
  h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
  h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
                                 TREE_VALUE (range->handlers));
                                 TREE_VALUE (range->handlers));
  h->next_sibling = NULL;
  h->next_sibling = NULL;
  h->expanded = 0;
  h->expanded = 0;
  h->stmt = NULL;
  h->stmt = NULL;
  h->outer = range->outer;
  h->outer = range->outer;
  h->first_child = NULL;
  h->first_child = NULL;
 
 
  ptr = range->first_child;
  ptr = range->first_child;
  first_child = &range->first_child;
  first_child = &range->first_child;
  second_child = &h->first_child;
  second_child = &h->first_child;
 
 
  /* Distribute the sub-ranges between the two new ranges.  */
  /* Distribute the sub-ranges between the two new ranges.  */
  for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
  for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
    {
    {
      if (ptr->start_pc < pc)
      if (ptr->start_pc < pc)
        {
        {
          *first_child = ptr;
          *first_child = ptr;
          ptr->outer = range;
          ptr->outer = range;
          first_child = &ptr->next_sibling;
          first_child = &ptr->next_sibling;
        }
        }
      else
      else
        {
        {
          *second_child = ptr;
          *second_child = ptr;
          ptr->outer = h;
          ptr->outer = h;
          second_child = &ptr->next_sibling;
          second_child = &ptr->next_sibling;
        }
        }
    }
    }
  *first_child = NULL;
  *first_child = NULL;
  *second_child = NULL;
  *second_child = NULL;
}
}
 
 
 
 
/* Add an exception range.
/* Add an exception range.
 
 
   There are some missed optimization opportunities here.  For
   There are some missed optimization opportunities here.  For
   example, some bytecode obfuscators generate seemingly
   example, some bytecode obfuscators generate seemingly
   nonoverlapping exception ranges which, when coalesced, do in fact
   nonoverlapping exception ranges which, when coalesced, do in fact
   nest correctly.  We could merge these, but we'd have to fix up all
   nest correctly.  We could merge these, but we'd have to fix up all
   the enclosed regions first and perhaps create a new range anyway if
   the enclosed regions first and perhaps create a new range anyway if
   it overlapped existing ranges.
   it overlapped existing ranges.
 
 
   Also, we don't attempt to detect the case where two previously
   Also, we don't attempt to detect the case where two previously
   added disjoint ranges could be coalesced by a new range.  */
   added disjoint ranges could be coalesced by a new range.  */
 
 
void
void
add_handler (int start_pc, int end_pc, tree handler, tree type)
add_handler (int start_pc, int end_pc, tree handler, tree type)
{
{
  struct eh_range *ptr, *h;
  struct eh_range *ptr, *h;
  struct eh_range **first_child, **prev;
  struct eh_range **first_child, **prev;
 
 
  /* First, split all the existing ranges that we need to enclose.  */
  /* First, split all the existing ranges that we need to enclose.  */
  for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
  for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
    {
    {
      if (start_pc > ptr->start_pc
      if (start_pc > ptr->start_pc
          && start_pc < ptr->end_pc)
          && start_pc < ptr->end_pc)
        {
        {
          split_range (ptr, start_pc);
          split_range (ptr, start_pc);
        }
        }
 
 
      if (end_pc > ptr->start_pc
      if (end_pc > ptr->start_pc
          && end_pc < ptr->end_pc)
          && end_pc < ptr->end_pc)
        {
        {
          split_range (ptr, end_pc);
          split_range (ptr, end_pc);
        }
        }
 
 
      if (ptr->start_pc >= end_pc)
      if (ptr->start_pc >= end_pc)
        break;
        break;
    }
    }
 
 
  /* Create the new range.  */
  /* Create the new range.  */
  h = XNEW (struct eh_range);
  h = XNEW (struct eh_range);
  first_child = &h->first_child;
  first_child = &h->first_child;
 
 
  h->start_pc = start_pc;
  h->start_pc = start_pc;
  h->end_pc = end_pc;
  h->end_pc = end_pc;
  h->first_child = NULL;
  h->first_child = NULL;
  h->outer = NULL_EH_RANGE;
  h->outer = NULL_EH_RANGE;
  h->handlers = build_tree_list (type, handler);
  h->handlers = build_tree_list (type, handler);
  h->next_sibling = NULL;
  h->next_sibling = NULL;
  h->expanded = 0;
  h->expanded = 0;
  h->stmt = NULL;
  h->stmt = NULL;
 
 
  /* Find every range at the top level that will be a sub-range of the
  /* Find every range at the top level that will be a sub-range of the
     range we're inserting and make it so.  */
     range we're inserting and make it so.  */
  {
  {
    struct eh_range **prev = &whole_range.first_child;
    struct eh_range **prev = &whole_range.first_child;
    for (ptr = *prev; ptr;)
    for (ptr = *prev; ptr;)
      {
      {
        struct eh_range *next = ptr->next_sibling;
        struct eh_range *next = ptr->next_sibling;
 
 
        if (ptr->start_pc >= end_pc)
        if (ptr->start_pc >= end_pc)
          break;
          break;
 
 
        if (ptr->start_pc < start_pc)
        if (ptr->start_pc < start_pc)
          {
          {
            prev = &ptr->next_sibling;
            prev = &ptr->next_sibling;
          }
          }
        else if (ptr->start_pc >= start_pc
        else if (ptr->start_pc >= start_pc
                 && ptr->start_pc < end_pc)
                 && ptr->start_pc < end_pc)
          {
          {
            *prev = next;
            *prev = next;
            *first_child = ptr;
            *first_child = ptr;
            first_child = &ptr->next_sibling;
            first_child = &ptr->next_sibling;
            ptr->outer = h;
            ptr->outer = h;
            ptr->next_sibling = NULL;
            ptr->next_sibling = NULL;
          }
          }
 
 
        ptr = next;
        ptr = next;
      }
      }
  }
  }
 
 
  /* Find the right place to insert the new range.  */
  /* Find the right place to insert the new range.  */
  prev = &whole_range.first_child;
  prev = &whole_range.first_child;
  for (ptr = *prev; ptr; prev = &ptr->next_sibling, ptr = ptr->next_sibling)
  for (ptr = *prev; ptr; prev = &ptr->next_sibling, ptr = ptr->next_sibling)
    {
    {
      gcc_assert (ptr->outer == NULL_EH_RANGE);
      gcc_assert (ptr->outer == NULL_EH_RANGE);
      if (ptr->start_pc >= start_pc)
      if (ptr->start_pc >= start_pc)
        break;
        break;
    }
    }
 
 
  /* And insert it there.  */
  /* And insert it there.  */
  *prev = h;
  *prev = h;
  if (ptr)
  if (ptr)
    {
    {
      h->next_sibling = ptr;
      h->next_sibling = ptr;
      h->outer = ptr->outer;
      h->outer = ptr->outer;
    }
    }
}
}
 
 
 
 
/* if there are any handlers for this range, issue start of region */
/* if there are any handlers for this range, issue start of region */
static void
static void
expand_start_java_handler (struct eh_range *range)
expand_start_java_handler (struct eh_range *range)
{
{
#if defined(DEBUG_JAVA_BINDING_LEVELS)
#if defined(DEBUG_JAVA_BINDING_LEVELS)
  indent ();
  indent ();
  fprintf (stderr, "expand start handler pc %d --> %d\n",
  fprintf (stderr, "expand start handler pc %d --> %d\n",
           current_pc, range->end_pc);
           current_pc, range->end_pc);
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
  pushlevel (0);
  pushlevel (0);
  register_exception_range (range,  range->start_pc, range->end_pc);
  register_exception_range (range,  range->start_pc, range->end_pc);
  range->expanded = 1;
  range->expanded = 1;
}
}
 
 
tree
tree
prepare_eh_table_type (tree type)
prepare_eh_table_type (tree type)
{
{
  tree exp;
  tree exp;
  tree *slot;
  tree *slot;
  const char *name;
  const char *name;
  char *buf;
  char *buf;
  tree decl;
  tree decl;
  tree utf8_ref;
  tree utf8_ref;
 
 
  /* The "type" (match_info) in a (Java) exception table is a pointer to:
  /* The "type" (match_info) in a (Java) exception table is a pointer to:
   * a) NULL - meaning match any type in a try-finally.
   * a) NULL - meaning match any type in a try-finally.
   * b) a pointer to a pointer to a class.
   * b) a pointer to a pointer to a class.
   * c) a pointer to a pointer to a utf8_ref.  The pointer is
   * c) a pointer to a pointer to a utf8_ref.  The pointer is
   * rewritten to point to the appropriate class.  */
   * rewritten to point to the appropriate class.  */
 
 
  if (type == NULL_TREE)
  if (type == NULL_TREE)
    return NULL_TREE;
    return NULL_TREE;
 
 
  if (TYPE_TO_RUNTIME_MAP (output_class) == NULL)
  if (TYPE_TO_RUNTIME_MAP (output_class) == NULL)
    TYPE_TO_RUNTIME_MAP (output_class) = java_treetreehash_create (10, 1);
    TYPE_TO_RUNTIME_MAP (output_class) = java_treetreehash_create (10, 1);
 
 
  slot = java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class), type);
  slot = java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class), type);
  if (*slot != NULL)
  if (*slot != NULL)
    return TREE_VALUE (*slot);
    return TREE_VALUE (*slot);
 
 
  if (is_compiled_class (type) && !flag_indirect_dispatch)
  if (is_compiled_class (type) && !flag_indirect_dispatch)
    {
    {
      name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
      name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
      buf = (char *) alloca (strlen (name) + 5);
      buf = (char *) alloca (strlen (name) + 5);
      sprintf (buf, "%s_ref", name);
      sprintf (buf, "%s_ref", name);
      decl = build_decl (input_location,
      decl = build_decl (input_location,
                         VAR_DECL, get_identifier (buf), ptr_type_node);
                         VAR_DECL, get_identifier (buf), ptr_type_node);
      TREE_STATIC (decl) = 1;
      TREE_STATIC (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
      DECL_IGNORED_P (decl) = 1;
      DECL_IGNORED_P (decl) = 1;
      TREE_READONLY (decl) = 1;
      TREE_READONLY (decl) = 1;
      TREE_THIS_VOLATILE (decl) = 0;
      TREE_THIS_VOLATILE (decl) = 0;
      DECL_INITIAL (decl) = build_class_ref (type);
      DECL_INITIAL (decl) = build_class_ref (type);
      layout_decl (decl, 0);
      layout_decl (decl, 0);
      pushdecl (decl);
      pushdecl (decl);
      exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl);
      exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl);
    }
    }
  else
  else
    {
    {
      utf8_ref = build_utf8_ref (DECL_NAME (TYPE_NAME (type)));
      utf8_ref = build_utf8_ref (DECL_NAME (TYPE_NAME (type)));
      name = IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref, 0)));
      name = IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref, 0)));
      buf = (char *) alloca (strlen (name) + 5);
      buf = (char *) alloca (strlen (name) + 5);
      sprintf (buf, "%s_ref", name);
      sprintf (buf, "%s_ref", name);
      decl = build_decl (input_location,
      decl = build_decl (input_location,
                         VAR_DECL, get_identifier (buf), utf8const_ptr_type);
                         VAR_DECL, get_identifier (buf), utf8const_ptr_type);
      TREE_STATIC (decl) = 1;
      TREE_STATIC (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
      DECL_IGNORED_P (decl) = 1;
      DECL_IGNORED_P (decl) = 1;
      TREE_READONLY (decl) = 1;
      TREE_READONLY (decl) = 1;
      TREE_THIS_VOLATILE (decl) = 0;
      TREE_THIS_VOLATILE (decl) = 0;
      layout_decl (decl, 0);
      layout_decl (decl, 0);
      pushdecl (decl);
      pushdecl (decl);
      exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl);
      exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl);
      TYPE_CATCH_CLASSES (output_class) =
      TYPE_CATCH_CLASSES (output_class) =
        tree_cons (NULL, make_catch_class_record (exp, utf8_ref),
        tree_cons (NULL, make_catch_class_record (exp, utf8_ref),
                   TYPE_CATCH_CLASSES (output_class));
                   TYPE_CATCH_CLASSES (output_class));
    }
    }
 
 
  exp = convert (ptr_type_node, exp);
  exp = convert (ptr_type_node, exp);
 
 
  *slot = tree_cons (type, exp, NULL_TREE);
  *slot = tree_cons (type, exp, NULL_TREE);
 
 
  return exp;
  return exp;
}
}
 
 
static int
static int
expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED)
expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED)
{
{
  struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
  struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
  tree addr = TREE_VALUE ((tree)ite->value);
  tree addr = TREE_VALUE ((tree)ite->value);
  tree decl;
  tree decl;
  STRIP_NOPS (addr);
  STRIP_NOPS (addr);
  decl = TREE_OPERAND (addr, 0);
  decl = TREE_OPERAND (addr, 0);
  rest_of_decl_compilation (decl, global_bindings_p (), 0);
  rest_of_decl_compilation (decl, global_bindings_p (), 0);
  return true;
  return true;
}
}
 
 
/* For every class in the TYPE_TO_RUNTIME_MAP, expand the
/* For every class in the TYPE_TO_RUNTIME_MAP, expand the
   corresponding object that is used by the runtime type matcher.  */
   corresponding object that is used by the runtime type matcher.  */
 
 
void
void
java_expand_catch_classes (tree this_class)
java_expand_catch_classes (tree this_class)
{
{
  if (TYPE_TO_RUNTIME_MAP (this_class))
  if (TYPE_TO_RUNTIME_MAP (this_class))
    htab_traverse
    htab_traverse
      (TYPE_TO_RUNTIME_MAP (this_class),
      (TYPE_TO_RUNTIME_MAP (this_class),
       expand_catch_class, NULL);
       expand_catch_class, NULL);
}
}
 
 
/* Build and push the variable that will hold the exception object
/* Build and push the variable that will hold the exception object
   within this function.  */
   within this function.  */
 
 
static tree
static tree
build_exception_object_var (void)
build_exception_object_var (void)
{
{
  tree decl = DECL_FUNCTION_EXC_OBJ (current_function_decl);
  tree decl = DECL_FUNCTION_EXC_OBJ (current_function_decl);
  if (decl == NULL)
  if (decl == NULL)
    {
    {
      decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
      decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
                         VAR_DECL, get_identifier ("#exc_obj"), ptr_type_node);
                         VAR_DECL, get_identifier ("#exc_obj"), ptr_type_node);
      DECL_IGNORED_P (decl) = 1;
      DECL_IGNORED_P (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
 
 
      DECL_FUNCTION_EXC_OBJ (current_function_decl) = decl;
      DECL_FUNCTION_EXC_OBJ (current_function_decl) = decl;
      pushdecl_function_level (decl);
      pushdecl_function_level (decl);
    }
    }
  return decl;
  return decl;
}
}
 
 
/* Build a reference to the jthrowable object being carried in the
/* Build a reference to the jthrowable object being carried in the
   exception header.  */
   exception header.  */
 
 
tree
tree
build_exception_object_ref (tree type)
build_exception_object_ref (tree type)
{
{
  tree obj;
  tree obj;
 
 
  /* Java only passes object via pointer and doesn't require adjusting.
  /* Java only passes object via pointer and doesn't require adjusting.
     The java object is immediately before the generic exception header.  */
     The java object is immediately before the generic exception header.  */
  obj = build_exception_object_var ();
  obj = build_exception_object_var ();
  obj = fold_convert (build_pointer_type (type), obj);
  obj = fold_convert (build_pointer_type (type), obj);
  obj = build2 (POINTER_PLUS_EXPR, TREE_TYPE (obj), obj,
  obj = build2 (POINTER_PLUS_EXPR, TREE_TYPE (obj), obj,
                fold_build1 (NEGATE_EXPR, sizetype,
                fold_build1 (NEGATE_EXPR, sizetype,
                             TYPE_SIZE_UNIT (TREE_TYPE (obj))));
                             TYPE_SIZE_UNIT (TREE_TYPE (obj))));
  obj = build1 (INDIRECT_REF, type, obj);
  obj = build1 (INDIRECT_REF, type, obj);
 
 
  return obj;
  return obj;
}
}
 
 
/* If there are any handlers for this range, issue end of range,
/* If there are any handlers for this range, issue end of range,
   and then all handler blocks */
   and then all handler blocks */
void
void
expand_end_java_handler (struct eh_range *range)
expand_end_java_handler (struct eh_range *range)
{
{
  tree handler = range->handlers;
  tree handler = range->handlers;
  if (handler)
  if (handler)
    {
    {
      tree exc_obj = build_exception_object_var ();
      tree exc_obj = build_exception_object_var ();
      tree catches = make_node (STATEMENT_LIST);
      tree catches = make_node (STATEMENT_LIST);
      tree_stmt_iterator catches_i = tsi_last (catches);
      tree_stmt_iterator catches_i = tsi_last (catches);
      tree *body;
      tree *body;
 
 
      for (; handler; handler = TREE_CHAIN (handler))
      for (; handler; handler = TREE_CHAIN (handler))
        {
        {
          tree type, eh_type, x;
          tree type, eh_type, x;
          tree stmts = make_node (STATEMENT_LIST);
          tree stmts = make_node (STATEMENT_LIST);
          tree_stmt_iterator stmts_i = tsi_last (stmts);
          tree_stmt_iterator stmts_i = tsi_last (stmts);
 
 
          type = TREE_PURPOSE (handler);
          type = TREE_PURPOSE (handler);
          if (type == NULL)
          if (type == NULL)
            type = throwable_type_node;
            type = throwable_type_node;
          eh_type = prepare_eh_table_type (type);
          eh_type = prepare_eh_table_type (type);
 
 
          x = build_call_expr (built_in_decls[BUILT_IN_EH_POINTER],
          x = build_call_expr (built_in_decls[BUILT_IN_EH_POINTER],
                                1, integer_zero_node);
                                1, integer_zero_node);
          x = build2 (MODIFY_EXPR, void_type_node, exc_obj, x);
          x = build2 (MODIFY_EXPR, void_type_node, exc_obj, x);
          tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
          tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
 
 
          x = build1 (GOTO_EXPR, void_type_node, TREE_VALUE (handler));
          x = build1 (GOTO_EXPR, void_type_node, TREE_VALUE (handler));
          tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
          tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
 
 
          x = build2 (CATCH_EXPR, void_type_node, eh_type, stmts);
          x = build2 (CATCH_EXPR, void_type_node, eh_type, stmts);
          tsi_link_after (&catches_i, x, TSI_CONTINUE_LINKING);
          tsi_link_after (&catches_i, x, TSI_CONTINUE_LINKING);
 
 
          /* Throwable can match anything in Java, and therefore
          /* Throwable can match anything in Java, and therefore
             any subsequent handlers are unreachable.  */
             any subsequent handlers are unreachable.  */
          /* ??? If we're assured of no foreign language exceptions,
          /* ??? If we're assured of no foreign language exceptions,
             we'd be better off using NULL as the exception type
             we'd be better off using NULL as the exception type
             for the catch.  */
             for the catch.  */
          if (type == throwable_type_node)
          if (type == throwable_type_node)
            break;
            break;
        }
        }
 
 
      body = get_stmts ();
      body = get_stmts ();
      *body = build2 (TRY_CATCH_EXPR, void_type_node, *body, catches);
      *body = build2 (TRY_CATCH_EXPR, void_type_node, *body, catches);
    }
    }
 
 
#if defined(DEBUG_JAVA_BINDING_LEVELS)
#if defined(DEBUG_JAVA_BINDING_LEVELS)
  indent ();
  indent ();
  fprintf (stderr, "expand end handler pc %d <-- %d\n",
  fprintf (stderr, "expand end handler pc %d <-- %d\n",
           current_pc, range->start_pc);
           current_pc, range->start_pc);
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
}
}
 
 
/* Recursive helper routine for maybe_start_handlers. */
/* Recursive helper routine for maybe_start_handlers. */
 
 
static void
static void
check_start_handlers (struct eh_range *range, int pc)
check_start_handlers (struct eh_range *range, int pc)
{
{
  if (range != NULL_EH_RANGE && range->start_pc == pc)
  if (range != NULL_EH_RANGE && range->start_pc == pc)
    {
    {
      check_start_handlers (range->outer, pc);
      check_start_handlers (range->outer, pc);
      if (!range->expanded)
      if (!range->expanded)
        expand_start_java_handler (range);
        expand_start_java_handler (range);
    }
    }
}
}
 
 
 
 
static struct eh_range *current_range;
static struct eh_range *current_range;
 
 
/* Emit any start-of-try-range starting at start_pc and ending after
/* Emit any start-of-try-range starting at start_pc and ending after
   end_pc. */
   end_pc. */
 
 
void
void
maybe_start_try (int start_pc, int end_pc)
maybe_start_try (int start_pc, int end_pc)
{
{
  struct eh_range *range;
  struct eh_range *range;
  if (! doing_eh (1))
  if (! doing_eh (1))
    return;
    return;
 
 
  range = find_handler (start_pc);
  range = find_handler (start_pc);
  while (range != NULL_EH_RANGE && range->start_pc == start_pc
  while (range != NULL_EH_RANGE && range->start_pc == start_pc
         && range->end_pc < end_pc)
         && range->end_pc < end_pc)
    range = range->outer;
    range = range->outer;
 
 
  current_range = range;
  current_range = range;
  check_start_handlers (range, start_pc);
  check_start_handlers (range, start_pc);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.