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

📄 expr.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Convert language-specific tree expression to rtl instructions,   for GNU CHILL compiler.   Copyright (C) 1992, 93, 1994, 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.  */#include "config.h"#include "system.h"#include "rtl.h"#include "tree.h"#include "flags.h"#include "expr.h"#include "ch-tree.h"#include "assert.h"#include "lex.h"#include "convert.h"#include "toplev.h"extern char **boolean_code_name;extern int  flag_old_strings;extern tree long_unsigned_type_node;extern int  ignore_case;extern int  special_UC;/* definitions for duration built-ins */#define MILLISECS_MULTIPLIER                                 1#define SECS_MULTIPLIER            MILLISECS_MULTIPLIER * 1000#define MINUTES_MULTIPLIER                SECS_MULTIPLIER * 60#define HOURS_MULTIPLIER               MINUTES_MULTIPLIER * 60#define DAYS_MULTIPLIER                  HOURS_MULTIPLIER * 24/* the maximum value for each of the calls */#define MILLISECS_MAX                               0xffffffff#define SECS_MAX                                       4294967#define MINUTES_MAX                                      71582#define HOURS_MAX                                         1193#define DAYS_MAX                                            49/* forward declaration */rtx chill_expand_expr PROTO((tree, rtx, enum machine_mode, 			     enum expand_modifier));/* variable to hold the type the DESCR built-in returns */static tree descr_type = NULL_TREE;/* called from ch-lex.l */voidinit_chill_expand (){  lang_expand_expr = chill_expand_expr;}/* Take the address of something that needs to be passed by reference. */treeforce_addr_of (value)     tree value;{  /* FIXME.  Move to memory, if needed. */  if (TREE_CODE (value) == INDIRECT_REF)    return convert_to_pointer (ptr_type_node, TREE_OPERAND (value, 0));  mark_addressable (value);  return build1 (ADDR_EXPR, ptr_type_node, value);}/* Check that EXP has a known type. */treecheck_have_mode (exp, context)     tree exp;     char *context;{  if (TREE_CODE (exp) != ERROR_MARK && TREE_TYPE (exp) == NULL_TREE)    {      if (TREE_CODE (exp) == CONSTRUCTOR)	error ("tuple without specified mode not allowed in %s", context);      else if (TREE_CODE (exp) == COND_EXPR || TREE_CODE (exp) == CASE_EXPR)	error ("conditional expression not allowed in %s", context);      else	error ("internal error:  unknown expression mode in %s", context);      return error_mark_node;    }  return exp;}/* Check that EXP is discrete.  Handle conversion if flag_old_strings. */treecheck_case_selector (exp)     tree exp;{  if (exp != NULL_TREE && TREE_TYPE (exp) != NULL_TREE)    exp = convert_to_discrete (exp);  if (exp)    return exp;  error ("CASE selector is not a discrete expression");  return error_mark_node;}treecheck_case_selector_list (list)     tree list;{  tree selector, exp, return_list = NULL_TREE;  for (selector = list; selector != NULL_TREE; selector = TREE_CHAIN (selector))    {      exp = check_case_selector (TREE_VALUE (selector));      if (exp == error_mark_node)	{	  return_list = error_mark_node;	  break;	}      return_list = tree_cons (TREE_PURPOSE (selector), exp, return_list);    }  return nreverse(return_list);}treechill_expand_case_expr (expr)     tree expr;{  tree selector_list = TREE_OPERAND (expr, 0), selector;  tree alternatives  = TREE_OPERAND (expr, 1);  tree type = TREE_TYPE (expr);  int  else_seen = 0;  tree result;  if (TREE_CODE (selector_list) != TREE_LIST    || TREE_CODE (alternatives) != TREE_LIST)    abort();  if (TREE_CHAIN (selector_list) != NULL_TREE)    abort ();  /* make a temp for the case result */  result = decl_temp1 (get_unique_identifier ("CASE_EXPR"),		       type, 0, NULL_TREE, 0, 0);  selector = check_case_selector (TREE_VALUE (selector_list));  expand_start_case (1, selector, TREE_TYPE (selector), "CASE expression");  alternatives = nreverse (alternatives);  for ( ; alternatives != NULL_TREE; alternatives = TREE_CHAIN (alternatives))    {       tree labels = TREE_PURPOSE (alternatives), t;            if (labels == NULL_TREE)	{	  chill_handle_case_default ();	  else_seen++;        }      else	{	  tree label;	  if (labels != NULL_TREE)	    {	      for (label = TREE_VALUE (labels);		   label != NULL_TREE; label = TREE_CHAIN (label))		chill_handle_case_label (TREE_VALUE (label), selector);	      labels = TREE_CHAIN (labels);	      if (labels != NULL_TREE)		error ("The number of CASE selectors does not match the number "                       "of CASE label lists");			    }        }      t = build (MODIFY_EXPR, type, result,		 convert (type, TREE_VALUE (alternatives)));      TREE_SIDE_EFFECTS (t) = 1;      expand_expr_stmt (t);      expand_exit_something ();    }  if (!else_seen)    {      chill_handle_case_default ();      expand_exit_something ();#if 0      expand_raise ();#endif      check_missing_cases (TREE_TYPE (selector));    }  expand_end_case (selector);  return result;}/* Hook used by expand_expr to expand CHILL-specific tree codes.  */rtxchill_expand_expr (exp, target, tmode, modifier)     tree exp;     rtx target;     enum machine_mode tmode;     enum expand_modifier modifier;{  tree type = TREE_TYPE (exp);  register enum machine_mode mode = TYPE_MODE (type);  register enum tree_code code = TREE_CODE (exp);  rtx original_target = target;  rtx op0, op1;  int ignore = target == const0_rtx;  char *lib_func;                   /* name of library routine */  if (ignore)    target = 0, original_target = 0;  /* No sense saving up arithmetic to be done     if it's all in the wrong mode to form part of an address.     And force_operand won't know whether to sign-extend or zero-extend.  */  if (mode != Pmode && modifier == EXPAND_SUM)    modifier = EXPAND_NORMAL;  switch (code)    {    case STRING_EQ_EXPR:    case STRING_LT_EXPR:      {	rtx func = gen_rtx (SYMBOL_REF, Pmode,			    code == STRING_EQ_EXPR ? "__eqstring"			    : "__ltstring");	tree exp0 = TREE_OPERAND (exp, 0);	tree exp1 = TREE_OPERAND (exp, 1);	tree size0, size1;	rtx op0, op1, siz0, siz1;	if (chill_varying_type_p (TREE_TYPE (exp0)))	  {	    exp0 = save_if_needed (exp0);	    size0 = convert (integer_type_node,			     build_component_ref (exp0, var_length_id));	    exp0 = build_component_ref (exp0, var_data_id);	  }	else	  size0 = size_in_bytes (TREE_TYPE (exp0));	if (chill_varying_type_p (TREE_TYPE (exp1)))	  {	    exp1 = save_if_needed (exp1);	    size1 = convert (integer_type_node,			     build_component_ref (exp1, var_length_id));	    exp1 = build_component_ref (exp1, var_data_id);	  }	else	  size1 = size_in_bytes (TREE_TYPE (exp1));	op0 = expand_expr (force_addr_of (exp0),			   NULL_RTX, MEM, EXPAND_CONST_ADDRESS);	op1 = expand_expr (force_addr_of (exp1),			   NULL_RTX, MEM, EXPAND_CONST_ADDRESS);	siz0 = expand_expr (size0, NULL_RTX, VOIDmode, 0);	siz1 = expand_expr (size1, NULL_RTX, VOIDmode, 0);	return emit_library_call_value (func, target,					0, QImode, 4,					op0, GET_MODE (op0),					siz0, TYPE_MODE (sizetype),					op1, GET_MODE (op1),					siz1, TYPE_MODE (sizetype));      }    case CASE_EXPR:      return expand_expr (chill_expand_case_expr (exp),			  NULL_RTX, VOIDmode, 0);      break;    case SLICE_EXPR:      {	tree func_call;	tree array = TREE_OPERAND (exp, 0);	tree min_value = TREE_OPERAND (exp, 1);	tree length = TREE_OPERAND (exp, 2);	tree new_type = TREE_TYPE (exp);	tree temp = decl_temp1 (get_unique_identifier ("BITSTRING"),				new_type, 0, NULL_TREE, 0, 0);	if (! CH_REFERABLE (array) && TYPE_MODE (TREE_TYPE (array)) != BLKmode)	  array = decl_temp1 (get_unique_identifier ("BSTRINGVAL"),				TREE_TYPE (array), 0, array, 0, 0);	func_call = build_chill_function_call (		    lookup_name (get_identifier ("__psslice")),			   tree_cons (NULL_TREE,                              build_chill_addr_expr (temp, (char *)0),			       tree_cons (NULL_TREE, length,		                 tree_cons (NULL_TREE,                                    force_addr_of (array),			             tree_cons (NULL_TREE, powersetlen (array),			               tree_cons (NULL_TREE, convert (integer_type_node, min_value),				         tree_cons (NULL_TREE, length, NULL_TREE)))))));	expand_expr (func_call, const0_rtx, VOIDmode, 0);	emit_queue ();	return expand_expr (temp, ignore ? const0_rtx : target,			    VOIDmode, 0);      }          /* void __concatstring (char *out, char *left, unsigned left_len,                            char *right, unsigned right_len) */    case CONCAT_EXPR:      {	tree exp0 = TREE_OPERAND (exp, 0);	tree exp1 = TREE_OPERAND (exp, 1);	rtx size0 = NULL_RTX, size1 = NULL_RTX;	rtx targetx;	if (TREE_CODE (exp1) == UNDEFINED_EXPR)	  {	    if (TYPE_MODE (TREE_TYPE (exp0)) == BLKmode		&& TYPE_MODE (TREE_TYPE (exp)) == BLKmode)	      {		rtx temp = expand_expr (exp0, target, tmode, modifier);		if (temp == target || target == NULL_RTX)		  return temp;		emit_block_move (target, temp, expr_size (exp0),				 TYPE_ALIGN (TREE_TYPE(exp0)) / BITS_PER_UNIT);		return target;	      }	    else	      {		exp0 = force_addr_of (exp0);		exp0 = convert (build_pointer_type (TREE_TYPE (exp)), exp0);		exp0 = build1 (INDIRECT_REF, TREE_TYPE (exp), exp0);		return expand_expr (exp0,				    NULL_RTX, Pmode, EXPAND_CONST_ADDRESS);	      }	  }	if (TREE_CODE (type) == ARRAY_TYPE)	  {	    /* No need to handle scalars or varying strings here, since that	       was done in convert or build_concat_expr. */	    size0 = expand_expr (size_in_bytes (TREE_TYPE (exp0)),				 NULL_RTX, Pmode, EXPAND_CONST_ADDRESS);	    size1 = expand_expr (size_in_bytes (TREE_TYPE (exp1)),				   NULL_RTX, Pmode, EXPAND_CONST_ADDRESS);	    /* build a temp for the result, target is its address */	    if (target == NULL_RTX)	      {		tree type0 = TREE_TYPE (exp0);		tree type1 = TREE_TYPE (exp1);		int	len0 = int_size_in_bytes (type0);		int	len1 = int_size_in_bytes (type1);		if (len0 < 0 && TYPE_ARRAY_MAX_SIZE (type0)		    && TREE_CODE (TYPE_ARRAY_MAX_SIZE (type0)) == INTEGER_CST)		  len0 = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type0));		if (len1 < 0 && TYPE_ARRAY_MAX_SIZE (type1)		    && TREE_CODE (TYPE_ARRAY_MAX_SIZE (type1)) == INTEGER_CST)		  len1 = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type1));		if (len0 < 0 || len1 < 0)		  fatal ("internal error - don't know how much space is needed for concatenation");		target = assign_stack_temp (mode, len0 + len1, 0);		preserve_temp_slots (target);	      }	  }	else if (TREE_CODE (type) == SET_TYPE)	  {	    if (target == NULL_RTX)	      {		target = assign_stack_temp (mode, int_size_in_bytes (type), 0);		preserve_temp_slots (target);	      }	  }	else	  abort ();	if (GET_CODE (target) == MEM)	  targetx = target;	else	  targetx = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);	/* expand 1st operand to a pointer to the array */	op0 = expand_expr (force_addr_of (exp0),			   NULL_RTX, MEM, EXPAND_CONST_ADDRESS);	/* expand 2nd operand to a pointer to the array */	op1 = expand_expr (force_addr_of (exp1),			   NULL_RTX, MEM, EXPAND_CONST_ADDRESS);	if (TREE_CODE (type) == SET_TYPE)	  {	    size0 = expand_expr (powersetlen (exp0),				 NULL_RTX, VOIDmode, 0);	    size1 = expand_expr (powersetlen (exp1),				 NULL_RTX, VOIDmode, 0);	    emit_library_call (gen_rtx(SYMBOL_REF, Pmode, "__concatps"),			       0, Pmode, 5, XEXP (targetx, 0), Pmode,			       op0, GET_MODE (op0),			       convert_to_mode (TYPE_MODE (sizetype),						size0, TREE_UNSIGNED (sizetype)),			       TYPE_MODE (sizetype),			       op1, GET_MODE (op1),			       convert_to_mode (TYPE_MODE (sizetype),						size1, TREE_UNSIGNED (sizetype)),			       TYPE_MODE (sizetype));	  }	else	  {	    /* copy left, then right array to target */	    emit_library_call (gen_rtx(SYMBOL_REF, Pmode, "__concatstring"),			       0, Pmode, 5, XEXP (targetx, 0), Pmode,			       op0, GET_MODE (op0),			       convert_to_mode (TYPE_MODE (sizetype),						size0, TREE_UNSIGNED (sizetype)),			       TYPE_MODE (sizetype),			       op1, GET_MODE (op1),			       convert_to_mode (TYPE_MODE (sizetype),						size1, TREE_UNSIGNED (sizetype)),			       TYPE_MODE (sizetype));	  }	if (targetx != target)	  emit_move_insn (target, targetx);	return target;      }      /* FIXME: the set_length computed below is a compile-time constant;	 you'll need to re-write that part for VARYING bit arrays, and	 possibly the set pointer will need to be adjusted to point past	 the word containing its dynamic length. */    /* void __notpowerset (char *out, char *src,       unsigned long bitlength) */    case SET_NOT_EXPR:      {		tree expr = TREE_OPERAND (exp, 0);	tree tsize = powersetlen (expr);	rtx targetx;	if (TREE_CODE (TREE_TYPE (expr)) != SET_TYPE)	  tsize = fold (build (MULT_EXPR, sizetype, tsize, 			       size_int (BITS_PER_UNIT)));	/* expand 1st operand to a pointer to the set */	op0 = expand_expr (force_addr_of (expr),			   NULL_RTX, MEM, EXPAND_CONST_ADDRESS);	/* build a temp for the result, target is its address */	if (target == NULL_RTX)	  {	    target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), 					int_size_in_bytes (TREE_TYPE (exp)),					0);	    preserve_temp_slots (target);	  }	if (GET_CODE (target) == MEM)	  targetx = target;	else	  targetx = assign_stack_temp (GET_MODE (target),				       GET_MODE_SIZE (GET_MODE (target)),				       0);	emit_library_call (gen_rtx(SYMBOL_REF, Pmode, "__notpowerset"), 

⌨️ 快捷键说明

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