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

📄 stmt.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* 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 ();	      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 (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 nclobbers;  tree tail;  register int i;  /* Vector of RTX's of evaluated output operands.  */  rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));  /* The insn we have emitted.  */  rtx insn;  if (output_bytecode)    {      error ("`asm' is invalid when generating bytecode");      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 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 '+':	    error ("output operand constraint contains `+'");	    return;	  case '=':	    found_equal = 1;	    break;	  case '?':  case '!':  case '*':  case '%':  case '&':	  case '0':  case '1':  case '2':  case '3':  case '4':	  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 'p':  case 'g':  case 'r':	  default:	    allows_reg = 1;	    break;	  }      if (! found_equal)	{	  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)	{	  if (! allows_reg)	    mark_addressable (TREE_VALUE (tail));	  output_rtx[i]	    = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);	  if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)	    error ("output number %d not directly addressable", i);	}      else	{	  if (TYPE_MODE (type) == BLKmode)	    {	      output_rtx[i] = assign_stack_temp (BLKmode,						 int_size_in_bytes (type), 0);	      MEM_IN_STRUCT_P (output_rtx[i]) = AGGREGATE_TYPE_P (type);	    }	  else	    output_rtx[i] = gen_reg_rtx (TYPE_MODE (type));	  TREE_VALUE (tail) = make_tree (type, output_rtx[i]);	}    }  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);  MEM_VOLATILE_P (body) = vol;  /* 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;	  case '0':  case '1':  case '2':  case '3':  case '4':	  case 'p':  case 'g':  case 'r':	  default:	    allows_reg = 1;	    break;	  }      if (! allows_reg)	mark_addressable (TREE_VALUE (tail));      XVECEXP (body, 3, i)      /* argvec */	= expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);      if (CONSTANT_P (XVECEXP (body, 3, i))	  && ! general_operand (XVECEXP (body, 3, i),				TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))	{	  if (allows_reg)	    XVECEXP (body, 3, i)	      = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),			   XVECEXP (body, 3, i));	  else	    XVECEXP (body, 3, i)	      = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),				 XVECEXP (body, 3, i));	}      if (! allows_reg	  && (GET_CODE (XVECEXP (body, 3, i)) == REG	      || GET_CODE (XVECEXP (body, 3, i)) == SUBREG	      || GET_CODE (XVECEXP (body, 3, i)) == CONCAT))	{	  tree type = TREE_TYPE (TREE_VALUE (tail));	  rtx memloc = assign_stack_temp (TYPE_MODE (type),					  int_size_in_bytes (type), 1);	  MEM_IN_STRUCT_P (memloc) = AGGREGATE_TYPE_P (type);	  emit_move_insn (memloc, XVECEXP (body, 3, i));	  XVECEXP (body, 3, i) = memloc;	}	        XVECEXP (body, 4, i)      /* constraints */	= gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),		   TREE_STRING_POINTER (TREE_PURPOSE (tail)));      i++;    }  /* Protect all the operands from the queue,     now that they have all been evaluated.  */  for (i = 0; i < ninputs; i++)    XVECEXP (body, 3, i) = protect_from_queue (XVECEXP (body, 3, i), 0);  for (i = 0; i < noutputs; i++)    output_rtx[i] = protect_from_queue (output_rtx[i], 1);  /* Now, for each output, construct an rtx     (set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT			       ARGVEC CONSTRAINTS))     If there is more than one, put them inside a PARALLEL.  */  if (noutputs == 1 && nclobbers == 0)    {      XSTR (body, 1) = TREE_STRING_POINTER (TREE_PURPOSE (outputs));      insn = emit_insn (gen_rtx (SET, VOIDmode, output_rtx[0], body));    }  else if (noutputs == 0 && nclobbers == 0)    {      /* No output operands: put in a raw ASM_OPERANDS rtx.  */      insn = emit_insn (body);    }  else    {      rtx obody = body;      int num = noutputs;      if (num == 0) num = 1;      body = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (num + nclobbers));      /* For each output operand, store a SET.  */      for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)	{	  XVECEXP (body, 0, i)	    = gen_rtx (SET, VOIDmode,		       output_rtx[i],		       gen_rtx (ASM_OPERANDS, VOIDmode,				TREE_STRING_POINTER (string),				TREE_STRING_POINTER (TREE_PURPOSE (tail)),

⌨️ 快捷键说明

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