1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
27 #include "coretypes.h"
32 #include "java-tree.h"
36 #include "java-opcodes.h"
37 #include "parse.h" /* for BLOCK_EXPR_BODY */
43 extern struct obstack temporary_obstack
;
45 /* Base directory in which `.class' files should be written.
46 NULL means to put the file into the same directory as the
47 corresponding .java file. */
48 const char *jcf_write_base_directory
= NULL
;
50 /* Make sure bytecode.data is big enough for at least N more bytes. */
53 do { CHECK_OP(state); \
54 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
55 buffer_grow (&state->bytecode, N); } while (0)
57 /* Add a 1-byte instruction/operand I to bytecode.data,
58 assuming space has already been RESERVE'd. */
60 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
62 /* Like OP1, but I is a 2-byte big endian integer. */
65 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
67 /* Like OP1, but I is a 4-byte big endian integer. */
70 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
71 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
73 /* Macro to call each time we push I words on the JVM stack. */
75 #define NOTE_PUSH(I) \
76 do { state->code_SP += (I); \
77 if (state->code_SP > state->code_SP_max) \
78 state->code_SP_max = state->code_SP; } while (0)
80 /* Macro to call each time we pop I words from the JVM stack. */
83 do { state->code_SP -= (I); gcc_assert (state->code_SP >= 0); } while (0)
85 /* A chunk or segment of a .class file. */
89 /* The next segment of this .class file. */
92 /* The actual data in this segment to be written to the .class file. */
95 /* The size of the segment to be written to the .class file. */
99 #define PENDING_CLEANUP_PC (-3)
100 #define PENDING_EXIT_PC (-2)
101 #define UNDEFINED_PC (-1)
103 /* Each "block" represents a label plus the bytecode instructions following.
104 There may be branches out of the block, but no incoming jumps, except
105 to the beginning of the block.
107 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
108 associated code yet), but it is an undefined label.
113 /* For blocks that that are defined, the next block (in pc order).
114 For blocks that are not-yet-defined the end label of a LABELED_BLOCK_EXPR
115 or a cleanup expression (from a TRY_FINALLY_EXPR),
116 this is the next (outer) such end label, in a stack headed by
117 labeled_blocks in jcf_partial. */
118 struct jcf_block
*next
;
120 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
121 pc is PENDING_EXIT_PC.
122 In the not-yet-defined end label for pending cleanup subroutine,
123 pc is PENDING_CLEANUP_PC.
124 For other not-yet-defined labels, pc is UNDEFINED_PC.
126 If the label has been defined:
127 Until perform_relocations is finished, this is the maximum possible
128 value of the bytecode offset at the beginning of this block.
129 After perform_relocations, it is the actual offset (pc). */
134 /* After finish_jcf_block is called, the actual instructions
135 contained in this block. Before that NULL, and the instructions
136 are in state->bytecode. */
140 /* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
141 covered by the cleanup. */
142 struct jcf_block
*start_label
;
146 /* Set of relocations (in reverse offset order) for this block. */
147 struct jcf_relocation
*relocations
;
149 /* If this block is that of the not-yet-defined end label of
150 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR.
151 If pc==PENDING_CLEANUP_PC, the cleanup that needs to be run. */
156 /* A "relocation" type for the 0-3 bytes of padding at the start
157 of a tableswitch or a lookupswitch. */
158 #define SWITCH_ALIGN_RELOC 4
160 /* A relocation type for the labels in a tableswitch or a lookupswitch;
161 these are relative to the start of the instruction, but (due to
162 th 0-3 bytes of padding), we don't know the offset before relocation. */
163 #define BLOCK_START_RELOC 1
165 struct jcf_relocation
167 /* Next relocation for the current jcf_block. */
168 struct jcf_relocation
*next
;
170 /* The (byte) offset within the current block that needs to be relocated. */
171 HOST_WIDE_INT offset
;
173 /* 0 if offset is a 4-byte relative offset.
174 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
175 for proper alignment in tableswitch/lookupswitch instructions.
176 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
177 to the start of the containing block.
178 -1 if offset is a 2-byte relative offset.
179 < -1 if offset is the address of an instruction with a 2-byte offset
180 that does not have a corresponding 4-byte offset version, in which
181 case the absolute value of kind is the inverted opcode.
182 > 4 if offset is the address of an instruction (such as jsr) with a
183 2-byte offset that does have a corresponding 4-byte offset version,
184 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
187 /* The label the relocation wants to actually transfer to. */
188 struct jcf_block
*label
;
191 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
192 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
194 /* State for single catch clause. */
198 struct jcf_handler
*next
;
200 struct jcf_block
*start_label
;
201 struct jcf_block
*end_label
;
202 struct jcf_block
*handler_label
;
204 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
208 /* State for the current switch statement. */
210 struct jcf_switch_state
212 struct jcf_switch_state
*prev
;
213 struct jcf_block
*default_label
;
215 struct jcf_relocation
*cases
;
217 HOST_WIDE_INT min_case
, max_case
;
220 /* This structure is used to contain the various pieces that will
221 become a .class file. */
227 struct obstack
*chunk_obstack
;
230 /* List of basic blocks for the current method. */
231 struct jcf_block
*blocks
;
232 struct jcf_block
*last_block
;
234 struct localvar_info
*first_lvar
;
235 struct localvar_info
*last_lvar
;
240 int linenumber_count
;
242 /* Until perform_relocations, this is a upper bound on the number
243 of bytes (so far) in the instructions for the current method. */
246 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
247 struct jcf_block
*labeled_blocks
;
249 /* The current stack size (stack pointer) in the current method. */
252 /* The largest extent of stack size (stack pointer) in the current method. */
255 /* Contains a mapping from local var slot number to localvar_info. */
256 struct buffer localvars
;
258 /* The buffer allocated for bytecode for the current jcf_block. */
259 struct buffer bytecode
;
261 /* Chain of exception handlers for the current method. */
262 struct jcf_handler
*handlers
;
264 /* Last element in handlers chain. */
265 struct jcf_handler
*last_handler
;
267 /* Number of exception handlers for the current method. */
270 /* Number of finalizers we are currently nested within. */
273 /* If non-NULL, use this for the return value. */
274 tree return_value_decl
;
276 /* Information about the current switch statement. */
277 struct jcf_switch_state
*sw_state
;
279 /* The count of jsr instructions that have been emitted. */
283 static void generate_bytecode_insns (tree
, int, struct jcf_partial
*);
284 static struct chunk
* alloc_chunk (struct chunk
*, unsigned char *,
285 int, struct obstack
*);
286 static unsigned char * append_chunk (unsigned char *, int,
287 struct jcf_partial
*);
288 static void append_chunk_copy (unsigned char *, int, struct jcf_partial
*);
289 static struct jcf_block
* gen_jcf_label (struct jcf_partial
*);
290 static void finish_jcf_block (struct jcf_partial
*);
291 static void define_jcf_label (struct jcf_block
*, struct jcf_partial
*);
292 static struct jcf_block
* get_jcf_label_here (struct jcf_partial
*);
293 static void put_linenumber (int, struct jcf_partial
*);
294 static void localvar_alloc (tree
, struct jcf_partial
*);
295 static void maybe_free_localvar (tree
, struct jcf_partial
*, int);
296 static int get_access_flags (tree
);
297 static void write_chunks (FILE *, struct chunk
*);
298 static int adjust_typed_op (tree
, int);
299 static void generate_bytecode_conditional (tree
, struct jcf_block
*,
300 struct jcf_block
*, int,
301 struct jcf_partial
*);
302 static void generate_bytecode_return (tree
, struct jcf_partial
*);
303 static void perform_relocations (struct jcf_partial
*);
304 static void init_jcf_state (struct jcf_partial
*, struct obstack
*);
305 static void init_jcf_method (struct jcf_partial
*, tree
);
306 static void release_jcf_state (struct jcf_partial
*);
307 static int get_classfile_modifiers (tree
class);
308 static struct chunk
* generate_classfile (tree
, struct jcf_partial
*);
309 static struct jcf_handler
*alloc_handler (struct jcf_block
*,
311 struct jcf_partial
*);
312 static void emit_iinc (tree
, HOST_WIDE_INT
, struct jcf_partial
*);
313 static void emit_reloc (HOST_WIDE_INT
, int, struct jcf_block
*,
314 struct jcf_partial
*);
315 static void push_constant1 (HOST_WIDE_INT
, struct jcf_partial
*);
316 static void push_constant2 (HOST_WIDE_INT
, struct jcf_partial
*);
317 static void push_int_const (HOST_WIDE_INT
, struct jcf_partial
*);
318 static int find_constant_wide (HOST_WIDE_INT
, HOST_WIDE_INT
,
319 struct jcf_partial
*);
320 static void push_long_const (HOST_WIDE_INT
, HOST_WIDE_INT
,
321 struct jcf_partial
*);
322 static int find_constant_index (tree
, struct jcf_partial
*);
323 static void push_long_const (HOST_WIDE_INT
, HOST_WIDE_INT
,
324 struct jcf_partial
*);
325 static void field_op (tree
, int, struct jcf_partial
*);
326 static void maybe_wide (int, int, struct jcf_partial
*);
327 static void emit_dup (int, int, struct jcf_partial
*);
328 static void emit_pop (int, struct jcf_partial
*);
329 static void emit_load_or_store (tree
, int, struct jcf_partial
*);
330 static void emit_load (tree
, struct jcf_partial
*);
331 static void emit_store (tree
, struct jcf_partial
*);
332 static void emit_unop (enum java_opcode
, tree
, struct jcf_partial
*);
333 static void emit_binop (enum java_opcode
, tree
, struct jcf_partial
*);
334 static void emit_reloc (HOST_WIDE_INT
, int, struct jcf_block
*,
335 struct jcf_partial
*);
336 static void emit_switch_reloc (struct jcf_block
*, struct jcf_partial
*);
337 static void emit_case_reloc (struct jcf_relocation
*, struct jcf_partial
*);
338 static void emit_if (struct jcf_block
*, int, int, struct jcf_partial
*);
339 static void emit_goto (struct jcf_block
*, struct jcf_partial
*);
340 static void emit_jsr (struct jcf_block
*, struct jcf_partial
*);
341 static void call_cleanups (struct jcf_block
*, struct jcf_partial
*);
342 static char *make_class_file_name (tree
);
343 static unsigned char *append_synthetic_attribute (struct jcf_partial
*);
344 static void append_deprecated_attribute (struct jcf_partial
*);
345 static void append_innerclasses_attribute (struct jcf_partial
*, tree
);
346 static void append_innerclasses_attribute_entry (struct jcf_partial
*, tree
, tree
);
347 static void append_gcj_attribute (struct jcf_partial
*, tree
);
349 /* Utility macros for appending (big-endian) data to a buffer.
350 We assume a local variable 'ptr' points into where we want to
351 write next, and we assume enough space has been allocated. */
353 #ifdef ENABLE_JC1_CHECKING
354 static int CHECK_PUT (void *, struct jcf_partial
*, int);
357 CHECK_PUT (void *ptr
, struct jcf_partial
*state
, int i
)
359 gcc_assert ((unsigned char *) ptr
>= state
->chunk
->data
360 && (unsigned char *) ptr
+ i
<= state
->chunk
->data
+ state
->chunk
->size
);
364 #define CHECK_PUT(PTR, STATE, I) ((void)0)
367 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
368 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
369 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
370 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
372 /* There are some cases below where CHECK_PUT is guaranteed to fail.
373 Use the following macros in those specific cases. */
374 #define UNSAFE_PUT1(X) (*ptr++ = (X))
375 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
376 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
377 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
380 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
381 Set the data and size fields to DATA and SIZE, respectively.
382 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
384 static struct chunk
*
385 alloc_chunk (struct chunk
*last
, unsigned char *data
,
386 int size
, struct obstack
*work
)
388 struct chunk
*chunk
= obstack_alloc (work
, sizeof(struct chunk
));
390 if (data
== NULL
&& size
> 0)
391 data
= obstack_alloc (work
, size
);
401 #ifdef ENABLE_JC1_CHECKING
402 static int CHECK_OP (struct jcf_partial
*);
405 CHECK_OP (struct jcf_partial
*state
)
407 gcc_assert (state
->bytecode
.ptr
<= state
->bytecode
.limit
);
411 #define CHECK_OP(STATE) ((void) 0)
414 static unsigned char *
415 append_chunk (unsigned char *data
, int size
, struct jcf_partial
*state
)
417 state
->chunk
= alloc_chunk (state
->chunk
, data
, size
, state
->chunk_obstack
);
418 if (state
->first
== NULL
)
419 state
->first
= state
->chunk
;
420 return state
->chunk
->data
;
424 append_chunk_copy (unsigned char *data
, int size
, struct jcf_partial
*state
)
426 unsigned char *ptr
= append_chunk (NULL
, size
, state
);
427 memcpy (ptr
, data
, size
);
430 static struct jcf_block
*
431 gen_jcf_label (struct jcf_partial
*state
)
433 struct jcf_block
*block
434 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_block
));
436 block
->linenumber
= -1;
437 block
->pc
= UNDEFINED_PC
;
442 finish_jcf_block (struct jcf_partial
*state
)
444 struct jcf_block
*block
= state
->last_block
;
445 struct jcf_relocation
*reloc
;
446 int code_length
= BUFFER_LENGTH (&state
->bytecode
);
447 int pc
= state
->code_length
;
448 append_chunk_copy (state
->bytecode
.data
, code_length
, state
);
449 BUFFER_RESET (&state
->bytecode
);
450 block
->v
.chunk
= state
->chunk
;
452 /* Calculate code_length to the maximum value it can have. */
453 pc
+= block
->v
.chunk
->size
;
454 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
456 int kind
= reloc
->kind
;
457 if (kind
== SWITCH_ALIGN_RELOC
)
459 else if (kind
> BLOCK_START_RELOC
)
460 pc
+= 2; /* 2-byte offset may grow to 4-byte offset */
462 pc
+= 5; /* May need to add a goto_w. */
464 state
->code_length
= pc
;
468 define_jcf_label (struct jcf_block
*label
, struct jcf_partial
*state
)
470 if (state
->last_block
!= NULL
)
471 finish_jcf_block (state
);
472 label
->pc
= state
->code_length
;
473 if (state
->blocks
== NULL
)
474 state
->blocks
= label
;
476 state
->last_block
->next
= label
;
477 state
->last_block
= label
;
479 label
->u
.relocations
= NULL
;
482 static struct jcf_block
*
483 get_jcf_label_here (struct jcf_partial
*state
)
485 if (state
->last_block
!= NULL
&& BUFFER_LENGTH (&state
->bytecode
) == 0)
486 return state
->last_block
;
489 struct jcf_block
*label
= gen_jcf_label (state
);
490 define_jcf_label (label
, state
);
495 /* Note a line number entry for the current PC and given LINE. */
498 put_linenumber (int line
, struct jcf_partial
*state
)
500 struct jcf_block
*label
= get_jcf_label_here (state
);
501 if (label
->linenumber
> 0)
503 label
= gen_jcf_label (state
);
504 define_jcf_label (label
, state
);
506 label
->linenumber
= line
;
507 state
->linenumber_count
++;
510 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
511 in the range (START_LABEL, END_LABEL). */
513 static struct jcf_handler
*
514 alloc_handler (struct jcf_block
*start_label
, struct jcf_block
*end_label
,
515 struct jcf_partial
*state
)
517 struct jcf_handler
*handler
518 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_handler
));
519 handler
->start_label
= start_label
;
520 handler
->end_label
= end_label
;
521 handler
->handler_label
= get_jcf_label_here (state
);
522 if (state
->handlers
== NULL
)
523 state
->handlers
= handler
;
525 state
->last_handler
->next
= handler
;
526 state
->last_handler
= handler
;
527 handler
->next
= NULL
;
528 state
->num_handlers
++;
533 /* The index of jvm local variable allocated for this DECL.
534 This is assigned when generating .class files;
535 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
536 (We don't allocate DECL_LANG_SPECIFIC for locals from Java source code.) */
538 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
542 struct localvar_info
*next
;
545 struct jcf_block
*start_label
;
546 struct jcf_block
*end_label
;
549 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
550 #define localvar_max \
551 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
554 localvar_alloc (tree decl
, struct jcf_partial
*state
)
556 struct jcf_block
*start_label
= get_jcf_label_here (state
);
557 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
559 struct localvar_info
*info
;
560 struct localvar_info
**ptr
= localvar_buffer
;
561 struct localvar_info
**limit
562 = (struct localvar_info
**) state
->localvars
.ptr
;
563 for (index
= 0; ptr
< limit
; index
++, ptr
++)
566 && (! wide
|| ((ptr
+1) < limit
&& ptr
[1] == NULL
)))
571 buffer_grow (&state
->localvars
, 2 * sizeof (struct localvar_info
*));
572 ptr
= (struct localvar_info
**) state
->localvars
.data
+ index
;
573 state
->localvars
.ptr
= (unsigned char *) (ptr
+ 1 + wide
);
575 info
= obstack_alloc (state
->chunk_obstack
, sizeof (struct localvar_info
));
578 ptr
[1] = (struct localvar_info
*)(~0);
579 DECL_LOCAL_INDEX (decl
) = index
;
581 info
->start_label
= start_label
;
583 if (debug_info_level
> DINFO_LEVEL_TERSE
584 && DECL_NAME (decl
) != NULL_TREE
)
586 /* Generate debugging info. */
588 if (state
->last_lvar
!= NULL
)
589 state
->last_lvar
->next
= info
;
591 state
->first_lvar
= info
;
592 state
->last_lvar
= info
;
598 maybe_free_localvar (tree decl
, struct jcf_partial
*state
, int really
)
600 struct jcf_block
*end_label
= get_jcf_label_here (state
);
601 int index
= DECL_LOCAL_INDEX (decl
);
602 struct localvar_info
**ptr
= &localvar_buffer
[index
];
603 struct localvar_info
*info
= *ptr
;
604 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
606 info
->end_label
= end_label
;
608 gcc_assert (info
->decl
== decl
);
614 gcc_assert (ptr
[1] == (struct localvar_info
*) (~0));
620 #define STACK_TARGET 1
621 #define IGNORE_TARGET 2
623 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
624 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
627 get_access_flags (tree decl
)
630 int isfield
= TREE_CODE (decl
) == FIELD_DECL
|| TREE_CODE (decl
) == VAR_DECL
;
632 if (isfield
|| TREE_CODE (decl
) == FUNCTION_DECL
)
634 if (TREE_PROTECTED (decl
))
635 flags
|= ACC_PROTECTED
;
636 if (TREE_PRIVATE (decl
))
637 flags
|= ACC_PRIVATE
;
639 else if (TREE_CODE (decl
) == TYPE_DECL
)
641 if (CLASS_PUBLIC (decl
))
643 if (CLASS_FINAL (decl
))
645 if (CLASS_SUPER (decl
))
647 if (CLASS_ABSTRACT (decl
))
648 flags
|= ACC_ABSTRACT
;
649 if (CLASS_INTERFACE (decl
))
650 flags
|= ACC_INTERFACE
;
651 if (CLASS_STATIC (decl
))
653 if (CLASS_PRIVATE (decl
))
654 flags
|= ACC_PRIVATE
;
655 if (CLASS_PROTECTED (decl
))
656 flags
|= ACC_PROTECTED
;
657 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl
))
658 || LOCAL_CLASS_P (TREE_TYPE (decl
)))
659 flags
|= ACC_PRIVATE
;
660 if (CLASS_STRICTFP (decl
))
666 if (TREE_CODE (decl
) == FUNCTION_DECL
)
668 if (METHOD_PUBLIC (decl
))
670 if (METHOD_FINAL (decl
))
672 if (METHOD_NATIVE (decl
))
674 if (METHOD_STATIC (decl
))
676 if (METHOD_SYNCHRONIZED (decl
))
677 flags
|= ACC_SYNCHRONIZED
;
678 if (METHOD_ABSTRACT (decl
))
679 flags
|= ACC_ABSTRACT
;
680 if (METHOD_STRICTFP (decl
))
685 if (FIELD_PUBLIC (decl
))
687 if (FIELD_FINAL (decl
))
689 if (FIELD_STATIC (decl
))
691 if (FIELD_VOLATILE (decl
))
692 flags
|= ACC_VOLATILE
;
693 if (FIELD_TRANSIENT (decl
))
694 flags
|= ACC_TRANSIENT
;
699 /* Write the list of segments starting at CHUNKS to STREAM. */
702 write_chunks (FILE* stream
, struct chunk
*chunks
)
704 for (; chunks
!= NULL
; chunks
= chunks
->next
)
705 fwrite (chunks
->data
, chunks
->size
, 1, stream
);
708 /* Push a 1-word constant in the constant pool at the given INDEX.
709 (Caller is responsible for doing NOTE_PUSH.) */
712 push_constant1 (HOST_WIDE_INT index
, struct jcf_partial
*state
)
727 /* Push a 2-word constant in the constant pool at the given INDEX.
728 (Caller is responsible for doing NOTE_PUSH.) */
731 push_constant2 (HOST_WIDE_INT index
, struct jcf_partial
*state
)
738 /* Push 32-bit integer constant on VM stack.
739 Caller is responsible for doing NOTE_PUSH. */
742 push_int_const (HOST_WIDE_INT i
, struct jcf_partial
*state
)
745 if (i
>= -1 && i
<= 5)
746 OP1(OPCODE_iconst_0
+ i
);
747 else if (i
>= -128 && i
< 128)
752 else if (i
>= -32768 && i
< 32768)
759 i
= find_constant1 (&state
->cpool
, CONSTANT_Integer
,
760 (jword
)(i
& 0xFFFFFFFF));
761 push_constant1 (i
, state
);
766 find_constant_wide (HOST_WIDE_INT lo
, HOST_WIDE_INT hi
,
767 struct jcf_partial
*state
)
769 unsigned HOST_WIDE_INT w1
;
771 lshift_double (lo
, hi
, -32, 64, &w1
, &w2
, 1);
772 return find_constant2 (&state
->cpool
, CONSTANT_Long
,
773 (jword
)(w1
& 0xFFFFFFFF), (jword
)(lo
& 0xFFFFFFFF));
776 /* Find or allocate a constant pool entry for the given VALUE.
777 Return the index in the constant pool. */
780 find_constant_index (tree value
, struct jcf_partial
*state
)
782 if (TREE_CODE (value
) == INTEGER_CST
)
784 if (TYPE_PRECISION (TREE_TYPE (value
)) <= 32)
785 return find_constant1 (&state
->cpool
, CONSTANT_Integer
,
786 (jword
)(TREE_INT_CST_LOW (value
) & 0xFFFFFFFF));
788 return find_constant_wide (TREE_INT_CST_LOW (value
),
789 TREE_INT_CST_HIGH (value
), state
);
791 else if (TREE_CODE (value
) == REAL_CST
)
795 /* IEEE NaN can have many values, but the Java VM spec defines a
797 if (flag_emit_class_files
798 && REAL_VALUE_ISNAN (TREE_REAL_CST (value
)))
800 if (TYPE_PRECISION (TREE_TYPE (value
)) == 32)
801 return find_constant1 (&state
->cpool
, CONSTANT_Float
,
804 return find_constant2 (&state
->cpool
, CONSTANT_Double
,
805 0x7ff80000, 0x00000000);
808 real_to_target (words
, &TREE_REAL_CST (value
),
809 TYPE_MODE (TREE_TYPE (value
)));
810 words
[0] &= 0xffffffff;
811 words
[1] &= 0xffffffff;
813 if (TYPE_PRECISION (TREE_TYPE (value
)) == 32)
814 return find_constant1 (&state
->cpool
, CONSTANT_Float
, (jword
)words
[0]);
816 return find_constant2 (&state
->cpool
, CONSTANT_Double
,
817 (jword
)words
[1-FLOAT_WORDS_BIG_ENDIAN
],
818 (jword
)words
[FLOAT_WORDS_BIG_ENDIAN
]);
820 else if (TREE_CODE (value
) == STRING_CST
)
821 return find_string_constant (&state
->cpool
, value
);
827 /* Push 64-bit long constant on VM stack.
828 Caller is responsible for doing NOTE_PUSH. */
831 push_long_const (HOST_WIDE_INT lo
, HOST_WIDE_INT hi
, struct jcf_partial
*state
)
833 unsigned HOST_WIDE_INT highpart
;
835 jint lowpart
= WORD_TO_INT (lo
);
837 rshift_double (lo
, hi
, 32, 64, &highpart
, &dummy
, 1);
839 if (highpart
== 0 && (lowpart
== 0 || lowpart
== 1))
842 OP1(OPCODE_lconst_0
+ lowpart
);
844 else if ((highpart
== 0 && lowpart
> 0 && lowpart
< 32768)
845 || (highpart
== (unsigned HOST_WIDE_INT
)-1
846 && lowpart
< 0 && lowpart
>= -32768))
848 push_int_const (lowpart
, state
);
853 push_constant2 (find_constant_wide (lo
, hi
, state
), state
);
857 field_op (tree field
, int opcode
, struct jcf_partial
*state
)
859 int index
= find_fieldref_index (&state
->cpool
, field
);
865 /* Returns an integer in the range 0 (for 'int') through 4 (for object
866 reference) to 7 (for 'short') which matches the pattern of how JVM
867 opcodes typically depend on the operand type. */
870 adjust_typed_op (tree type
, int max
)
872 switch (TREE_CODE (type
))
875 case RECORD_TYPE
: return 4;
877 return TYPE_PRECISION (type
) == 32 || max
< 5 ? 0 : 5;
879 if (type
== char_type_node
|| type
== promoted_char_type_node
)
880 return TYPE_PRECISION (type
) == 32 || max
< 6 ? 0 : 6;
881 switch (TYPE_PRECISION (type
))
883 case 8: return max
< 5 ? 0 : 5;
884 case 16: return max
< 7 ? 0 : 7;
890 switch (TYPE_PRECISION (type
))
903 maybe_wide (int opcode
, int index
, struct jcf_partial
*state
)
920 /* Compile code to duplicate with offset, where
921 SIZE is the size of the stack item to duplicate (1 or 2), abd
922 OFFSET is where to insert the result (must be 0, 1, or 2).
923 (The new words get inserted at stack[SP-size-offset].) */
926 emit_dup (int size
, int offset
, struct jcf_partial
*state
)
933 kind
= size
== 1 ? OPCODE_dup
: OPCODE_dup2
;
934 else if (offset
== 1)
935 kind
= size
== 1 ? OPCODE_dup_x1
: OPCODE_dup2_x1
;
936 else if (offset
== 2)
937 kind
= size
== 1 ? OPCODE_dup_x2
: OPCODE_dup2_x2
;
945 emit_pop (int size
, struct jcf_partial
*state
)
948 OP1 (OPCODE_pop
- 1 + size
);
952 emit_iinc (tree var
, HOST_WIDE_INT value
, struct jcf_partial
*state
)
954 int slot
= DECL_LOCAL_INDEX (var
);
956 if (value
< -128 || value
> 127 || slot
>= 256)
974 emit_load_or_store (tree var
, /* Variable to load from or store into. */
975 int opcode
, /* Either OPCODE_iload or OPCODE_istore. */
976 struct jcf_partial
*state
)
978 tree type
= TREE_TYPE (var
);
979 int kind
= adjust_typed_op (type
, 4);
980 int index
= DECL_LOCAL_INDEX (var
);
984 OP1 (opcode
+ 5 + 4 * kind
+ index
); /* [ilfda]{load,store}_[0123] */
987 maybe_wide (opcode
+ kind
, index
, state
); /* [ilfda]{load,store} */
991 emit_load (tree var
, struct jcf_partial
*state
)
993 emit_load_or_store (var
, OPCODE_iload
, state
);
994 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
998 emit_store (tree var
, struct jcf_partial
*state
)
1000 emit_load_or_store (var
, OPCODE_istore
, state
);
1001 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
1005 emit_unop (enum java_opcode opcode
, tree type ATTRIBUTE_UNUSED
,
1006 struct jcf_partial
*state
)
1013 emit_binop (enum java_opcode opcode
, tree type
, struct jcf_partial
*state
)
1015 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1022 emit_reloc (HOST_WIDE_INT value
, int kind
,
1023 struct jcf_block
*target
, struct jcf_partial
*state
)
1025 struct jcf_relocation
*reloc
1026 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1027 struct jcf_block
*block
= state
->last_block
;
1028 reloc
->next
= block
->u
.relocations
;
1029 block
->u
.relocations
= reloc
;
1030 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1031 reloc
->label
= target
;
1033 if (kind
== 0 || kind
== BLOCK_START_RELOC
)
1035 else if (kind
!= SWITCH_ALIGN_RELOC
)
1040 emit_switch_reloc (struct jcf_block
*label
, struct jcf_partial
*state
)
1042 emit_reloc (RELOCATION_VALUE_0
, BLOCK_START_RELOC
, label
, state
);
1045 /* Similar to emit_switch_reloc,
1046 but re-uses an existing case reloc. */
1049 emit_case_reloc (struct jcf_relocation
*reloc
, struct jcf_partial
*state
)
1051 struct jcf_block
*block
= state
->last_block
;
1052 reloc
->next
= block
->u
.relocations
;
1053 block
->u
.relocations
= reloc
;
1054 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1055 reloc
->kind
= BLOCK_START_RELOC
;
1059 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1060 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1063 emit_if (struct jcf_block
*target
, int opcode
, int inv_opcode
,
1064 struct jcf_partial
*state
)
1068 /* value is 1 byte from reloc back to start of instruction. */
1069 emit_reloc (RELOCATION_VALUE_1
, - inv_opcode
, target
, state
);
1073 emit_goto (struct jcf_block
*target
, struct jcf_partial
*state
)
1077 /* Value is 1 byte from reloc back to start of instruction. */
1078 emit_reloc (RELOCATION_VALUE_1
, OPCODE_goto_w
, target
, state
);
1082 emit_jsr (struct jcf_block
*target
, struct jcf_partial
*state
)
1086 /* Value is 1 byte from reloc back to start of instruction. */
1087 emit_reloc (RELOCATION_VALUE_1
, OPCODE_jsr_w
, target
, state
);
1091 /* Generate code to evaluate EXP. If the result is true,
1092 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1093 TRUE_BRANCH_FIRST is a code generation hint that the
1094 TRUE_LABEL may follow right after this. (The idea is that we
1095 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1098 generate_bytecode_conditional (tree exp
,
1099 struct jcf_block
*true_label
,
1100 struct jcf_block
*false_label
,
1101 int true_branch_first
,
1102 struct jcf_partial
*state
)
1104 tree exp0
, exp1
, type
;
1105 int save_SP
= state
->code_SP
;
1106 enum java_opcode op
, negop
;
1109 switch (TREE_CODE (exp
))
1112 emit_goto (integer_zerop (exp
) ? false_label
: true_label
, state
);
1116 struct jcf_block
*then_label
= gen_jcf_label (state
);
1117 struct jcf_block
*else_label
= gen_jcf_label (state
);
1118 int save_SP_before
, save_SP_after
;
1119 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1120 then_label
, else_label
, 1, state
);
1121 define_jcf_label (then_label
, state
);
1122 save_SP_before
= state
->code_SP
;
1123 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1124 true_label
, false_label
, 1, state
);
1125 save_SP_after
= state
->code_SP
;
1126 state
->code_SP
= save_SP_before
;
1127 define_jcf_label (else_label
, state
);
1128 generate_bytecode_conditional (TREE_OPERAND (exp
, 2),
1129 true_label
, false_label
,
1130 true_branch_first
, state
);
1131 gcc_assert (state
->code_SP
== save_SP_after
);
1134 case TRUTH_NOT_EXPR
:
1135 generate_bytecode_conditional (TREE_OPERAND (exp
, 0), false_label
,
1136 true_label
, ! true_branch_first
, state
);
1138 case TRUTH_ANDIF_EXPR
:
1140 struct jcf_block
*next_label
= gen_jcf_label (state
);
1141 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1142 next_label
, false_label
, 1, state
);
1143 define_jcf_label (next_label
, state
);
1144 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1145 true_label
, false_label
, 1, state
);
1148 case TRUTH_ORIF_EXPR
:
1150 struct jcf_block
*next_label
= gen_jcf_label (state
);
1151 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1152 true_label
, next_label
, 1, state
);
1153 define_jcf_label (next_label
, state
);
1154 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1155 true_label
, false_label
, 1, state
);
1159 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1160 set it to the corresponding 1-operand if<COND> instructions. */
1164 /* The opcodes with their inverses are allocated in pairs.
1165 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1166 negop
= (op
& 1) ? op
+ 1 : op
- 1;
1168 if (true_branch_first
)
1170 emit_if (false_label
, negop
, op
, state
);
1171 emit_goto (true_label
, state
);
1175 emit_if (true_label
, op
, negop
, state
);
1176 emit_goto (false_label
, state
);
1183 op
= OPCODE_if_icmpeq
;
1189 op
= OPCODE_if_icmpne
;
1195 op
= OPCODE_if_icmpgt
;
1201 op
= OPCODE_if_icmplt
;
1207 op
= OPCODE_if_icmpge
;
1213 op
= OPCODE_if_icmple
;
1219 /* UNLT_EXPR(a, b) means 'a < b || unordered(a, b)'. This is
1220 the same as the Java source expression '!(a >= b)', so handle
1222 struct jcf_block
*tmp
= true_label
;
1223 true_label
= false_label
;
1225 true_branch_first
= !true_branch_first
;
1228 exp0
= TREE_OPERAND (exp
, 0);
1229 exp1
= TREE_OPERAND (exp
, 1);
1230 type
= TREE_TYPE (exp0
);
1231 switch (TREE_CODE (type
))
1234 case POINTER_TYPE
: case RECORD_TYPE
:
1235 switch (TREE_CODE (exp
))
1237 case EQ_EXPR
: op
= OPCODE_if_acmpeq
; break;
1238 case NE_EXPR
: op
= OPCODE_if_acmpne
; break;
1242 if (integer_zerop (exp1
) || integer_zerop (exp0
))
1244 generate_bytecode_insns (integer_zerop (exp0
) ? exp1
: exp0
,
1245 STACK_TARGET
, state
);
1246 op
= op
+ (OPCODE_ifnull
- OPCODE_if_acmpeq
);
1247 negop
= (op
& 1) ? op
- 1 : op
+ 1;
1251 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1252 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1256 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1257 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1258 if (op
== OPCODE_if_icmplt
|| op
== OPCODE_if_icmple
)
1262 if (TYPE_PRECISION (type
) > 32)
1273 if (TYPE_PRECISION (type
) > 32)
1275 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1276 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1284 if (integer_zerop (exp1
))
1286 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1290 if (integer_zerop (exp0
))
1294 case OPCODE_if_icmplt
:
1295 case OPCODE_if_icmpge
:
1298 case OPCODE_if_icmpgt
:
1299 case OPCODE_if_icmple
:
1305 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1309 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1310 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1316 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1318 if (true_branch_first
)
1320 emit_if (false_label
, OPCODE_ifeq
, OPCODE_ifne
, state
);
1321 emit_goto (true_label
, state
);
1325 emit_if (true_label
, OPCODE_ifne
, OPCODE_ifeq
, state
);
1326 emit_goto (false_label
, state
);
1330 gcc_assert (save_SP
== state
->code_SP
);
1333 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1334 but only as far out as LIMIT (since we are about to jump to the
1335 emit label that is LIMIT). */
1338 call_cleanups (struct jcf_block
*limit
, struct jcf_partial
*state
)
1340 struct jcf_block
*block
= state
->labeled_blocks
;
1341 for (; block
!= limit
; block
= block
->next
)
1343 if (block
->pc
== PENDING_CLEANUP_PC
)
1344 emit_jsr (block
, state
);
1349 generate_bytecode_return (tree exp
, struct jcf_partial
*state
)
1351 tree return_type
= TREE_TYPE (TREE_TYPE (state
->current_method
));
1352 int returns_void
= TREE_CODE (return_type
) == VOID_TYPE
;
1357 switch (TREE_CODE (exp
))
1360 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
,
1362 exp
= TREE_OPERAND (exp
, 1);
1366 struct jcf_block
*then_label
= gen_jcf_label (state
);
1367 struct jcf_block
*else_label
= gen_jcf_label (state
);
1368 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1369 then_label
, else_label
, 1, state
);
1370 define_jcf_label (then_label
, state
);
1371 generate_bytecode_return (TREE_OPERAND (exp
, 1), state
);
1372 define_jcf_label (else_label
, state
);
1373 generate_bytecode_return (TREE_OPERAND (exp
, 2), state
);
1377 generate_bytecode_insns (exp
,
1378 returns_void
? IGNORE_TARGET
1379 : STACK_TARGET
, state
);
1385 call_cleanups (NULL
, state
);
1389 op
= OPCODE_ireturn
+ adjust_typed_op (return_type
, 4);
1390 if (state
->num_finalizers
> 0)
1392 if (state
->return_value_decl
== NULL_TREE
)
1394 state
->return_value_decl
1395 = build_decl (VAR_DECL
, NULL_TREE
, TREE_TYPE (exp
));
1396 localvar_alloc (state
->return_value_decl
, state
);
1398 emit_store (state
->return_value_decl
, state
);
1399 call_cleanups (NULL
, state
);
1400 emit_load (state
->return_value_decl
, state
);
1401 /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
1402 then we risk the save decl erroneously re-used in the
1403 finalizer. Instead, we keep the state->return_value_decl
1404 allocated through the rest of the method. This is not
1405 the greatest solution, but it is at least simple and safe. */
1412 /* Generate bytecode for sub-expression EXP of METHOD.
1413 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1416 generate_bytecode_insns (tree exp
, int target
, struct jcf_partial
*state
)
1419 enum java_opcode jopcode
;
1421 HOST_WIDE_INT value
;
1426 if (exp
== NULL
&& target
== IGNORE_TARGET
)
1429 type
= TREE_TYPE (exp
);
1431 switch (TREE_CODE (exp
))
1434 if (BLOCK_EXPR_BODY (exp
))
1437 tree body
= BLOCK_EXPR_BODY (exp
);
1438 long jsrs
= state
->num_jsrs
;
1439 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1441 tree next
= TREE_CHAIN (local
);
1442 localvar_alloc (local
, state
);
1445 /* Avoid deep recursion for long blocks. */
1446 while (TREE_CODE (body
) == COMPOUND_EXPR
)
1448 generate_bytecode_insns (TREE_OPERAND (body
, 0), target
, state
);
1449 body
= TREE_OPERAND (body
, 1);
1451 generate_bytecode_insns (body
, target
, state
);
1453 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1455 tree next
= TREE_CHAIN (local
);
1456 maybe_free_localvar (local
, state
, state
->num_jsrs
<= jsrs
);
1462 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
1463 /* Normally the first operand to a COMPOUND_EXPR must complete
1464 normally. However, in the special case of a do-while
1465 statement this is not necessarily the case. */
1466 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 0)))
1467 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1469 case EXPR_WITH_FILE_LOCATION
:
1471 location_t saved_location
= input_location
;
1472 tree body
= EXPR_WFL_NODE (exp
);
1473 if (IS_EMPTY_STMT (body
))
1475 #ifdef USE_MAPPED_LOCATION
1476 input_location
= EXPR_LOCATION (exp
);
1478 input_filename
= EXPR_WFL_FILENAME (exp
);
1479 input_line
= EXPR_WFL_LINENO (exp
);
1481 if (EXPR_WFL_EMIT_LINE_NOTE (exp
) && input_line
> 0
1482 && debug_info_level
> DINFO_LEVEL_NONE
)
1483 put_linenumber (input_line
, state
);
1484 generate_bytecode_insns (body
, target
, state
);
1485 input_location
= saved_location
;
1489 if (target
== IGNORE_TARGET
) ; /* do nothing */
1490 else if (TREE_CODE (type
) == POINTER_TYPE
)
1492 gcc_assert (integer_zerop (exp
));
1494 OP1 (OPCODE_aconst_null
);
1497 else if (TYPE_PRECISION (type
) <= 32)
1499 push_int_const (TREE_INT_CST_LOW (exp
), state
);
1504 push_long_const (TREE_INT_CST_LOW (exp
), TREE_INT_CST_HIGH (exp
),
1511 int prec
= TYPE_PRECISION (type
) >> 5;
1513 if (real_zerop (exp
) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp
)))
1514 OP1 (prec
== 1 ? OPCODE_fconst_0
: OPCODE_dconst_0
);
1515 else if (real_onep (exp
))
1516 OP1 (prec
== 1 ? OPCODE_fconst_1
: OPCODE_dconst_1
);
1517 else if (prec
== 1 && real_twop (exp
))
1518 OP1 (OPCODE_fconst_2
);
1519 /* ??? We could also use iconst_3/ldc followed by i2f/i2d
1520 for other float/double when the value is a small integer. */
1523 offset
= find_constant_index (exp
, state
);
1525 push_constant1 (offset
, state
);
1527 push_constant2 (offset
, state
);
1533 push_constant1 (find_string_constant (&state
->cpool
, exp
), state
);
1537 if (TREE_STATIC (exp
))
1539 field_op (exp
, OPCODE_getstatic
, state
);
1540 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1543 /* ... fall through ... */
1545 emit_load (exp
, state
);
1547 case NON_LVALUE_EXPR
:
1549 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1552 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1553 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1554 if (target
!= IGNORE_TARGET
)
1556 jopcode
= OPCODE_iaload
+ adjust_typed_op (type
, 7);
1559 if (! TYPE_IS_WIDE (type
))
1565 tree obj
= TREE_OPERAND (exp
, 0);
1566 tree field
= TREE_OPERAND (exp
, 1);
1567 int is_static
= FIELD_STATIC (field
);
1568 generate_bytecode_insns (obj
,
1569 is_static
? IGNORE_TARGET
: target
, state
);
1570 if (target
!= IGNORE_TARGET
)
1572 if (DECL_NAME (field
) == length_identifier_node
&& !is_static
1573 && TYPE_ARRAY_P (TREE_TYPE (obj
)))
1576 OP1 (OPCODE_arraylength
);
1580 field_op (field
, is_static
? OPCODE_getstatic
: OPCODE_getfield
,
1584 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1589 case TRUTH_ANDIF_EXPR
:
1590 case TRUTH_ORIF_EXPR
:
1604 struct jcf_block
*then_label
= gen_jcf_label (state
);
1605 struct jcf_block
*else_label
= gen_jcf_label (state
);
1606 struct jcf_block
*end_label
= gen_jcf_label (state
);
1607 generate_bytecode_conditional (exp
,
1608 then_label
, else_label
, 1, state
);
1609 define_jcf_label (then_label
, state
);
1610 push_int_const (1, state
);
1611 emit_goto (end_label
, state
);
1612 define_jcf_label (else_label
, state
);
1613 push_int_const (0, state
);
1614 define_jcf_label (end_label
, state
);
1620 struct jcf_block
*then_label
= gen_jcf_label (state
);
1621 struct jcf_block
*else_label
= gen_jcf_label (state
);
1622 struct jcf_block
*end_label
= gen_jcf_label (state
);
1623 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1624 then_label
, else_label
, 1, state
);
1625 define_jcf_label (then_label
, state
);
1626 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1627 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 1))
1628 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1629 || TREE_CODE (TREE_TYPE (exp
)) != VOID_TYPE
)
1630 emit_goto (end_label
, state
);
1631 define_jcf_label (else_label
, state
);
1632 generate_bytecode_insns (TREE_OPERAND (exp
, 2), target
, state
);
1633 define_jcf_label (end_label
, state
);
1634 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1635 if (TREE_TYPE (exp
) != void_type_node
)
1636 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1641 struct jcf_switch_state
*sw_state
= state
->sw_state
;
1642 struct jcf_relocation
*reloc
1643 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1644 HOST_WIDE_INT case_value
= TREE_INT_CST_LOW (TREE_OPERAND (exp
, 0));
1646 reloc
->label
= get_jcf_label_here (state
);
1647 reloc
->offset
= case_value
;
1648 reloc
->next
= sw_state
->cases
;
1649 sw_state
->cases
= reloc
;
1650 if (sw_state
->num_cases
== 0)
1652 sw_state
->min_case
= case_value
;
1653 sw_state
->max_case
= case_value
;
1657 if (case_value
< sw_state
->min_case
)
1658 sw_state
->min_case
= case_value
;
1659 if (case_value
> sw_state
->max_case
)
1660 sw_state
->max_case
= case_value
;
1662 sw_state
->num_cases
++;
1666 state
->sw_state
->default_label
= get_jcf_label_here (state
);
1671 /* The SWITCH_EXPR has three parts, generated in the following order:
1672 1. the switch_expression (the value used to select the correct case);
1674 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1675 After code generation, we will re-order them in the order 1, 3, 2.
1676 This is to avoid any extra GOTOs. */
1677 struct jcf_switch_state sw_state
;
1678 struct jcf_block
*expression_last
; /* Last block of the switch_expression. */
1679 struct jcf_block
*body_last
; /* Last block of the switch_body. */
1680 struct jcf_block
*switch_instruction
; /* First block of switch_instruction. */
1681 struct jcf_block
*instruction_last
; /* Last block of the switch_instruction. */
1682 struct jcf_block
*body_block
;
1684 sw_state
.prev
= state
->sw_state
;
1685 state
->sw_state
= &sw_state
;
1686 sw_state
.cases
= NULL
;
1687 sw_state
.num_cases
= 0;
1688 sw_state
.default_label
= NULL
;
1689 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1690 expression_last
= state
->last_block
;
1691 /* Force a new block here. */
1692 body_block
= gen_jcf_label (state
);
1693 define_jcf_label (body_block
, state
);
1694 generate_bytecode_insns (TREE_OPERAND (exp
, 1), IGNORE_TARGET
, state
);
1695 body_last
= state
->last_block
;
1697 switch_instruction
= gen_jcf_label (state
);
1698 define_jcf_label (switch_instruction
, state
);
1699 if (sw_state
.default_label
== NULL
)
1700 sw_state
.default_label
= gen_jcf_label (state
);
1702 if (sw_state
.num_cases
<= 1)
1704 if (sw_state
.num_cases
== 0)
1706 emit_pop (1, state
);
1711 push_int_const (sw_state
.cases
->offset
, state
);
1713 emit_if (sw_state
.cases
->label
,
1714 OPCODE_if_icmpeq
, OPCODE_if_icmpne
, state
);
1716 emit_goto (sw_state
.default_label
, state
);
1721 unsigned HOST_WIDE_INT delta
;
1722 /* Copy the chain of relocs into a sorted array. */
1723 struct jcf_relocation
**relocs
1724 = XNEWVEC (struct jcf_relocation
*, sw_state
.num_cases
);
1725 /* The relocs arrays is a buffer with a gap.
1726 The assumption is that cases will normally come in "runs". */
1728 int gap_end
= sw_state
.num_cases
;
1729 struct jcf_relocation
*reloc
;
1730 for (reloc
= sw_state
.cases
; reloc
!= NULL
; reloc
= reloc
->next
)
1732 HOST_WIDE_INT case_value
= reloc
->offset
;
1733 while (gap_end
< sw_state
.num_cases
)
1735 struct jcf_relocation
*end
= relocs
[gap_end
];
1736 if (case_value
<= end
->offset
)
1738 relocs
[gap_start
++] = end
;
1741 while (gap_start
> 0)
1743 struct jcf_relocation
*before
= relocs
[gap_start
-1];
1744 if (case_value
>= before
->offset
)
1746 relocs
[--gap_end
] = before
;
1749 relocs
[gap_start
++] = reloc
;
1750 /* Note we don't check for duplicates. This is
1751 handled by the parser. */
1754 /* We could have DELTA < 0 if sw_state.min_case is
1755 something like Integer.MIN_VALUE. That is why delta is
1757 delta
= sw_state
.max_case
- sw_state
.min_case
;
1758 if (2 * (unsigned) sw_state
.num_cases
>= delta
)
1759 { /* Use tableswitch. */
1761 RESERVE (13 + 4 * (sw_state
.max_case
- sw_state
.min_case
+ 1));
1762 OP1 (OPCODE_tableswitch
);
1763 emit_reloc (RELOCATION_VALUE_0
,
1764 SWITCH_ALIGN_RELOC
, NULL
, state
);
1765 emit_switch_reloc (sw_state
.default_label
, state
);
1766 OP4 (sw_state
.min_case
);
1767 OP4 (sw_state
.max_case
);
1768 for (i
= sw_state
.min_case
; ; )
1770 reloc
= relocs
[index
];
1771 if (i
== reloc
->offset
)
1773 emit_case_reloc (reloc
, state
);
1774 if (i
== sw_state
.max_case
)
1779 emit_switch_reloc (sw_state
.default_label
, state
);
1784 { /* Use lookupswitch. */
1785 RESERVE(9 + 8 * sw_state
.num_cases
);
1786 OP1 (OPCODE_lookupswitch
);
1787 emit_reloc (RELOCATION_VALUE_0
,
1788 SWITCH_ALIGN_RELOC
, NULL
, state
);
1789 emit_switch_reloc (sw_state
.default_label
, state
);
1790 OP4 (sw_state
.num_cases
);
1791 for (i
= 0; i
< sw_state
.num_cases
; i
++)
1793 struct jcf_relocation
*reloc
= relocs
[i
];
1794 OP4 (reloc
->offset
);
1795 emit_case_reloc (reloc
, state
);
1801 instruction_last
= state
->last_block
;
1802 if (sw_state
.default_label
->pc
< 0)
1803 define_jcf_label (sw_state
.default_label
, state
);
1804 else /* Force a new block. */
1805 sw_state
.default_label
= get_jcf_label_here (state
);
1806 /* Now re-arrange the blocks so the switch_instruction
1807 comes before the switch_body. */
1808 switch_length
= state
->code_length
- switch_instruction
->pc
;
1809 switch_instruction
->pc
= body_block
->pc
;
1810 instruction_last
->next
= body_block
;
1811 instruction_last
->v
.chunk
->next
= body_block
->v
.chunk
;
1812 expression_last
->next
= switch_instruction
;
1813 expression_last
->v
.chunk
->next
= switch_instruction
->v
.chunk
;
1814 body_last
->next
= sw_state
.default_label
;
1815 body_last
->v
.chunk
->next
= NULL
;
1816 state
->chunk
= body_last
->v
.chunk
;
1817 for (; body_block
!= sw_state
.default_label
; body_block
= body_block
->next
)
1818 body_block
->pc
+= switch_length
;
1820 state
->sw_state
= sw_state
.prev
;
1825 exp
= TREE_OPERAND (exp
, 0);
1826 if (exp
== NULL_TREE
)
1827 exp
= build_java_empty_stmt ();
1828 else if (TREE_CODE (exp
) != MODIFY_EXPR
)
1831 exp
= TREE_OPERAND (exp
, 1);
1832 generate_bytecode_return (exp
, state
);
1834 case LABELED_BLOCK_EXPR
:
1836 struct jcf_block
*end_label
= gen_jcf_label (state
);
1837 end_label
->next
= state
->labeled_blocks
;
1838 state
->labeled_blocks
= end_label
;
1839 end_label
->pc
= PENDING_EXIT_PC
;
1840 end_label
->u
.labeled_block
= exp
;
1841 if (LABELED_BLOCK_BODY (exp
))
1842 generate_bytecode_insns (LABELED_BLOCK_BODY (exp
), target
, state
);
1843 gcc_assert (state
->labeled_blocks
== end_label
);
1844 state
->labeled_blocks
= end_label
->next
;
1845 define_jcf_label (end_label
, state
);
1850 tree body
= TREE_OPERAND (exp
, 0);
1852 if (TREE_CODE (body
) == COMPOUND_EXPR
1853 && TREE_CODE (TREE_OPERAND (body
, 0)) == EXIT_EXPR
)
1855 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1856 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1857 struct jcf_block
*head_label
;
1858 struct jcf_block
*body_label
;
1859 struct jcf_block
*end_label
= gen_jcf_label (state
);
1860 struct jcf_block
*exit_label
= state
->labeled_blocks
;
1861 head_label
= gen_jcf_label (state
);
1862 emit_goto (head_label
, state
);
1863 body_label
= get_jcf_label_here (state
);
1864 generate_bytecode_insns (TREE_OPERAND (body
, 1), target
, state
);
1865 define_jcf_label (head_label
, state
);
1866 generate_bytecode_conditional (TREE_OPERAND (body
, 0),
1867 end_label
, body_label
, 1, state
);
1868 define_jcf_label (end_label
, state
);
1873 struct jcf_block
*head_label
= get_jcf_label_here (state
);
1874 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1875 if (CAN_COMPLETE_NORMALLY (body
))
1876 emit_goto (head_label
, state
);
1882 struct jcf_block
*label
= state
->labeled_blocks
;
1883 struct jcf_block
*end_label
= gen_jcf_label (state
);
1884 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1885 label
, end_label
, 0, state
);
1886 define_jcf_label (end_label
, state
);
1889 case EXIT_BLOCK_EXPR
:
1891 struct jcf_block
*label
= state
->labeled_blocks
;
1892 while (label
->u
.labeled_block
!= EXIT_BLOCK_LABELED_BLOCK (exp
))
1893 label
= label
->next
;
1894 call_cleanups (label
, state
);
1895 emit_goto (label
, state
);
1899 case PREDECREMENT_EXPR
: value
= -1; post_op
= 0; goto increment
;
1900 case PREINCREMENT_EXPR
: value
= 1; post_op
= 0; goto increment
;
1901 case POSTDECREMENT_EXPR
: value
= -1; post_op
= 1; goto increment
;
1902 case POSTINCREMENT_EXPR
: value
= 1; post_op
= 1; goto increment
;
1905 arg
= TREE_OPERAND (exp
, 1);
1906 exp
= TREE_OPERAND (exp
, 0);
1907 type
= TREE_TYPE (exp
);
1908 size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1909 if ((TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1910 && ! TREE_STATIC (exp
)
1911 && TREE_CODE (type
) == INTEGER_TYPE
1912 && TYPE_PRECISION (type
) == 32)
1914 if (target
!= IGNORE_TARGET
&& post_op
)
1915 emit_load (exp
, state
);
1916 emit_iinc (exp
, value
, state
);
1917 if (target
!= IGNORE_TARGET
&& ! post_op
)
1918 emit_load (exp
, state
);
1921 if (TREE_CODE (exp
) == COMPONENT_REF
)
1923 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1924 emit_dup (1, 0, state
);
1925 /* Stack: ..., objectref, objectref. */
1926 field_op (TREE_OPERAND (exp
, 1), OPCODE_getfield
, state
);
1928 /* Stack: ..., objectref, oldvalue. */
1931 else if (TREE_CODE (exp
) == ARRAY_REF
)
1933 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1934 generate_bytecode_insns (TREE_OPERAND (exp
, 1), STACK_TARGET
, state
);
1935 emit_dup (2, 0, state
);
1936 /* Stack: ..., array, index, array, index. */
1937 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (exp
), 7);
1941 /* Stack: ..., array, index, oldvalue. */
1944 else if (TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1946 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1947 /* Stack: ..., oldvalue. */
1953 if (target
!= IGNORE_TARGET
&& post_op
)
1954 emit_dup (size
, offset
, state
);
1955 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1956 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1957 /* Stack, otherwise: ..., [result, ] oldvalue. */
1958 generate_bytecode_insns (arg
, STACK_TARGET
, state
);
1959 emit_binop ((value
>= 0 ? OPCODE_iadd
: OPCODE_isub
)
1960 + adjust_typed_op (type
, 3),
1962 if (target
!= IGNORE_TARGET
&& ! post_op
)
1963 emit_dup (size
, offset
, state
);
1964 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1965 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1966 /* Stack, otherwise: ..., [result, ] newvalue. */
1967 goto finish_assignment
;
1971 tree lhs
= TREE_OPERAND (exp
, 0);
1972 tree rhs
= TREE_OPERAND (exp
, 1);
1975 /* See if we can use the iinc instruction. */
1976 if ((TREE_CODE (lhs
) == VAR_DECL
|| TREE_CODE (lhs
) == PARM_DECL
)
1977 && ! TREE_STATIC (lhs
)
1978 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
1979 && TYPE_PRECISION (TREE_TYPE (lhs
)) == 32
1980 && (TREE_CODE (rhs
) == PLUS_EXPR
|| TREE_CODE (rhs
) == MINUS_EXPR
))
1982 tree arg0
= TREE_OPERAND (rhs
, 0);
1983 tree arg1
= TREE_OPERAND (rhs
, 1);
1984 HOST_WIDE_INT min_value
= -32768;
1985 HOST_WIDE_INT max_value
= 32767;
1986 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1991 else if (arg1
== lhs
)
1994 arg1
= TREE_OPERAND (rhs
, 0);
1996 if (lhs
== arg0
&& TREE_CODE (arg1
) == INTEGER_CST
)
1998 HOST_WIDE_INT hi_value
= TREE_INT_CST_HIGH (arg1
);
1999 value
= TREE_INT_CST_LOW (arg1
);
2000 if ((hi_value
== 0 && value
<= max_value
)
2001 || (hi_value
== -1 && value
>= min_value
))
2003 if (TREE_CODE (rhs
) == MINUS_EXPR
)
2005 emit_iinc (lhs
, value
, state
);
2006 if (target
!= IGNORE_TARGET
)
2007 emit_load (lhs
, state
);
2013 if (TREE_CODE (lhs
) == COMPONENT_REF
)
2015 generate_bytecode_insns (TREE_OPERAND (lhs
, 0),
2016 STACK_TARGET
, state
);
2019 else if (TREE_CODE (lhs
) == ARRAY_REF
)
2021 generate_bytecode_insns (TREE_OPERAND(lhs
, 0),
2022 STACK_TARGET
, state
);
2023 generate_bytecode_insns (TREE_OPERAND(lhs
, 1),
2024 STACK_TARGET
, state
);
2030 /* If the rhs is a binary expression and the left operand is
2031 `==' to the lhs then we have an OP= expression. In this
2032 case we must do some special processing. */
2033 if (BINARY_CLASS_P (rhs
) && lhs
== TREE_OPERAND (rhs
, 0))
2035 if (TREE_CODE (lhs
) == COMPONENT_REF
)
2037 tree field
= TREE_OPERAND (lhs
, 1);
2038 if (! FIELD_STATIC (field
))
2040 /* Duplicate the object reference so we can get
2042 emit_dup (TYPE_IS_WIDE (field
) ? 2 : 1, 0, state
);
2045 field_op (field
, (FIELD_STATIC (field
)
2050 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
2052 else if (TREE_CODE (lhs
) == VAR_DECL
2053 || TREE_CODE (lhs
) == PARM_DECL
)
2055 if (FIELD_STATIC (lhs
))
2057 field_op (lhs
, OPCODE_getstatic
, state
);
2058 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs
)) ? 2 : 1);
2061 emit_load (lhs
, state
);
2063 else if (TREE_CODE (lhs
) == ARRAY_REF
)
2065 /* Duplicate the array and index, which are on the
2066 stack, so that we can load the old value. */
2067 emit_dup (2, 0, state
);
2069 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (lhs
), 7);
2072 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs
)) ? 2 : 1);
2077 /* This function correctly handles the case where the LHS
2078 of a binary expression is NULL_TREE. */
2079 rhs
= build2 (TREE_CODE (rhs
), TREE_TYPE (rhs
),
2080 NULL_TREE
, TREE_OPERAND (rhs
, 1));
2083 generate_bytecode_insns (rhs
, STACK_TARGET
, state
);
2084 if (target
!= IGNORE_TARGET
)
2085 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1 , offset
, state
);
2091 if (TREE_CODE (exp
) == COMPONENT_REF
)
2093 tree field
= TREE_OPERAND (exp
, 1);
2094 if (! FIELD_STATIC (field
))
2097 FIELD_STATIC (field
) ? OPCODE_putstatic
: OPCODE_putfield
,
2100 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
2102 else if (TREE_CODE (exp
) == VAR_DECL
2103 || TREE_CODE (exp
) == PARM_DECL
)
2105 if (FIELD_STATIC (exp
))
2107 field_op (exp
, OPCODE_putstatic
, state
);
2108 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
2111 emit_store (exp
, state
);
2113 else if (TREE_CODE (exp
) == ARRAY_REF
)
2115 jopcode
= OPCODE_iastore
+ adjust_typed_op (TREE_TYPE (exp
), 7);
2118 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 4 : 3);
2124 jopcode
= OPCODE_iadd
;
2127 jopcode
= OPCODE_isub
;
2130 jopcode
= OPCODE_imul
;
2132 case TRUNC_DIV_EXPR
:
2134 jopcode
= OPCODE_idiv
;
2136 case TRUNC_MOD_EXPR
:
2137 jopcode
= OPCODE_irem
;
2139 case LSHIFT_EXPR
: jopcode
= OPCODE_ishl
; goto binop
;
2141 jopcode
= TYPE_UNSIGNED (type
) ? OPCODE_iushr
: OPCODE_ishr
;
2143 case URSHIFT_EXPR
: jopcode
= OPCODE_iushr
; goto binop
;
2144 case TRUTH_AND_EXPR
:
2145 case BIT_AND_EXPR
: jopcode
= OPCODE_iand
; goto binop
;
2147 case BIT_IOR_EXPR
: jopcode
= OPCODE_ior
; goto binop
;
2148 case TRUTH_XOR_EXPR
:
2149 case BIT_XOR_EXPR
: jopcode
= OPCODE_ixor
; goto binop
;
2152 tree arg0
= TREE_OPERAND (exp
, 0);
2153 tree arg1
= TREE_OPERAND (exp
, 1);
2154 jopcode
+= adjust_typed_op (type
, 3);
2155 if (arg0
!= NULL_TREE
&& operand_equal_p (arg0
, arg1
, 0))
2157 /* fold may (e.g) convert 2*x to x+x. */
2158 generate_bytecode_insns (arg0
, target
, state
);
2159 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0
)) > 32 ? 2 : 1, 0, state
);
2163 /* ARG0 will be NULL_TREE if we're handling an `OP='
2164 expression. In this case the stack already holds the
2165 LHS. See the MODIFY_EXPR case. */
2166 if (arg0
!= NULL_TREE
)
2167 generate_bytecode_insns (arg0
, target
, state
);
2168 if (jopcode
>= OPCODE_lshl
&& jopcode
<= OPCODE_lushr
)
2169 arg1
= convert (int_type_node
, arg1
);
2170 generate_bytecode_insns (arg1
, target
, state
);
2172 /* For most binary operations, both operands and the result have the
2173 same type. Shift operations are different. Using arg1's type
2174 gets us the correct SP adjustment in all cases. */
2175 if (target
== STACK_TARGET
)
2176 emit_binop (jopcode
, TREE_TYPE (arg1
), state
);
2179 case TRUTH_NOT_EXPR
:
2181 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2182 if (target
== STACK_TARGET
)
2184 int is_long
= TYPE_PRECISION (TREE_TYPE (exp
)) > 32;
2185 push_int_const (TREE_CODE (exp
) == BIT_NOT_EXPR
? -1 : 1, state
);
2189 NOTE_PUSH (1 + is_long
);
2190 OP1 (OPCODE_ixor
+ is_long
);
2191 NOTE_POP (1 + is_long
);
2195 jopcode
= OPCODE_ineg
;
2196 jopcode
+= adjust_typed_op (type
, 3);
2197 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2198 if (target
== STACK_TARGET
)
2199 emit_unop (jopcode
, type
, state
);
2201 case INSTANCEOF_EXPR
:
2203 int index
= find_class_constant (&state
->cpool
, TREE_OPERAND (exp
, 1));
2204 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2206 OP1 (OPCODE_instanceof
);
2211 /* The first time through, the argument of the SAVE_EXPR will be
2212 something complex. Evaluate it, and replace the argument with
2213 a VAR_DECL that holds the result. */
2214 arg
= TREE_OPERAND (exp
, 0);
2215 if (TREE_CODE (arg
) != VAR_DECL
|| DECL_NAME (arg
))
2217 tree type
= TREE_TYPE (exp
);
2218 tree decl
= build_decl (VAR_DECL
, NULL_TREE
, type
);
2219 generate_bytecode_insns (arg
, STACK_TARGET
, state
);
2220 localvar_alloc (decl
, state
);
2221 TREE_OPERAND (exp
, 0) = decl
;
2222 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1, 0, state
);
2223 emit_store (decl
, state
);
2227 emit_load (arg
, state
);
2233 case FIX_TRUNC_EXPR
:
2235 tree src
= TREE_OPERAND (exp
, 0);
2236 tree src_type
= TREE_TYPE (src
);
2237 tree dst_type
= TREE_TYPE (exp
);
2238 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2239 if (target
== IGNORE_TARGET
|| src_type
== dst_type
)
2241 if (TREE_CODE (dst_type
) == POINTER_TYPE
)
2243 if (TREE_CODE (exp
) == CONVERT_EXPR
)
2245 int index
= find_class_constant (&state
->cpool
,
2246 TREE_TYPE (dst_type
));
2248 OP1 (OPCODE_checkcast
);
2252 else /* Convert numeric types. */
2254 int src_prec
= TYPE_PRECISION (src_type
);
2255 int dst_prec
= TYPE_PRECISION (dst_type
);
2256 int wide_src
= src_prec
> 32;
2257 int wide_dst
= dst_prec
> 32;
2258 if (TREE_CODE (dst_type
) == REAL_TYPE
)
2260 NOTE_POP (1 + wide_src
);
2262 if (TREE_CODE (src_type
) == REAL_TYPE
)
2263 OP1 (wide_dst
? OPCODE_f2d
: OPCODE_d2f
);
2264 else if (src_prec
== 64)
2265 OP1 (OPCODE_l2f
+ wide_dst
);
2267 OP1 (OPCODE_i2f
+ wide_dst
);
2268 NOTE_PUSH (1 + wide_dst
);
2270 /* Convert to integral type (but ignore non-widening
2271 and non-narrowing integer type conversions). */
2272 else if (TREE_CODE (src_type
) == REAL_TYPE
2273 || src_prec
!= dst_prec
)
2275 NOTE_POP (1 + wide_src
);
2277 if (TREE_CODE (src_type
) == REAL_TYPE
)
2278 OP1 (OPCODE_f2i
+ wide_dst
+ 3 * wide_src
);
2286 /* Already converted to int, if needed. */
2289 else if (TYPE_UNSIGNED (dst_type
))
2294 NOTE_PUSH (1 + wide_dst
);
2302 tree try_clause
= TREE_OPERAND (exp
, 0);
2303 struct jcf_block
*start_label
= get_jcf_label_here (state
);
2304 struct jcf_block
*end_label
; /* End of try clause. */
2305 struct jcf_block
*finished_label
= gen_jcf_label (state
);
2306 tree clause
= TREE_OPERAND (exp
, 1);
2307 gcc_assert (target
== IGNORE_TARGET
);
2308 generate_bytecode_insns (try_clause
, IGNORE_TARGET
, state
);
2309 end_label
= get_jcf_label_here (state
);
2310 if (end_label
== start_label
)
2312 if (CAN_COMPLETE_NORMALLY (try_clause
))
2313 emit_goto (finished_label
, state
);
2314 while (clause
!= NULL_TREE
)
2316 tree catch_clause
= TREE_OPERAND (clause
, 0);
2317 tree exception_decl
= BLOCK_EXPR_DECLS (catch_clause
);
2318 struct jcf_handler
*handler
= alloc_handler (start_label
,
2320 if (exception_decl
== NULL_TREE
)
2321 handler
->type
= NULL_TREE
;
2323 handler
->type
= TREE_TYPE (TREE_TYPE (exception_decl
));
2324 generate_bytecode_insns (catch_clause
, IGNORE_TARGET
, state
);
2325 clause
= TREE_CHAIN (clause
);
2326 if (CAN_COMPLETE_NORMALLY (catch_clause
) && clause
!= NULL_TREE
)
2327 emit_goto (finished_label
, state
);
2329 define_jcf_label (finished_label
, state
);
2333 case TRY_FINALLY_EXPR
:
2335 struct jcf_block
*finished_label
= NULL
;
2336 struct jcf_block
*finally_label
, *start_label
, *end_label
;
2337 struct jcf_handler
*handler
;
2338 tree try_block
= TREE_OPERAND (exp
, 0);
2339 tree finally
= TREE_OPERAND (exp
, 1);
2340 tree return_link
= NULL_TREE
, exception_decl
= NULL_TREE
;
2342 tree exception_type
;
2344 finally_label
= gen_jcf_label (state
);
2345 start_label
= get_jcf_label_here (state
);
2346 /* If the `finally' clause can complete normally, we emit it
2347 as a subroutine and let the other clauses call it via
2348 `jsr'. If it can't complete normally, then we simply emit
2349 `goto's directly to it. */
2350 if (CAN_COMPLETE_NORMALLY (finally
))
2352 finally_label
->pc
= PENDING_CLEANUP_PC
;
2353 finally_label
->next
= state
->labeled_blocks
;
2354 state
->labeled_blocks
= finally_label
;
2355 state
->num_finalizers
++;
2358 generate_bytecode_insns (try_block
, target
, state
);
2360 if (CAN_COMPLETE_NORMALLY (finally
))
2362 gcc_assert (state
->labeled_blocks
== finally_label
);
2363 state
->labeled_blocks
= finally_label
->next
;
2365 end_label
= get_jcf_label_here (state
);
2367 if (end_label
== start_label
)
2369 state
->num_finalizers
--;
2370 define_jcf_label (finally_label
, state
);
2371 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2375 if (CAN_COMPLETE_NORMALLY (finally
))
2377 return_link
= build_decl (VAR_DECL
, NULL_TREE
,
2378 return_address_type_node
);
2379 finished_label
= gen_jcf_label (state
);
2382 if (CAN_COMPLETE_NORMALLY (try_block
))
2384 if (CAN_COMPLETE_NORMALLY (finally
))
2386 emit_jsr (finally_label
, state
);
2387 emit_goto (finished_label
, state
);
2390 emit_goto (finally_label
, state
);
2393 /* Handle exceptions. */
2395 exception_type
= build_pointer_type (throwable_type_node
);
2396 if (CAN_COMPLETE_NORMALLY (finally
))
2398 /* We're going to generate a subroutine, so we'll need to
2399 save and restore the exception around the `jsr'. */
2400 exception_decl
= build_decl (VAR_DECL
, NULL_TREE
, exception_type
);
2401 localvar_alloc (return_link
, state
);
2403 handler
= alloc_handler (start_label
, end_label
, state
);
2404 handler
->type
= NULL_TREE
;
2405 if (CAN_COMPLETE_NORMALLY (finally
))
2407 localvar_alloc (exception_decl
, state
);
2409 emit_store (exception_decl
, state
);
2410 emit_jsr (finally_label
, state
);
2411 emit_load (exception_decl
, state
);
2413 OP1 (OPCODE_athrow
);
2418 /* We're not generating a subroutine. In this case we can
2419 simply have the exception handler pop the exception and
2420 then fall through to the `finally' block. */
2422 emit_pop (1, state
);
2426 /* The finally block. If we're generating a subroutine, first
2427 save return PC into return_link. Otherwise, just generate
2428 the code for the `finally' block. */
2429 define_jcf_label (finally_label
, state
);
2430 if (CAN_COMPLETE_NORMALLY (finally
))
2433 emit_store (return_link
, state
);
2436 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2437 if (CAN_COMPLETE_NORMALLY (finally
))
2439 maybe_wide (OPCODE_ret
, DECL_LOCAL_INDEX (return_link
), state
);
2440 maybe_free_localvar (exception_decl
, state
, 1);
2441 maybe_free_localvar (return_link
, state
, 1);
2442 define_jcf_label (finished_label
, state
);
2447 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
2449 OP1 (OPCODE_athrow
);
2451 case NEW_ARRAY_INIT
:
2453 VEC(constructor_elt
,gc
) *v
= CONSTRUCTOR_ELTS (TREE_OPERAND (exp
, 0));
2454 tree array_type
= TREE_TYPE (TREE_TYPE (exp
));
2455 tree element_type
= TYPE_ARRAY_ELEMENT (array_type
);
2456 unsigned HOST_WIDE_INT idx
;
2458 HOST_WIDE_INT length
= java_array_type_length (array_type
);
2459 if (target
== IGNORE_TARGET
)
2461 FOR_EACH_CONSTRUCTOR_VALUE (v
, idx
, value
)
2462 generate_bytecode_insns (value
, target
, state
);
2465 push_int_const (length
, state
);
2468 if (JPRIMITIVE_TYPE_P (element_type
))
2470 int atype
= encode_newarray_type (element_type
);
2471 OP1 (OPCODE_newarray
);
2476 int index
= find_class_constant (&state
->cpool
,
2477 TREE_TYPE (element_type
));
2478 OP1 (OPCODE_anewarray
);
2482 jopcode
= OPCODE_iastore
+ adjust_typed_op (element_type
, 7);
2483 FOR_EACH_CONSTRUCTOR_VALUE (v
, idx
, value
)
2485 int save_SP
= state
->code_SP
;
2486 emit_dup (1, 0, state
);
2487 push_int_const (offset
, state
);
2489 generate_bytecode_insns (value
, STACK_TARGET
, state
);
2492 state
->code_SP
= save_SP
;
2497 case JAVA_EXC_OBJ_EXPR
:
2498 NOTE_PUSH (1); /* Pushed by exception system. */
2503 /* This copes with cases where fold() has created MIN or MAX
2504 from a conditional expression. */
2505 enum tree_code code
= TREE_CODE (exp
) == MIN_EXPR
? LT_EXPR
: GT_EXPR
;
2506 tree op0
= TREE_OPERAND (exp
, 0);
2507 tree op1
= TREE_OPERAND (exp
, 1);
2509 gcc_assert (! TREE_SIDE_EFFECTS (op0
) && ! TREE_SIDE_EFFECTS (op1
));
2510 x
= build3 (COND_EXPR
, TREE_TYPE (exp
),
2511 build2 (code
, boolean_type_node
, op0
, op1
),
2513 generate_bytecode_insns (x
, target
, state
);
2516 case NEW_CLASS_EXPR
:
2518 tree
class = TREE_TYPE (TREE_TYPE (exp
));
2519 int need_result
= target
!= IGNORE_TARGET
;
2520 int index
= find_class_constant (&state
->cpool
, class);
2526 NOTE_PUSH (1 + need_result
);
2528 /* ... fall though ... */
2531 tree f
= TREE_OPERAND (exp
, 0);
2532 tree x
= TREE_OPERAND (exp
, 1);
2533 int save_SP
= state
->code_SP
;
2535 if (TREE_CODE (f
) == ADDR_EXPR
)
2536 f
= TREE_OPERAND (f
, 0);
2537 if (f
== soft_newarray_node
)
2539 int type_code
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2540 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x
)),
2541 STACK_TARGET
, state
);
2543 OP1 (OPCODE_newarray
);
2547 else if (f
== soft_multianewarray_node
)
2551 int index
= find_class_constant (&state
->cpool
,
2552 TREE_TYPE (TREE_TYPE (exp
)));
2553 x
= TREE_CHAIN (x
); /* Skip class argument. */
2554 ndims
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2555 for (idim
= ndims
; --idim
>= 0; )
2558 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2561 OP1 (OPCODE_multianewarray
);
2564 NOTE_POP (ndims
- 1);
2567 else if (f
== soft_anewarray_node
)
2569 tree cl
= TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp
)));
2570 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (cl
));
2571 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2573 OP1 (OPCODE_anewarray
);
2577 else if (f
== soft_monitorenter_node
2578 || f
== soft_monitorexit_node
2581 if (f
== soft_monitorenter_node
)
2582 op
= OPCODE_monitorenter
;
2583 else if (f
== soft_monitorexit_node
)
2584 op
= OPCODE_monitorexit
;
2587 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2593 for ( ; x
!= NULL_TREE
; x
= TREE_CHAIN (x
))
2595 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2597 nargs
= state
->code_SP
- save_SP
;
2598 state
->code_SP
= save_SP
;
2599 if (f
== soft_fmod_node
)
2606 if (TREE_CODE (exp
) == NEW_CLASS_EXPR
)
2607 NOTE_POP (1); /* Pop implicit this. */
2608 if (TREE_CODE (f
) == FUNCTION_DECL
&& DECL_CONTEXT (f
) != NULL_TREE
)
2610 tree context
= DECL_CONTEXT (f
);
2611 int index
, interface
= 0;
2614 /* If the method is not static, use the qualifying type.
2615 However, don't use the qualifying type if the method
2616 was declared in Object. */
2617 if (! METHOD_STATIC (f
)
2618 && ! DECL_CONSTRUCTOR_P (f
)
2619 && ! METHOD_PRIVATE (f
)
2620 && DECL_CONTEXT (f
) != object_type_node
)
2622 tree arg1
= TREE_VALUE (TREE_OPERAND (exp
, 1));
2623 context
= TREE_TYPE (TREE_TYPE (arg1
));
2626 if (METHOD_STATIC (f
))
2627 OP1 (OPCODE_invokestatic
);
2628 else if (DECL_CONSTRUCTOR_P (f
) || CALL_USING_SUPER (exp
)
2629 || METHOD_PRIVATE (f
))
2630 OP1 (OPCODE_invokespecial
);
2633 if (CLASS_INTERFACE (TYPE_NAME (context
)))
2636 OP1 (OPCODE_invokeinterface
);
2638 OP1 (OPCODE_invokevirtual
);
2641 index
= find_methodref_with_class_index (&state
->cpool
, f
,
2646 gcc_assert (nargs
> 0);
2650 f
= TREE_TYPE (TREE_TYPE (f
));
2651 if (TREE_CODE (f
) != VOID_TYPE
)
2653 int size
= TYPE_IS_WIDE (f
) ? 2 : 1;
2654 if (target
== IGNORE_TARGET
)
2655 emit_pop (size
, state
);
2664 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2665 tree_code_name
[(int) TREE_CODE (exp
)]);
2670 perform_relocations (struct jcf_partial
*state
)
2672 struct jcf_block
*block
;
2673 struct jcf_relocation
*reloc
;
2677 /* Before we start, the pc field of each block is an upper bound on
2678 the block's start pc (it may be less, if previous blocks need less
2679 than their maximum).
2681 The minimum size of each block is in the block's chunk->size. */
2683 /* First, figure out the actual locations of each block. */
2686 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2688 int block_size
= block
->v
.chunk
->size
;
2692 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2693 Assumes relocations are in reverse order. */
2694 reloc
= block
->u
.relocations
;
2695 while (reloc
!= NULL
2696 && reloc
->kind
== OPCODE_goto_w
2697 && reloc
->label
->pc
== block
->next
->pc
2698 && reloc
->offset
+ 2 == block_size
)
2700 reloc
= reloc
->next
;
2701 block
->u
.relocations
= reloc
;
2702 block
->v
.chunk
->size
-= 3;
2707 /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2708 jump directly to X. We're careful here to avoid an infinite
2709 loop if the `goto's themselves form one. We do this
2710 optimization because we can generate a goto-to-goto for some
2711 try/finally blocks. */
2712 while (reloc
!= NULL
2713 && reloc
->kind
== OPCODE_goto_w
2714 && reloc
->label
!= block
2715 && reloc
->label
->v
.chunk
->data
!= NULL
2716 && reloc
->label
->v
.chunk
->data
[0] == OPCODE_goto
)
2718 /* Find the reloc for the first instruction of the
2719 destination block. */
2720 struct jcf_relocation
*first_reloc
;
2721 for (first_reloc
= reloc
->label
->u
.relocations
;
2723 first_reloc
= first_reloc
->next
)
2725 if (first_reloc
->offset
== 1
2726 && first_reloc
->kind
== OPCODE_goto_w
)
2728 reloc
->label
= first_reloc
->label
;
2733 /* If we didn't do anything, exit the loop. */
2734 if (first_reloc
== NULL
)
2738 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
2740 if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2742 /* We assume this is the first relocation in this block,
2743 so we know its final pc. */
2744 int where
= pc
+ reloc
->offset
;
2745 int pad
= ((where
+ 3) & ~3) - where
;
2748 else if (reloc
->kind
< -1 || reloc
->kind
> BLOCK_START_RELOC
)
2750 int delta
= reloc
->label
->pc
- (pc
+ reloc
->offset
- 1);
2751 int expand
= reloc
->kind
> 0 ? 2 : 5;
2755 if (delta
>= -32768 && delta
<= 32767)
2761 block_size
+= expand
;
2767 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2769 struct chunk
*chunk
= block
->v
.chunk
;
2770 int old_size
= chunk
->size
;
2771 int next_pc
= block
->next
== NULL
? pc
: block
->next
->pc
;
2772 int new_size
= next_pc
- block
->pc
;
2773 unsigned char *new_ptr
;
2774 unsigned char *old_buffer
= chunk
->data
;
2775 unsigned char *old_ptr
= old_buffer
+ old_size
;
2776 if (new_size
!= old_size
)
2778 chunk
->data
= obstack_alloc (state
->chunk_obstack
, new_size
);
2779 chunk
->size
= new_size
;
2781 new_ptr
= chunk
->data
+ new_size
;
2783 /* We do the relocations from back to front, because
2784 the relocations are in reverse order. */
2785 for (reloc
= block
->u
.relocations
; ; reloc
= reloc
->next
)
2787 /* new_ptr and old_ptr point into the old and new buffers,
2788 respectively. (If no relocations cause the buffer to
2789 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2790 The bytes at higher address have been copied and relocations
2791 handled; those at lower addresses remain to process. */
2793 /* Lower old index of piece to be copied with no relocation.
2794 I.e. high index of the first piece that does need relocation. */
2795 int start
= reloc
== NULL
? 0
2796 : reloc
->kind
== SWITCH_ALIGN_RELOC
? reloc
->offset
2797 : (reloc
->kind
== 0 || reloc
->kind
== BLOCK_START_RELOC
)
2799 : reloc
->offset
+ 2;
2802 int n
= (old_ptr
- old_buffer
) - start
;
2805 /* Don't "copy" bytes in place, this causes valgrind
2807 if (n
> 0 && new_ptr
!= old_ptr
)
2808 memcpy (new_ptr
, old_ptr
, n
);
2809 if (old_ptr
== old_buffer
)
2812 new_offset
= new_ptr
- chunk
->data
;
2813 new_offset
-= (reloc
->kind
== -1 ? 2 : 4);
2814 if (reloc
->kind
== 0)
2817 value
= GET_u4 (old_ptr
);
2819 else if (reloc
->kind
== BLOCK_START_RELOC
)
2825 else if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2827 int where
= block
->pc
+ reloc
->offset
;
2828 int pad
= ((where
+ 3) & ~3) - where
;
2836 value
= GET_u2 (old_ptr
);
2838 value
+= reloc
->label
->pc
- (block
->pc
+ new_offset
);
2839 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2840 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2841 if (reloc
->kind
!= -1)
2843 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2844 *--new_ptr
= (unsigned char) value
;
2846 if (reloc
->kind
> BLOCK_START_RELOC
)
2848 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2850 *--new_ptr
= reloc
->kind
;
2852 else if (reloc
->kind
< -1)
2854 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2856 *--new_ptr
= OPCODE_goto_w
;
2859 *--new_ptr
= - reloc
->kind
;
2862 gcc_assert (new_ptr
== chunk
->data
);
2864 state
->code_length
= pc
;
2868 init_jcf_state (struct jcf_partial
*state
, struct obstack
*work
)
2870 state
->chunk_obstack
= work
;
2871 state
->first
= state
->chunk
= NULL
;
2872 CPOOL_INIT (&state
->cpool
);
2873 BUFFER_INIT (&state
->localvars
);
2874 BUFFER_INIT (&state
->bytecode
);
2878 init_jcf_method (struct jcf_partial
*state
, tree method
)
2880 state
->current_method
= method
;
2881 state
->blocks
= state
->last_block
= NULL
;
2882 state
->linenumber_count
= 0;
2883 state
->first_lvar
= state
->last_lvar
= NULL
;
2884 state
->lvar_count
= 0;
2885 state
->labeled_blocks
= NULL
;
2886 state
->code_length
= 0;
2887 BUFFER_RESET (&state
->bytecode
);
2888 BUFFER_RESET (&state
->localvars
);
2890 state
->code_SP_max
= 0;
2891 state
->handlers
= NULL
;
2892 state
->last_handler
= NULL
;
2893 state
->num_handlers
= 0;
2894 state
->num_finalizers
= 0;
2895 state
->return_value_decl
= NULL_TREE
;
2899 release_jcf_state (struct jcf_partial
*state
)
2901 CPOOL_FINISH (&state
->cpool
);
2902 obstack_free (state
->chunk_obstack
, state
->first
);
2905 /* Get the access flags (modifiers) of a class (TYPE_DECL) to be used in the
2906 access_flags field of the class file header. */
2909 get_classfile_modifiers (tree
class)
2911 /* These are the flags which are valid class file modifiers.
2913 int valid_toplevel_class_flags
= (ACC_PUBLIC
| ACC_FINAL
| ACC_SUPER
|
2914 ACC_INTERFACE
| ACC_ABSTRACT
);
2915 int flags
= get_access_flags (class);
2917 /* ACC_SUPER should always be set, except for interfaces. */
2918 if (! (flags
& ACC_INTERFACE
))
2921 /* A protected member class becomes public at the top level. */
2922 if (flags
& ACC_PROTECTED
)
2923 flags
|= ACC_PUBLIC
;
2925 /* Filter out flags that are not valid for a class or interface in the
2926 top-level access_flags field. */
2927 flags
&= valid_toplevel_class_flags
;
2932 /* Get the access flags (modifiers) for a method to be used in the class
2936 get_method_access_flags (tree decl
)
2938 int flags
= get_access_flags (decl
);
2940 /* Promote "private" inner-class constructors to package-private. */
2941 if (DECL_CONSTRUCTOR_P (decl
)
2942 && INNER_CLASS_DECL_P (TYPE_NAME (DECL_CONTEXT (decl
))))
2943 flags
&= ~(ACC_PRIVATE
);
2948 /* Generate and return a list of chunks containing the class CLAS
2949 in the .class file representation. The list can be written to a
2950 .class file using write_chunks. Allocate chunks from obstack WORK. */
2952 static GTY(()) tree SourceFile_node
;
2953 static struct chunk
*
2954 generate_classfile (tree clas
, struct jcf_partial
*state
)
2956 struct chunk
*cpool_chunk
;
2957 const char *source_file
, *s
;
2960 unsigned char *fields_count_ptr
;
2961 int fields_count
= 0;
2962 unsigned char *methods_count_ptr
;
2963 int methods_count
= 0;
2966 = clas
== object_type_node
? 0 : BINFO_N_BASE_BINFOS (TYPE_BINFO (clas
));
2968 ptr
= append_chunk (NULL
, 8, state
);
2969 PUT4 (0xCafeBabe); /* Magic number */
2970 PUT2 (3); /* Minor version */
2971 PUT2 (45); /* Major version */
2973 append_chunk (NULL
, 0, state
);
2974 cpool_chunk
= state
->chunk
;
2976 /* Next allocate the chunk containing access_flags through fields_count. */
2977 if (clas
== object_type_node
)
2980 i
= 8 + 2 * total_supers
;
2981 ptr
= append_chunk (NULL
, i
, state
);
2982 i
= get_classfile_modifiers (TYPE_NAME (clas
));
2983 PUT2 (i
); /* access_flags */
2984 i
= find_class_constant (&state
->cpool
, clas
); PUT2 (i
); /* this_class */
2985 if (clas
== object_type_node
)
2987 PUT2(0); /* super_class */
2988 PUT2(0); /* interfaces_count */
2992 tree binfo
= TYPE_BINFO (clas
);
2993 tree base_binfo
= BINFO_BASE_BINFO (binfo
, 0);
2994 int j
= find_class_constant (&state
->cpool
, BINFO_TYPE (base_binfo
));
2996 PUT2 (j
); /* super_class */
2997 PUT2 (total_supers
- 1); /* interfaces_count */
2998 for (i
= 1; BINFO_BASE_ITERATE (binfo
, i
, base_binfo
); i
++)
3000 j
= find_class_constant (&state
->cpool
, BINFO_TYPE (base_binfo
));
3004 fields_count_ptr
= ptr
;
3006 for (part
= TYPE_FIELDS (clas
); part
; part
= TREE_CHAIN (part
))
3008 int have_value
, attr_count
= 0;
3009 if (DECL_NAME (part
) == NULL_TREE
|| DECL_ARTIFICIAL (part
))
3011 ptr
= append_chunk (NULL
, 8, state
);
3012 i
= get_access_flags (part
); PUT2 (i
);
3013 i
= find_utf8_constant (&state
->cpool
, DECL_NAME (part
)); PUT2 (i
);
3014 i
= find_utf8_constant (&state
->cpool
,
3015 build_java_signature (TREE_TYPE (part
)));
3017 have_value
= DECL_INITIAL (part
) != NULL_TREE
3018 && FIELD_STATIC (part
) && CONSTANT_VALUE_P (DECL_INITIAL (part
))
3019 && FIELD_FINAL (part
)
3020 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part
))
3021 || TREE_TYPE (part
) == string_ptr_type_node
);
3025 if (FIELD_THISN (part
) || FIELD_LOCAL_ALIAS (part
)
3026 || FIELD_SYNTHETIC (part
))
3028 if (FIELD_DEPRECATED (part
))
3031 PUT2 (attr_count
); /* attributes_count */
3034 tree init
= DECL_INITIAL (part
);
3035 static tree ConstantValue_node
= NULL_TREE
;
3036 if (TREE_TYPE (part
) != TREE_TYPE (init
))
3037 fatal_error ("field initializer type mismatch");
3038 ptr
= append_chunk (NULL
, 8, state
);
3039 if (ConstantValue_node
== NULL_TREE
)
3040 ConstantValue_node
= get_identifier ("ConstantValue");
3041 i
= find_utf8_constant (&state
->cpool
, ConstantValue_node
);
3042 PUT2 (i
); /* attribute_name_index */
3043 PUT4 (2); /* attribute_length */
3044 i
= find_constant_index (init
, state
); PUT2 (i
);
3046 /* Emit the "Synthetic" attribute for val$<x> and this$<n>
3047 fields and other fields which need it. */
3048 if (FIELD_THISN (part
) || FIELD_LOCAL_ALIAS (part
)
3049 || FIELD_SYNTHETIC (part
))
3050 ptr
= append_synthetic_attribute (state
);
3051 if (FIELD_DEPRECATED (part
))
3052 append_deprecated_attribute (state
);
3055 ptr
= fields_count_ptr
; UNSAFE_PUT2 (fields_count
);
3057 ptr
= methods_count_ptr
= append_chunk (NULL
, 2, state
);
3060 for (part
= TYPE_METHODS (clas
); part
; part
= TREE_CHAIN (part
))
3062 struct jcf_block
*block
;
3063 tree function_body
= DECL_FUNCTION_BODY (part
);
3064 tree body
= function_body
== NULL_TREE
? NULL_TREE
3065 : BLOCK_EXPR_BODY (function_body
);
3066 tree name
= DECL_CONSTRUCTOR_P (part
) ? init_identifier_node
3068 tree type
= TREE_TYPE (part
);
3069 tree save_function
= current_function_decl
;
3070 int synthetic_p
= 0;
3072 /* Invisible Miranda methods shouldn't end up in the .class
3074 if (METHOD_INVISIBLE (part
))
3077 current_function_decl
= part
;
3078 ptr
= append_chunk (NULL
, 8, state
);
3079 i
= get_method_access_flags (part
); PUT2 (i
);
3080 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
3081 i
= find_utf8_constant (&state
->cpool
, build_java_signature (type
));
3083 i
= (body
!= NULL_TREE
) + (DECL_FUNCTION_THROWS (part
) != NULL_TREE
);
3085 /* Make room for the Synthetic attribute (of zero length.) */
3086 if (DECL_FINIT_P (part
)
3087 || DECL_INSTINIT_P (part
)
3088 || NESTED_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part
))
3089 || TYPE_DOT_CLASS (clas
) == part
)
3094 /* Make room for Deprecated attribute. */
3095 if (METHOD_DEPRECATED (part
))
3098 PUT2 (i
); /* attributes_count */
3101 ptr
= append_synthetic_attribute (state
);
3103 if (body
!= NULL_TREE
)
3105 int code_attributes_count
= 0;
3106 static tree Code_node
= NULL_TREE
;
3108 unsigned char *attr_len_ptr
;
3109 struct jcf_handler
*handler
;
3110 if (Code_node
== NULL_TREE
)
3111 Code_node
= get_identifier ("Code");
3112 ptr
= append_chunk (NULL
, 14, state
);
3113 i
= find_utf8_constant (&state
->cpool
, Code_node
); PUT2 (i
);
3115 init_jcf_method (state
, part
);
3116 get_jcf_label_here (state
); /* Force a first block. */
3117 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3118 localvar_alloc (t
, state
);
3119 state
->num_jsrs
= 0;
3120 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
3121 if (CAN_COMPLETE_NORMALLY (body
))
3123 gcc_assert (TREE_CODE (TREE_TYPE (type
)) == VOID_TYPE
);
3125 OP1 (OPCODE_return
);
3127 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3128 maybe_free_localvar (t
, state
, 1);
3129 if (state
->return_value_decl
!= NULL_TREE
)
3130 maybe_free_localvar (state
->return_value_decl
, state
, 1);
3131 finish_jcf_block (state
);
3132 perform_relocations (state
);
3135 i
= 8 + state
->code_length
+ 4 + 8 * state
->num_handlers
;
3136 if (state
->linenumber_count
> 0)
3138 code_attributes_count
++;
3139 i
+= 8 + 4 * state
->linenumber_count
;
3141 if (state
->lvar_count
> 0)
3143 code_attributes_count
++;
3144 i
+= 8 + 10 * state
->lvar_count
;
3146 UNSAFE_PUT4 (i
); /* attribute_length */
3147 UNSAFE_PUT2 (state
->code_SP_max
); /* max_stack */
3148 UNSAFE_PUT2 (localvar_max
); /* max_locals */
3149 UNSAFE_PUT4 (state
->code_length
);
3151 /* Emit the exception table. */
3152 ptr
= append_chunk (NULL
, 2 + 8 * state
->num_handlers
, state
);
3153 PUT2 (state
->num_handlers
); /* exception_table_length */
3154 handler
= state
->handlers
;
3155 for (; handler
!= NULL
; handler
= handler
->next
)
3158 PUT2 (handler
->start_label
->pc
);
3159 PUT2 (handler
->end_label
->pc
);
3160 PUT2 (handler
->handler_label
->pc
);
3161 if (handler
->type
== NULL_TREE
)
3164 type_index
= find_class_constant (&state
->cpool
,
3169 ptr
= append_chunk (NULL
, 2, state
);
3170 PUT2 (code_attributes_count
);
3172 /* Write the LineNumberTable attribute. */
3173 if (state
->linenumber_count
> 0)
3175 static tree LineNumberTable_node
= NULL_TREE
;
3176 ptr
= append_chunk (NULL
,
3177 8 + 4 * state
->linenumber_count
, state
);
3178 if (LineNumberTable_node
== NULL_TREE
)
3179 LineNumberTable_node
= get_identifier ("LineNumberTable");
3180 i
= find_utf8_constant (&state
->cpool
, LineNumberTable_node
);
3181 PUT2 (i
); /* attribute_name_index */
3182 i
= 2+4*state
->linenumber_count
; PUT4(i
); /* attribute_length */
3183 i
= state
->linenumber_count
; PUT2 (i
);
3184 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
3186 int line
= block
->linenumber
;
3195 /* Write the LocalVariableTable attribute. */
3196 if (state
->lvar_count
> 0)
3198 static tree LocalVariableTable_node
= NULL_TREE
;
3199 struct localvar_info
*lvar
= state
->first_lvar
;
3200 ptr
= append_chunk (NULL
, 8 + 10 * state
->lvar_count
, state
);
3201 if (LocalVariableTable_node
== NULL_TREE
)
3202 LocalVariableTable_node
= get_identifier("LocalVariableTable");
3203 i
= find_utf8_constant (&state
->cpool
, LocalVariableTable_node
);
3204 PUT2 (i
); /* attribute_name_index */
3205 i
= 2 + 10 * state
->lvar_count
; PUT4 (i
); /* attribute_length */
3206 i
= state
->lvar_count
; PUT2 (i
);
3207 for ( ; lvar
!= NULL
; lvar
= lvar
->next
)
3209 tree name
= DECL_NAME (lvar
->decl
);
3210 tree sig
= build_java_signature (TREE_TYPE (lvar
->decl
));
3211 i
= lvar
->start_label
->pc
; PUT2 (i
);
3212 i
= lvar
->end_label
->pc
- i
; PUT2 (i
);
3213 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
3214 i
= find_utf8_constant (&state
->cpool
, sig
); PUT2 (i
);
3215 i
= DECL_LOCAL_INDEX (lvar
->decl
); PUT2 (i
);
3219 if (DECL_FUNCTION_THROWS (part
) != NULL_TREE
)
3221 tree t
= DECL_FUNCTION_THROWS (part
);
3222 int throws_count
= list_length (t
);
3223 static tree Exceptions_node
= NULL_TREE
;
3224 if (Exceptions_node
== NULL_TREE
)
3225 Exceptions_node
= get_identifier ("Exceptions");
3226 ptr
= append_chunk (NULL
, 8 + 2 * throws_count
, state
);
3227 i
= find_utf8_constant (&state
->cpool
, Exceptions_node
);
3228 PUT2 (i
); /* attribute_name_index */
3229 i
= 2 + 2 * throws_count
; PUT4(i
); /* attribute_length */
3230 i
= throws_count
; PUT2 (i
);
3231 for (; t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3233 i
= find_class_constant (&state
->cpool
, TREE_VALUE (t
));
3238 if (METHOD_DEPRECATED (part
))
3239 append_deprecated_attribute (state
);
3242 current_function_decl
= save_function
;
3244 ptr
= methods_count_ptr
; UNSAFE_PUT2 (methods_count
);
3246 source_file
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3247 for (s
= source_file
; ; s
++)
3252 if (ch
== '/' || ch
== '\\')
3255 ptr
= append_chunk (NULL
, 10, state
);
3257 i
= 1; /* Source file always exists as an attribute */
3258 if (INNER_CLASS_TYPE_P (clas
) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas
)))
3260 if (clas
== object_type_node
)
3262 if (CLASS_DEPRECATED (TYPE_NAME (clas
)))
3265 PUT2 (i
); /* attributes_count */
3267 /* generate the SourceFile attribute. */
3268 if (SourceFile_node
== NULL_TREE
)
3270 SourceFile_node
= get_identifier ("SourceFile");
3273 i
= find_utf8_constant (&state
->cpool
, SourceFile_node
);
3274 PUT2 (i
); /* attribute_name_index */
3276 i
= find_utf8_constant (&state
->cpool
, get_identifier (source_file
));
3278 append_gcj_attribute (state
, clas
);
3279 append_innerclasses_attribute (state
, clas
);
3280 if (CLASS_DEPRECATED (TYPE_NAME (clas
)))
3281 append_deprecated_attribute (state
);
3283 /* New finally generate the contents of the constant pool chunk. */
3284 i
= count_constant_pool_bytes (&state
->cpool
);
3285 ptr
= obstack_alloc (state
->chunk_obstack
, i
);
3286 cpool_chunk
->data
= ptr
;
3287 cpool_chunk
->size
= i
;
3288 write_constant_pool (&state
->cpool
, ptr
, i
);
3289 return state
->first
;
3292 static GTY(()) tree Synthetic_node
;
3293 static unsigned char *
3294 append_synthetic_attribute (struct jcf_partial
*state
)
3296 unsigned char *ptr
= append_chunk (NULL
, 6, state
);
3299 if (Synthetic_node
== NULL_TREE
)
3301 Synthetic_node
= get_identifier ("Synthetic");
3303 i
= find_utf8_constant (&state
->cpool
, Synthetic_node
);
3304 PUT2 (i
); /* Attribute string index */
3305 PUT4 (0); /* Attribute length */
3311 append_deprecated_attribute (struct jcf_partial
*state
)
3313 unsigned char *ptr
= append_chunk (NULL
, 6, state
);
3316 i
= find_utf8_constant (&state
->cpool
, get_identifier ("Deprecated"));
3317 PUT2 (i
); /* Attribute string index */
3318 PUT4 (0); /* Attribute length */
3322 append_gcj_attribute (struct jcf_partial
*state
, tree
class)
3327 if (class != object_type_node
)
3330 ptr
= append_chunk (NULL
, 6, state
); /* 2+4 */
3331 i
= find_utf8_constant (&state
->cpool
,
3332 get_identifier ("gnu.gcj.gcj-compiled"));
3333 PUT2 (i
); /* Attribute string index */
3334 PUT4 (0); /* Attribute length */
3337 static tree InnerClasses_node
;
3339 append_innerclasses_attribute (struct jcf_partial
*state
, tree
class)
3341 tree orig_decl
= TYPE_NAME (class);
3344 unsigned char *ptr
, *length_marker
, *number_marker
;
3346 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl
))
3349 ptr
= append_chunk (NULL
, 8, state
); /* 2+4+2 */
3351 if (InnerClasses_node
== NULL_TREE
)
3353 InnerClasses_node
= get_identifier ("InnerClasses");
3355 i
= find_utf8_constant (&state
->cpool
, InnerClasses_node
);
3357 length_marker
= ptr
; PUT4 (0); /* length, to be later patched */
3358 number_marker
= ptr
; PUT2 (0); /* number of classes, tblp */
3360 /* Generate the entries: all inner classes visible from the one we
3361 process: itself, up and down. */
3362 while (class && INNER_CLASS_TYPE_P (class))
3366 decl
= TYPE_NAME (class);
3367 n
= IDENTIFIER_POINTER (DECL_NAME (decl
)) +
3368 IDENTIFIER_LENGTH (DECL_NAME (decl
));
3370 while (n
[-1] != '$')
3372 append_innerclasses_attribute_entry (state
, decl
, get_identifier (n
));
3375 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3379 for (current
= DECL_INNER_CLASS_LIST (decl
);
3380 current
; current
= TREE_CHAIN (current
))
3382 append_innerclasses_attribute_entry (state
, TREE_PURPOSE (current
),
3383 TREE_VALUE (current
));
3387 ptr
= length_marker
; PUT4 (8*length
+2);
3388 ptr
= number_marker
; PUT2 (length
);
3392 append_innerclasses_attribute_entry (struct jcf_partial
*state
,
3393 tree decl
, tree name
)
3396 int ocii
= 0, ini
= 0;
3397 unsigned char *ptr
= append_chunk (NULL
, 8, state
);
3399 icii
= find_class_constant (&state
->cpool
, TREE_TYPE (decl
));
3401 /* Sun's implementation seems to generate ocii to 0 for inner
3402 classes (which aren't considered members of the class they're
3403 in.) The specs are saying that if the class is anonymous,
3404 inner_name_index must be zero. */
3405 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl
)))
3407 ocii
= find_class_constant (&state
->cpool
,
3408 TREE_TYPE (DECL_CONTEXT (decl
)));
3409 ini
= find_utf8_constant (&state
->cpool
, name
);
3411 icaf
= get_access_flags (decl
);
3413 PUT2 (icii
); PUT2 (ocii
); PUT2 (ini
); PUT2 (icaf
);
3417 make_class_file_name (tree clas
)
3419 const char *dname
, *cname
, *slash
;
3424 cname
= IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas
)),
3425 "", '.', DIR_SEPARATOR
,
3427 if (jcf_write_base_directory
== NULL
)
3429 /* Make sure we put the class file into the .java file's
3430 directory, and not into some subdirectory thereof. */
3432 dname
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3433 slash
= strrchr (dname
, DIR_SEPARATOR
);
3434 #ifdef DIR_SEPARATOR_2
3436 slash
= strrchr (dname
, DIR_SEPARATOR_2
);
3442 sep
= DIR_SEPARATOR
;
3447 t
= strrchr (cname
, DIR_SEPARATOR
);
3455 dname
= jcf_write_base_directory
;
3457 s
= strrchr (dname
, DIR_SEPARATOR
);
3458 #ifdef DIR_SEPARATOR_2
3460 s
= strrchr (dname
, DIR_SEPARATOR_2
);
3465 sep
= DIR_SEPARATOR
;
3467 slash
= dname
+ strlen (dname
);
3470 r
= XNEWVEC (char, slash
- dname
+ strlen (cname
) + 2);
3471 strncpy (r
, dname
, slash
- dname
);
3472 r
[slash
- dname
] = sep
;
3473 strcpy (&r
[slash
- dname
+ 1], cname
);
3475 /* We try to make new directories when we need them. We only do
3476 this for directories which "might not" exist. For instance, we
3477 assume the `-d' directory exists, but we don't assume that any
3478 subdirectory below it exists. It might be worthwhile to keep
3479 track of which directories we've created to avoid gratuitous
3481 dname
= r
+ (slash
- dname
) + 1;
3484 char *s
= strchr (dname
, sep
);
3488 /* Try to make directory if it doesn't already exist. */
3489 if (stat (r
, &sb
) == -1
3490 && mkdir (r
, 0755) == -1
3491 /* The directory might have been made by another process. */
3493 fatal_error ("can't create directory %s: %m", r
);
3496 /* Skip consecutive separators. */
3497 for (dname
= s
+ 1; *dname
&& *dname
== sep
; ++dname
)
3504 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3505 The output .class file name is make_class_file_name(CLAS). */
3508 write_classfile (tree clas
)
3510 struct obstack
*work
= &temporary_obstack
;
3511 struct jcf_partial state
[1];
3512 char *class_file_name
= make_class_file_name (clas
);
3513 struct chunk
*chunks
;
3515 if (class_file_name
!= NULL
)
3518 char *temporary_file_name
;
3519 char pid
[sizeof (long) * 2 + 2];
3521 /* The .class file is initially written to a ".PID" file so that
3522 if multiple instances of the compiler are running at once
3523 they do not see partially formed class files nor override
3524 each other, which may happen in libjava with parallel build.
3526 sprintf (pid
, ".%lx", (unsigned long) getpid ());
3527 temporary_file_name
= concat (class_file_name
, pid
, NULL
);
3528 stream
= fopen (temporary_file_name
, "wb");
3530 fatal_error ("can't open %s for writing: %m", temporary_file_name
);
3532 jcf_dependency_add_target (class_file_name
);
3533 init_jcf_state (state
, work
);
3534 chunks
= generate_classfile (clas
, state
);
3535 write_chunks (stream
, chunks
);
3536 if (fclose (stream
))
3537 fatal_error ("error closing %s: %m", temporary_file_name
);
3539 /* If a file named by the string pointed to by `new' exists
3540 prior to the call to the `rename' function, the behavior
3541 is implementation-defined. ISO 9899-1990 7.9.4.2.
3543 For example, on Win32 with MSVCRT, it is an error. */
3545 unlink (class_file_name
);
3547 if (rename (temporary_file_name
, class_file_name
) == -1)
3549 int errno_saved
= errno
;
3550 remove (temporary_file_name
);
3551 errno
= errno_saved
;
3552 fatal_error ("can't create %s: %m", class_file_name
);
3554 free (temporary_file_name
);
3555 free (class_file_name
);
3557 release_jcf_state (state
);
3561 string concatenation
3562 synchronized statement
3565 #include "gt-java-jcf-write.h"