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

📄 stmt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		       output_rtx[i],		       gen_rtx (ASM_OPERANDS, VOIDmode,				TREE_STRING_POINTER (string),				TREE_STRING_POINTER (TREE_PURPOSE (tail)),				i, argvec, constraints,				filename, line));	  MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;	}      /* If there are no outputs (but there are some clobbers)	 store the bare ASM_OPERANDS into the PARALLEL.  */      if (i == 0)	XVECEXP (body, 0, i++) = obody;      /* Store (clobber REG) for each clobbered register specified.  */      for (tail = clobbers; tail; tail = TREE_CHAIN (tail))	{	  char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));	  int j = decode_reg_name (regname);	  if (j < 0)	    {	      if (j == -3)	/* `cc', which is not a register */		continue;	      if (j == -4)	/* `memory', don't cache memory across asm */		{		  XVECEXP (body, 0, i++) = gen_rtx (CLOBBER, VOIDmode, const0_rtx);		  continue;		}	      error ("unknown register name `%s' in `asm'", regname);	      return;	    }	  /* Use QImode since that's guaranteed to clobber just one reg.  */	  XVECEXP (body, 0, i++)	    = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, QImode, j));	}      insn = emit_insn (body);    }  free_temp_slots ();}/* Generate RTL to evaluate the expression EXP   and remember it in case this is the VALUE in a ({... VALUE; }) constr.  */voidexpand_expr_stmt (exp)     tree exp;{  /* If -W, warn about statements with no side effects,     except for an explicit cast to void (e.g. for assert()), and     except inside a ({...}) where they may be useful.  */  if (expr_stmts_for_value == 0 && exp != error_mark_node)    {      if (! TREE_SIDE_EFFECTS (exp) && (extra_warnings || warn_unused)	  && !(TREE_CODE (exp) == CONVERT_EXPR	       && TREE_TYPE (exp) == void_type_node))	warning_with_file_and_line (emit_filename, emit_lineno,				    "statement with no effect");      else if (warn_unused)	warn_if_unused_value (exp);    }  last_expr_type = TREE_TYPE (exp);  if (! flag_syntax_only)    last_expr_value = expand_expr (exp,				   (expr_stmts_for_value				    ? NULL_RTX : const0_rtx),				   VOIDmode, 0);  /* If all we do is reference a volatile value in memory,     copy it to a register to be sure it is actually touched.  */  if (last_expr_value != 0 && GET_CODE (last_expr_value) == MEM      && TREE_THIS_VOLATILE (exp))    {      if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)	copy_to_reg (last_expr_value);      else	{	  rtx lab = gen_label_rtx ();	  	  /* Compare the value with itself to reference it.  */	  emit_cmp_insn (last_expr_value, last_expr_value, EQ,			 expand_expr (TYPE_SIZE (last_expr_type),				      NULL_RTX, VOIDmode, 0),			 BLKmode, 0,			 TYPE_ALIGN (last_expr_type) / BITS_PER_UNIT);	  emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (lab));	  emit_label (lab);	}    }  /* If this expression is part of a ({...}) and is in memory, we may have     to preserve temporaries.  */  preserve_temp_slots (last_expr_value);  /* Free any temporaries used to evaluate this expression.  Any temporary     used as a result of this expression will already have been preserved     above.  */  free_temp_slots ();  emit_queue ();}/* Warn if EXP contains any computations whose results are not used.   Return 1 if a warning is printed; 0 otherwise.  */static intwarn_if_unused_value (exp)     tree exp;{  if (TREE_USED (exp))    return 0;  switch (TREE_CODE (exp))    {    case PREINCREMENT_EXPR:    case POSTINCREMENT_EXPR:    case PREDECREMENT_EXPR:    case POSTDECREMENT_EXPR:    case MODIFY_EXPR:    case INIT_EXPR:    case TARGET_EXPR:    case CALL_EXPR:    case METHOD_CALL_EXPR:    case RTL_EXPR:    case WITH_CLEANUP_EXPR:    case EXIT_EXPR:      /* We don't warn about COND_EXPR because it may be a useful	 construct if either arm contains a side effect.  */    case COND_EXPR:      return 0;    case BIND_EXPR:      /* For a binding, warn if no side effect within it.  */      return warn_if_unused_value (TREE_OPERAND (exp, 1));    case TRUTH_ORIF_EXPR:    case TRUTH_ANDIF_EXPR:      /* In && or ||, warn if 2nd operand has no side effect.  */      return warn_if_unused_value (TREE_OPERAND (exp, 1));    case COMPOUND_EXPR:      if (warn_if_unused_value (TREE_OPERAND (exp, 0)))	return 1;      /* Let people do `(foo (), 0)' without a warning.  */      if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))	return 0;      return warn_if_unused_value (TREE_OPERAND (exp, 1));    case NOP_EXPR:    case CONVERT_EXPR:    case NON_LVALUE_EXPR:      /* Don't warn about values cast to void.  */      if (TREE_TYPE (exp) == void_type_node)	return 0;      /* Don't warn about conversions not explicit in the user's program.  */      if (TREE_NO_UNUSED_WARNING (exp))	return 0;      /* Assignment to a cast usually results in a cast of a modify.	 Don't complain about that.  */      if (TREE_CODE (TREE_OPERAND (exp, 0)) == MODIFY_EXPR)	return 0;      /* Sometimes it results in a cast of a cast of a modify.	 Don't complain about that.  */      if ((TREE_CODE (TREE_OPERAND (exp, 0)) == CONVERT_EXPR	   || TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR)	  && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == MODIFY_EXPR)	return 0;    default:      /* Referencing a volatile value is a side effect, so don't warn.  */      if ((TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'	   || TREE_CODE_CLASS (TREE_CODE (exp)) == 'r')	  && TREE_THIS_VOLATILE (exp))	return 0;      warning_with_file_and_line (emit_filename, emit_lineno,				  "value computed is not used");      return 1;    }}/* Clear out the memory of the last expression evaluated.  */voidclear_last_expr (){  last_expr_type = 0;}/* Begin a statement which will return a value.   Return the RTL_EXPR for this statement expr.   The caller must save that value and pass it to expand_end_stmt_expr.  */treeexpand_start_stmt_expr (){  /* Make the RTL_EXPR node temporary, not momentary,     so that rtl_expr_chain doesn't become garbage.  */  int momentary = suspend_momentary ();  tree t = make_node (RTL_EXPR);  resume_momentary (momentary);  start_sequence ();  NO_DEFER_POP;  expr_stmts_for_value++;  return t;}/* Restore the previous state at the end of a statement that returns a value.   Returns a tree node representing the statement's value and the   insns to compute the value.   The nodes of that expression have been freed by now, so we cannot use them.   But we don't want to do that anyway; the expression has already been   evaluated and now we just want to use the value.  So generate a RTL_EXPR   with the proper type and RTL value.   If the last substatement was not an expression,   return something with type `void'.  */treeexpand_end_stmt_expr (t)     tree t;{  OK_DEFER_POP;  if (last_expr_type == 0)    {      last_expr_type = void_type_node;      last_expr_value = const0_rtx;    }  else if (last_expr_value == 0)    /* There are some cases where this can happen, such as when the       statement is void type.  */    last_expr_value = const0_rtx;  else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value))    /* Remove any possible QUEUED.  */    last_expr_value = protect_from_queue (last_expr_value, 0);  emit_queue ();  TREE_TYPE (t) = last_expr_type;  RTL_EXPR_RTL (t) = last_expr_value;  RTL_EXPR_SEQUENCE (t) = get_insns ();  rtl_expr_chain = tree_cons (NULL_TREE, t, rtl_expr_chain);  end_sequence ();  /* Don't consider deleting this expr or containing exprs at tree level.  */  TREE_SIDE_EFFECTS (t) = 1;  /* Propagate volatility of the actual RTL expr.  */  TREE_THIS_VOLATILE (t) = volatile_refs_p (last_expr_value);  last_expr_type = 0;  expr_stmts_for_value--;  return t;}/* The exception handling nesting looks like this:		<-- Level N-1    {		<-- exception handler block		<-- Level N		<-- in an exception handler	{	<-- try block	:	<-- in a TRY block	:	<-- in an exception handler	:	}	{	<-- except block	:	<-- in an except block	:	<-- in an exception handler	:	}    }*//* Return nonzero iff in a try block at level LEVEL.  */intin_try_block (level)     int level;{  struct nesting *n = except_stack;  while (1)    {      while (n && n->data.except_stmt.after_label != 0)	n = n->next;      if (n == 0)	return 0;      if (level == 0)	return n != 0;      level--;      n = n->next;    }}/* Return nonzero iff in an except block at level LEVEL.  */intin_except_block (level)     int level;{  struct nesting *n = except_stack;  while (1)    {      while (n && n->data.except_stmt.after_label == 0)	n = n->next;      if (n == 0)	return 0;      if (level == 0)	return n != 0;      level--;      n = n->next;    }}/* Return nonzero iff in an exception handler at level LEVEL.  */intin_exception_handler (level)     int level;{  struct nesting *n = except_stack;  while (n && level--)    n = n->next;  return n != 0;}/* Record the fact that the current exception nesting raises   exception EX.  If not in an exception handler, return 0.  */intexpand_raise (ex)     tree ex;{  tree *raises_ptr;  if (except_stack == 0)    return 0;  raises_ptr = &except_stack->data.except_stmt.raised;  if (! value_member (ex, *raises_ptr))    *raises_ptr = tree_cons (NULL_TREE, ex, *raises_ptr);  return 1;}/* Generate RTL for the start of a try block.   TRY_CLAUSE is the condition to test to enter the try block.  */voidexpand_start_try (try_clause, exitflag, escapeflag)     tree try_clause;     int exitflag;     int escapeflag;{  struct nesting *thishandler = ALLOC_NESTING ();  /* Make an entry on cond_stack for the cond we are entering.  */  thishandler->next = except_stack;  thishandler->all = nesting_stack;  thishandler->depth = ++nesting_depth;  thishandler->data.except_stmt.raised = 0;  thishandler->data.except_stmt.handled = 0;  thishandler->data.except_stmt.first_insn = get_insns ();  thishandler->data.except_stmt.except_label = gen_label_rtx ();  thishandler->data.except_stmt.unhandled_label = 0;  thishandler->data.except_stmt.after_label = 0;  thishandler->data.except_stmt.escape_label    = escapeflag ? thishandler->data.except_stmt.except_label : 0;  thishandler->exit_label = exitflag ? gen_label_rtx () : 0;  except_stack = thishandler;  nesting_stack = thishandler;  do_jump (try_clause, thishandler->data.except_stmt.except_label, NULL_RTX);}/* End of a TRY block.  Nothing to do for now.  */voidexpand_end_try (){  except_stack->data.except_stmt.after_label = gen_label_rtx ();  expand_goto_internal (NULL_TREE, except_stack->data.except_stmt.after_label,			NULL_RTX);}/* Start an `except' nesting contour.   EXITFLAG says whether this contour should be able to `exit' something.   ESCAPEFLAG says whether this contour should be escapable.  */voidexpand_start_except (exitflag, escapeflag)     int exitflag;     int escapeflag;{  if (exitflag)    {      struct nesting *n;      /* An `exit' from catch clauses goes out to next exit level,	 if there is one.  Otherwise, it just goes to the end	 of the construct.  */      for (n = except_stack->next; n; n = n->next)	if (n->exit_label != 0)	  {	    except_stack->exit_label = n->exit_label;

⌨️ 快捷键说明

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