1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, 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); if (state->code_SP < 0) abort(); } 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 struct chunk
* generate_classfile (tree
, struct jcf_partial
*);
308 static struct jcf_handler
*alloc_handler (struct jcf_block
*,
310 struct jcf_partial
*);
311 static void emit_iinc (tree
, HOST_WIDE_INT
, struct jcf_partial
*);
312 static void emit_reloc (HOST_WIDE_INT
, int, struct jcf_block
*,
313 struct jcf_partial
*);
314 static void push_constant1 (HOST_WIDE_INT
, struct jcf_partial
*);
315 static void push_constant2 (HOST_WIDE_INT
, struct jcf_partial
*);
316 static void push_int_const (HOST_WIDE_INT
, struct jcf_partial
*);
317 static int find_constant_wide (HOST_WIDE_INT
, HOST_WIDE_INT
,
318 struct jcf_partial
*);
319 static void push_long_const (HOST_WIDE_INT
, HOST_WIDE_INT
,
320 struct jcf_partial
*);
321 static int find_constant_index (tree
, struct jcf_partial
*);
322 static void push_long_const (HOST_WIDE_INT
, HOST_WIDE_INT
,
323 struct jcf_partial
*);
324 static void field_op (tree
, int, struct jcf_partial
*);
325 static void maybe_wide (int, int, struct jcf_partial
*);
326 static void emit_dup (int, int, struct jcf_partial
*);
327 static void emit_pop (int, struct jcf_partial
*);
328 static void emit_load_or_store (tree
, int, struct jcf_partial
*);
329 static void emit_load (tree
, struct jcf_partial
*);
330 static void emit_store (tree
, struct jcf_partial
*);
331 static void emit_unop (enum java_opcode
, tree
, struct jcf_partial
*);
332 static void emit_binop (enum java_opcode
, tree
, struct jcf_partial
*);
333 static void emit_reloc (HOST_WIDE_INT
, int, struct jcf_block
*,
334 struct jcf_partial
*);
335 static void emit_switch_reloc (struct jcf_block
*, struct jcf_partial
*);
336 static void emit_case_reloc (struct jcf_relocation
*, struct jcf_partial
*);
337 static void emit_if (struct jcf_block
*, int, int, struct jcf_partial
*);
338 static void emit_goto (struct jcf_block
*, struct jcf_partial
*);
339 static void emit_jsr (struct jcf_block
*, struct jcf_partial
*);
340 static void call_cleanups (struct jcf_block
*, struct jcf_partial
*);
341 static char *make_class_file_name (tree
);
342 static unsigned char *append_synthetic_attribute (struct jcf_partial
*);
343 static void append_deprecated_attribute (struct jcf_partial
*);
344 static void append_innerclasses_attribute (struct jcf_partial
*, tree
);
345 static void append_innerclasses_attribute_entry (struct jcf_partial
*, tree
, tree
);
346 static void append_gcj_attribute (struct jcf_partial
*, tree
);
348 /* Utility macros for appending (big-endian) data to a buffer.
349 We assume a local variable 'ptr' points into where we want to
350 write next, and we assume enough space has been allocated. */
352 #ifdef ENABLE_JC1_CHECKING
353 static int CHECK_PUT (void *, struct jcf_partial
*, int);
356 CHECK_PUT (void *ptr
, struct jcf_partial
*state
, int i
)
358 if ((unsigned char *) ptr
< state
->chunk
->data
359 || (unsigned char *) ptr
+ i
> state
->chunk
->data
+ state
->chunk
->size
)
365 #define CHECK_PUT(PTR, STATE, I) ((void)0)
368 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
369 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
370 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
371 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
373 /* There are some cases below where CHECK_PUT is guaranteed to fail.
374 Use the following macros in those specific cases. */
375 #define UNSAFE_PUT1(X) (*ptr++ = (X))
376 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
377 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
378 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
381 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
382 Set the data and size fields to DATA and SIZE, respectively.
383 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
385 static struct chunk
*
386 alloc_chunk (struct chunk
*last
, unsigned char *data
,
387 int size
, struct obstack
*work
)
389 struct chunk
*chunk
= obstack_alloc (work
, sizeof(struct chunk
));
391 if (data
== NULL
&& size
> 0)
392 data
= obstack_alloc (work
, size
);
402 #ifdef ENABLE_JC1_CHECKING
403 static int CHECK_OP (struct jcf_partial
*);
406 CHECK_OP (struct jcf_partial
*state
)
408 if (state
->bytecode
.ptr
> state
->bytecode
.limit
)
414 #define CHECK_OP(STATE) ((void) 0)
417 static unsigned char *
418 append_chunk (unsigned char *data
, int size
, struct jcf_partial
*state
)
420 state
->chunk
= alloc_chunk (state
->chunk
, data
, size
, state
->chunk_obstack
);
421 if (state
->first
== NULL
)
422 state
->first
= state
->chunk
;
423 return state
->chunk
->data
;
427 append_chunk_copy (unsigned char *data
, int size
, struct jcf_partial
*state
)
429 unsigned char *ptr
= append_chunk (NULL
, size
, state
);
430 memcpy (ptr
, data
, size
);
433 static struct jcf_block
*
434 gen_jcf_label (struct jcf_partial
*state
)
436 struct jcf_block
*block
437 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_block
));
439 block
->linenumber
= -1;
440 block
->pc
= UNDEFINED_PC
;
445 finish_jcf_block (struct jcf_partial
*state
)
447 struct jcf_block
*block
= state
->last_block
;
448 struct jcf_relocation
*reloc
;
449 int code_length
= BUFFER_LENGTH (&state
->bytecode
);
450 int pc
= state
->code_length
;
451 append_chunk_copy (state
->bytecode
.data
, code_length
, state
);
452 BUFFER_RESET (&state
->bytecode
);
453 block
->v
.chunk
= state
->chunk
;
455 /* Calculate code_length to the maximum value it can have. */
456 pc
+= block
->v
.chunk
->size
;
457 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
459 int kind
= reloc
->kind
;
460 if (kind
== SWITCH_ALIGN_RELOC
)
462 else if (kind
> BLOCK_START_RELOC
)
463 pc
+= 2; /* 2-byte offset may grow to 4-byte offset */
465 pc
+= 5; /* May need to add a goto_w. */
467 state
->code_length
= pc
;
471 define_jcf_label (struct jcf_block
*label
, struct jcf_partial
*state
)
473 if (state
->last_block
!= NULL
)
474 finish_jcf_block (state
);
475 label
->pc
= state
->code_length
;
476 if (state
->blocks
== NULL
)
477 state
->blocks
= label
;
479 state
->last_block
->next
= label
;
480 state
->last_block
= label
;
482 label
->u
.relocations
= NULL
;
485 static struct jcf_block
*
486 get_jcf_label_here (struct jcf_partial
*state
)
488 if (state
->last_block
!= NULL
&& BUFFER_LENGTH (&state
->bytecode
) == 0)
489 return state
->last_block
;
492 struct jcf_block
*label
= gen_jcf_label (state
);
493 define_jcf_label (label
, state
);
498 /* Note a line number entry for the current PC and given LINE. */
501 put_linenumber (int line
, struct jcf_partial
*state
)
503 struct jcf_block
*label
= get_jcf_label_here (state
);
504 if (label
->linenumber
> 0)
506 label
= gen_jcf_label (state
);
507 define_jcf_label (label
, state
);
509 label
->linenumber
= line
;
510 state
->linenumber_count
++;
513 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
514 in the range (START_LABEL, END_LABEL). */
516 static struct jcf_handler
*
517 alloc_handler (struct jcf_block
*start_label
, struct jcf_block
*end_label
,
518 struct jcf_partial
*state
)
520 struct jcf_handler
*handler
521 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_handler
));
522 handler
->start_label
= start_label
;
523 handler
->end_label
= end_label
;
524 handler
->handler_label
= get_jcf_label_here (state
);
525 if (state
->handlers
== NULL
)
526 state
->handlers
= handler
;
528 state
->last_handler
->next
= handler
;
529 state
->last_handler
= handler
;
530 handler
->next
= NULL
;
531 state
->num_handlers
++;
536 /* The index of jvm local variable allocated for this DECL.
537 This is assigned when generating .class files;
538 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
539 (We don't allocate DECL_LANG_SPECIFIC for locals from Java source code.) */
541 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
545 struct localvar_info
*next
;
548 struct jcf_block
*start_label
;
549 struct jcf_block
*end_label
;
552 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
553 #define localvar_max \
554 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
557 localvar_alloc (tree decl
, struct jcf_partial
*state
)
559 struct jcf_block
*start_label
= get_jcf_label_here (state
);
560 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
562 struct localvar_info
*info
;
563 struct localvar_info
**ptr
= localvar_buffer
;
564 struct localvar_info
**limit
565 = (struct localvar_info
**) state
->localvars
.ptr
;
566 for (index
= 0; ptr
< limit
; index
++, ptr
++)
569 && (! wide
|| ((ptr
+1) < limit
&& ptr
[1] == NULL
)))
574 buffer_grow (&state
->localvars
, 2 * sizeof (struct localvar_info
*));
575 ptr
= (struct localvar_info
**) state
->localvars
.data
+ index
;
576 state
->localvars
.ptr
= (unsigned char *) (ptr
+ 1 + wide
);
578 info
= obstack_alloc (state
->chunk_obstack
, sizeof (struct localvar_info
));
581 ptr
[1] = (struct localvar_info
*)(~0);
582 DECL_LOCAL_INDEX (decl
) = index
;
584 info
->start_label
= start_label
;
586 if (debug_info_level
> DINFO_LEVEL_TERSE
587 && DECL_NAME (decl
) != NULL_TREE
)
589 /* Generate debugging info. */
591 if (state
->last_lvar
!= NULL
)
592 state
->last_lvar
->next
= info
;
594 state
->first_lvar
= info
;
595 state
->last_lvar
= info
;
601 maybe_free_localvar (tree decl
, struct jcf_partial
*state
, int really
)
603 struct jcf_block
*end_label
= get_jcf_label_here (state
);
604 int index
= DECL_LOCAL_INDEX (decl
);
605 struct localvar_info
**ptr
= &localvar_buffer
[index
];
606 struct localvar_info
*info
= *ptr
;
607 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
609 info
->end_label
= end_label
;
611 if (info
->decl
!= decl
)
618 if (ptr
[1] != (struct localvar_info
*)(~0))
625 #define STACK_TARGET 1
626 #define IGNORE_TARGET 2
628 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
629 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
632 get_access_flags (tree decl
)
635 int isfield
= TREE_CODE (decl
) == FIELD_DECL
|| TREE_CODE (decl
) == VAR_DECL
;
636 if (CLASS_PUBLIC (decl
)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
638 if (CLASS_FINAL (decl
)) /* same as FIELD_FINAL and METHOD_FINAL */
640 if (isfield
|| TREE_CODE (decl
) == FUNCTION_DECL
)
642 if (TREE_PROTECTED (decl
))
643 flags
|= ACC_PROTECTED
;
644 if (TREE_PRIVATE (decl
))
645 flags
|= ACC_PRIVATE
;
647 else if (TREE_CODE (decl
) == TYPE_DECL
)
649 if (CLASS_SUPER (decl
))
651 if (CLASS_ABSTRACT (decl
))
652 flags
|= ACC_ABSTRACT
;
653 if (CLASS_INTERFACE (decl
))
654 flags
|= ACC_INTERFACE
;
655 if (CLASS_STATIC (decl
))
657 if (CLASS_PRIVATE (decl
))
658 flags
|= ACC_PRIVATE
;
659 if (CLASS_PROTECTED (decl
))
660 flags
|= ACC_PROTECTED
;
661 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl
))
662 || LOCAL_CLASS_P (TREE_TYPE (decl
)))
663 flags
|= ACC_PRIVATE
;
664 if (CLASS_STRICTFP (decl
))
670 if (TREE_CODE (decl
) == FUNCTION_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_STATIC (decl
))
687 if (FIELD_VOLATILE (decl
))
688 flags
|= ACC_VOLATILE
;
689 if (FIELD_TRANSIENT (decl
))
690 flags
|= ACC_TRANSIENT
;
695 /* Write the list of segments starting at CHUNKS to STREAM. */
698 write_chunks (FILE* stream
, struct chunk
*chunks
)
700 for (; chunks
!= NULL
; chunks
= chunks
->next
)
701 fwrite (chunks
->data
, chunks
->size
, 1, stream
);
704 /* Push a 1-word constant in the constant pool at the given INDEX.
705 (Caller is responsible for doing NOTE_PUSH.) */
708 push_constant1 (HOST_WIDE_INT index
, struct jcf_partial
*state
)
723 /* Push a 2-word constant in the constant pool at the given INDEX.
724 (Caller is responsible for doing NOTE_PUSH.) */
727 push_constant2 (HOST_WIDE_INT index
, struct jcf_partial
*state
)
734 /* Push 32-bit integer constant on VM stack.
735 Caller is responsible for doing NOTE_PUSH. */
738 push_int_const (HOST_WIDE_INT i
, struct jcf_partial
*state
)
741 if (i
>= -1 && i
<= 5)
742 OP1(OPCODE_iconst_0
+ i
);
743 else if (i
>= -128 && i
< 128)
748 else if (i
>= -32768 && i
< 32768)
755 i
= find_constant1 (&state
->cpool
, CONSTANT_Integer
,
756 (jword
)(i
& 0xFFFFFFFF));
757 push_constant1 (i
, state
);
762 find_constant_wide (HOST_WIDE_INT lo
, HOST_WIDE_INT hi
,
763 struct jcf_partial
*state
)
765 HOST_WIDE_INT w1
, w2
;
766 lshift_double (lo
, hi
, -32, 64, &w1
, &w2
, 1);
767 return find_constant2 (&state
->cpool
, CONSTANT_Long
,
768 (jword
)(w1
& 0xFFFFFFFF), (jword
)(lo
& 0xFFFFFFFF));
771 /* Find or allocate a constant pool entry for the given VALUE.
772 Return the index in the constant pool. */
775 find_constant_index (tree value
, struct jcf_partial
*state
)
777 if (TREE_CODE (value
) == INTEGER_CST
)
779 if (TYPE_PRECISION (TREE_TYPE (value
)) <= 32)
780 return find_constant1 (&state
->cpool
, CONSTANT_Integer
,
781 (jword
)(TREE_INT_CST_LOW (value
) & 0xFFFFFFFF));
783 return find_constant_wide (TREE_INT_CST_LOW (value
),
784 TREE_INT_CST_HIGH (value
), state
);
786 else if (TREE_CODE (value
) == REAL_CST
)
790 real_to_target (words
, &TREE_REAL_CST (value
),
791 TYPE_MODE (TREE_TYPE (value
)));
792 words
[0] &= 0xffffffff;
793 words
[1] &= 0xffffffff;
795 if (TYPE_PRECISION (TREE_TYPE (value
)) == 32)
796 return find_constant1 (&state
->cpool
, CONSTANT_Float
, (jword
)words
[0]);
798 return find_constant2 (&state
->cpool
, CONSTANT_Double
,
799 (jword
)words
[1-FLOAT_WORDS_BIG_ENDIAN
],
800 (jword
)words
[FLOAT_WORDS_BIG_ENDIAN
]);
802 else if (TREE_CODE (value
) == STRING_CST
)
803 return find_string_constant (&state
->cpool
, value
);
809 /* Push 64-bit long constant on VM stack.
810 Caller is responsible for doing NOTE_PUSH. */
813 push_long_const (HOST_WIDE_INT lo
, HOST_WIDE_INT hi
, struct jcf_partial
*state
)
815 HOST_WIDE_INT highpart
, dummy
;
816 jint lowpart
= WORD_TO_INT (lo
);
818 rshift_double (lo
, hi
, 32, 64, &highpart
, &dummy
, 1);
820 if (highpart
== 0 && (lowpart
== 0 || lowpart
== 1))
823 OP1(OPCODE_lconst_0
+ lowpart
);
825 else if ((highpart
== 0 && lowpart
> 0 && lowpart
< 32768)
826 || (highpart
== -1 && lowpart
< 0 && lowpart
>= -32768))
828 push_int_const (lowpart
, state
);
833 push_constant2 (find_constant_wide (lo
, hi
, state
), state
);
837 field_op (tree field
, int opcode
, struct jcf_partial
*state
)
839 int index
= find_fieldref_index (&state
->cpool
, field
);
845 /* Returns an integer in the range 0 (for 'int') through 4 (for object
846 reference) to 7 (for 'short') which matches the pattern of how JVM
847 opcodes typically depend on the operand type. */
850 adjust_typed_op (tree type
, int max
)
852 switch (TREE_CODE (type
))
855 case RECORD_TYPE
: return 4;
857 return TYPE_PRECISION (type
) == 32 || max
< 5 ? 0 : 5;
859 return TYPE_PRECISION (type
) == 32 || max
< 6 ? 0 : 6;
861 switch (TYPE_PRECISION (type
))
863 case 8: return max
< 5 ? 0 : 5;
864 case 16: return max
< 7 ? 0 : 7;
870 switch (TYPE_PRECISION (type
))
883 maybe_wide (int opcode
, int index
, struct jcf_partial
*state
)
900 /* Compile code to duplicate with offset, where
901 SIZE is the size of the stack item to duplicate (1 or 2), abd
902 OFFSET is where to insert the result (must be 0, 1, or 2).
903 (The new words get inserted at stack[SP-size-offset].) */
906 emit_dup (int size
, int offset
, struct jcf_partial
*state
)
913 kind
= size
== 1 ? OPCODE_dup
: OPCODE_dup2
;
914 else if (offset
== 1)
915 kind
= size
== 1 ? OPCODE_dup_x1
: OPCODE_dup2_x1
;
916 else if (offset
== 2)
917 kind
= size
== 1 ? OPCODE_dup_x2
: OPCODE_dup2_x2
;
925 emit_pop (int size
, struct jcf_partial
*state
)
928 OP1 (OPCODE_pop
- 1 + size
);
932 emit_iinc (tree var
, HOST_WIDE_INT value
, struct jcf_partial
*state
)
934 int slot
= DECL_LOCAL_INDEX (var
);
936 if (value
< -128 || value
> 127 || slot
>= 256)
954 emit_load_or_store (tree var
, /* Variable to load from or store into. */
955 int opcode
, /* Either OPCODE_iload or OPCODE_istore. */
956 struct jcf_partial
*state
)
958 tree type
= TREE_TYPE (var
);
959 int kind
= adjust_typed_op (type
, 4);
960 int index
= DECL_LOCAL_INDEX (var
);
964 OP1 (opcode
+ 5 + 4 * kind
+ index
); /* [ilfda]{load,store}_[0123] */
967 maybe_wide (opcode
+ kind
, index
, state
); /* [ilfda]{load,store} */
971 emit_load (tree var
, struct jcf_partial
*state
)
973 emit_load_or_store (var
, OPCODE_iload
, state
);
974 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
978 emit_store (tree var
, struct jcf_partial
*state
)
980 emit_load_or_store (var
, OPCODE_istore
, state
);
981 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
985 emit_unop (enum java_opcode opcode
, tree type ATTRIBUTE_UNUSED
,
986 struct jcf_partial
*state
)
993 emit_binop (enum java_opcode opcode
, tree type
, struct jcf_partial
*state
)
995 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1002 emit_reloc (HOST_WIDE_INT value
, int kind
,
1003 struct jcf_block
*target
, struct jcf_partial
*state
)
1005 struct jcf_relocation
*reloc
1006 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1007 struct jcf_block
*block
= state
->last_block
;
1008 reloc
->next
= block
->u
.relocations
;
1009 block
->u
.relocations
= reloc
;
1010 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1011 reloc
->label
= target
;
1013 if (kind
== 0 || kind
== BLOCK_START_RELOC
)
1015 else if (kind
!= SWITCH_ALIGN_RELOC
)
1020 emit_switch_reloc (struct jcf_block
*label
, struct jcf_partial
*state
)
1022 emit_reloc (RELOCATION_VALUE_0
, BLOCK_START_RELOC
, label
, state
);
1025 /* Similar to emit_switch_reloc,
1026 but re-uses an existing case reloc. */
1029 emit_case_reloc (struct jcf_relocation
*reloc
, struct jcf_partial
*state
)
1031 struct jcf_block
*block
= state
->last_block
;
1032 reloc
->next
= block
->u
.relocations
;
1033 block
->u
.relocations
= reloc
;
1034 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1035 reloc
->kind
= BLOCK_START_RELOC
;
1039 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1040 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1043 emit_if (struct jcf_block
*target
, int opcode
, int inv_opcode
,
1044 struct jcf_partial
*state
)
1048 /* value is 1 byte from reloc back to start of instruction. */
1049 emit_reloc (RELOCATION_VALUE_1
, - inv_opcode
, target
, state
);
1053 emit_goto (struct jcf_block
*target
, struct jcf_partial
*state
)
1057 /* Value is 1 byte from reloc back to start of instruction. */
1058 emit_reloc (RELOCATION_VALUE_1
, OPCODE_goto_w
, target
, state
);
1062 emit_jsr (struct jcf_block
*target
, struct jcf_partial
*state
)
1066 /* Value is 1 byte from reloc back to start of instruction. */
1067 emit_reloc (RELOCATION_VALUE_1
, OPCODE_jsr_w
, target
, state
);
1071 /* Generate code to evaluate EXP. If the result is true,
1072 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1073 TRUE_BRANCH_FIRST is a code generation hint that the
1074 TRUE_LABEL may follow right after this. (The idea is that we
1075 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1078 generate_bytecode_conditional (tree exp
,
1079 struct jcf_block
*true_label
,
1080 struct jcf_block
*false_label
,
1081 int true_branch_first
,
1082 struct jcf_partial
*state
)
1084 tree exp0
, exp1
, type
;
1085 int save_SP
= state
->code_SP
;
1086 enum java_opcode op
, negop
;
1087 switch (TREE_CODE (exp
))
1090 emit_goto (integer_zerop (exp
) ? false_label
: true_label
, state
);
1094 struct jcf_block
*then_label
= gen_jcf_label (state
);
1095 struct jcf_block
*else_label
= gen_jcf_label (state
);
1096 int save_SP_before
, save_SP_after
;
1097 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1098 then_label
, else_label
, 1, state
);
1099 define_jcf_label (then_label
, state
);
1100 save_SP_before
= state
->code_SP
;
1101 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1102 true_label
, false_label
, 1, state
);
1103 save_SP_after
= state
->code_SP
;
1104 state
->code_SP
= save_SP_before
;
1105 define_jcf_label (else_label
, state
);
1106 generate_bytecode_conditional (TREE_OPERAND (exp
, 2),
1107 true_label
, false_label
,
1108 true_branch_first
, state
);
1109 if (state
->code_SP
!= save_SP_after
)
1113 case TRUTH_NOT_EXPR
:
1114 generate_bytecode_conditional (TREE_OPERAND (exp
, 0), false_label
,
1115 true_label
, ! true_branch_first
, state
);
1117 case TRUTH_ANDIF_EXPR
:
1119 struct jcf_block
*next_label
= gen_jcf_label (state
);
1120 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1121 next_label
, false_label
, 1, state
);
1122 define_jcf_label (next_label
, state
);
1123 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1124 true_label
, false_label
, 1, state
);
1127 case TRUTH_ORIF_EXPR
:
1129 struct jcf_block
*next_label
= gen_jcf_label (state
);
1130 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1131 true_label
, next_label
, 1, state
);
1132 define_jcf_label (next_label
, state
);
1133 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1134 true_label
, false_label
, 1, state
);
1138 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1139 set it to the corresponding 1-operand if<COND> instructions. */
1143 /* The opcodes with their inverses are allocated in pairs.
1144 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1145 negop
= (op
& 1) ? op
+ 1 : op
- 1;
1147 if (true_branch_first
)
1149 emit_if (false_label
, negop
, op
, state
);
1150 emit_goto (true_label
, state
);
1154 emit_if (true_label
, op
, negop
, state
);
1155 emit_goto (false_label
, state
);
1159 op
= OPCODE_if_icmpeq
;
1162 op
= OPCODE_if_icmpne
;
1165 op
= OPCODE_if_icmpgt
;
1168 op
= OPCODE_if_icmplt
;
1171 op
= OPCODE_if_icmpge
;
1174 op
= OPCODE_if_icmple
;
1177 exp0
= TREE_OPERAND (exp
, 0);
1178 exp1
= TREE_OPERAND (exp
, 1);
1179 type
= TREE_TYPE (exp0
);
1180 switch (TREE_CODE (type
))
1183 case POINTER_TYPE
: case RECORD_TYPE
:
1184 switch (TREE_CODE (exp
))
1186 case EQ_EXPR
: op
= OPCODE_if_acmpeq
; break;
1187 case NE_EXPR
: op
= OPCODE_if_acmpne
; break;
1190 if (integer_zerop (exp1
) || integer_zerop (exp0
))
1192 generate_bytecode_insns (integer_zerop (exp0
) ? exp1
: exp0
,
1193 STACK_TARGET
, state
);
1194 op
= op
+ (OPCODE_ifnull
- OPCODE_if_acmpeq
);
1195 negop
= (op
& 1) ? op
- 1 : op
+ 1;
1199 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1200 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1204 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1205 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1206 if (op
== OPCODE_if_icmplt
|| op
== OPCODE_if_icmple
)
1210 if (TYPE_PRECISION (type
) > 32)
1221 if (TYPE_PRECISION (type
) > 32)
1223 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1224 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1232 if (integer_zerop (exp1
))
1234 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1238 if (integer_zerop (exp0
))
1242 case OPCODE_if_icmplt
:
1243 case OPCODE_if_icmpge
:
1246 case OPCODE_if_icmpgt
:
1247 case OPCODE_if_icmple
:
1253 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1257 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1258 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1264 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1266 if (true_branch_first
)
1268 emit_if (false_label
, OPCODE_ifeq
, OPCODE_ifne
, state
);
1269 emit_goto (true_label
, state
);
1273 emit_if (true_label
, OPCODE_ifne
, OPCODE_ifeq
, state
);
1274 emit_goto (false_label
, state
);
1278 if (save_SP
!= state
->code_SP
)
1282 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1283 but only as far out as LIMIT (since we are about to jump to the
1284 emit label that is LIMIT). */
1287 call_cleanups (struct jcf_block
*limit
, struct jcf_partial
*state
)
1289 struct jcf_block
*block
= state
->labeled_blocks
;
1290 for (; block
!= limit
; block
= block
->next
)
1292 if (block
->pc
== PENDING_CLEANUP_PC
)
1293 emit_jsr (block
, state
);
1298 generate_bytecode_return (tree exp
, struct jcf_partial
*state
)
1300 tree return_type
= TREE_TYPE (TREE_TYPE (state
->current_method
));
1301 int returns_void
= TREE_CODE (return_type
) == VOID_TYPE
;
1306 switch (TREE_CODE (exp
))
1309 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
,
1311 exp
= TREE_OPERAND (exp
, 1);
1315 struct jcf_block
*then_label
= gen_jcf_label (state
);
1316 struct jcf_block
*else_label
= gen_jcf_label (state
);
1317 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1318 then_label
, else_label
, 1, state
);
1319 define_jcf_label (then_label
, state
);
1320 generate_bytecode_return (TREE_OPERAND (exp
, 1), state
);
1321 define_jcf_label (else_label
, state
);
1322 generate_bytecode_return (TREE_OPERAND (exp
, 2), state
);
1326 generate_bytecode_insns (exp
,
1327 returns_void
? IGNORE_TARGET
1328 : STACK_TARGET
, state
);
1334 call_cleanups (NULL
, state
);
1338 op
= OPCODE_ireturn
+ adjust_typed_op (return_type
, 4);
1339 if (state
->num_finalizers
> 0)
1341 if (state
->return_value_decl
== NULL_TREE
)
1343 state
->return_value_decl
1344 = build_decl (VAR_DECL
, NULL_TREE
, TREE_TYPE (exp
));
1345 localvar_alloc (state
->return_value_decl
, state
);
1347 emit_store (state
->return_value_decl
, state
);
1348 call_cleanups (NULL
, state
);
1349 emit_load (state
->return_value_decl
, state
);
1350 /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
1351 then we risk the save decl erroneously re-used in the
1352 finalizer. Instead, we keep the state->return_value_decl
1353 allocated through the rest of the method. This is not
1354 the greatest solution, but it is at least simple and safe. */
1361 /* Generate bytecode for sub-expression EXP of METHOD.
1362 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1365 generate_bytecode_insns (tree exp
, int target
, struct jcf_partial
*state
)
1368 enum java_opcode jopcode
;
1370 HOST_WIDE_INT value
;
1375 if (exp
== NULL
&& target
== IGNORE_TARGET
)
1378 type
= TREE_TYPE (exp
);
1380 switch (TREE_CODE (exp
))
1383 if (BLOCK_EXPR_BODY (exp
))
1386 tree body
= BLOCK_EXPR_BODY (exp
);
1387 long jsrs
= state
->num_jsrs
;
1388 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1390 tree next
= TREE_CHAIN (local
);
1391 localvar_alloc (local
, state
);
1394 /* Avoid deep recursion for long blocks. */
1395 while (TREE_CODE (body
) == COMPOUND_EXPR
)
1397 generate_bytecode_insns (TREE_OPERAND (body
, 0), target
, state
);
1398 body
= TREE_OPERAND (body
, 1);
1400 generate_bytecode_insns (body
, target
, state
);
1402 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1404 tree next
= TREE_CHAIN (local
);
1405 maybe_free_localvar (local
, state
, state
->num_jsrs
<= jsrs
);
1411 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
1412 /* Normally the first operand to a COMPOUND_EXPR must complete
1413 normally. However, in the special case of a do-while
1414 statement this is not necessarily the case. */
1415 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 0)))
1416 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1418 case EXPR_WITH_FILE_LOCATION
:
1420 location_t saved_location
= input_location
;
1421 tree body
= EXPR_WFL_NODE (exp
);
1422 if (body
== empty_stmt_node
)
1424 input_filename
= EXPR_WFL_FILENAME (exp
);
1425 input_line
= EXPR_WFL_LINENO (exp
);
1426 if (EXPR_WFL_EMIT_LINE_NOTE (exp
) && input_line
> 0
1427 && debug_info_level
> DINFO_LEVEL_NONE
)
1428 put_linenumber (input_line
, state
);
1429 generate_bytecode_insns (body
, target
, state
);
1430 input_location
= saved_location
;
1434 if (target
== IGNORE_TARGET
) ; /* do nothing */
1435 else if (TREE_CODE (type
) == POINTER_TYPE
)
1437 if (! integer_zerop (exp
))
1440 OP1 (OPCODE_aconst_null
);
1443 else if (TYPE_PRECISION (type
) <= 32)
1445 push_int_const (TREE_INT_CST_LOW (exp
), state
);
1450 push_long_const (TREE_INT_CST_LOW (exp
), TREE_INT_CST_HIGH (exp
),
1457 int prec
= TYPE_PRECISION (type
) >> 5;
1459 if (real_zerop (exp
) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp
)))
1460 OP1 (prec
== 1 ? OPCODE_fconst_0
: OPCODE_dconst_0
);
1461 else if (real_onep (exp
))
1462 OP1 (prec
== 1 ? OPCODE_fconst_1
: OPCODE_dconst_1
);
1463 else if (prec
== 1 && real_twop (exp
))
1464 OP1 (OPCODE_fconst_2
);
1465 /* ??? We could also use iconst_3/ldc followed by i2f/i2d
1466 for other float/double when the value is a small integer. */
1469 offset
= find_constant_index (exp
, state
);
1471 push_constant1 (offset
, state
);
1473 push_constant2 (offset
, state
);
1479 push_constant1 (find_string_constant (&state
->cpool
, exp
), state
);
1483 if (TREE_STATIC (exp
))
1485 field_op (exp
, OPCODE_getstatic
, state
);
1486 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1489 /* ... fall through ... */
1491 emit_load (exp
, state
);
1493 case NON_LVALUE_EXPR
:
1495 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1498 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1499 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1500 if (target
!= IGNORE_TARGET
)
1502 jopcode
= OPCODE_iaload
+ adjust_typed_op (type
, 7);
1505 if (! TYPE_IS_WIDE (type
))
1511 tree obj
= TREE_OPERAND (exp
, 0);
1512 tree field
= TREE_OPERAND (exp
, 1);
1513 int is_static
= FIELD_STATIC (field
);
1514 generate_bytecode_insns (obj
,
1515 is_static
? IGNORE_TARGET
: target
, state
);
1516 if (target
!= IGNORE_TARGET
)
1518 if (DECL_NAME (field
) == length_identifier_node
&& !is_static
1519 && TYPE_ARRAY_P (TREE_TYPE (obj
)))
1522 OP1 (OPCODE_arraylength
);
1526 field_op (field
, is_static
? OPCODE_getstatic
: OPCODE_getfield
,
1530 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1535 case TRUTH_ANDIF_EXPR
:
1536 case TRUTH_ORIF_EXPR
:
1544 struct jcf_block
*then_label
= gen_jcf_label (state
);
1545 struct jcf_block
*else_label
= gen_jcf_label (state
);
1546 struct jcf_block
*end_label
= gen_jcf_label (state
);
1547 generate_bytecode_conditional (exp
,
1548 then_label
, else_label
, 1, state
);
1549 define_jcf_label (then_label
, state
);
1550 push_int_const (1, state
);
1551 emit_goto (end_label
, state
);
1552 define_jcf_label (else_label
, state
);
1553 push_int_const (0, state
);
1554 define_jcf_label (end_label
, state
);
1560 struct jcf_block
*then_label
= gen_jcf_label (state
);
1561 struct jcf_block
*else_label
= gen_jcf_label (state
);
1562 struct jcf_block
*end_label
= gen_jcf_label (state
);
1563 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1564 then_label
, else_label
, 1, state
);
1565 define_jcf_label (then_label
, state
);
1566 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1567 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 1))
1568 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1569 || TREE_CODE (TREE_TYPE (exp
)) != VOID_TYPE
)
1570 emit_goto (end_label
, state
);
1571 define_jcf_label (else_label
, state
);
1572 generate_bytecode_insns (TREE_OPERAND (exp
, 2), target
, state
);
1573 define_jcf_label (end_label
, state
);
1574 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1575 if (TREE_TYPE (exp
) != void_type_node
)
1576 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1581 struct jcf_switch_state
*sw_state
= state
->sw_state
;
1582 struct jcf_relocation
*reloc
1583 = obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1584 HOST_WIDE_INT case_value
= TREE_INT_CST_LOW (TREE_OPERAND (exp
, 0));
1586 reloc
->label
= get_jcf_label_here (state
);
1587 reloc
->offset
= case_value
;
1588 reloc
->next
= sw_state
->cases
;
1589 sw_state
->cases
= reloc
;
1590 if (sw_state
->num_cases
== 0)
1592 sw_state
->min_case
= case_value
;
1593 sw_state
->max_case
= case_value
;
1597 if (case_value
< sw_state
->min_case
)
1598 sw_state
->min_case
= case_value
;
1599 if (case_value
> sw_state
->max_case
)
1600 sw_state
->max_case
= case_value
;
1602 sw_state
->num_cases
++;
1606 state
->sw_state
->default_label
= get_jcf_label_here (state
);
1611 /* The SWITCH_EXPR has three parts, generated in the following order:
1612 1. the switch_expression (the value used to select the correct case);
1614 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1615 After code generation, we will re-order them in the order 1, 3, 2.
1616 This is to avoid any extra GOTOs. */
1617 struct jcf_switch_state sw_state
;
1618 struct jcf_block
*expression_last
; /* Last block of the switch_expression. */
1619 struct jcf_block
*body_last
; /* Last block of the switch_body. */
1620 struct jcf_block
*switch_instruction
; /* First block of switch_instruction. */
1621 struct jcf_block
*instruction_last
; /* Last block of the switch_instruction. */
1622 struct jcf_block
*body_block
;
1624 sw_state
.prev
= state
->sw_state
;
1625 state
->sw_state
= &sw_state
;
1626 sw_state
.cases
= NULL
;
1627 sw_state
.num_cases
= 0;
1628 sw_state
.default_label
= NULL
;
1629 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1630 expression_last
= state
->last_block
;
1631 /* Force a new block here. */
1632 body_block
= gen_jcf_label (state
);
1633 define_jcf_label (body_block
, state
);
1634 generate_bytecode_insns (TREE_OPERAND (exp
, 1), IGNORE_TARGET
, state
);
1635 body_last
= state
->last_block
;
1637 switch_instruction
= gen_jcf_label (state
);
1638 define_jcf_label (switch_instruction
, state
);
1639 if (sw_state
.default_label
== NULL
)
1640 sw_state
.default_label
= gen_jcf_label (state
);
1642 if (sw_state
.num_cases
<= 1)
1644 if (sw_state
.num_cases
== 0)
1646 emit_pop (1, state
);
1651 push_int_const (sw_state
.cases
->offset
, state
);
1653 emit_if (sw_state
.cases
->label
,
1654 OPCODE_if_icmpeq
, OPCODE_if_icmpne
, state
);
1656 emit_goto (sw_state
.default_label
, state
);
1661 unsigned HOST_WIDE_INT delta
;
1662 /* Copy the chain of relocs into a sorted array. */
1663 struct jcf_relocation
**relocs
1664 = xmalloc (sw_state
.num_cases
* sizeof (struct jcf_relocation
*));
1665 /* The relocs arrays is a buffer with a gap.
1666 The assumption is that cases will normally come in "runs". */
1668 int gap_end
= sw_state
.num_cases
;
1669 struct jcf_relocation
*reloc
;
1670 for (reloc
= sw_state
.cases
; reloc
!= NULL
; reloc
= reloc
->next
)
1672 HOST_WIDE_INT case_value
= reloc
->offset
;
1673 while (gap_end
< sw_state
.num_cases
)
1675 struct jcf_relocation
*end
= relocs
[gap_end
];
1676 if (case_value
<= end
->offset
)
1678 relocs
[gap_start
++] = end
;
1681 while (gap_start
> 0)
1683 struct jcf_relocation
*before
= relocs
[gap_start
-1];
1684 if (case_value
>= before
->offset
)
1686 relocs
[--gap_end
] = before
;
1689 relocs
[gap_start
++] = reloc
;
1690 /* Note we don't check for duplicates. This is
1691 handled by the parser. */
1694 /* We could have DELTA < 0 if sw_state.min_case is
1695 something like Integer.MIN_VALUE. That is why delta is
1697 delta
= sw_state
.max_case
- sw_state
.min_case
;
1698 if (2 * (unsigned) sw_state
.num_cases
>= delta
)
1699 { /* Use tableswitch. */
1701 RESERVE (13 + 4 * (sw_state
.max_case
- sw_state
.min_case
+ 1));
1702 OP1 (OPCODE_tableswitch
);
1703 emit_reloc (RELOCATION_VALUE_0
,
1704 SWITCH_ALIGN_RELOC
, NULL
, state
);
1705 emit_switch_reloc (sw_state
.default_label
, state
);
1706 OP4 (sw_state
.min_case
);
1707 OP4 (sw_state
.max_case
);
1708 for (i
= sw_state
.min_case
; ; )
1710 reloc
= relocs
[index
];
1711 if (i
== reloc
->offset
)
1713 emit_case_reloc (reloc
, state
);
1714 if (i
== sw_state
.max_case
)
1719 emit_switch_reloc (sw_state
.default_label
, state
);
1724 { /* Use lookupswitch. */
1725 RESERVE(9 + 8 * sw_state
.num_cases
);
1726 OP1 (OPCODE_lookupswitch
);
1727 emit_reloc (RELOCATION_VALUE_0
,
1728 SWITCH_ALIGN_RELOC
, NULL
, state
);
1729 emit_switch_reloc (sw_state
.default_label
, state
);
1730 OP4 (sw_state
.num_cases
);
1731 for (i
= 0; i
< sw_state
.num_cases
; i
++)
1733 struct jcf_relocation
*reloc
= relocs
[i
];
1734 OP4 (reloc
->offset
);
1735 emit_case_reloc (reloc
, state
);
1741 instruction_last
= state
->last_block
;
1742 if (sw_state
.default_label
->pc
< 0)
1743 define_jcf_label (sw_state
.default_label
, state
);
1744 else /* Force a new block. */
1745 sw_state
.default_label
= get_jcf_label_here (state
);
1746 /* Now re-arrange the blocks so the switch_instruction
1747 comes before the switch_body. */
1748 switch_length
= state
->code_length
- switch_instruction
->pc
;
1749 switch_instruction
->pc
= body_block
->pc
;
1750 instruction_last
->next
= body_block
;
1751 instruction_last
->v
.chunk
->next
= body_block
->v
.chunk
;
1752 expression_last
->next
= switch_instruction
;
1753 expression_last
->v
.chunk
->next
= switch_instruction
->v
.chunk
;
1754 body_last
->next
= sw_state
.default_label
;
1755 body_last
->v
.chunk
->next
= NULL
;
1756 state
->chunk
= body_last
->v
.chunk
;
1757 for (; body_block
!= sw_state
.default_label
; body_block
= body_block
->next
)
1758 body_block
->pc
+= switch_length
;
1760 state
->sw_state
= sw_state
.prev
;
1765 exp
= TREE_OPERAND (exp
, 0);
1766 if (exp
== NULL_TREE
)
1767 exp
= empty_stmt_node
;
1768 else if (TREE_CODE (exp
) != MODIFY_EXPR
)
1771 exp
= TREE_OPERAND (exp
, 1);
1772 generate_bytecode_return (exp
, state
);
1774 case LABELED_BLOCK_EXPR
:
1776 struct jcf_block
*end_label
= gen_jcf_label (state
);
1777 end_label
->next
= state
->labeled_blocks
;
1778 state
->labeled_blocks
= end_label
;
1779 end_label
->pc
= PENDING_EXIT_PC
;
1780 end_label
->u
.labeled_block
= exp
;
1781 if (LABELED_BLOCK_BODY (exp
))
1782 generate_bytecode_insns (LABELED_BLOCK_BODY (exp
), target
, state
);
1783 if (state
->labeled_blocks
!= end_label
)
1785 state
->labeled_blocks
= end_label
->next
;
1786 define_jcf_label (end_label
, state
);
1791 tree body
= TREE_OPERAND (exp
, 0);
1793 if (TREE_CODE (body
) == COMPOUND_EXPR
1794 && TREE_CODE (TREE_OPERAND (body
, 0)) == EXIT_EXPR
)
1796 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1797 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1798 struct jcf_block
*head_label
;
1799 struct jcf_block
*body_label
;
1800 struct jcf_block
*end_label
= gen_jcf_label (state
);
1801 struct jcf_block
*exit_label
= state
->labeled_blocks
;
1802 head_label
= gen_jcf_label (state
);
1803 emit_goto (head_label
, state
);
1804 body_label
= get_jcf_label_here (state
);
1805 generate_bytecode_insns (TREE_OPERAND (body
, 1), target
, state
);
1806 define_jcf_label (head_label
, state
);
1807 generate_bytecode_conditional (TREE_OPERAND (body
, 0),
1808 end_label
, body_label
, 1, state
);
1809 define_jcf_label (end_label
, state
);
1814 struct jcf_block
*head_label
= get_jcf_label_here (state
);
1815 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1816 if (CAN_COMPLETE_NORMALLY (body
))
1817 emit_goto (head_label
, state
);
1823 struct jcf_block
*label
= state
->labeled_blocks
;
1824 struct jcf_block
*end_label
= gen_jcf_label (state
);
1825 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1826 label
, end_label
, 0, state
);
1827 define_jcf_label (end_label
, state
);
1830 case EXIT_BLOCK_EXPR
:
1832 struct jcf_block
*label
= state
->labeled_blocks
;
1833 if (TREE_OPERAND (exp
, 1) != NULL
) goto notimpl
;
1834 while (label
->u
.labeled_block
!= TREE_OPERAND (exp
, 0))
1835 label
= label
->next
;
1836 call_cleanups (label
, state
);
1837 emit_goto (label
, state
);
1841 case PREDECREMENT_EXPR
: value
= -1; post_op
= 0; goto increment
;
1842 case PREINCREMENT_EXPR
: value
= 1; post_op
= 0; goto increment
;
1843 case POSTDECREMENT_EXPR
: value
= -1; post_op
= 1; goto increment
;
1844 case POSTINCREMENT_EXPR
: value
= 1; post_op
= 1; goto increment
;
1847 arg
= TREE_OPERAND (exp
, 1);
1848 exp
= TREE_OPERAND (exp
, 0);
1849 type
= TREE_TYPE (exp
);
1850 size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1851 if ((TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1852 && ! TREE_STATIC (exp
)
1853 && TREE_CODE (type
) == INTEGER_TYPE
1854 && TYPE_PRECISION (type
) == 32)
1856 if (target
!= IGNORE_TARGET
&& post_op
)
1857 emit_load (exp
, state
);
1858 emit_iinc (exp
, value
, state
);
1859 if (target
!= IGNORE_TARGET
&& ! post_op
)
1860 emit_load (exp
, state
);
1863 if (TREE_CODE (exp
) == COMPONENT_REF
)
1865 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1866 emit_dup (1, 0, state
);
1867 /* Stack: ..., objectref, objectref. */
1868 field_op (TREE_OPERAND (exp
, 1), OPCODE_getfield
, state
);
1870 /* Stack: ..., objectref, oldvalue. */
1873 else if (TREE_CODE (exp
) == ARRAY_REF
)
1875 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1876 generate_bytecode_insns (TREE_OPERAND (exp
, 1), STACK_TARGET
, state
);
1877 emit_dup (2, 0, state
);
1878 /* Stack: ..., array, index, array, index. */
1879 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (exp
), 7);
1883 /* Stack: ..., array, index, oldvalue. */
1886 else if (TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1888 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1889 /* Stack: ..., oldvalue. */
1895 if (target
!= IGNORE_TARGET
&& post_op
)
1896 emit_dup (size
, offset
, state
);
1897 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1898 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1899 /* Stack, otherwise: ..., [result, ] oldvalue. */
1900 generate_bytecode_insns (arg
, STACK_TARGET
, state
);
1901 emit_binop ((value
>= 0 ? OPCODE_iadd
: OPCODE_isub
)
1902 + adjust_typed_op (type
, 3),
1904 if (target
!= IGNORE_TARGET
&& ! post_op
)
1905 emit_dup (size
, offset
, state
);
1906 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1907 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1908 /* Stack, otherwise: ..., [result, ] newvalue. */
1909 goto finish_assignment
;
1913 tree lhs
= TREE_OPERAND (exp
, 0);
1914 tree rhs
= TREE_OPERAND (exp
, 1);
1917 /* See if we can use the iinc instruction. */
1918 if ((TREE_CODE (lhs
) == VAR_DECL
|| TREE_CODE (lhs
) == PARM_DECL
)
1919 && ! TREE_STATIC (lhs
)
1920 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
1921 && TYPE_PRECISION (TREE_TYPE (lhs
)) == 32
1922 && (TREE_CODE (rhs
) == PLUS_EXPR
|| TREE_CODE (rhs
) == MINUS_EXPR
))
1924 tree arg0
= TREE_OPERAND (rhs
, 0);
1925 tree arg1
= TREE_OPERAND (rhs
, 1);
1926 HOST_WIDE_INT min_value
= -32768;
1927 HOST_WIDE_INT max_value
= 32767;
1928 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1933 else if (arg1
== lhs
)
1936 arg1
= TREE_OPERAND (rhs
, 0);
1938 if (lhs
== arg0
&& TREE_CODE (arg1
) == INTEGER_CST
)
1940 HOST_WIDE_INT hi_value
= TREE_INT_CST_HIGH (arg1
);
1941 value
= TREE_INT_CST_LOW (arg1
);
1942 if ((hi_value
== 0 && value
<= max_value
)
1943 || (hi_value
== -1 && value
>= min_value
))
1945 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1947 emit_iinc (lhs
, value
, state
);
1948 if (target
!= IGNORE_TARGET
)
1949 emit_load (lhs
, state
);
1955 if (TREE_CODE (lhs
) == COMPONENT_REF
)
1957 generate_bytecode_insns (TREE_OPERAND (lhs
, 0),
1958 STACK_TARGET
, state
);
1961 else if (TREE_CODE (lhs
) == ARRAY_REF
)
1963 generate_bytecode_insns (TREE_OPERAND(lhs
, 0),
1964 STACK_TARGET
, state
);
1965 generate_bytecode_insns (TREE_OPERAND(lhs
, 1),
1966 STACK_TARGET
, state
);
1972 /* If the rhs is a binary expression and the left operand is
1973 `==' to the lhs then we have an OP= expression. In this
1974 case we must do some special processing. */
1975 if (TREE_CODE_CLASS (TREE_CODE (rhs
)) == '2'
1976 && lhs
== TREE_OPERAND (rhs
, 0))
1978 if (TREE_CODE (lhs
) == COMPONENT_REF
)
1980 tree field
= TREE_OPERAND (lhs
, 1);
1981 if (! FIELD_STATIC (field
))
1983 /* Duplicate the object reference so we can get
1985 emit_dup (TYPE_IS_WIDE (field
) ? 2 : 1, 0, state
);
1988 field_op (field
, (FIELD_STATIC (field
)
1993 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1995 else if (TREE_CODE (lhs
) == VAR_DECL
1996 || TREE_CODE (lhs
) == PARM_DECL
)
1998 if (FIELD_STATIC (lhs
))
2000 field_op (lhs
, OPCODE_getstatic
, state
);
2001 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs
)) ? 2 : 1);
2004 emit_load (lhs
, state
);
2006 else if (TREE_CODE (lhs
) == ARRAY_REF
)
2008 /* Duplicate the array and index, which are on the
2009 stack, so that we can load the old value. */
2010 emit_dup (2, 0, state
);
2012 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (lhs
), 7);
2015 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs
)) ? 2 : 1);
2020 /* This function correctly handles the case where the LHS
2021 of a binary expression is NULL_TREE. */
2022 rhs
= build (TREE_CODE (rhs
), TREE_TYPE (rhs
),
2023 NULL_TREE
, TREE_OPERAND (rhs
, 1));
2026 generate_bytecode_insns (rhs
, STACK_TARGET
, state
);
2027 if (target
!= IGNORE_TARGET
)
2028 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1 , offset
, state
);
2034 if (TREE_CODE (exp
) == COMPONENT_REF
)
2036 tree field
= TREE_OPERAND (exp
, 1);
2037 if (! FIELD_STATIC (field
))
2040 FIELD_STATIC (field
) ? OPCODE_putstatic
: OPCODE_putfield
,
2043 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
2045 else if (TREE_CODE (exp
) == VAR_DECL
2046 || TREE_CODE (exp
) == PARM_DECL
)
2048 if (FIELD_STATIC (exp
))
2050 field_op (exp
, OPCODE_putstatic
, state
);
2051 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
2054 emit_store (exp
, state
);
2056 else if (TREE_CODE (exp
) == ARRAY_REF
)
2058 jopcode
= OPCODE_iastore
+ adjust_typed_op (TREE_TYPE (exp
), 7);
2061 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 4 : 3);
2067 jopcode
= OPCODE_iadd
;
2070 jopcode
= OPCODE_isub
;
2073 jopcode
= OPCODE_imul
;
2075 case TRUNC_DIV_EXPR
:
2077 jopcode
= OPCODE_idiv
;
2079 case TRUNC_MOD_EXPR
:
2080 jopcode
= OPCODE_irem
;
2082 case LSHIFT_EXPR
: jopcode
= OPCODE_ishl
; goto binop
;
2083 case RSHIFT_EXPR
: jopcode
= OPCODE_ishr
; goto binop
;
2084 case URSHIFT_EXPR
: jopcode
= OPCODE_iushr
; goto binop
;
2085 case TRUTH_AND_EXPR
:
2086 case BIT_AND_EXPR
: jopcode
= OPCODE_iand
; goto binop
;
2088 case BIT_IOR_EXPR
: jopcode
= OPCODE_ior
; goto binop
;
2089 case TRUTH_XOR_EXPR
:
2090 case BIT_XOR_EXPR
: jopcode
= OPCODE_ixor
; goto binop
;
2093 tree arg0
= TREE_OPERAND (exp
, 0);
2094 tree arg1
= TREE_OPERAND (exp
, 1);
2095 jopcode
+= adjust_typed_op (type
, 3);
2096 if (arg0
!= NULL_TREE
&& operand_equal_p (arg0
, arg1
, 0))
2098 /* fold may (e.g) convert 2*x to x+x. */
2099 generate_bytecode_insns (arg0
, target
, state
);
2100 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0
)) > 32 ? 2 : 1, 0, state
);
2104 /* ARG0 will be NULL_TREE if we're handling an `OP='
2105 expression. In this case the stack already holds the
2106 LHS. See the MODIFY_EXPR case. */
2107 if (arg0
!= NULL_TREE
)
2108 generate_bytecode_insns (arg0
, target
, state
);
2109 if (jopcode
>= OPCODE_lshl
&& jopcode
<= OPCODE_lushr
)
2110 arg1
= convert (int_type_node
, arg1
);
2111 generate_bytecode_insns (arg1
, target
, state
);
2113 /* For most binary operations, both operands and the result have the
2114 same type. Shift operations are different. Using arg1's type
2115 gets us the correct SP adjustment in all cases. */
2116 if (target
== STACK_TARGET
)
2117 emit_binop (jopcode
, TREE_TYPE (arg1
), state
);
2120 case TRUTH_NOT_EXPR
:
2122 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2123 if (target
== STACK_TARGET
)
2125 int is_long
= TYPE_PRECISION (TREE_TYPE (exp
)) > 32;
2126 push_int_const (TREE_CODE (exp
) == BIT_NOT_EXPR
? -1 : 1, state
);
2130 NOTE_PUSH (1 + is_long
);
2131 OP1 (OPCODE_ixor
+ is_long
);
2132 NOTE_POP (1 + is_long
);
2136 jopcode
= OPCODE_ineg
;
2137 jopcode
+= adjust_typed_op (type
, 3);
2138 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2139 if (target
== STACK_TARGET
)
2140 emit_unop (jopcode
, type
, state
);
2142 case INSTANCEOF_EXPR
:
2144 int index
= find_class_constant (&state
->cpool
, TREE_OPERAND (exp
, 1));
2145 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2147 OP1 (OPCODE_instanceof
);
2152 /* Because the state associated with a SAVE_EXPR tree node must
2153 be a RTL expression, we use it to store the DECL_LOCAL_INDEX
2154 of a temporary variable in a CONST_INT. */
2155 if (! SAVE_EXPR_RTL (exp
))
2157 tree type
= TREE_TYPE (exp
);
2158 tree decl
= build_decl (VAR_DECL
, NULL_TREE
, type
);
2159 generate_bytecode_insns (TREE_OPERAND (exp
, 0),
2160 STACK_TARGET
, state
);
2161 localvar_alloc (decl
, state
);
2162 SAVE_EXPR_RTL (exp
) = GEN_INT (DECL_LOCAL_INDEX (decl
));
2163 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1, 0, state
);
2164 emit_store (decl
, state
);
2168 /* The following code avoids creating a temporary DECL just
2169 to pass to emit_load. This code could be factored with
2170 the similar implementation in emit_load_or_store. */
2171 tree type
= TREE_TYPE (exp
);
2172 int kind
= adjust_typed_op (type
, 4);
2173 int index
= (int) INTVAL (SAVE_EXPR_RTL (exp
));
2176 RESERVE (1); /* [ilfda]load_[0123] */
2177 OP1 (OPCODE_iload
+ 5 + 4*kind
+ index
);
2179 else /* [ilfda]load */
2180 maybe_wide (OPCODE_iload
+ kind
, index
, state
);
2181 NOTE_PUSH (TYPE_IS_WIDE (type
) ? 2 : 1);
2187 case FIX_TRUNC_EXPR
:
2189 tree src
= TREE_OPERAND (exp
, 0);
2190 tree src_type
= TREE_TYPE (src
);
2191 tree dst_type
= TREE_TYPE (exp
);
2192 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2193 if (target
== IGNORE_TARGET
|| src_type
== dst_type
)
2195 if (TREE_CODE (dst_type
) == POINTER_TYPE
)
2197 if (TREE_CODE (exp
) == CONVERT_EXPR
)
2199 int index
= find_class_constant (&state
->cpool
,
2200 TREE_TYPE (dst_type
));
2202 OP1 (OPCODE_checkcast
);
2206 else /* Convert numeric types. */
2208 int wide_src
= TYPE_PRECISION (src_type
) > 32;
2209 int wide_dst
= TYPE_PRECISION (dst_type
) > 32;
2210 NOTE_POP (1 + wide_src
);
2212 if (TREE_CODE (dst_type
) == REAL_TYPE
)
2214 if (TREE_CODE (src_type
) == REAL_TYPE
)
2215 OP1 (wide_dst
? OPCODE_f2d
: OPCODE_d2f
);
2216 else if (TYPE_PRECISION (src_type
) == 64)
2217 OP1 (OPCODE_l2f
+ wide_dst
);
2219 OP1 (OPCODE_i2f
+ wide_dst
);
2221 else /* Convert to integral type. */
2223 if (TREE_CODE (src_type
) == REAL_TYPE
)
2224 OP1 (OPCODE_f2i
+ wide_dst
+ 3 * wide_src
);
2229 if (TYPE_PRECISION (dst_type
) < 32)
2232 /* Already converted to int, if needed. */
2233 if (TYPE_PRECISION (dst_type
) <= 8)
2235 else if (TREE_UNSIGNED (dst_type
))
2241 NOTE_PUSH (1 + wide_dst
);
2248 tree try_clause
= TREE_OPERAND (exp
, 0);
2249 struct jcf_block
*start_label
= get_jcf_label_here (state
);
2250 struct jcf_block
*end_label
; /* End of try clause. */
2251 struct jcf_block
*finished_label
= gen_jcf_label (state
);
2252 tree clause
= TREE_OPERAND (exp
, 1);
2253 if (target
!= IGNORE_TARGET
)
2255 generate_bytecode_insns (try_clause
, IGNORE_TARGET
, state
);
2256 end_label
= get_jcf_label_here (state
);
2257 if (end_label
== start_label
)
2259 if (CAN_COMPLETE_NORMALLY (try_clause
))
2260 emit_goto (finished_label
, state
);
2261 while (clause
!= NULL_TREE
)
2263 tree catch_clause
= TREE_OPERAND (clause
, 0);
2264 tree exception_decl
= BLOCK_EXPR_DECLS (catch_clause
);
2265 struct jcf_handler
*handler
= alloc_handler (start_label
,
2267 if (exception_decl
== NULL_TREE
)
2268 handler
->type
= NULL_TREE
;
2270 handler
->type
= TREE_TYPE (TREE_TYPE (exception_decl
));
2271 generate_bytecode_insns (catch_clause
, IGNORE_TARGET
, state
);
2272 clause
= TREE_CHAIN (clause
);
2273 if (CAN_COMPLETE_NORMALLY (catch_clause
) && clause
!= NULL_TREE
)
2274 emit_goto (finished_label
, state
);
2276 define_jcf_label (finished_label
, state
);
2280 case TRY_FINALLY_EXPR
:
2282 struct jcf_block
*finished_label
= NULL
;
2283 struct jcf_block
*finally_label
, *start_label
, *end_label
;
2284 struct jcf_handler
*handler
;
2285 tree try_block
= TREE_OPERAND (exp
, 0);
2286 tree finally
= TREE_OPERAND (exp
, 1);
2287 tree return_link
= NULL_TREE
, exception_decl
= NULL_TREE
;
2289 tree exception_type
;
2291 finally_label
= gen_jcf_label (state
);
2292 start_label
= get_jcf_label_here (state
);
2293 /* If the `finally' clause can complete normally, we emit it
2294 as a subroutine and let the other clauses call it via
2295 `jsr'. If it can't complete normally, then we simply emit
2296 `goto's directly to it. */
2297 if (CAN_COMPLETE_NORMALLY (finally
))
2299 finally_label
->pc
= PENDING_CLEANUP_PC
;
2300 finally_label
->next
= state
->labeled_blocks
;
2301 state
->labeled_blocks
= finally_label
;
2302 state
->num_finalizers
++;
2305 generate_bytecode_insns (try_block
, target
, state
);
2307 if (CAN_COMPLETE_NORMALLY (finally
))
2309 if (state
->labeled_blocks
!= finally_label
)
2311 state
->labeled_blocks
= finally_label
->next
;
2313 end_label
= get_jcf_label_here (state
);
2315 if (end_label
== start_label
)
2317 state
->num_finalizers
--;
2318 define_jcf_label (finally_label
, state
);
2319 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2323 if (CAN_COMPLETE_NORMALLY (finally
))
2325 return_link
= build_decl (VAR_DECL
, NULL_TREE
,
2326 return_address_type_node
);
2327 finished_label
= gen_jcf_label (state
);
2330 if (CAN_COMPLETE_NORMALLY (try_block
))
2332 if (CAN_COMPLETE_NORMALLY (finally
))
2334 emit_jsr (finally_label
, state
);
2335 emit_goto (finished_label
, state
);
2338 emit_goto (finally_label
, state
);
2341 /* Handle exceptions. */
2343 exception_type
= build_pointer_type (throwable_type_node
);
2344 if (CAN_COMPLETE_NORMALLY (finally
))
2346 /* We're going to generate a subroutine, so we'll need to
2347 save and restore the exception around the `jsr'. */
2348 exception_decl
= build_decl (VAR_DECL
, NULL_TREE
, exception_type
);
2349 localvar_alloc (return_link
, state
);
2351 handler
= alloc_handler (start_label
, end_label
, state
);
2352 handler
->type
= NULL_TREE
;
2353 if (CAN_COMPLETE_NORMALLY (finally
))
2355 localvar_alloc (exception_decl
, state
);
2357 emit_store (exception_decl
, state
);
2358 emit_jsr (finally_label
, state
);
2359 emit_load (exception_decl
, state
);
2361 OP1 (OPCODE_athrow
);
2366 /* We're not generating a subroutine. In this case we can
2367 simply have the exception handler pop the exception and
2368 then fall through to the `finally' block. */
2370 emit_pop (1, state
);
2374 /* The finally block. If we're generating a subroutine, first
2375 save return PC into return_link. Otherwise, just generate
2376 the code for the `finally' block. */
2377 define_jcf_label (finally_label
, state
);
2378 if (CAN_COMPLETE_NORMALLY (finally
))
2381 emit_store (return_link
, state
);
2384 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2385 if (CAN_COMPLETE_NORMALLY (finally
))
2387 maybe_wide (OPCODE_ret
, DECL_LOCAL_INDEX (return_link
), state
);
2388 maybe_free_localvar (exception_decl
, state
, 1);
2389 maybe_free_localvar (return_link
, state
, 1);
2390 define_jcf_label (finished_label
, state
);
2395 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
2397 OP1 (OPCODE_athrow
);
2399 case NEW_ARRAY_INIT
:
2401 tree values
= CONSTRUCTOR_ELTS (TREE_OPERAND (exp
, 0));
2402 tree array_type
= TREE_TYPE (TREE_TYPE (exp
));
2403 tree element_type
= TYPE_ARRAY_ELEMENT (array_type
);
2404 HOST_WIDE_INT length
= java_array_type_length (array_type
);
2405 if (target
== IGNORE_TARGET
)
2407 for ( ; values
!= NULL_TREE
; values
= TREE_CHAIN (values
))
2408 generate_bytecode_insns (TREE_VALUE (values
), target
, state
);
2411 push_int_const (length
, state
);
2414 if (JPRIMITIVE_TYPE_P (element_type
))
2416 int atype
= encode_newarray_type (element_type
);
2417 OP1 (OPCODE_newarray
);
2422 int index
= find_class_constant (&state
->cpool
,
2423 TREE_TYPE (element_type
));
2424 OP1 (OPCODE_anewarray
);
2428 jopcode
= OPCODE_iastore
+ adjust_typed_op (element_type
, 7);
2429 for ( ; values
!= NULL_TREE
; values
= TREE_CHAIN (values
), offset
++)
2431 int save_SP
= state
->code_SP
;
2432 emit_dup (1, 0, state
);
2433 push_int_const (offset
, state
);
2435 generate_bytecode_insns (TREE_VALUE (values
), STACK_TARGET
, state
);
2438 state
->code_SP
= save_SP
;
2442 case JAVA_EXC_OBJ_EXPR
:
2443 NOTE_PUSH (1); /* Pushed by exception system. */
2448 /* This copes with cases where fold() has created MIN or MAX
2449 from a conditional expression. */
2450 enum tree_code code
= TREE_CODE (exp
) == MIN_EXPR
? LT_EXPR
: GT_EXPR
;
2451 tree op0
= TREE_OPERAND (exp
, 0);
2452 tree op1
= TREE_OPERAND (exp
, 1);
2454 if (TREE_SIDE_EFFECTS (op0
) || TREE_SIDE_EFFECTS (op1
))
2456 x
= build (COND_EXPR
, TREE_TYPE (exp
),
2457 build (code
, boolean_type_node
, op0
, op1
),
2459 generate_bytecode_insns (x
, target
, state
);
2462 case NEW_CLASS_EXPR
:
2464 tree
class = TREE_TYPE (TREE_TYPE (exp
));
2465 int need_result
= target
!= IGNORE_TARGET
;
2466 int index
= find_class_constant (&state
->cpool
, class);
2472 NOTE_PUSH (1 + need_result
);
2474 /* ... fall though ... */
2477 tree f
= TREE_OPERAND (exp
, 0);
2478 tree x
= TREE_OPERAND (exp
, 1);
2479 int save_SP
= state
->code_SP
;
2481 if (TREE_CODE (f
) == ADDR_EXPR
)
2482 f
= TREE_OPERAND (f
, 0);
2483 if (f
== soft_newarray_node
)
2485 int type_code
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2486 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x
)),
2487 STACK_TARGET
, state
);
2489 OP1 (OPCODE_newarray
);
2493 else if (f
== soft_multianewarray_node
)
2497 int index
= find_class_constant (&state
->cpool
,
2498 TREE_TYPE (TREE_TYPE (exp
)));
2499 x
= TREE_CHAIN (x
); /* Skip class argument. */
2500 ndims
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2501 for (idim
= ndims
; --idim
>= 0; )
2504 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2507 OP1 (OPCODE_multianewarray
);
2512 else if (f
== soft_anewarray_node
)
2514 tree cl
= TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp
)));
2515 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (cl
));
2516 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2518 OP1 (OPCODE_anewarray
);
2522 else if (f
== soft_monitorenter_node
2523 || f
== soft_monitorexit_node
2526 if (f
== soft_monitorenter_node
)
2527 op
= OPCODE_monitorenter
;
2528 else if (f
== soft_monitorexit_node
)
2529 op
= OPCODE_monitorexit
;
2532 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2538 for ( ; x
!= NULL_TREE
; x
= TREE_CHAIN (x
))
2540 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2542 nargs
= state
->code_SP
- save_SP
;
2543 state
->code_SP
= save_SP
;
2544 if (f
== soft_fmod_node
)
2551 if (TREE_CODE (exp
) == NEW_CLASS_EXPR
)
2552 NOTE_POP (1); /* Pop implicit this. */
2553 if (TREE_CODE (f
) == FUNCTION_DECL
&& DECL_CONTEXT (f
) != NULL_TREE
)
2555 tree context
= DECL_CONTEXT (f
);
2556 int index
, interface
= 0;
2558 if (METHOD_STATIC (f
))
2559 OP1 (OPCODE_invokestatic
);
2560 else if (DECL_CONSTRUCTOR_P (f
) || CALL_USING_SUPER (exp
)
2561 || METHOD_PRIVATE (f
))
2562 OP1 (OPCODE_invokespecial
);
2565 if (CLASS_INTERFACE (TYPE_NAME (context
)))
2567 tree arg1
= TREE_VALUE (TREE_OPERAND (exp
, 1));
2568 context
= TREE_TYPE (TREE_TYPE (arg1
));
2569 if (CLASS_INTERFACE (TYPE_NAME (context
)))
2573 OP1 (OPCODE_invokeinterface
);
2575 OP1 (OPCODE_invokevirtual
);
2577 index
= find_methodref_with_class_index (&state
->cpool
, f
, context
);
2587 f
= TREE_TYPE (TREE_TYPE (f
));
2588 if (TREE_CODE (f
) != VOID_TYPE
)
2590 int size
= TYPE_IS_WIDE (f
) ? 2 : 1;
2591 if (target
== IGNORE_TARGET
)
2592 emit_pop (size
, state
);
2602 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2603 tree_code_name
[(int) TREE_CODE (exp
)]);
2608 perform_relocations (struct jcf_partial
*state
)
2610 struct jcf_block
*block
;
2611 struct jcf_relocation
*reloc
;
2615 /* Before we start, the pc field of each block is an upper bound on
2616 the block's start pc (it may be less, if previous blocks need less
2617 than their maximum).
2619 The minimum size of each block is in the block's chunk->size. */
2621 /* First, figure out the actual locations of each block. */
2624 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2626 int block_size
= block
->v
.chunk
->size
;
2630 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2631 Assumes relocations are in reverse order. */
2632 reloc
= block
->u
.relocations
;
2633 while (reloc
!= NULL
2634 && reloc
->kind
== OPCODE_goto_w
2635 && reloc
->label
->pc
== block
->next
->pc
2636 && reloc
->offset
+ 2 == block_size
)
2638 reloc
= reloc
->next
;
2639 block
->u
.relocations
= reloc
;
2640 block
->v
.chunk
->size
-= 3;
2645 /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2646 jump directly to X. We're careful here to avoid an infinite
2647 loop if the `goto's themselves form one. We do this
2648 optimization because we can generate a goto-to-goto for some
2649 try/finally blocks. */
2650 while (reloc
!= NULL
2651 && reloc
->kind
== OPCODE_goto_w
2652 && reloc
->label
!= block
2653 && reloc
->label
->v
.chunk
->data
!= NULL
2654 && reloc
->label
->v
.chunk
->data
[0] == OPCODE_goto
)
2656 /* Find the reloc for the first instruction of the
2657 destination block. */
2658 struct jcf_relocation
*first_reloc
;
2659 for (first_reloc
= reloc
->label
->u
.relocations
;
2661 first_reloc
= first_reloc
->next
)
2663 if (first_reloc
->offset
== 1
2664 && first_reloc
->kind
== OPCODE_goto_w
)
2666 reloc
->label
= first_reloc
->label
;
2671 /* If we didn't do anything, exit the loop. */
2672 if (first_reloc
== NULL
)
2676 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
2678 if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2680 /* We assume this is the first relocation in this block,
2681 so we know its final pc. */
2682 int where
= pc
+ reloc
->offset
;
2683 int pad
= ((where
+ 3) & ~3) - where
;
2686 else if (reloc
->kind
< -1 || reloc
->kind
> BLOCK_START_RELOC
)
2688 int delta
= reloc
->label
->pc
- (pc
+ reloc
->offset
- 1);
2689 int expand
= reloc
->kind
> 0 ? 2 : 5;
2693 if (delta
>= -32768 && delta
<= 32767)
2699 block_size
+= expand
;
2705 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2707 struct chunk
*chunk
= block
->v
.chunk
;
2708 int old_size
= chunk
->size
;
2709 int next_pc
= block
->next
== NULL
? pc
: block
->next
->pc
;
2710 int new_size
= next_pc
- block
->pc
;
2711 unsigned char *new_ptr
;
2712 unsigned char *old_buffer
= chunk
->data
;
2713 unsigned char *old_ptr
= old_buffer
+ old_size
;
2714 if (new_size
!= old_size
)
2716 chunk
->data
= obstack_alloc (state
->chunk_obstack
, new_size
);
2717 chunk
->size
= new_size
;
2719 new_ptr
= chunk
->data
+ new_size
;
2721 /* We do the relocations from back to front, because
2722 the relocations are in reverse order. */
2723 for (reloc
= block
->u
.relocations
; ; reloc
= reloc
->next
)
2725 /* new_ptr and old_ptr point into the old and new buffers,
2726 respectively. (If no relocations cause the buffer to
2727 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2728 The bytes at higher address have been copied and relocations
2729 handled; those at lower addresses remain to process. */
2731 /* Lower old index of piece to be copied with no relocation.
2732 I.e. high index of the first piece that does need relocation. */
2733 int start
= reloc
== NULL
? 0
2734 : reloc
->kind
== SWITCH_ALIGN_RELOC
? reloc
->offset
2735 : (reloc
->kind
== 0 || reloc
->kind
== BLOCK_START_RELOC
)
2737 : reloc
->offset
+ 2;
2740 int n
= (old_ptr
- old_buffer
) - start
;
2744 memcpy (new_ptr
, old_ptr
, n
);
2745 if (old_ptr
== old_buffer
)
2748 new_offset
= new_ptr
- chunk
->data
;
2749 new_offset
-= (reloc
->kind
== -1 ? 2 : 4);
2750 if (reloc
->kind
== 0)
2753 value
= GET_u4 (old_ptr
);
2755 else if (reloc
->kind
== BLOCK_START_RELOC
)
2761 else if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2763 int where
= block
->pc
+ reloc
->offset
;
2764 int pad
= ((where
+ 3) & ~3) - where
;
2772 value
= GET_u2 (old_ptr
);
2774 value
+= reloc
->label
->pc
- (block
->pc
+ new_offset
);
2775 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2776 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2777 if (reloc
->kind
!= -1)
2779 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2780 *--new_ptr
= (unsigned char) value
;
2782 if (reloc
->kind
> BLOCK_START_RELOC
)
2784 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2786 *--new_ptr
= reloc
->kind
;
2788 else if (reloc
->kind
< -1)
2790 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2792 *--new_ptr
= OPCODE_goto_w
;
2795 *--new_ptr
= - reloc
->kind
;
2798 if (new_ptr
!= chunk
->data
)
2801 state
->code_length
= pc
;
2805 init_jcf_state (struct jcf_partial
*state
, struct obstack
*work
)
2807 state
->chunk_obstack
= work
;
2808 state
->first
= state
->chunk
= NULL
;
2809 CPOOL_INIT (&state
->cpool
);
2810 BUFFER_INIT (&state
->localvars
);
2811 BUFFER_INIT (&state
->bytecode
);
2815 init_jcf_method (struct jcf_partial
*state
, tree method
)
2817 state
->current_method
= method
;
2818 state
->blocks
= state
->last_block
= NULL
;
2819 state
->linenumber_count
= 0;
2820 state
->first_lvar
= state
->last_lvar
= NULL
;
2821 state
->lvar_count
= 0;
2822 state
->labeled_blocks
= NULL
;
2823 state
->code_length
= 0;
2824 BUFFER_RESET (&state
->bytecode
);
2825 BUFFER_RESET (&state
->localvars
);
2827 state
->code_SP_max
= 0;
2828 state
->handlers
= NULL
;
2829 state
->last_handler
= NULL
;
2830 state
->num_handlers
= 0;
2831 state
->num_finalizers
= 0;
2832 state
->return_value_decl
= NULL_TREE
;
2836 release_jcf_state (struct jcf_partial
*state
)
2838 CPOOL_FINISH (&state
->cpool
);
2839 obstack_free (state
->chunk_obstack
, state
->first
);
2842 /* Generate and return a list of chunks containing the class CLAS
2843 in the .class file representation. The list can be written to a
2844 .class file using write_chunks. Allocate chunks from obstack WORK. */
2846 static GTY(()) tree SourceFile_node
;
2847 static struct chunk
*
2848 generate_classfile (tree clas
, struct jcf_partial
*state
)
2850 struct chunk
*cpool_chunk
;
2851 const char *source_file
, *s
;
2854 char *fields_count_ptr
;
2855 int fields_count
= 0;
2856 char *methods_count_ptr
;
2857 int methods_count
= 0;
2860 = clas
== object_type_node
? 0
2861 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas
));
2863 ptr
= append_chunk (NULL
, 8, state
);
2864 PUT4 (0xCafeBabe); /* Magic number */
2865 PUT2 (3); /* Minor version */
2866 PUT2 (45); /* Major version */
2868 append_chunk (NULL
, 0, state
);
2869 cpool_chunk
= state
->chunk
;
2871 /* Next allocate the chunk containing access_flags through fields_count. */
2872 if (clas
== object_type_node
)
2875 i
= 8 + 2 * total_supers
;
2876 ptr
= append_chunk (NULL
, i
, state
);
2877 i
= get_access_flags (TYPE_NAME (clas
));
2878 if (! (i
& ACC_INTERFACE
))
2880 PUT2 (i
); /* access_flags */
2881 i
= find_class_constant (&state
->cpool
, clas
); PUT2 (i
); /* this_class */
2882 if (clas
== object_type_node
)
2884 PUT2(0); /* super_class */
2885 PUT2(0); /* interfaces_count */
2889 tree basetypes
= TYPE_BINFO_BASETYPES (clas
);
2890 tree base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, 0));
2891 int j
= find_class_constant (&state
->cpool
, base
);
2892 PUT2 (j
); /* super_class */
2893 PUT2 (total_supers
- 1); /* interfaces_count */
2894 for (i
= 1; i
< total_supers
; i
++)
2896 base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, i
));
2897 j
= find_class_constant (&state
->cpool
, base
);
2901 fields_count_ptr
= ptr
;
2903 for (part
= TYPE_FIELDS (clas
); part
; part
= TREE_CHAIN (part
))
2905 int have_value
, attr_count
= 0;
2906 if (DECL_NAME (part
) == NULL_TREE
|| DECL_ARTIFICIAL (part
))
2908 ptr
= append_chunk (NULL
, 8, state
);
2909 i
= get_access_flags (part
); PUT2 (i
);
2910 i
= find_utf8_constant (&state
->cpool
, DECL_NAME (part
)); PUT2 (i
);
2911 i
= find_utf8_constant (&state
->cpool
,
2912 build_java_signature (TREE_TYPE (part
)));
2914 have_value
= DECL_INITIAL (part
) != NULL_TREE
2915 && FIELD_STATIC (part
) && CONSTANT_VALUE_P (DECL_INITIAL (part
))
2916 && FIELD_FINAL (part
)
2917 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part
))
2918 || TREE_TYPE (part
) == string_ptr_type_node
);
2922 if (FIELD_THISN (part
) || FIELD_LOCAL_ALIAS (part
)
2923 || FIELD_SYNTHETIC (part
))
2925 if (FIELD_DEPRECATED (part
))
2928 PUT2 (attr_count
); /* attributes_count */
2931 tree init
= DECL_INITIAL (part
);
2932 static tree ConstantValue_node
= NULL_TREE
;
2933 if (TREE_TYPE (part
) != TREE_TYPE (init
))
2934 fatal_error ("field initializer type mismatch");
2935 ptr
= append_chunk (NULL
, 8, state
);
2936 if (ConstantValue_node
== NULL_TREE
)
2937 ConstantValue_node
= get_identifier ("ConstantValue");
2938 i
= find_utf8_constant (&state
->cpool
, ConstantValue_node
);
2939 PUT2 (i
); /* attribute_name_index */
2940 PUT4 (2); /* attribute_length */
2941 i
= find_constant_index (init
, state
); PUT2 (i
);
2943 /* Emit the "Synthetic" attribute for val$<x> and this$<n>
2944 fields and other fields which need it. */
2945 if (FIELD_THISN (part
) || FIELD_LOCAL_ALIAS (part
)
2946 || FIELD_SYNTHETIC (part
))
2947 ptr
= append_synthetic_attribute (state
);
2948 if (FIELD_DEPRECATED (part
))
2949 append_deprecated_attribute (state
);
2952 ptr
= fields_count_ptr
; UNSAFE_PUT2 (fields_count
);
2954 ptr
= methods_count_ptr
= append_chunk (NULL
, 2, state
);
2957 for (part
= TYPE_METHODS (clas
); part
; part
= TREE_CHAIN (part
))
2959 struct jcf_block
*block
;
2960 tree function_body
= DECL_FUNCTION_BODY (part
);
2961 tree body
= function_body
== NULL_TREE
? NULL_TREE
2962 : BLOCK_EXPR_BODY (function_body
);
2963 tree name
= DECL_CONSTRUCTOR_P (part
) ? init_identifier_node
2965 tree type
= TREE_TYPE (part
);
2966 tree save_function
= current_function_decl
;
2967 int synthetic_p
= 0;
2969 /* Invisible Miranda methods shouldn't end up in the .class
2971 if (METHOD_INVISIBLE (part
))
2974 current_function_decl
= part
;
2975 ptr
= append_chunk (NULL
, 8, state
);
2976 i
= get_access_flags (part
); PUT2 (i
);
2977 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
2978 i
= find_utf8_constant (&state
->cpool
, build_java_signature (type
));
2980 i
= (body
!= NULL_TREE
) + (DECL_FUNCTION_THROWS (part
) != NULL_TREE
);
2982 /* Make room for the Synthetic attribute (of zero length.) */
2983 if (DECL_FINIT_P (part
)
2984 || DECL_INSTINIT_P (part
)
2985 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part
))
2986 || TYPE_DOT_CLASS (clas
) == part
)
2991 /* Make room for Deprecated attribute. */
2992 if (METHOD_DEPRECATED (part
))
2995 PUT2 (i
); /* attributes_count */
2998 ptr
= append_synthetic_attribute (state
);
3000 if (body
!= NULL_TREE
)
3002 int code_attributes_count
= 0;
3003 static tree Code_node
= NULL_TREE
;
3006 struct jcf_handler
*handler
;
3007 if (Code_node
== NULL_TREE
)
3008 Code_node
= get_identifier ("Code");
3009 ptr
= append_chunk (NULL
, 14, state
);
3010 i
= find_utf8_constant (&state
->cpool
, Code_node
); PUT2 (i
);
3012 init_jcf_method (state
, part
);
3013 get_jcf_label_here (state
); /* Force a first block. */
3014 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3015 localvar_alloc (t
, state
);
3016 state
->num_jsrs
= 0;
3017 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
3018 if (CAN_COMPLETE_NORMALLY (body
))
3020 if (TREE_CODE (TREE_TYPE (type
)) != VOID_TYPE
)
3023 OP1 (OPCODE_return
);
3025 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3026 maybe_free_localvar (t
, state
, 1);
3027 if (state
->return_value_decl
!= NULL_TREE
)
3028 maybe_free_localvar (state
->return_value_decl
, state
, 1);
3029 finish_jcf_block (state
);
3030 perform_relocations (state
);
3033 i
= 8 + state
->code_length
+ 4 + 8 * state
->num_handlers
;
3034 if (state
->linenumber_count
> 0)
3036 code_attributes_count
++;
3037 i
+= 8 + 4 * state
->linenumber_count
;
3039 if (state
->lvar_count
> 0)
3041 code_attributes_count
++;
3042 i
+= 8 + 10 * state
->lvar_count
;
3044 UNSAFE_PUT4 (i
); /* attribute_length */
3045 UNSAFE_PUT2 (state
->code_SP_max
); /* max_stack */
3046 UNSAFE_PUT2 (localvar_max
); /* max_locals */
3047 UNSAFE_PUT4 (state
->code_length
);
3049 /* Emit the exception table. */
3050 ptr
= append_chunk (NULL
, 2 + 8 * state
->num_handlers
, state
);
3051 PUT2 (state
->num_handlers
); /* exception_table_length */
3052 handler
= state
->handlers
;
3053 for (; handler
!= NULL
; handler
= handler
->next
)
3056 PUT2 (handler
->start_label
->pc
);
3057 PUT2 (handler
->end_label
->pc
);
3058 PUT2 (handler
->handler_label
->pc
);
3059 if (handler
->type
== NULL_TREE
)
3062 type_index
= find_class_constant (&state
->cpool
,
3067 ptr
= append_chunk (NULL
, 2, state
);
3068 PUT2 (code_attributes_count
);
3070 /* Write the LineNumberTable attribute. */
3071 if (state
->linenumber_count
> 0)
3073 static tree LineNumberTable_node
= NULL_TREE
;
3074 ptr
= append_chunk (NULL
,
3075 8 + 4 * state
->linenumber_count
, state
);
3076 if (LineNumberTable_node
== NULL_TREE
)
3077 LineNumberTable_node
= get_identifier ("LineNumberTable");
3078 i
= find_utf8_constant (&state
->cpool
, LineNumberTable_node
);
3079 PUT2 (i
); /* attribute_name_index */
3080 i
= 2+4*state
->linenumber_count
; PUT4(i
); /* attribute_length */
3081 i
= state
->linenumber_count
; PUT2 (i
);
3082 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
3084 int line
= block
->linenumber
;
3093 /* Write the LocalVariableTable attribute. */
3094 if (state
->lvar_count
> 0)
3096 static tree LocalVariableTable_node
= NULL_TREE
;
3097 struct localvar_info
*lvar
= state
->first_lvar
;
3098 ptr
= append_chunk (NULL
, 8 + 10 * state
->lvar_count
, state
);
3099 if (LocalVariableTable_node
== NULL_TREE
)
3100 LocalVariableTable_node
= get_identifier("LocalVariableTable");
3101 i
= find_utf8_constant (&state
->cpool
, LocalVariableTable_node
);
3102 PUT2 (i
); /* attribute_name_index */
3103 i
= 2 + 10 * state
->lvar_count
; PUT4 (i
); /* attribute_length */
3104 i
= state
->lvar_count
; PUT2 (i
);
3105 for ( ; lvar
!= NULL
; lvar
= lvar
->next
)
3107 tree name
= DECL_NAME (lvar
->decl
);
3108 tree sig
= build_java_signature (TREE_TYPE (lvar
->decl
));
3109 i
= lvar
->start_label
->pc
; PUT2 (i
);
3110 i
= lvar
->end_label
->pc
- i
; PUT2 (i
);
3111 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
3112 i
= find_utf8_constant (&state
->cpool
, sig
); PUT2 (i
);
3113 i
= DECL_LOCAL_INDEX (lvar
->decl
); PUT2 (i
);
3117 if (DECL_FUNCTION_THROWS (part
) != NULL_TREE
)
3119 tree t
= DECL_FUNCTION_THROWS (part
);
3120 int throws_count
= list_length (t
);
3121 static tree Exceptions_node
= NULL_TREE
;
3122 if (Exceptions_node
== NULL_TREE
)
3123 Exceptions_node
= get_identifier ("Exceptions");
3124 ptr
= append_chunk (NULL
, 8 + 2 * throws_count
, state
);
3125 i
= find_utf8_constant (&state
->cpool
, Exceptions_node
);
3126 PUT2 (i
); /* attribute_name_index */
3127 i
= 2 + 2 * throws_count
; PUT4(i
); /* attribute_length */
3128 i
= throws_count
; PUT2 (i
);
3129 for (; t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3131 i
= find_class_constant (&state
->cpool
, TREE_VALUE (t
));
3136 if (METHOD_DEPRECATED (part
))
3137 append_deprecated_attribute (state
);
3140 current_function_decl
= save_function
;
3142 ptr
= methods_count_ptr
; UNSAFE_PUT2 (methods_count
);
3144 source_file
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3145 for (s
= source_file
; ; s
++)
3150 if (ch
== '/' || ch
== '\\')
3153 ptr
= append_chunk (NULL
, 10, state
);
3155 i
= 1; /* Source file always exists as an attribute */
3156 if (INNER_CLASS_TYPE_P (clas
) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas
)))
3158 if (clas
== object_type_node
)
3160 if (CLASS_DEPRECATED (TYPE_NAME (clas
)))
3163 PUT2 (i
); /* attributes_count */
3165 /* generate the SourceFile attribute. */
3166 if (SourceFile_node
== NULL_TREE
)
3168 SourceFile_node
= get_identifier ("SourceFile");
3171 i
= find_utf8_constant (&state
->cpool
, SourceFile_node
);
3172 PUT2 (i
); /* attribute_name_index */
3174 i
= find_utf8_constant (&state
->cpool
, get_identifier (source_file
));
3176 append_gcj_attribute (state
, clas
);
3177 append_innerclasses_attribute (state
, clas
);
3178 if (CLASS_DEPRECATED (TYPE_NAME (clas
)))
3179 append_deprecated_attribute (state
);
3181 /* New finally generate the contents of the constant pool chunk. */
3182 i
= count_constant_pool_bytes (&state
->cpool
);
3183 ptr
= obstack_alloc (state
->chunk_obstack
, i
);
3184 cpool_chunk
->data
= ptr
;
3185 cpool_chunk
->size
= i
;
3186 write_constant_pool (&state
->cpool
, ptr
, i
);
3187 return state
->first
;
3190 static GTY(()) tree Synthetic_node
;
3191 static unsigned char *
3192 append_synthetic_attribute (struct jcf_partial
*state
)
3194 unsigned char *ptr
= append_chunk (NULL
, 6, state
);
3197 if (Synthetic_node
== NULL_TREE
)
3199 Synthetic_node
= get_identifier ("Synthetic");
3201 i
= find_utf8_constant (&state
->cpool
, Synthetic_node
);
3202 PUT2 (i
); /* Attribute string index */
3203 PUT4 (0); /* Attribute length */
3209 append_deprecated_attribute (struct jcf_partial
*state
)
3211 unsigned char *ptr
= append_chunk (NULL
, 6, state
);
3214 i
= find_utf8_constant (&state
->cpool
, get_identifier ("Deprecated"));
3215 PUT2 (i
); /* Attribute string index */
3216 PUT4 (0); /* Attribute length */
3220 append_gcj_attribute (struct jcf_partial
*state
, tree
class)
3225 if (class != object_type_node
)
3228 ptr
= append_chunk (NULL
, 6, state
); /* 2+4 */
3229 i
= find_utf8_constant (&state
->cpool
,
3230 get_identifier ("gnu.gcj.gcj-compiled"));
3231 PUT2 (i
); /* Attribute string index */
3232 PUT4 (0); /* Attribute length */
3235 static tree InnerClasses_node
;
3237 append_innerclasses_attribute (struct jcf_partial
*state
, tree
class)
3239 tree orig_decl
= TYPE_NAME (class);
3242 unsigned char *ptr
, *length_marker
, *number_marker
;
3244 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl
))
3247 ptr
= append_chunk (NULL
, 8, state
); /* 2+4+2 */
3249 if (InnerClasses_node
== NULL_TREE
)
3251 InnerClasses_node
= get_identifier ("InnerClasses");
3253 i
= find_utf8_constant (&state
->cpool
, InnerClasses_node
);
3255 length_marker
= ptr
; PUT4 (0); /* length, to be later patched */
3256 number_marker
= ptr
; PUT2 (0); /* number of classes, tblp */
3258 /* Generate the entries: all inner classes visible from the one we
3259 process: itself, up and down. */
3260 while (class && INNER_CLASS_TYPE_P (class))
3264 decl
= TYPE_NAME (class);
3265 n
= IDENTIFIER_POINTER (DECL_NAME (decl
)) +
3266 IDENTIFIER_LENGTH (DECL_NAME (decl
));
3268 while (n
[-1] != '$')
3270 append_innerclasses_attribute_entry (state
, decl
, get_identifier (n
));
3273 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3277 for (current
= DECL_INNER_CLASS_LIST (decl
);
3278 current
; current
= TREE_CHAIN (current
))
3280 append_innerclasses_attribute_entry (state
, TREE_PURPOSE (current
),
3281 TREE_VALUE (current
));
3285 ptr
= length_marker
; PUT4 (8*length
+2);
3286 ptr
= number_marker
; PUT2 (length
);
3290 append_innerclasses_attribute_entry (struct jcf_partial
*state
,
3291 tree decl
, tree name
)
3294 int ocii
= 0, ini
= 0;
3295 unsigned char *ptr
= append_chunk (NULL
, 8, state
);
3297 icii
= find_class_constant (&state
->cpool
, TREE_TYPE (decl
));
3299 /* Sun's implementation seems to generate ocii to 0 for inner
3300 classes (which aren't considered members of the class they're
3301 in.) The specs are saying that if the class is anonymous,
3302 inner_name_index must be zero. */
3303 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl
)))
3305 ocii
= find_class_constant (&state
->cpool
,
3306 TREE_TYPE (DECL_CONTEXT (decl
)));
3307 ini
= find_utf8_constant (&state
->cpool
, name
);
3309 icaf
= get_access_flags (decl
);
3311 PUT2 (icii
); PUT2 (ocii
); PUT2 (ini
); PUT2 (icaf
);
3315 make_class_file_name (tree clas
)
3317 const char *dname
, *cname
, *slash
;
3322 cname
= IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas
)),
3323 "", '.', DIR_SEPARATOR
,
3325 if (jcf_write_base_directory
== NULL
)
3327 /* Make sure we put the class file into the .java file's
3328 directory, and not into some subdirectory thereof. */
3330 dname
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3331 slash
= strrchr (dname
, DIR_SEPARATOR
);
3332 #ifdef DIR_SEPARATOR_2
3334 slash
= strrchr (dname
, DIR_SEPARATOR_2
);
3340 sep
= DIR_SEPARATOR
;
3345 t
= strrchr (cname
, DIR_SEPARATOR
);
3353 dname
= jcf_write_base_directory
;
3355 s
= strrchr (dname
, DIR_SEPARATOR
);
3356 #ifdef DIR_SEPARATOR_2
3358 s
= strrchr (dname
, DIR_SEPARATOR_2
);
3363 sep
= DIR_SEPARATOR
;
3365 slash
= dname
+ strlen (dname
);
3368 r
= xmalloc (slash
- dname
+ strlen (cname
) + 2);
3369 strncpy (r
, dname
, slash
- dname
);
3370 r
[slash
- dname
] = sep
;
3371 strcpy (&r
[slash
- dname
+ 1], cname
);
3373 /* We try to make new directories when we need them. We only do
3374 this for directories which "might not" exist. For instance, we
3375 assume the `-d' directory exists, but we don't assume that any
3376 subdirectory below it exists. It might be worthwhile to keep
3377 track of which directories we've created to avoid gratuitous
3379 dname
= r
+ (slash
- dname
) + 1;
3382 char *s
= strchr (dname
, sep
);
3386 if (stat (r
, &sb
) == -1
3387 /* Try to make it. */
3388 && mkdir (r
, 0755) == -1)
3389 fatal_error ("can't create directory %s: %m", r
);
3392 /* Skip consecutive separators. */
3393 for (dname
= s
+ 1; *dname
&& *dname
== sep
; ++dname
)
3400 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3401 The output .class file name is make_class_file_name(CLAS). */
3404 write_classfile (tree clas
)
3406 struct obstack
*work
= &temporary_obstack
;
3407 struct jcf_partial state
[1];
3408 char *class_file_name
= make_class_file_name (clas
);
3409 struct chunk
*chunks
;
3411 if (class_file_name
!= NULL
)
3414 char *temporary_file_name
;
3416 /* The .class file is initially written to a ".tmp" file so that
3417 if multiple instances of the compiler are running at once
3418 they do not see partially formed class files. */
3419 temporary_file_name
= concat (class_file_name
, ".tmp", NULL
);
3420 stream
= fopen (temporary_file_name
, "wb");
3422 fatal_error ("can't open %s for writing: %m", temporary_file_name
);
3424 jcf_dependency_add_target (class_file_name
);
3425 init_jcf_state (state
, work
);
3426 chunks
= generate_classfile (clas
, state
);
3427 write_chunks (stream
, chunks
);
3428 if (fclose (stream
))
3429 fatal_error ("error closing %s: %m", temporary_file_name
);
3431 /* If a file named by the string pointed to by `new' exists
3432 prior to the call to the `rename' function, the behavior
3433 is implementation-defined. ISO 9899-1990 7.9.4.2.
3435 For example, on Win32 with MSVCRT, it is an error. */
3437 unlink (class_file_name
);
3439 if (rename (temporary_file_name
, class_file_name
) == -1)
3441 remove (temporary_file_name
);
3442 fatal_error ("can't create %s: %m", class_file_name
);
3444 free (temporary_file_name
);
3445 free (class_file_name
);
3447 release_jcf_state (state
);
3451 string concatenation
3452 synchronized statement
3455 #include "gt-java-jcf-write.h"