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

📄 jcf-write.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Generate bytecode for sub-expression EXP of METHOD.   TARGET is one of STACK_TARGET or IGNORE_TARGET. */static voidgenerate_bytecode_insns (exp, target, state)     tree exp;     int target;     struct jcf_partial *state;{  tree type;  enum java_opcode jopcode;  int op;  HOST_WIDE_INT value;  int post_op;  int size;  int offset;  if (exp == NULL && target == IGNORE_TARGET)    return;  type = TREE_TYPE (exp);  switch (TREE_CODE (exp))    {    case BLOCK:      if (BLOCK_EXPR_BODY (exp))	{	  tree local;	  tree body = BLOCK_EXPR_BODY (exp);	  for (local = BLOCK_EXPR_DECLS (exp); local; )	    {	      tree next = TREE_CHAIN (local);	      localvar_alloc (local, state);	      local = next;	    }	  /* Avoid deep recursion for long blocks. */	  while (TREE_CODE (body) == COMPOUND_EXPR)	    {	      generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);	      body = TREE_OPERAND (body, 1);	    }	  generate_bytecode_insns (body, target, state);	  for (local = BLOCK_EXPR_DECLS (exp); local; )	    {	      tree next = TREE_CHAIN (local);	      localvar_free (local, state);	      local = next;	    }	}      break;      case COMPOUND_EXPR:		generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);	generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);      break;    case EXPR_WITH_FILE_LOCATION:      {	char *saved_input_filename = input_filename;	tree body = EXPR_WFL_NODE (exp);	int saved_lineno = lineno;	if (body == empty_stmt_node)	  break;	input_filename = EXPR_WFL_FILENAME (exp);	lineno = EXPR_WFL_LINENO (exp);	if (EXPR_WFL_EMIT_LINE_NOTE (exp) && lineno > 0	    && debug_info_level > DINFO_LEVEL_NONE)	  put_linenumber (lineno, state);	generate_bytecode_insns (body, target, state);	input_filename = saved_input_filename;	lineno = saved_lineno;      }      break;    case INTEGER_CST:      if (target == IGNORE_TARGET) ; /* do nothing */      else if (TREE_CODE (type) == POINTER_TYPE)	{	  if (! integer_zerop (exp))	    abort();	  RESERVE(1);	  OP1 (OPCODE_aconst_null);	  NOTE_PUSH (1);	}      else if (TYPE_PRECISION (type) <= 32)	{	  push_int_const (TREE_INT_CST_LOW (exp), state);	  NOTE_PUSH (1);	}      else	{	  push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),			   state);	  NOTE_PUSH (2);	}      break;    case REAL_CST:      {	int prec = TYPE_PRECISION (type) >> 5;	RESERVE(1);	if (real_zerop (exp))	  OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);	else if (real_onep (exp))	  OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);	/* FIXME Should also use fconst_2 for 2.0f.	   Also, should use iconst_2/ldc followed by i2f/i2d	   for other float/double when the value is a small integer. */	else	  {	    offset = find_constant_index (exp, state);	    if (prec == 1)	      push_constant1 (offset, state);	    else	      push_constant2 (offset, state);	  }	NOTE_PUSH (prec);      }      break;    case STRING_CST:      push_constant1 (find_string_constant (&state->cpool, exp), state);      NOTE_PUSH (1);      break;    case VAR_DECL:      if (TREE_STATIC (exp))	{	  field_op (exp, OPCODE_getstatic, state);	  NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);	  break;	}      /* ... fall through ... */    case PARM_DECL:      emit_load (exp, state);      break;    case NON_LVALUE_EXPR:    case INDIRECT_REF:      generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);      break;    case ARRAY_REF:      generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);      generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);      if (target != IGNORE_TARGET)	{	  jopcode = OPCODE_iaload + adjust_typed_op (type, 7);	  RESERVE(1);	  OP1 (jopcode);	  if (! TYPE_IS_WIDE (type))	    NOTE_POP (1);	}      break;    case COMPONENT_REF:      {	tree obj = TREE_OPERAND (exp, 0);	tree field = TREE_OPERAND (exp, 1);	int is_static = FIELD_STATIC (field);	generate_bytecode_insns (obj,				 is_static ? IGNORE_TARGET : target, state);	if (target != IGNORE_TARGET)	  {	    if (DECL_NAME (field) == length_identifier_node && !is_static		&& TYPE_ARRAY_P (TREE_TYPE (obj)))	      {		RESERVE (1);		OP1 (OPCODE_arraylength);	      }	    else	      {		field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,			  state);		if (! is_static)		  NOTE_POP (1);		NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);	      }	  }      }      break;    case TRUTH_ANDIF_EXPR:    case TRUTH_ORIF_EXPR:    case EQ_EXPR:    case NE_EXPR:    case GT_EXPR:    case LT_EXPR:    case GE_EXPR:    case LE_EXPR:      {	struct jcf_block *then_label = gen_jcf_label (state);	struct jcf_block *else_label = gen_jcf_label (state);	struct jcf_block *end_label = gen_jcf_label (state);	generate_bytecode_conditional (exp,				       then_label, else_label, 1, state);	define_jcf_label (then_label, state);	push_int_const (1, state);	emit_goto (end_label, state);	define_jcf_label (else_label, state);	push_int_const (0, state);	define_jcf_label (end_label, state);	NOTE_PUSH (1);      }      break;    case COND_EXPR:      {	struct jcf_block *then_label = gen_jcf_label (state);	struct jcf_block *else_label = gen_jcf_label (state);	struct jcf_block *end_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_insns (TREE_OPERAND (exp, 1), target, state);	if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))	    /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */	    || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)	  emit_goto (end_label, state);	define_jcf_label (else_label, state);	generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);	define_jcf_label (end_label, state);      }      break;    case CASE_EXPR:      {	struct jcf_switch_state *sw_state = state->sw_state;	struct jcf_relocation *reloc = (struct jcf_relocation *)	  obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));	HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));	reloc->kind = 0;	reloc->label = get_jcf_label_here (state);	reloc->offset = case_value;	reloc->next = sw_state->cases;	sw_state->cases = reloc;	if (sw_state->num_cases == 0)	  {	    sw_state->min_case = case_value;	    sw_state->max_case = case_value;	  }	else	  {	    if (case_value < sw_state->min_case)	      sw_state->min_case = case_value;	    if (case_value > sw_state->max_case)	      sw_state->max_case = case_value;	  }	sw_state->num_cases++;      }      break;    case DEFAULT_EXPR:      state->sw_state->default_label = get_jcf_label_here (state);      break;    case SWITCH_EXPR:      {	/* The SWITCH_EXPR has three parts, generated in the following order:	   1.  the switch_expression (the value used to select the correct case);	   2.  the switch_body;	   3.  the switch_instruction (the tableswitch/loopupswitch instruction.).	   After code generation, we will re-order then in the order 1, 3, 2.	   This is to avoid an extra GOTOs. */	struct jcf_switch_state sw_state;	struct jcf_block *expression_last; /* Last block of the switch_expression. */	struct jcf_block *body_last; /* Last block of the switch_body. */	struct jcf_block *switch_instruction;  /* First block of switch_instruction. */	struct jcf_block *instruction_last; /* Last block of the switch_instruction. */	struct jcf_block *body_block;	int switch_length;	sw_state.prev = state->sw_state;	state->sw_state = &sw_state;	sw_state.cases = NULL;	sw_state.num_cases = 0;	sw_state.default_label = NULL;	generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);	expression_last = state->last_block;	body_block = get_jcf_label_here (state);  /* Force a new block here. */	generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);	body_last = state->last_block;	switch_instruction = gen_jcf_label (state);	define_jcf_label (switch_instruction, state);	if (sw_state.default_label == NULL)	  sw_state.default_label = gen_jcf_label (state);	if (sw_state.num_cases <= 1)	  {	    if (sw_state.num_cases == 0)	      {		emit_pop (1, state);		NOTE_POP (1);	      }	    else	      {		push_int_const (sw_state.cases->offset, state);		emit_if (sw_state.cases->label,			 OPCODE_ifeq, OPCODE_ifne, state);	      }	    emit_goto (sw_state.default_label, state);	  }	else	  {	    HOST_WIDE_INT i;	    /* Copy the chain of relocs into a sorted array. */	    struct jcf_relocation **relocs = (struct jcf_relocation **)	      xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));	    /* The relocs arrays is a buffer with a gap.	       The assumption is that cases will normally come in "runs". */	    int gap_start = 0;	    int gap_end = sw_state.num_cases;	    struct jcf_relocation *reloc;	    for (reloc = sw_state.cases;  reloc != NULL;  reloc = reloc->next)	      {		HOST_WIDE_INT case_value = reloc->offset;		while (gap_end < sw_state.num_cases)		  {		    struct jcf_relocation *end = relocs[gap_end];		    if (case_value <= end->offset)		      break;		    relocs[gap_start++] = end;		    gap_end++;		  }		while (gap_start > 0)		  {		    struct jcf_relocation *before = relocs[gap_start-1];		    if (case_value >= before->offset)		      break;		    relocs[--gap_end] = before;		    gap_start--;		  }		relocs[gap_start++] = reloc;		/* Note we don't check for duplicates.  FIXME! */	      }	    if (2 * sw_state.num_cases		>= sw_state.max_case - sw_state.min_case)	      { /* Use tableswitch. */		int index = 0;		RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));		OP1 (OPCODE_tableswitch);		emit_reloc (0, SWITCH_ALIGN_RELOC, NULL, state);		emit_switch_reloc (sw_state.default_label, state);		OP4 (sw_state.min_case);		OP4 (sw_state.max_case);		for (i = sw_state.min_case; ; )		  {		    reloc = relocs[index];		    if (i == reloc->offset)		      {			emit_case_reloc (reloc, state);			if (i == sw_state.max_case)			  break;			index++;		      }		    else		      emit_switch_reloc (sw_state.default_label, state);		    i++;		  }	      }	    else	      { /* Use lookupswitch. */		RESERVE(9 + 8 * sw_state.num_cases);		OP1 (OPCODE_lookupswitch);		emit_reloc (0, SWITCH_ALIGN_RELOC, NULL, state);		emit_switch_reloc (sw_state.default_label, state);		OP4 (sw_state.num_cases);		for (i = 0;  i < sw_state.num_cases;  i++)		  {		    struct jcf_relocation *reloc = relocs[i];		    OP4 (reloc->offset);		    emit_case_reloc (reloc, state);		  }	      }	    free (relocs);	  }	instruction_last = state->last_block;	if (sw_state.default_label->pc < 0)	  define_jcf_label (sw_state.default_label, state);	else /* Force a new block. */	  sw_state.default_label = get_jcf_label_here (state);	/* Now re-arrange the blocks so the switch_instruction	   comes before the switch_body. */	switch_length = state->code_length - switch_instruction->pc;	switch_instruction->pc = body_block->pc;	instruction_last->next = body_block;	instruction_last->v.chunk->next = body_block->v.chunk;	expression_last->next = switch_instruction;	expression_last->v.chunk->next = switch_instruction->v.chunk;	body_last->next = sw_state.default_label;	body_last->v.chunk->next = NULL;	state->chunk = body_last->v.chunk;	for (;  body_block != sw_state.default_label;  body_block = body_block->next)	  body_block->pc += switch_length;	state->sw_state = sw_state.prev;	break;      }    case RETURN_EXPR:      exp = TREE_OPERAND (exp, 0);      if (exp == NULL_TREE)	exp = empty_stmt_node;      else if (TREE_CODE (exp) != MODIFY_EXPR) 	abort ();      else	exp = TREE_OPERAND (exp, 1);      generate_bytecode_return (exp, state);      break;    case LABELED_BLOCK_EXPR:      {	struct jcf_block *end_label = gen_jcf_label (state);	end_label->next = state->labeled_blocks;	state->labeled_blocks = end_label;	end_label->pc = PENDING_EXIT_PC;	end_label->u.labeled_block = exp;	if (LABELED_BLOCK_BODY (exp))	  generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);	if (state->labeled_blocks != end_label)	  abort();	state->labeled_blocks = end_label->next;	define_jcf_label (end_label, state);      }      break;    case LOOP_EXPR:      {	tree body = TREE_OPERAND (exp, 0);#if 0	if (TREE_CODE (body) == COMPOUND_EXPR	    && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)	  {	    /* Optimize:  H: if (TEST) GOTO L; BODY; GOTO H; L:	       to:  GOTO L;  BODY;  L:  if (!TEST) GOTO L; */	    struct jcf_block *head_label;	    struct jcf_block *body_label;	    struct jcf_block *end_label = gen_jcf_label (state);	    struct jcf_block *exit_label = state->labeled_blocks;	    head_label = gen_jcf_label (state);	    emit_goto (head_label, state);	    body_label = get_jcf_label_here (state);	    generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);	    define_jcf_label (head_label, state);	    generate_bytecode_conditional (TREE_OPERAND (body, 0),					   end_label, body_label, 1, state);	    define_jcf_label (end_label, state);	  }	else#endif	  {	    struct jcf_block *head_label = get_jcf_label_here (state);	    generate_bytecode_insns (body, IGNORE_TARGET, state);	    emit_goto (head_label, state);	  }      }      break;    case EXIT_EXPR:      {	struct jcf_block *label = state->labeled_blocks;	struct jcf_block *end_label = gen_jcf_label (state);	generate_bytecode_conditional (TREE_OPERAND (exp, 0),				       label, end_label, 0, state);	define_jcf_label (end_label, state);      }      break;

⌨️ 快捷键说明

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