[multiple changes]
Tue Oct 3 13:44:37 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> * decl.c (find_local_variable): Removed uncessary type check and fixed range check typo. From Corey Minyard. Wed Sep 13 16:06:52 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> * decl.c (give_name_to_locals): New local `code_offset'. Call `maybe_adjust_start_pc.' * expr.c (note_instructions): New function. (expand_byte_code): Don't collect insn starts here. (peek_opcode_at_pc): New function. (maybe_adjust_start_pc): Likewise. * java-tree.h (maybe_adjust_start_pc): Declare. (note_instructions): Likewise. * jcf-parse.c (parse_class_file): Call `note_instructions.' Wed Sep 13 11:50:35 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> * parse.y (field_access:): Fixed indentation. (qualify_ambiguous_name): Properly qualify `this.a[b].c'. (http://gcc.gnu.org/ml/gcc-patches/2000-10/msg00067.html) From-SVN: r36717
This commit is contained in:
parent
e23062d5a7
commit
6e22695a4c
@ -1,3 +1,25 @@
|
||||
Tue Oct 3 13:44:37 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* decl.c (find_local_variable): Removed uncessary type check and
|
||||
fixed range check typo. From Corey Minyard.
|
||||
|
||||
Wed Sep 13 16:06:52 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* decl.c (give_name_to_locals): New local `code_offset'. Call
|
||||
`maybe_adjust_start_pc.'
|
||||
* expr.c (note_instructions): New function.
|
||||
(expand_byte_code): Don't collect insn starts here.
|
||||
(peek_opcode_at_pc): New function.
|
||||
(maybe_adjust_start_pc): Likewise.
|
||||
* java-tree.h (maybe_adjust_start_pc): Declare.
|
||||
(note_instructions): Likewise.
|
||||
* jcf-parse.c (parse_class_file): Call `note_instructions.'
|
||||
|
||||
Wed Sep 13 11:50:35 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* parse.y (field_access:): Fixed indentation.
|
||||
(qualify_ambiguous_name): Properly qualify `this.a[b].c'.
|
||||
|
||||
2000-09-07 Tom Tromey <tromey@cygnus.com>
|
||||
|
||||
Fix for PR gcj/307:
|
||||
|
@ -170,9 +170,8 @@ find_local_variable (index, type, pc)
|
||||
&& in_range)
|
||||
{
|
||||
if (best == NULL_TREE
|
||||
|| (TREE_TYPE (decl) == type && TREE_TYPE (best) != type)
|
||||
|| DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
|
||||
|| DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (decl))
|
||||
|| (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
|
||||
&& DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (best)))
|
||||
best = decl;
|
||||
}
|
||||
decl = DECL_LOCAL_SLOT_CHAIN (decl);
|
||||
@ -1517,6 +1516,7 @@ give_name_to_locals (jcf)
|
||||
JCF *jcf;
|
||||
{
|
||||
int i, n = DECL_LOCALVARIABLES_OFFSET (current_function_decl);
|
||||
int code_offset = DECL_CODE_OFFSET (current_function_decl);
|
||||
tree parm;
|
||||
pending_local_decls = NULL_TREE;
|
||||
if (n == 0)
|
||||
@ -1553,6 +1553,13 @@ give_name_to_locals (jcf)
|
||||
"bad PC range for debug info for local `%s'");
|
||||
end_pc = DECL_CODE_LENGTH (current_function_decl);
|
||||
}
|
||||
|
||||
/* Adjust start_pc if necessary so that the local's first
|
||||
store operation will use the relevant DECL as a
|
||||
destination. Fore more information, read the leading
|
||||
comments for expr.c:maybe_adjust_start_pc. */
|
||||
start_pc = maybe_adjust_start_pc (jcf, code_offset, start_pc, slot);
|
||||
|
||||
DECL_LANG_SPECIFIC (decl)
|
||||
= (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl_var));
|
||||
DECL_LOCAL_SLOT_NUMBER (decl) = slot;
|
||||
|
209
gcc/java/expr.c
209
gcc/java/expr.c
@ -80,6 +80,7 @@ static tree build_java_throw_out_of_bounds_exception PARAMS ((tree));
|
||||
static tree build_java_check_indexed_type PARAMS ((tree, tree));
|
||||
static tree java_array_data_offset PARAMS ((tree));
|
||||
static tree case_identity PARAMS ((tree, tree));
|
||||
static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int));
|
||||
|
||||
static tree operand_type[59];
|
||||
extern struct obstack permanent_obstack;
|
||||
@ -2479,16 +2480,20 @@ java_lang_expand_expr (exp, target, tmode, modifier)
|
||||
}
|
||||
}
|
||||
|
||||
/* Go over METHOD's bytecode and note instruction starts in
|
||||
instruction_bits[]. */
|
||||
|
||||
void
|
||||
expand_byte_code (jcf, method)
|
||||
note_instructions (jcf, method)
|
||||
JCF *jcf;
|
||||
tree method;
|
||||
{
|
||||
int PC;
|
||||
int i;
|
||||
int PC;
|
||||
unsigned char* byte_ops;
|
||||
long length = DECL_CODE_LENGTH (method);
|
||||
|
||||
int saw_index;
|
||||
const unsigned char *linenumber_pointer;
|
||||
int dead_code_index = -1;
|
||||
jint INT_temp;
|
||||
|
||||
#undef RET /* Defined by config/i386/i386.h */
|
||||
#undef AND /* Causes problems with opcodes for iand and land. */
|
||||
@ -2503,14 +2508,6 @@ expand_byte_code (jcf, method)
|
||||
#define FLOAT_type_node float_type_node
|
||||
#define DOUBLE_type_node double_type_node
|
||||
#define VOID_type_node void_type_node
|
||||
jint INT_temp;
|
||||
unsigned char* byte_ops;
|
||||
long length = DECL_CODE_LENGTH (method);
|
||||
|
||||
stack_pointer = 0;
|
||||
JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
|
||||
byte_ops = jcf->read_ptr;
|
||||
|
||||
#define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
|
||||
#define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
|
||||
#define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
|
||||
@ -2518,28 +2515,12 @@ expand_byte_code (jcf, method)
|
||||
|
||||
#define CHECK_PC_IN_RANGE(PC) ((void)1) /* Already handled by verifier. */
|
||||
|
||||
JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
|
||||
byte_ops = jcf->read_ptr;
|
||||
instruction_bits = oballoc (length + 1);
|
||||
bzero (instruction_bits, length + 1);
|
||||
|
||||
/* We make an initial pass of the line number table, to note
|
||||
which instructions have associated line number entries. */
|
||||
linenumber_pointer = linenumber_table;
|
||||
for (i = 0; i < linenumber_count; i++)
|
||||
{
|
||||
int pc = GET_u2 (linenumber_pointer);
|
||||
linenumber_pointer += 4;
|
||||
if (pc >= length)
|
||||
warning ("invalid PC in line number table");
|
||||
else
|
||||
{
|
||||
if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0)
|
||||
instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS;
|
||||
instruction_bits[pc] |= BCODE_HAS_LINENUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do a preliminary pass.
|
||||
* This figures out which PC can be the targets of jumps. */
|
||||
/* This pass figures out which PC can be the targets of jumps. */
|
||||
for (PC = 0; PC < length;)
|
||||
{
|
||||
int oldpc = PC; /* PC at instruction start. */
|
||||
@ -2586,8 +2567,6 @@ expand_byte_code (jcf, method)
|
||||
} \
|
||||
}
|
||||
|
||||
/* nothing */ /* XXX JH */
|
||||
|
||||
#define PRE_IMPL(IGNORE1, IGNORE2) /* nothing */
|
||||
|
||||
#define PRE_MONITOR(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
|
||||
@ -2647,6 +2626,40 @@ expand_byte_code (jcf, method)
|
||||
#undef JAVAOP
|
||||
}
|
||||
} /* for */
|
||||
}
|
||||
|
||||
void
|
||||
expand_byte_code (jcf, method)
|
||||
JCF *jcf;
|
||||
tree method;
|
||||
{
|
||||
int PC;
|
||||
int i;
|
||||
const unsigned char *linenumber_pointer;
|
||||
int dead_code_index = -1;
|
||||
unsigned char* byte_ops;
|
||||
long length = DECL_CODE_LENGTH (method);
|
||||
|
||||
stack_pointer = 0;
|
||||
JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
|
||||
byte_ops = jcf->read_ptr;
|
||||
|
||||
/* We make an initial pass of the line number table, to note
|
||||
which instructions have associated line number entries. */
|
||||
linenumber_pointer = linenumber_table;
|
||||
for (i = 0; i < linenumber_count; i++)
|
||||
{
|
||||
int pc = GET_u2 (linenumber_pointer);
|
||||
linenumber_pointer += 4;
|
||||
if (pc >= length)
|
||||
warning ("invalid PC in line number table");
|
||||
else
|
||||
{
|
||||
if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0)
|
||||
instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS;
|
||||
instruction_bits[pc] |= BCODE_HAS_LINENUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
if (! verify_jvm_instructions (jcf, byte_ops, length))
|
||||
return;
|
||||
@ -3064,6 +3077,134 @@ process_jvm_instruction (PC, byte_ops, length)
|
||||
return PC;
|
||||
}
|
||||
|
||||
/* Return the opcode at PC in the code section pointed to by
|
||||
CODE_OFFSET. */
|
||||
|
||||
static unsigned char
|
||||
peek_opcode_at_pc (jcf, code_offset, pc)
|
||||
JCF *jcf;
|
||||
int code_offset, pc;
|
||||
{
|
||||
unsigned char opcode;
|
||||
long absolute_offset = (long)JCF_TELL (jcf);
|
||||
|
||||
JCF_SEEK (jcf, code_offset);
|
||||
opcode = jcf->read_ptr [pc];
|
||||
JCF_SEEK (jcf, absolute_offset);
|
||||
return opcode;
|
||||
}
|
||||
|
||||
/* Some bytecode compilers are emitting accurate LocalVariableTable
|
||||
attributes. Here's an example:
|
||||
|
||||
PC <t>store_<n>
|
||||
PC+1 ...
|
||||
|
||||
Attribute "LocalVariableTable"
|
||||
slot #<n>: ... (PC: PC+1 length: L)
|
||||
|
||||
This is accurate because the local in slot <n> really exists after
|
||||
the opcode at PC is executed, hence from PC+1 to PC+1+L.
|
||||
|
||||
This procedure recognizes this situation and extends the live range
|
||||
of the local in SLOT to START_PC-1 or START_PC-2 (depending on the
|
||||
length of the store instruction.)
|
||||
|
||||
This function is used by `give_name_to_locals' so that a local's
|
||||
DECL features a DECL_LOCAL_START_PC such that the first related
|
||||
store operation will use DECL as a destination, not a unrelated
|
||||
temporary created for the occasion.
|
||||
|
||||
This function uses a global (instruction_bits) `note_instructions' should
|
||||
have allocated and filled properly. */
|
||||
|
||||
int
|
||||
maybe_adjust_start_pc (jcf, code_offset, start_pc, slot)
|
||||
struct JCF *jcf;
|
||||
int code_offset, start_pc, slot;
|
||||
{
|
||||
int first, index, opcode;
|
||||
int pc, insn_pc;
|
||||
int wide_found = 0;
|
||||
|
||||
if (!start_pc)
|
||||
return start_pc;
|
||||
|
||||
first = index = -1;
|
||||
|
||||
/* Find last previous instruction and remember it */
|
||||
for (pc = start_pc-1; pc; pc--)
|
||||
if (instruction_bits [pc] & BCODE_INSTRUCTION_START)
|
||||
break;
|
||||
insn_pc = pc;
|
||||
|
||||
/* Retrieve the instruction, handle `wide'. */
|
||||
opcode = (int) peek_opcode_at_pc (jcf, code_offset, pc++);
|
||||
if (opcode == OPCODE_wide)
|
||||
{
|
||||
wide_found = 1;
|
||||
opcode = (int) peek_opcode_at_pc (jcf, code_offset, pc++);
|
||||
}
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case OPCODE_astore_0:
|
||||
case OPCODE_astore_1:
|
||||
case OPCODE_astore_2:
|
||||
case OPCODE_astore_3:
|
||||
first = OPCODE_astore_0;
|
||||
break;
|
||||
|
||||
case OPCODE_istore_0:
|
||||
case OPCODE_istore_1:
|
||||
case OPCODE_istore_2:
|
||||
case OPCODE_istore_3:
|
||||
first = OPCODE_istore_0;
|
||||
break;
|
||||
|
||||
case OPCODE_lstore_0:
|
||||
case OPCODE_lstore_1:
|
||||
case OPCODE_lstore_2:
|
||||
case OPCODE_lstore_3:
|
||||
first = OPCODE_lstore_0;
|
||||
break;
|
||||
|
||||
case OPCODE_fstore_0:
|
||||
case OPCODE_fstore_1:
|
||||
case OPCODE_fstore_2:
|
||||
case OPCODE_fstore_3:
|
||||
first = OPCODE_fstore_0;
|
||||
break;
|
||||
|
||||
case OPCODE_dstore_0:
|
||||
case OPCODE_dstore_1:
|
||||
case OPCODE_dstore_2:
|
||||
case OPCODE_dstore_3:
|
||||
first = OPCODE_dstore_0;
|
||||
break;
|
||||
|
||||
case OPCODE_astore:
|
||||
case OPCODE_istore:
|
||||
case OPCODE_lstore:
|
||||
case OPCODE_fstore:
|
||||
case OPCODE_dstore:
|
||||
index = peek_opcode_at_pc (jcf, code_offset, pc);
|
||||
if (wide_found)
|
||||
{
|
||||
int other = peek_opcode_at_pc (jcf, code_offset, ++pc);
|
||||
index = (other << 8) + index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now we decide: first >0 means we have a <t>store_<n>, index >0
|
||||
means we have a <t>store. */
|
||||
if ((first > 0 && opcode - first == slot) || (index > 0 && index == slot))
|
||||
start_pc = insn_pc;
|
||||
|
||||
return start_pc;
|
||||
}
|
||||
|
||||
/* Force the (direct) sub-operands of NODE to be evaluated in left-to-right
|
||||
order, as specified by Java Language Specification.
|
||||
|
||||
|
@ -1003,6 +1003,7 @@ extern void maybe_pushlevels PARAMS ((int));
|
||||
extern void maybe_poplevels PARAMS ((int));
|
||||
extern void force_poplevels PARAMS ((int));
|
||||
extern int process_jvm_instruction PARAMS ((int, const unsigned char *, long));
|
||||
extern int maybe_adjust_start_pc PARAMS ((struct JCF *, int, int, int));
|
||||
extern void set_local_type PARAMS ((int, tree));
|
||||
extern int merge_type_state PARAMS ((tree));
|
||||
extern void push_type PARAMS ((tree));
|
||||
@ -1016,6 +1017,7 @@ extern int verify_constant_pool PARAMS ((struct JCF *));
|
||||
extern void start_java_method PARAMS ((tree));
|
||||
extern void end_java_method PARAMS ((void));
|
||||
extern void give_name_to_locals PARAMS ((struct JCF *));
|
||||
extern void note_instructions PARAMS ((struct JCF *, tree));
|
||||
extern void expand_byte_code PARAMS ((struct JCF *, tree));
|
||||
extern int open_in_zip PARAMS ((struct JCF *, const char *, const char *, int));
|
||||
extern void set_constant_value PARAMS ((tree, tree));
|
||||
|
@ -2172,8 +2172,7 @@ field_access:
|
||||
{ $$ = build_binop (COMPONENT_REF, $2.location, $1, $3); } */
|
||||
| SUPER_TK DOT_TK identifier
|
||||
{
|
||||
tree super_wfl =
|
||||
build_wfl_node (super_identifier_node);
|
||||
tree super_wfl = build_wfl_node (super_identifier_node);
|
||||
EXPR_WFL_LINECOL (super_wfl) = $1.location;
|
||||
$$ = make_qualified_name (super_wfl, $3, $2.location);
|
||||
}
|
||||
@ -10741,6 +10740,17 @@ qualify_ambiguous_name (id)
|
||||
/* If we have a THIS (from a primary), we set the context accordingly */
|
||||
if (name == this_identifier_node)
|
||||
{
|
||||
/* This isn't really elegant. One more added irregularity
|
||||
before I start using COMPONENT_REF (hopefully very soon.) */
|
||||
if (TREE_CODE (TREE_PURPOSE (qual)) == ARRAY_REF
|
||||
&& TREE_CODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) ==
|
||||
EXPR_WITH_FILE_LOCATION
|
||||
&& EXPR_WFL_NODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) ==
|
||||
this_identifier_node)
|
||||
{
|
||||
qual = TREE_OPERAND (TREE_PURPOSE (qual), 0);
|
||||
qual = EXPR_WFL_QUALIFICATION (qual);
|
||||
}
|
||||
qual = TREE_CHAIN (qual);
|
||||
qual_wfl = QUAL_WFL (qual);
|
||||
if (TREE_CODE (qual_wfl) == CALL_EXPR)
|
||||
|
Loading…
Reference in New Issue
Block a user