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

📄 jcf-write.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
     int value;     struct jcf_partial *state;{  int slot = DECL_LOCAL_INDEX (var);  if (value < -128 || value > 127 || slot >= 256)    {      RESERVE (6);      OP1 (OPCODE_wide);      OP1 (OPCODE_iinc);      OP2 (slot);      OP2 (value);    }  else    {      RESERVE (3);      OP1 (OPCODE_iinc);      OP1 (slot);      OP1 (value);    }}static voidemit_load_or_store (var, opcode, state)     tree var;    /* Variable to load from or store into. */     int opcode;  /* Either OPCODE_iload or OPCODE_istore. */     struct jcf_partial *state;{  tree type = TREE_TYPE (var);  int kind = adjust_typed_op (type, 4);  int index = DECL_LOCAL_INDEX (var);  if (index <= 3)    {      RESERVE (1);      OP1 (opcode + 5 + 4 * kind + index);    /* [ilfda]{load,store}_[0123] */    }  else    maybe_wide (opcode + kind, index, state);  /* [ilfda]{load,store} */}static voidemit_load (var, state)     tree var;     struct jcf_partial *state;{  emit_load_or_store (var, OPCODE_iload, state);  NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);}static voidemit_store (var, state)     tree var;     struct jcf_partial *state;{  emit_load_or_store (var, OPCODE_istore, state);  NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);}static voidemit_unop (opcode, type, state)     enum java_opcode opcode;     tree type ATTRIBUTE_UNUSED;     struct jcf_partial *state;{  RESERVE(1);  OP1 (opcode);}static voidemit_binop (opcode, type, state)     enum java_opcode opcode;     tree type;     struct jcf_partial *state;{  int size = TYPE_IS_WIDE (type) ? 2 : 1;  RESERVE(1);  OP1 (opcode);  NOTE_POP (size);}static voidemit_reloc (value, kind, target, state)     HOST_WIDE_INT value;     int kind;     struct jcf_block *target;     struct jcf_partial *state;{  struct jcf_relocation *reloc = (struct jcf_relocation *)    obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));  struct jcf_block *block = state->last_block;  reloc->next = block->u.relocations;  block->u.relocations = reloc;  reloc->offset = BUFFER_LENGTH (&state->bytecode);  reloc->label = target;  reloc->kind = kind;  if (kind == 0 || kind == BLOCK_START_RELOC)    OP4 (value);  else if (kind != SWITCH_ALIGN_RELOC)    OP2 (value);}static voidemit_switch_reloc (label, state)     struct jcf_block *label;     struct jcf_partial *state;{  emit_reloc (0, BLOCK_START_RELOC, label, state);}/* Similar to emit_switch_reloc,   but re-uses an existing case reloc. */static voidemit_case_reloc (reloc, state)     struct jcf_relocation *reloc;     struct jcf_partial *state;{  struct jcf_block *block = state->last_block;  reloc->next = block->u.relocations;  block->u.relocations = reloc;  reloc->offset = BUFFER_LENGTH (&state->bytecode);  reloc->kind = BLOCK_START_RELOC;  OP4 (0);}/* Emit a conditional jump to TARGET with a 2-byte relative jump offset   The opcode is OPCODE, the inverted opcode is INV_OPCODE. */static voidemit_if (target, opcode, inv_opcode, state)     struct jcf_block *target;     int opcode, inv_opcode;     struct jcf_partial *state;{  OP1 (opcode);  // value is 1 byte from reloc back to start of instruction.  emit_reloc (1, - inv_opcode, target, state);}static voidemit_goto (target, state)     struct jcf_block *target;     struct jcf_partial *state;{  OP1 (OPCODE_goto); // Value is 1 byte from reloc back to start of instruction.  emit_reloc (1, OPCODE_goto_w, target, state);}static voidemit_jsr (target, state)     struct jcf_block *target;     struct jcf_partial *state;{  OP1 (OPCODE_jsr); // Value is 1 byte from reloc back to start of instruction.  emit_reloc (1, OPCODE_jsr_w, target, state);}/* Generate code to evaluate EXP.  If the result is true,   branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.   TRUE_BRANCH_FIRST is a code geneation hint that the   TRUE_LABEL may follow right after this. (The idea is that we   may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */static voidgenerate_bytecode_conditional (exp, true_label, false_label,			       true_branch_first, state)     tree exp;     struct jcf_block *true_label;     struct jcf_block *false_label;     int true_branch_first;     struct jcf_partial *state;{  tree exp0, exp1, type;  int save_SP = state->code_SP;  enum java_opcode op, negop;  switch (TREE_CODE (exp))    {    case INTEGER_CST:      emit_goto (integer_zerop (exp) ? false_label : true_label, state);      break;    case COND_EXPR:      {	struct jcf_block *then_label = gen_jcf_label (state);	struct jcf_block *else_label = gen_jcf_label (state);	int save_SP_before, save_SP_after;	generate_bytecode_conditional (TREE_OPERAND (exp, 0),				       then_label, else_label, 1, state);	define_jcf_label (then_label, state);	save_SP_before = state->code_SP;	generate_bytecode_conditional (TREE_OPERAND (exp, 1),				       true_label, false_label, 1, state);	save_SP_after = state->code_SP;	state->code_SP = save_SP_before;	define_jcf_label (else_label, state);	generate_bytecode_conditional (TREE_OPERAND (exp, 2),				       true_label, false_label,				       true_branch_first, state);	if (state->code_SP != save_SP_after)	  fatal ("internal error  non-matching SP");      }      break;    case TRUTH_NOT_EXPR:      generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label, true_label,				     ! true_branch_first, state);      break;    case TRUTH_ANDIF_EXPR:      {	struct jcf_block *next_label = gen_jcf_label (state);	generate_bytecode_conditional (TREE_OPERAND (exp, 0),				       next_label, false_label, 1, state);	define_jcf_label (next_label, state);	generate_bytecode_conditional (TREE_OPERAND (exp, 1),				       true_label, false_label, 1, state);      }      break;    case TRUTH_ORIF_EXPR:      {	struct jcf_block *next_label = gen_jcf_label (state);	generate_bytecode_conditional (TREE_OPERAND (exp, 0),				       true_label, next_label, 1, state);	define_jcf_label (next_label, state);	generate_bytecode_conditional (TREE_OPERAND (exp, 1),				       true_label, false_label, 1, state);      }      break;    compare_1:      /* Assuming op is one of the 2-operand if_icmp<COND> instructions,	 set it to the corresponding 1-operand if<COND> instructions. */      op = op - 6;      /* FALLTHROUGH */    compare_2:      /* The opcodes with their inverses are allocated in pairs.	 E.g.  The inverse of if_icmplt (161) is if_icmpge (162). */      negop = (op & 1) ? op + 1 : op - 1;    compare_2_ptr:      if (true_branch_first)	{	  emit_if (false_label, negop, op, state);	  emit_goto (true_label, state);	}      else	{	  emit_if (true_label, op, negop, state);	  emit_goto (false_label, state);	}      break;    case EQ_EXPR:      op = OPCODE_if_icmpeq;      goto compare;    case NE_EXPR:      op = OPCODE_if_icmpne;      goto compare;    case GT_EXPR:      op = OPCODE_if_icmpgt;      goto compare;    case LT_EXPR:      op = OPCODE_if_icmplt;      goto compare;    case GE_EXPR:      op = OPCODE_if_icmpge;      goto compare;    case LE_EXPR:      op = OPCODE_if_icmple;      goto compare;    compare:      exp0 = TREE_OPERAND (exp, 0);      exp1 = TREE_OPERAND (exp, 1);      type = TREE_TYPE (exp0);      switch (TREE_CODE (type))	{	  int opf;	case POINTER_TYPE:  case RECORD_TYPE:	  switch (TREE_CODE (exp))	    {	    case EQ_EXPR:  op = OPCODE_if_acmpeq;  break;	    case NE_EXPR:  op = OPCODE_if_acmpne;  break;	    default:  abort();	    }	  if (integer_zerop (exp1) || integer_zerop (exp0))	    {	      generate_bytecode_insns (integer_zerop (exp1) ? exp0 : exp0,				       STACK_TARGET, state);	      op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);	      negop = (op & 1) ? op - 1 : op + 1;	      NOTE_POP (1);	      goto compare_2_ptr;	    }	  generate_bytecode_insns (exp0, STACK_TARGET, state);	  generate_bytecode_insns (exp1, STACK_TARGET, state);	  NOTE_POP (2);	  goto compare_2;	case REAL_TYPE:	  generate_bytecode_insns (exp0, STACK_TARGET, state);	  generate_bytecode_insns (exp1, STACK_TARGET, state);	  if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)	    opf = OPCODE_fcmpg;	  else	    opf = OPCODE_fcmpl;	  if (TYPE_PRECISION (type) > 32)	    {	      opf += 2;	      NOTE_POP (4);	    }	  else	    NOTE_POP (2);	  RESERVE (1);	  OP1 (opf);	  goto compare_1;	case INTEGER_TYPE:	  if (TYPE_PRECISION (type) > 32)	    {	      generate_bytecode_insns (exp0, STACK_TARGET, state);	      generate_bytecode_insns (exp1, STACK_TARGET, state);	      NOTE_POP (4);	      RESERVE (1);	      OP1 (OPCODE_lcmp);	      goto compare_1;	    }	  /* FALLTHOUGH */	default:	  if (integer_zerop (exp1))	    {	      generate_bytecode_insns (exp0, STACK_TARGET, state);	      NOTE_POP (1);	      goto compare_1;	    }	  if (integer_zerop (exp0))	    {	      switch (op)		{		case OPCODE_if_icmplt:		case OPCODE_if_icmpge:		  op += 2;		  break;		case OPCODE_if_icmpgt:		case OPCODE_if_icmple:		  op -= 2;		  break;		default:		  break;		}	      generate_bytecode_insns (exp1, STACK_TARGET, state);	      NOTE_POP (1);	      goto compare_1;	    }	  generate_bytecode_insns (exp0, STACK_TARGET, state);	  generate_bytecode_insns (exp1, STACK_TARGET, state);	  NOTE_POP (2);	  goto compare_2;	}    default:      generate_bytecode_insns (exp, STACK_TARGET, state);      NOTE_POP (1);      if (true_branch_first)	{	  emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);	  emit_goto (true_label, state);	}      else	{	  emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);	  emit_goto (false_label, state);	}      break;    }  if (save_SP != state->code_SP)    fatal ("internal error - SP mismatch");}/* Call pending cleanups i.e. those for surrounding CLEANUP_POINT_EXPRs   but only as far out as LIMIT (since we are about to jump to the   emit label that is LIMIT). */static voidcall_cleanups (limit, state)     struct jcf_block *limit;     struct jcf_partial *state;{  struct jcf_block *block = state->labeled_blocks;  for (;  block != limit;  block = block->next)    {      if (block->pc == PENDING_CLEANUP_PC)	emit_jsr (block, state);    }}static voidgenerate_bytecode_return (exp, state)     tree exp;     struct jcf_partial *state;{  tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));  int returns_void = TREE_CODE (return_type) == VOID_TYPE;  int op; again:  if (exp != NULL)    {      switch (TREE_CODE (exp))	{ 	case COMPOUND_EXPR:		  generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,				   state);	  exp = TREE_OPERAND (exp, 1);	  goto again;	case COND_EXPR:	  {	    struct jcf_block *then_label = gen_jcf_label (state);	    struct jcf_block *else_label = gen_jcf_label (state);	    generate_bytecode_conditional (TREE_OPERAND (exp, 0),					   then_label, else_label, 1, state);	    define_jcf_label (then_label, state);	    generate_bytecode_return (TREE_OPERAND (exp, 1), state);	    define_jcf_label (else_label, state);	    generate_bytecode_return (TREE_OPERAND (exp, 2), state);	  }	  return;	default:	  generate_bytecode_insns (exp,				   returns_void ? IGNORE_TARGET				   : STACK_TARGET, state);	}    }  if (returns_void)    {      op = OPCODE_return;      call_cleanups (NULL_TREE, state);    }  else    {      op = OPCODE_ireturn + adjust_typed_op (return_type, 4);      if (state->num_finalizers > 0)	{	  if (state->return_value_decl == NULL_TREE)	    {	      state->return_value_decl		= build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));	      localvar_alloc (state->return_value_decl, state);	    }	  emit_store (state->return_value_decl, state);	  call_cleanups (NULL_TREE, state);	  emit_load (state->return_value_decl, state);	  /* If we call localvar_free (state->return_value_decl, state),	     then we risk the save decl erroneously re-used in the	     finalizer.  Instead, we keep the state->return_value_decl	     allocated through the rest of the method.  This is not	     the greatest solution, but it is at least simple and safe. */	}    }  RESERVE (1);  OP1 (op);}

⌨️ 快捷键说明

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