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

📄 stmt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      /* Ok, a fixup is needed.  Add a fixup to the list of such.  */      struct goto_fixup *fixup	= (struct goto_fixup *) oballoc (sizeof (struct goto_fixup));      /* In case an old stack level is restored, make sure that comes	 after any pending stack adjust.  */      /* ?? If the fixup isn't to come at the present position,	 doing the stack adjust here isn't useful.  Doing it with our	 settings at that location isn't useful either.  Let's hope	 someone does it!  */      if (last_insn == 0)	do_pending_stack_adjust ();      fixup->target = tree_label;      fixup->target_rtl = rtl_label;      /* Create a BLOCK node and a corresponding matched set of	 NOTE_INSN_BEGIN_BLOCK and NOTE_INSN_END_BLOCK notes at	 this point.  The notes will encapsulate any and all fixup	 code which we might later insert at this point in the insn	 stream.  Also, the BLOCK node will be the parent (i.e. the	 `SUPERBLOCK') of any other BLOCK nodes which we might create	 later on when we are expanding the fixup code.  */      {        register rtx original_before_jump          = last_insn ? last_insn : get_last_insn ();        start_sequence ();        pushlevel (0);        fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG);        last_block_end_note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END);        fixup->context = poplevel (1, 0, 0);  /* Create the BLOCK node now! */        end_sequence ();        emit_insns_after (fixup->before_jump, original_before_jump);      }      fixup->block_start_count = block_start_count;      fixup->stack_level = 0;      fixup->cleanup_list_list	= (((block->data.block.outer_cleanups#if 0	     && block->data.block.outer_cleanups != empty_cleanup_list#endif	     )	    || block->data.block.cleanups)	   ? tree_cons (NULL_TREE, block->data.block.cleanups,			block->data.block.outer_cleanups)	   : 0);      fixup->next = goto_fixup_chain;      goto_fixup_chain = fixup;    }  return block != 0;}/* When exiting a binding contour, process all pending gotos requiring fixups.   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.  */voidfixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)     struct nesting *thisblock;     rtx stack_level;     tree cleanup_list;     rtx first_insn;     int dont_jump_in;{  register struct goto_fixup *f, *prev;  /* F is the fixup we are considering; PREV is the previous one.  */  /* We run this loop in two passes so that cleanups of exited blocks     are run first, and blocks that are exited are marked so     afterwards.  */  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 != 0)	    prev->next = f->next;	}      /* Has this fixup's target label been defined?	 If so, we can finalize it.  */      else if (PREV_INSN (f->target_rtl) != 0)	{	  register rtx cleanup_insns;	  /* Get the first non-label after the label	     this goto jumps to.  If that's before this scope begins,	     we don't have a jump into the scope.  */	  rtx after_label = f->target_rtl;	  while (after_label != 0 && GET_CODE (after_label) == CODE_LABEL)	    after_label = NEXT_INSN (after_label);	  /* If this fixup jumped into this contour from before the beginning	     of this contour, report an error.  */	  /* ??? Bug: this does not detect jumping in through intermediate	     blocks that have stack levels or cleanups.	     It detects only a problem with the innermost block	     around the label.  */	  if (f->target != 0	      && (dont_jump_in || stack_level || cleanup_list)	      /* If AFTER_LABEL is 0, it means the jump goes to the end		 of the rtl, which means it jumps into this scope.  */	      && (after_label == 0		  || INSN_UID (first_insn) < INSN_UID (after_label))	      && INSN_UID (first_insn) > INSN_UID (f->before_jump)	      && ! DECL_REGISTER (f->target))	    {	      error_with_decl (f->target,			       "label `%s' used before containing binding contour");	      /* Prevent multiple errors for one label.  */	      DECL_REGISTER (f->target) = 1;	    }	  /* We will expand the cleanups into a sequence of their own and	     then later on we will attach this new sequence to the insn	     stream just ahead of the actual jump insn.  */	  start_sequence ();	  /* Temporarily restore the lexical context where we will	     logically be inserting the fixup code.  We do this for the	     sake of getting the debugging information right.  */	  pushlevel (0);	  set_block (f->context);	  /* Expand the cleanups for blocks this jump exits.  */	  if (f->cleanup_list_list)	    {	      tree lists;	      for (lists = f->cleanup_list_list; lists; lists = TREE_CHAIN (lists))		/* Marked elements correspond to blocks that have been closed.		   Do their cleanups.  */		if (TREE_ADDRESSABLE (lists)		    && TREE_VALUE (lists) != 0)		  {		    expand_cleanups (TREE_VALUE (lists), 0);		    /* Pop any pushes done in the cleanups,		       in case function is about to return.  */		    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;	}    }  /* Mark the cleanups of exited blocks so that they are executed     by the code above.  */  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.	   Also mark the cleanup_list_list element for F	   that corresponds to this block, so that ultimately	   this block's cleanups will be executed by the code above.  */	&& 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;	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)	    TREE_ADDRESSABLE (lists) = 1;	if (stack_level)	  f->stack_level = stack_level;      }}/* 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 (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;  /* 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;    }  last_expr_type = 0;  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)    {      tree val = TREE_VALUE (tail);      tree val1;      int j;      int found_equal;      /* 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 `+'.  */      found_equal = 0;      for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)); j++)	{	  if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+')	    {	      error ("output operand constraint contains `+'");	      return;	    }	  if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '=')	    found_equal = 1;	}      if (! found_equal)	{	  error ("output operand constraint lacks `='");	  return;	}      /* If an output operand is not a variable or indirect ref,	 or a part of one,	 create a SAVE_EXPR which is a pseudo-reg	 to act as an intermediate temporary.	 Make the asm insn write into that, then copy it to	 the real output operand.  */      while (TREE_CODE (val) == COMPONENT_REF	     || TREE_CODE (val) == ARRAY_REF)	val = TREE_OPERAND (val, 0);      if (TREE_CODE (val) != VAR_DECL	  && TREE_CODE (val) != PARM_DECL	  && TREE_CODE (val) != INDIRECT_REF)	TREE_VALUE (tail) = save_expr (TREE_VALUE (tail));      output_rtx[i] = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);    }  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;      /* 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)); j++)	if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '='	    || TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+')	  {	    error ("input operand constraint contains `%c'",		   TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);	    return;	  }      XVECEXP (body, 3, i)      /* argvec */	= expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);      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,

⌨️ 快捷键说明

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