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

📄 stmt.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		    do_pending_stack_adjust ();		  }	    }	  /* Restore stack level for the biggest contour that this	     jump jumps out of.  */	  if (f->stack_level)	    emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);	  /* Finish up the sequence containing the insns which implement the	     necessary cleanups, and then attach that whole sequence to the	     insn stream just ahead of the actual jump insn.  Attaching it	     at that point insures that any cleanups which are in fact	     implicit C++ object destructions (which must be executed upon	     leaving the block) appear (to the debugger) to be taking place	     in an area of the generated code where the object(s) being	     destructed are still "in scope".  */	  cleanup_insns = get_insns ();	  poplevel (1, 0, 0);	  end_sequence ();	  emit_insns_after (cleanup_insns, f->before_jump);	  f->before_jump = 0;	}    }  /* For any still-undefined labels, do the cleanups for this block now.     We must do this now since items in the cleanup list may go out     of scope when the block ends.  */  for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)    if (f->before_jump != 0	&& PREV_INSN (f->target_rtl) == 0	/* Label has still not appeared.  If we are exiting a block with	   a stack level to restore, that started before the fixup,	   mark this stack level as needing restoration	   when the fixup is later finalized.   */	&& thisblock != 0	/* Note: if THISBLOCK == 0 and we have a label that hasn't appeared, it	   means the label is undefined.  That's erroneous, but possible.  */	&& (thisblock->data.block.block_start_count	    <= f->block_start_count))      {	tree lists = f->cleanup_list_list;	rtx cleanup_insns;	for (; lists; lists = TREE_CHAIN (lists))	  /* If the following elt. corresponds to our containing block	     then the elt. must be for this block.  */	  if (TREE_CHAIN (lists) == thisblock->data.block.outer_cleanups)	    {	      start_sequence ();	      pushlevel (0);	      set_block (f->context);	      expand_cleanups (TREE_VALUE (lists), NULL_TREE, 1, 1);	      do_pending_stack_adjust ();	      cleanup_insns = get_insns ();	      poplevel (1, 0, 0);	      end_sequence ();	      if (cleanup_insns != 0)		f->before_jump		  = emit_insns_after (cleanup_insns, f->before_jump);	      f->cleanup_list_list = TREE_CHAIN (lists);	    }	if (stack_level)	  f->stack_level = stack_level;      }}/* When exiting a binding contour, process all pending gotos requiring fixups.   Note: STACK_DEPTH is not altered.   The arguments are currently not used in the bytecode compiler, but we may   need them one day for languages other than C.   THISBLOCK is the structure that describes the block being exited.   STACK_LEVEL is the rtx for the stack level to restore exiting this contour.   CLEANUP_LIST is a list of expressions to evaluate on exiting this contour.   FIRST_INSN is the insn that began this contour.   Gotos that jump out of this contour must restore the   stack level and do the cleanups before actually jumping.   DONT_JUMP_IN nonzero means report error there is a jump into this   contour from before the beginning of the contour.   This is also done if STACK_LEVEL is nonzero.  */static voidbc_fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)     struct nesting *thisblock;     int stack_level;     tree cleanup_list;     rtx first_insn;     int dont_jump_in;{  register struct goto_fixup *f, *prev;  int saved_stack_depth;  /* F is the fixup we are considering; PREV is the previous one.  */  for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)    {      /* Test for a fixup that is inactive because it is already handled.  */      if (f->before_jump == 0)	{	  /* Delete inactive fixup from the chain, if that is easy to do.  */	  if (prev)	    prev->next = f->next;	}      /* Emit code to restore the stack and continue */      bc_emit_bytecode_labeldef (f->label);      /* Save stack_depth across call, since bc_adjust_stack will alter         the perceived stack depth via the instructions generated.  */      if (f->bc_stack_level >= 0)	{	  saved_stack_depth = stack_depth;	  bc_adjust_stack (stack_depth - f->bc_stack_level);	  stack_depth = saved_stack_depth;	}      bc_emit_bytecode (jump);      bc_emit_bytecode_labelref (f->bc_target);#ifdef DEBUG_PRINT_CODE  fputc ('\n', stderr);#endif    }  goto_fixup_chain = NULL;}/* Generate RTL for an asm statement (explicit assembler code).   BODY is a STRING_CST node containing the assembler code text,   or an ADDR_EXPR containing a STRING_CST.  */voidexpand_asm (body)     tree body;{  if (output_bytecode)    {      error ("`asm' is invalid when generating bytecode");      return;    }  if (flag_check_memory_usage)    {      error ("`asm' cannot be used with `-fcheck-memory-usage'");      return;    }  if (TREE_CODE (body) == ADDR_EXPR)    body = TREE_OPERAND (body, 0);  emit_insn (gen_rtx (ASM_INPUT, VOIDmode,		      TREE_STRING_POINTER (body)));  last_expr_type = 0;}/* Generate RTL for an asm statement with arguments.   STRING is the instruction template.   OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.   Each output or input has an expression in the TREE_VALUE and   a constraint-string in the TREE_PURPOSE.   CLOBBERS is a list of STRING_CST nodes each naming a hard register   that is clobbered by this insn.   Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.   Some elements of OUTPUTS may be replaced with trees representing temporary   values.  The caller should copy those temporary values to the originally   specified lvalues.   VOL nonzero means the insn is volatile; don't optimize it.  */voidexpand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)     tree string, outputs, inputs, clobbers;     int vol;     char *filename;     int line;{  rtvec argvec, constraints;  rtx body;  int ninputs = list_length (inputs);  int noutputs = list_length (outputs);  int ninout = 0;  int nclobbers;  tree tail;  register int i;  /* Vector of RTX's of evaluated output operands.  */  rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));  int *inout_opnum = (int *) alloca (noutputs * sizeof (int));  enum machine_mode *inout_mode    = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));  /* The insn we have emitted.  */  rtx insn;  if (output_bytecode)    {      error ("`asm' is invalid when generating bytecode");      return;    }  if (flag_check_memory_usage)    {      error ("`asm' cannot be used with `-fcheck-memory-usage'");      return;    }  /* Count the number of meaningful clobbered registers, ignoring what     we would ignore later.  */  nclobbers = 0;  for (tail = clobbers; tail; tail = TREE_CHAIN (tail))    {      char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));      i = decode_reg_name (regname);      if (i >= 0 || i == -4)	++nclobbers;      else if (i == -2)	error ("unknown register name `%s' in `asm'", regname);    }  last_expr_type = 0;  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)    {      tree val = TREE_VALUE (tail);      tree type = TREE_TYPE (val);      tree val1;      int j;      int found_equal = 0;      int found_plus = 0;      int allows_reg = 0;      /* If there's an erroneous arg, emit no insn.  */      if (TREE_TYPE (val) == error_mark_node)	return;      /* Make sure constraint has `=' and does not have `+'.  Also, see	 if it allows any register.  Be liberal on the latter test, since	 the worst that happens if we get it wrong is we issue an error	 message.  */      for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)	switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])	  {	  case '+':	    /* Make sure we can specify the matching operand.  */	    if (i > 9)	      {		error ("output operand constraint %d contains `+'", i);		return;	      }	    /* Replace '+' with '='.  */	    TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] = '=';	    found_plus = 1;	    break;	  case '=':	    found_equal = 1;	    break;	  case '?':  case '!':  case '*':  case '%':  case '&':	  case 'V':  case 'm':  case 'o':  case '<':  case '>':	  case 'E':  case 'F':  case 'G':  case 'H':  case 'X':	  case 's':  case 'i':  case 'n':	  case 'I':  case 'J':  case 'K':  case 'L':  case 'M':	  case 'N':  case 'O':  case 'P':  case ',':#ifdef EXTRA_CONSTRAINT	  case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':#endif	    break;	  case '0':  case '1':  case '2':  case '3':  case '4':	  case '5':  case '6':  case '7':  case '8':  case '9':	    error ("matching constraint not valid in output operand");	    break;	  case 'p':  case 'g':  case 'r':	  default:	    allows_reg = 1;	    break;	  }      if (! found_equal && ! found_plus)	{	  error ("output operand constraint lacks `='");	  return;	}      /* If an output operand is not a decl or indirect ref and our constraint	 allows a register, make a temporary to act as an intermediate.	 Make the asm insn write into that, then our caller will copy it to	 the real output operand.  Likewise for promoted variables.  */      if (TREE_CODE (val) == INDIRECT_REF	  || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'	      && ! (GET_CODE (DECL_RTL (val)) == REG		    && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))	  || ! allows_reg	  || found_plus)	{	  if (! allows_reg)	    mark_addressable (TREE_VALUE (tail));	  output_rtx[i]	    = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode,			   EXPAND_MEMORY_USE_WO);	  if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)	    error ("output number %d not directly addressable", i);	}      else	{	  output_rtx[i] = assign_temp (type, 0, 0, 0);	  TREE_VALUE (tail) = make_tree (type, output_rtx[i]);	}      if (found_plus)	{	  inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)));	  inout_opnum[ninout++] = i;	}    }  ninputs += ninout;  if (ninputs + noutputs > MAX_RECOG_OPERANDS)    {      error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);      return;    }  /* Make vectors for the expression-rtx and constraint strings.  */  argvec = rtvec_alloc (ninputs);  constraints = rtvec_alloc (ninputs);  body = gen_rtx (ASM_OPERANDS, VOIDmode,		  TREE_STRING_POINTER (string), "", 0, argvec, constraints,		  filename, line);  /* The only use of BODY is if no outputs are specified, so set     it volatile, at least for now.  */  MEM_VOLATILE_P (body) = 1;  /* Eval the inputs and put them into ARGVEC.     Put their constraints into ASM_INPUTs and store in CONSTRAINTS.  */  i = 0;  for (tail = inputs; tail; tail = TREE_CHAIN (tail))    {      int j;      int allows_reg = 0;      /* If there's an erroneous arg, emit no insn,	 because the ASM_INPUT would get VOIDmode	 and that could cause a crash in reload.  */      if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)	return;      if (TREE_PURPOSE (tail) == NULL_TREE)	{	  error ("hard register `%s' listed as input operand to `asm'",		 TREE_STRING_POINTER (TREE_VALUE (tail)) );	  return;	}      /* Make sure constraint has neither `=' nor `+'.  */      for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)	switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])	  {	  case '+':   case '=':	    error ("input operand constraint contains `%c'",		   TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);	    return;	  case '?':  case '!':  case '*':  case '%':  case '&':	  case 'V':  case 'm':  case 'o':  case '<':  case '>':	  case 'E':  case 'F':  case 'G':  case 'H':  case 'X':	  case 's':  case 'i':  case 'n':	  case 'I':  case 'J':  case 'K':  case 'L':  case 'M':	  case 'N':  case 'O':  case 'P':  case ',':#ifdef EXTRA_CONSTRAINT	  case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':#endif	    break;	    /* Whether or not a numeric constraint allows a register is	       decided by the matching constraint, and so there is no need	       to do anything special with them.  We must handle them in	       the default case, so that we don't unnecessarily force	       operands to memory.  */	  case '0':  case '1':  case '2':  case '3':  case '4':	  case '5':  case '6':  case '7':  case '8':  case '9':	    if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]		>= '0' + noutputs)	      {

⌨️ 快捷键说明

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