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

📄 expr.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Process expressions for the GNU compiler for the Java(TM) language.   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.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.  Java and all Java-based marks are trademarks or registered trademarksof Sun Microsystems, Inc. in the United States and other countries.The Free Software Foundation is independent of Sun Microsystems, Inc.  *//* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */#include "config.h"#include "system.h"#include "tree.h"#include "real.h"#include "rtl.h"#include "flags.h"#include "expr.h"#include "java-tree.h"#include "javaop.h"#include "java-opcodes.h"#include "jcf.h"#include "java-except.h"#include "parse.h"#include "toplev.h"#include "except.h"static void flush_quick_stack PROTO ((void));static void push_value PROTO ((tree));static tree pop_value PROTO ((tree));static void java_stack_swap PROTO ((void));static void java_stack_dup PROTO ((int, int));static tree build_java_athrow PROTO ((tree));static void build_java_jsr PROTO ((tree, tree));static void build_java_ret PROTO ((tree));static void expand_java_multianewarray PROTO ((tree, int));static void expand_java_arraystore PROTO ((tree));static void expand_java_arrayload PROTO ((tree));static void expand_java_array_length PROTO ((void));static tree build_java_monitor PROTO ((tree, tree));static void expand_java_pushc PROTO ((int, tree));static void expand_java_return PROTO ((tree));static void expand_java_NEW PROTO ((tree));static void expand_java_INSTANCEOF PROTO ((tree));static void expand_java_CHECKCAST PROTO ((tree));static void expand_iinc PROTO ((unsigned int, int, int));static void expand_java_binop PROTO ((tree, enum tree_code));static void note_label PROTO ((int, int));static void expand_compare PROTO ((enum tree_code, tree, tree, int));static void expand_test PROTO ((enum tree_code, tree, int));static void expand_cond PROTO ((enum tree_code, tree, int));static void expand_java_goto PROTO ((int));#if 0static void expand_java_call PROTO ((int, int));static void expand_java_ret PROTO ((tree)); #endifstatic tree pop_arguments PROTO ((tree)); static void expand_invoke PROTO ((int, int, int)); static void expand_java_field_op PROTO ((int, int, int)); static void java_push_constant_from_pool PROTO ((struct JCF *, int));  static tree operand_type[59];extern struct obstack permanent_obstack;voidinit_expr_processing(){  operand_type[21] = operand_type[54] = int_type_node;  operand_type[22] = operand_type[55] = long_type_node;  operand_type[23] = operand_type[56] = float_type_node;  operand_type[24] = operand_type[57] = double_type_node;  operand_type[25] = operand_type[58] = ptr_type_node;}/* We store the stack state in two places:   Within a basic block, we use the quick_stack, which is a   pushdown list (TREE_LISTs) of expression nodes.   This is the top part of the stack;  below that we use find_stack_slot.   At the end of a basic block, the quick_stack must be flushed   to the stack slot array (as handled by find_stack_slot).   Using quick_stack generates better code (especially when   compiled without optimization), because we do not have to   explicitly store and load trees to temporary variables.   If a variable is on the quick stack, it means the value of variable   when the quick stack was last flushed.  Conceptually, flush_quick_stack   saves all the the quick_stack elements in parellel.  However, that is   complicated, so it actually saves them (i.e. copies each stack value   to is home virtual register) from low indexes.  This allows a quick_stack   element at index i (counting from the bottom of stack the) to references   slot virtuals for register that are >= i, but not those that are deeper.   This convention makes most operations easier.  For example iadd works   even when the stack contains (reg[0], reg[1]):  It results in the   stack containing (reg[0]+reg[1]), which is OK.  However, some stack   operations are more complicated.  For example dup given a stack   containing (reg[0]) would yield (reg[0], reg[0]), which would violate   the convention, since stack value 1 would refer to a register with   lower index (reg[0]), which flush_quick_stack does not safely handle.   So dup cannot just add an extra element to the quick_stack, but iadd can.*/tree quick_stack = NULL_TREE;/* A free-list of unused permamnet TREE_LIST nodes. */tree tree_list_free_list = NULL_TREE;/* The stack pointer of the Java virtual machine.   This does include the size of the quick_stack. */int stack_pointer;unsigned char *linenumber_table;int linenumber_count;treetruthvalue_conversion (expr)     tree expr;{  /* It is simpler and generates better code to have only TRUTH_*_EXPR     or comparison expressions as truth values at this level.     This function should normally be identity for Java.  */  switch (TREE_CODE (expr))    {    case EQ_EXPR:    case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:    case TRUTH_ANDIF_EXPR:    case TRUTH_ORIF_EXPR:    case TRUTH_AND_EXPR:    case TRUTH_OR_EXPR:    case ERROR_MARK:      return expr;    case INTEGER_CST:      return integer_zerop (expr) ? boolean_false_node : boolean_true_node;    case REAL_CST:      return real_zerop (expr) ? boolean_false_node : boolean_true_node;    /* are these legal? XXX JH */    case NEGATE_EXPR:    case ABS_EXPR:    case FLOAT_EXPR:    case FFS_EXPR:      /* These don't change whether an object is non-zero or zero.  */      return truthvalue_conversion (TREE_OPERAND (expr, 0));    case COND_EXPR:      /* Distribute the conversion into the arms of a COND_EXPR.  */      return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0),                          truthvalue_conversion (TREE_OPERAND (expr, 1)),                          truthvalue_conversion (TREE_OPERAND (expr, 2))));    case NOP_EXPR:      /* If this is widening the argument, we can ignore it.  */      if (TYPE_PRECISION (TREE_TYPE (expr))          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))        return truthvalue_conversion (TREE_OPERAND (expr, 0));      /* fall through to default */    default:      return fold (build (NE_EXPR, boolean_type_node, expr, boolean_false_node));    }}#ifdef JAVA_USE_HANDLES/* Given a pointer to a handle, get a pointer to an object. */treeunhand_expr (expr)     tree expr;{  tree field, handle_type;  expr = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);  handle_type = TREE_TYPE (expr);  field = TYPE_FIELDS (handle_type);  expr = build (COMPONENT_REF, TREE_TYPE (field), expr, field);  return expr;}#endif/* Save any stack slots that happen to be in the quick_stack into their   home virtual register slots.   The copy order is from low stack index to high, to support the invariant   that the expression for a slot may contain decls for stack slots with   higher (or the same) index, but not lower. */static voidflush_quick_stack (){  int stack_index = stack_pointer;  register tree prev, cur, next;  /* First reverse the quick_stack, and count the number of slots it has. */  for (cur = quick_stack, prev = NULL_TREE; cur != NULL_TREE; cur = next)    {      next = TREE_CHAIN (cur);      TREE_CHAIN (cur) = prev;      prev = cur;      stack_index -= 1 + TYPE_IS_WIDE (TREE_TYPE (TREE_VALUE (cur)));    }  quick_stack = prev;  while (quick_stack != NULL_TREE)    {      tree decl;      tree node = quick_stack, type;      quick_stack = TREE_CHAIN (node);      TREE_CHAIN (node) = tree_list_free_list;      tree_list_free_list = node;      node = TREE_VALUE (node);      type = TREE_TYPE (node);      decl = find_stack_slot (stack_index, type);      if (decl != node)	  expand_assignment (decl, node, 0, 0);      stack_index += 1 + TYPE_IS_WIDE (type);    }}voidpush_type (type)     tree type;{  int n_words;  type = promote_type (type);  n_words = 1 + TYPE_IS_WIDE (type);  if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))    fatal ("stack overflow");  stack_type_map[stack_pointer++] = type;  n_words--;  while (--n_words >= 0)    stack_type_map[stack_pointer++] = TYPE_SECOND;}static voidpush_value (value)     tree value;{  tree type = TREE_TYPE (value);  if (TYPE_PRECISION (type) < 32 && INTEGRAL_TYPE_P (type))    {      type = promote_type (type);      value = convert (type, value);    }  push_type (type);  if (tree_list_free_list == NULL_TREE)    quick_stack = perm_tree_cons (NULL_TREE, value, quick_stack);  else    {      tree node = tree_list_free_list;      tree_list_free_list = TREE_CHAIN (tree_list_free_list);      TREE_VALUE (node) = value;      TREE_CHAIN (node) = quick_stack;      quick_stack = node;    }}/* Pop a type from the type stack.   TYPE is the expected type.   Return the actual type, which must be   convertible to TYPE, otherwise NULL_TREE is returned. */treepop_type_0 (type)     tree type;{  int n_words;  tree t;  if (TREE_CODE (type) == RECORD_TYPE)    type = promote_type (type);  n_words = 1 + TYPE_IS_WIDE (type);  if (stack_pointer < n_words)    fatal ("stack underflow");  while (--n_words > 0)    {      if (stack_type_map[--stack_pointer] != void_type_node)	fatal ("Invalid multi-word value on type stack");    }  t = stack_type_map[--stack_pointer];  if (type == NULL_TREE || t == type)    return t;  if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)      && TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)      return t;  if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (t) == POINTER_TYPE)    {      if (type == ptr_type_node || type == object_ptr_type_node)	return t;      else if (t == ptr_type_node)  /* Special case for null reference. */	return type;      else if (can_widen_reference_to (t, type))	return t;      /* This is a kludge, but matches what Sun's verifier does.	 It can be tricked, but is safe as long as type errors	 (i.e. interface method calls) are caught at run-time. */      else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type)))	       && t == object_ptr_type_node)	return t;    }  return NULL_TREE;}/* Pop a type from the type stack.   TYPE is the expected type.  Return the actual type, which must be   convertible to TYPE, otherwise call error. */treepop_type (type)     tree type;{  tree t = pop_type_0 (type);  if (t != NULL_TREE)    return t;  error ("unexpected type on stack");  return type;}/* Return 1f if SOURCE_TYPE can be safely widened to TARGET_TYPE.   Handles array types and interfaces.  */intcan_widen_reference_to (source_type, target_type)     tree source_type, target_type;{  if (source_type == ptr_type_node || target_type == object_ptr_type_node)    return 1;  /* Get rid of pointers  */  if (TREE_CODE (source_type) == POINTER_TYPE)    source_type = TREE_TYPE (source_type);  if (TREE_CODE (target_type) == POINTER_TYPE)    target_type = TREE_TYPE (target_type);  if (source_type == target_type)    return 1;  else    {      source_type = HANDLE_TO_CLASS_TYPE (source_type);      target_type = HANDLE_TO_CLASS_TYPE (target_type);      if (TYPE_ARRAY_P (source_type) || TYPE_ARRAY_P (target_type))	{	  HOST_WIDE_INT source_length, target_length;	  if (TYPE_ARRAY_P (source_type) != TYPE_ARRAY_P (target_type))	    return 0;	  target_length = java_array_type_length (target_type);	  if (target_length >= 0)	    {	      source_length = java_array_type_length (source_type);	      if (source_length != target_length)		return 0;	    }	  source_type = TYPE_ARRAY_ELEMENT (source_type);	  target_type = TYPE_ARRAY_ELEMENT (target_type);	  if (source_type == target_type)	    return 1;	  if (TREE_CODE (source_type) != POINTER_TYPE	      || TREE_CODE (target_type) != POINTER_TYPE)	    return 0;	  return can_widen_reference_to (source_type, target_type);	}      else	{	  int source_depth = class_depth (source_type);	  int target_depth = class_depth (target_type);	  if (CLASS_INTERFACE (TYPE_NAME (target_type)))	    {	      /* target_type is OK if source_type or source_type ancestors		 implement target_type. We handle multiple sub-interfaces  */	      tree basetype_vec = TYPE_BINFO_BASETYPES (source_type);	      int n = TREE_VEC_LENGTH (basetype_vec), i;	      for (i=0 ; i < n; i++)	        if (can_widen_reference_to 		    (TREE_TYPE (TREE_VEC_ELT (basetype_vec, i)),		     target_type))		  return 1;		if (n == 0)		  return 0;	    }	  for ( ; source_depth > target_depth;  source_depth--) 	    {	      source_type = TYPE_BINFO_BASETYPE (source_type, 0); 	    }	  return source_type == target_type;	}    }}static treepop_value (type)     tree type;{  type = pop_type (type);  if (quick_stack)    {      tree node = quick_stack;      quick_stack = TREE_CHAIN (quick_stack);      TREE_CHAIN (node) = tree_list_free_list;      tree_list_free_list = node;      node = TREE_VALUE (node);      return node;    }  else    return find_stack_slot (stack_pointer, promote_type (type));}/* Pop and discrad the top COUNT stack slots. */static voidjava_stack_pop (count)     int count;{  while (count > 0)    {      tree type, val;      if (stack_pointer == 0)	fatal ("stack underflow");      type = stack_type_map[stack_pointer - 1];      if (type == TYPE_SECOND)

⌨️ 快捷键说明

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