1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU CC; see the file COPYING. If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc. */
28 #include "java-tree.h"
33 #include "java-opcodes.h"
34 #include "parse.h" /* for BLOCK_EXPR_BODY */
40 #define DIR_SEPARATOR '/'
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 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 begnning 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
;
280 static void generate_bytecode_insns
PARAMS ((tree
, int, struct jcf_partial
*));
281 static struct chunk
* alloc_chunk
PARAMS ((struct chunk
*, unsigned char *,
282 int, struct obstack
*));
283 static unsigned char * append_chunk
PARAMS ((unsigned char *, int,
284 struct jcf_partial
*));
285 static void append_chunk_copy
PARAMS ((unsigned char *, int,
286 struct jcf_partial
*));
287 static struct jcf_block
* gen_jcf_label
PARAMS ((struct jcf_partial
*));
288 static void finish_jcf_block
PARAMS ((struct jcf_partial
*));
289 static void define_jcf_label
PARAMS ((struct jcf_block
*,
290 struct jcf_partial
*));
291 static struct jcf_block
* get_jcf_label_here
PARAMS ((struct jcf_partial
*));
292 static void put_linenumber
PARAMS ((int, struct jcf_partial
*));
293 static void localvar_alloc
PARAMS ((tree
, struct jcf_partial
*));
294 static void localvar_free
PARAMS ((tree
, struct jcf_partial
*));
295 static int get_access_flags
PARAMS ((tree
));
296 static void write_chunks
PARAMS ((FILE *, struct chunk
*));
297 static int adjust_typed_op
PARAMS ((tree
, int));
298 static void generate_bytecode_conditional
PARAMS ((tree
, struct jcf_block
*,
299 struct jcf_block
*, int,
300 struct jcf_partial
*));
301 static void generate_bytecode_return
PARAMS ((tree
, struct jcf_partial
*));
302 static void perform_relocations
PARAMS ((struct jcf_partial
*));
303 static void init_jcf_state
PARAMS ((struct jcf_partial
*, struct obstack
*));
304 static void init_jcf_method
PARAMS ((struct jcf_partial
*, tree
));
305 static void release_jcf_state
PARAMS ((struct jcf_partial
*));
306 static struct chunk
* generate_classfile
PARAMS ((tree
, struct jcf_partial
*));
307 static struct jcf_handler
*alloc_handler
PARAMS ((struct jcf_block
*,
309 struct jcf_partial
*));
310 static void emit_iinc
PARAMS ((tree
, HOST_WIDE_INT
, struct jcf_partial
*));
311 static void emit_reloc
PARAMS ((HOST_WIDE_INT
, int, struct jcf_block
*,
312 struct jcf_partial
*));
313 static void push_constant1
PARAMS ((HOST_WIDE_INT
, struct jcf_partial
*));
314 static void push_constant2
PARAMS ((HOST_WIDE_INT
, struct jcf_partial
*));
315 static void push_int_const
PARAMS ((HOST_WIDE_INT
, struct jcf_partial
*));
316 static int find_constant_wide
PARAMS ((HOST_WIDE_INT
, HOST_WIDE_INT
,
317 struct jcf_partial
*));
318 static void push_long_const
PARAMS ((HOST_WIDE_INT
, HOST_WIDE_INT
,
319 struct jcf_partial
*));
320 static int find_constant_index
PARAMS ((tree
, struct jcf_partial
*));
321 static void push_long_const
PARAMS ((HOST_WIDE_INT
, HOST_WIDE_INT
,
322 struct jcf_partial
*));
323 static void field_op
PARAMS ((tree
, int, struct jcf_partial
*));
324 static void maybe_wide
PARAMS ((int, int, struct jcf_partial
*));
325 static void emit_dup
PARAMS ((int, int, struct jcf_partial
*));
326 static void emit_pop
PARAMS ((int, struct jcf_partial
*));
327 static void emit_load_or_store
PARAMS ((tree
, int, struct jcf_partial
*));
328 static void emit_load
PARAMS ((tree
, struct jcf_partial
*));
329 static void emit_store
PARAMS ((tree
, struct jcf_partial
*));
330 static void emit_unop
PARAMS ((enum java_opcode
, tree
, struct jcf_partial
*));
331 static void emit_binop
PARAMS ((enum java_opcode
, tree
, struct jcf_partial
*));
332 static void emit_reloc
PARAMS ((HOST_WIDE_INT
, int, struct jcf_block
*,
333 struct jcf_partial
*));
334 static void emit_switch_reloc
PARAMS ((struct jcf_block
*,
335 struct jcf_partial
*));
336 static void emit_case_reloc
PARAMS ((struct jcf_relocation
*,
337 struct jcf_partial
*));
338 static void emit_if
PARAMS ((struct jcf_block
*, int, int,
339 struct jcf_partial
*));
340 static void emit_goto
PARAMS ((struct jcf_block
*, struct jcf_partial
*));
341 static void emit_jsr
PARAMS ((struct jcf_block
*, struct jcf_partial
*));
342 static void call_cleanups
PARAMS ((struct jcf_block
*, struct jcf_partial
*));
343 static char *make_class_file_name
PARAMS ((tree
));
344 static unsigned char *append_synthetic_attribute
PARAMS ((struct jcf_partial
*));
345 static void append_innerclasses_attribute
PARAMS ((struct jcf_partial
*, tree
));
346 static void append_innerclasses_attribute_entry
PARAMS ((struct jcf_partial
*, tree
, tree
));
347 static void append_gcj_attribute
PARAMS ((struct jcf_partial
*, tree
));
349 /* Utility macros for appending (big-endian) data to a buffer.
350 We assume a local variable 'ptr' points into where we want to
351 write next, and we assume enough space has been allocated. */
353 #ifdef ENABLE_JC1_CHECKING
354 static int CHECK_PUT
PARAMS ((void *, struct jcf_partial
*, int));
357 CHECK_PUT (ptr
, state
, i
)
359 struct jcf_partial
*state
;
362 if ((unsigned char *) ptr
< state
->chunk
->data
363 || (unsigned char *) ptr
+ i
> state
->chunk
->data
+ state
->chunk
->size
)
369 #define CHECK_PUT(PTR, STATE, I) ((void)0)
372 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
373 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
374 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
375 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
377 /* There are some cases below where CHECK_PUT is guaranteed to fail.
378 Use the following macros in those specific cases. */
379 #define UNSAFE_PUT1(X) (*ptr++ = (X))
380 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
381 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
382 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
385 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
386 Set the data and size fields to DATA and SIZE, respectively.
387 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
389 static struct chunk
*
390 alloc_chunk (last
, data
, size
, work
)
394 struct obstack
*work
;
396 struct chunk
*chunk
= (struct chunk
*)
397 obstack_alloc (work
, sizeof(struct chunk
));
399 if (data
== NULL
&& size
> 0)
400 data
= obstack_alloc (work
, size
);
410 #ifdef ENABLE_JC1_CHECKING
411 static int CHECK_OP
PARAMS ((struct jcf_partial
*));
415 struct jcf_partial
*state
;
417 if (state
->bytecode
.ptr
> state
->bytecode
.limit
)
423 #define CHECK_OP(STATE) ((void) 0)
426 static unsigned char *
427 append_chunk (data
, size
, state
)
430 struct jcf_partial
*state
;
432 state
->chunk
= alloc_chunk (state
->chunk
, data
, size
, state
->chunk_obstack
);
433 if (state
->first
== NULL
)
434 state
->first
= state
->chunk
;
435 return state
->chunk
->data
;
439 append_chunk_copy (data
, size
, state
)
442 struct jcf_partial
*state
;
444 unsigned char *ptr
= append_chunk (NULL
, size
, state
);
445 memcpy (ptr
, data
, size
);
448 static struct jcf_block
*
449 gen_jcf_label (state
)
450 struct jcf_partial
*state
;
452 struct jcf_block
*block
= (struct jcf_block
*)
453 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_block
));
455 block
->linenumber
= -1;
456 block
->pc
= UNDEFINED_PC
;
461 finish_jcf_block (state
)
462 struct jcf_partial
*state
;
464 struct jcf_block
*block
= state
->last_block
;
465 struct jcf_relocation
*reloc
;
466 int code_length
= BUFFER_LENGTH (&state
->bytecode
);
467 int pc
= state
->code_length
;
468 append_chunk_copy (state
->bytecode
.data
, code_length
, state
);
469 BUFFER_RESET (&state
->bytecode
);
470 block
->v
.chunk
= state
->chunk
;
472 /* Calculate code_length to the maximum value it can have. */
473 pc
+= block
->v
.chunk
->size
;
474 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
476 int kind
= reloc
->kind
;
477 if (kind
== SWITCH_ALIGN_RELOC
)
479 else if (kind
> BLOCK_START_RELOC
)
480 pc
+= 2; /* 2-byte offset may grow to 4-byte offset */
482 pc
+= 5; /* May need to add a goto_w. */
484 state
->code_length
= pc
;
488 define_jcf_label (label
, state
)
489 struct jcf_block
*label
;
490 struct jcf_partial
*state
;
492 if (state
->last_block
!= NULL
)
493 finish_jcf_block (state
);
494 label
->pc
= state
->code_length
;
495 if (state
->blocks
== NULL
)
496 state
->blocks
= label
;
498 state
->last_block
->next
= label
;
499 state
->last_block
= label
;
501 label
->u
.relocations
= NULL
;
504 static struct jcf_block
*
505 get_jcf_label_here (state
)
506 struct jcf_partial
*state
;
508 if (state
->last_block
!= NULL
&& BUFFER_LENGTH (&state
->bytecode
) == 0)
509 return state
->last_block
;
512 struct jcf_block
*label
= gen_jcf_label (state
);
513 define_jcf_label (label
, state
);
518 /* Note a line number entry for the current PC and given LINE. */
521 put_linenumber (line
, state
)
523 struct jcf_partial
*state
;
525 struct jcf_block
*label
= get_jcf_label_here (state
);
526 if (label
->linenumber
> 0)
528 label
= gen_jcf_label (state
);
529 define_jcf_label (label
, state
);
531 label
->linenumber
= line
;
532 state
->linenumber_count
++;
535 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
536 in the range (START_LABEL, END_LABEL). */
538 static struct jcf_handler
*
539 alloc_handler (start_label
, end_label
, state
)
540 struct jcf_block
*start_label
;
541 struct jcf_block
*end_label
;
542 struct jcf_partial
*state
;
544 struct jcf_handler
*handler
= (struct jcf_handler
*)
545 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_handler
));
546 handler
->start_label
= start_label
;
547 handler
->end_label
= end_label
;
548 handler
->handler_label
= get_jcf_label_here (state
);
549 if (state
->handlers
== NULL
)
550 state
->handlers
= handler
;
552 state
->last_handler
->next
= handler
;
553 state
->last_handler
= handler
;
554 handler
->next
= NULL
;
555 state
->num_handlers
++;
560 /* The index of jvm local variable allocated for this DECL.
561 This is assigned when generating .class files;
562 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
563 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
565 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
569 struct localvar_info
*next
;
572 struct jcf_block
*start_label
;
573 struct jcf_block
*end_label
;
576 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
577 #define localvar_max \
578 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
581 localvar_alloc (decl
, state
)
583 struct jcf_partial
*state
;
585 struct jcf_block
*start_label
= get_jcf_label_here (state
);
586 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
588 register struct localvar_info
*info
;
589 register struct localvar_info
**ptr
= localvar_buffer
;
590 register struct localvar_info
**limit
591 = (struct localvar_info
**) state
->localvars
.ptr
;
592 for (index
= 0; ptr
< limit
; index
++, ptr
++)
595 && (! wide
|| ((ptr
+1) < limit
&& ptr
[1] == NULL
)))
600 buffer_grow (&state
->localvars
, 2 * sizeof (struct localvar_info
*));
601 ptr
= (struct localvar_info
**) state
->localvars
.data
+ index
;
602 state
->localvars
.ptr
= (unsigned char *) (ptr
+ 1 + wide
);
604 info
= (struct localvar_info
*)
605 obstack_alloc (state
->chunk_obstack
, sizeof (struct localvar_info
));
608 ptr
[1] = (struct localvar_info
*)(~0);
609 DECL_LOCAL_INDEX (decl
) = index
;
611 info
->start_label
= start_label
;
613 if (debug_info_level
> DINFO_LEVEL_TERSE
614 && DECL_NAME (decl
) != NULL_TREE
)
616 /* Generate debugging info. */
618 if (state
->last_lvar
!= NULL
)
619 state
->last_lvar
->next
= info
;
621 state
->first_lvar
= info
;
622 state
->last_lvar
= info
;
628 localvar_free (decl
, state
)
630 struct jcf_partial
*state
;
632 struct jcf_block
*end_label
= get_jcf_label_here (state
);
633 int index
= DECL_LOCAL_INDEX (decl
);
634 register struct localvar_info
**ptr
= &localvar_buffer
[index
];
635 register struct localvar_info
*info
= *ptr
;
636 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
638 info
->end_label
= end_label
;
640 if (info
->decl
!= decl
)
645 if (ptr
[1] != (struct localvar_info
*)(~0))
652 #define STACK_TARGET 1
653 #define IGNORE_TARGET 2
655 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
656 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
659 get_access_flags (decl
)
663 int isfield
= TREE_CODE (decl
) == FIELD_DECL
|| TREE_CODE (decl
) == VAR_DECL
;
664 if (CLASS_PUBLIC (decl
)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
666 if (CLASS_FINAL (decl
)) /* same as FIELD_FINAL and METHOD_FINAL */
668 if (isfield
|| TREE_CODE (decl
) == FUNCTION_DECL
)
670 if (TREE_PROTECTED (decl
))
671 flags
|= ACC_PROTECTED
;
672 if (TREE_PRIVATE (decl
))
673 flags
|= ACC_PRIVATE
;
675 else if (TREE_CODE (decl
) == TYPE_DECL
)
677 if (CLASS_SUPER (decl
))
679 if (CLASS_ABSTRACT (decl
))
680 flags
|= ACC_ABSTRACT
;
681 if (CLASS_INTERFACE (decl
))
682 flags
|= ACC_INTERFACE
;
683 if (CLASS_STATIC (decl
))
685 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl
))
686 || LOCAL_CLASS_P (TREE_TYPE (decl
)))
687 flags
|= ACC_PRIVATE
;
688 if (CLASS_STRICTFP (decl
))
694 if (TREE_CODE (decl
) == FUNCTION_DECL
)
696 if (METHOD_NATIVE (decl
))
698 if (METHOD_STATIC (decl
))
700 if (METHOD_SYNCHRONIZED (decl
))
701 flags
|= ACC_SYNCHRONIZED
;
702 if (METHOD_ABSTRACT (decl
))
703 flags
|= ACC_ABSTRACT
;
704 if (METHOD_STRICTFP (decl
))
709 if (FIELD_STATIC (decl
))
711 if (FIELD_VOLATILE (decl
))
712 flags
|= ACC_VOLATILE
;
713 if (FIELD_TRANSIENT (decl
))
714 flags
|= ACC_TRANSIENT
;
719 /* Write the list of segments starting at CHUNKS to STREAM. */
722 write_chunks (stream
, chunks
)
724 struct chunk
*chunks
;
726 for (; chunks
!= NULL
; chunks
= chunks
->next
)
727 fwrite (chunks
->data
, chunks
->size
, 1, stream
);
730 /* Push a 1-word constant in the constant pool at the given INDEX.
731 (Caller is responsible for doing NOTE_PUSH.) */
734 push_constant1 (index
, state
)
736 struct jcf_partial
*state
;
751 /* Push a 2-word constant in the constant pool at the given INDEX.
752 (Caller is responsible for doing NOTE_PUSH.) */
755 push_constant2 (index
, state
)
757 struct jcf_partial
*state
;
764 /* Push 32-bit integer constant on VM stack.
765 Caller is responsible for doing NOTE_PUSH. */
768 push_int_const (i
, state
)
770 struct jcf_partial
*state
;
773 if (i
>= -1 && i
<= 5)
774 OP1(OPCODE_iconst_0
+ i
);
775 else if (i
>= -128 && i
< 128)
780 else if (i
>= -32768 && i
< 32768)
787 i
= find_constant1 (&state
->cpool
, CONSTANT_Integer
,
788 (jword
)(i
& 0xFFFFFFFF));
789 push_constant1 (i
, state
);
794 find_constant_wide (lo
, hi
, state
)
795 HOST_WIDE_INT lo
, hi
;
796 struct jcf_partial
*state
;
798 HOST_WIDE_INT w1
, w2
;
799 lshift_double (lo
, hi
, -32, 64, &w1
, &w2
, 1);
800 return find_constant2 (&state
->cpool
, CONSTANT_Long
,
801 (jword
)(w1
& 0xFFFFFFFF), (jword
)(lo
& 0xFFFFFFFF));
804 /* Find or allocate a constant pool entry for the given VALUE.
805 Return the index in the constant pool. */
808 find_constant_index (value
, state
)
810 struct jcf_partial
*state
;
812 if (TREE_CODE (value
) == INTEGER_CST
)
814 if (TYPE_PRECISION (TREE_TYPE (value
)) <= 32)
815 return find_constant1 (&state
->cpool
, CONSTANT_Integer
,
816 (jword
)(TREE_INT_CST_LOW (value
) & 0xFFFFFFFF));
818 return find_constant_wide (TREE_INT_CST_LOW (value
),
819 TREE_INT_CST_HIGH (value
), state
);
821 else if (TREE_CODE (value
) == REAL_CST
)
824 if (TYPE_PRECISION (TREE_TYPE (value
)) == 32)
826 words
[0] = etarsingle (TREE_REAL_CST (value
)) & 0xFFFFFFFF;
827 return find_constant1 (&state
->cpool
, CONSTANT_Float
,
832 etardouble (TREE_REAL_CST (value
), words
);
833 return find_constant2 (&state
->cpool
, CONSTANT_Double
,
834 (jword
)(words
[1-FLOAT_WORDS_BIG_ENDIAN
] &
836 (jword
)(words
[FLOAT_WORDS_BIG_ENDIAN
] &
840 else if (TREE_CODE (value
) == STRING_CST
)
841 return find_string_constant (&state
->cpool
, value
);
847 /* Push 64-bit long constant on VM stack.
848 Caller is responsible for doing NOTE_PUSH. */
851 push_long_const (lo
, hi
, state
)
852 HOST_WIDE_INT lo
, hi
;
853 struct jcf_partial
*state
;
855 if (hi
== 0 && lo
>= 0 && lo
<= 1)
858 OP1(OPCODE_lconst_0
+ lo
);
860 else if ((hi
== 0 && (jword
)(lo
& 0xFFFFFFFF) < 32768)
861 || (hi
== -1 && (lo
& 0xFFFFFFFF) >= (jword
)-32768))
863 push_int_const (lo
, state
);
868 push_constant2 (find_constant_wide (lo
, hi
, state
), state
);
872 field_op (field
, opcode
, state
)
875 struct jcf_partial
*state
;
877 int index
= find_fieldref_index (&state
->cpool
, field
);
883 /* Returns an integer in the range 0 (for 'int') through 4 (for object
884 reference) to 7 (for 'short') which matches the pattern of how JVM
885 opcodes typically depend on the operand type. */
888 adjust_typed_op (type
, max
)
892 switch (TREE_CODE (type
))
895 case RECORD_TYPE
: return 4;
897 return TYPE_PRECISION (type
) == 32 || max
< 5 ? 0 : 5;
899 return TYPE_PRECISION (type
) == 32 || max
< 6 ? 0 : 6;
901 switch (TYPE_PRECISION (type
))
903 case 8: return max
< 5 ? 0 : 5;
904 case 16: return max
< 7 ? 0 : 7;
910 switch (TYPE_PRECISION (type
))
923 maybe_wide (opcode
, index
, state
)
925 struct jcf_partial
*state
;
942 /* Compile code to duplicate with offset, where
943 SIZE is the size of the stack item to duplicate (1 or 2), abd
944 OFFSET is where to insert the result (must be 0, 1, or 2).
945 (The new words get inserted at stack[SP-size-offset].) */
948 emit_dup (size
, offset
, state
)
950 struct jcf_partial
*state
;
957 kind
= size
== 1 ? OPCODE_dup
: OPCODE_dup2
;
958 else if (offset
== 1)
959 kind
= size
== 1 ? OPCODE_dup_x1
: OPCODE_dup2_x1
;
960 else if (offset
== 2)
961 kind
= size
== 1 ? OPCODE_dup_x2
: OPCODE_dup2_x2
;
969 emit_pop (size
, state
)
971 struct jcf_partial
*state
;
974 OP1 (OPCODE_pop
- 1 + size
);
978 emit_iinc (var
, value
, state
)
981 struct jcf_partial
*state
;
983 int slot
= DECL_LOCAL_INDEX (var
);
985 if (value
< -128 || value
> 127 || slot
>= 256)
1003 emit_load_or_store (var
, opcode
, state
)
1004 tree var
; /* Variable to load from or store into. */
1005 int opcode
; /* Either OPCODE_iload or OPCODE_istore. */
1006 struct jcf_partial
*state
;
1008 tree type
= TREE_TYPE (var
);
1009 int kind
= adjust_typed_op (type
, 4);
1010 int index
= DECL_LOCAL_INDEX (var
);
1014 OP1 (opcode
+ 5 + 4 * kind
+ index
); /* [ilfda]{load,store}_[0123] */
1017 maybe_wide (opcode
+ kind
, index
, state
); /* [ilfda]{load,store} */
1021 emit_load (var
, state
)
1023 struct jcf_partial
*state
;
1025 emit_load_or_store (var
, OPCODE_iload
, state
);
1026 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
1030 emit_store (var
, state
)
1032 struct jcf_partial
*state
;
1034 emit_load_or_store (var
, OPCODE_istore
, state
);
1035 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
1039 emit_unop (opcode
, type
, state
)
1040 enum java_opcode opcode
;
1041 tree type ATTRIBUTE_UNUSED
;
1042 struct jcf_partial
*state
;
1049 emit_binop (opcode
, type
, state
)
1050 enum java_opcode opcode
;
1052 struct jcf_partial
*state
;
1054 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1061 emit_reloc (value
, kind
, target
, state
)
1062 HOST_WIDE_INT value
;
1064 struct jcf_block
*target
;
1065 struct jcf_partial
*state
;
1067 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
1068 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1069 struct jcf_block
*block
= state
->last_block
;
1070 reloc
->next
= block
->u
.relocations
;
1071 block
->u
.relocations
= reloc
;
1072 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1073 reloc
->label
= target
;
1075 if (kind
== 0 || kind
== BLOCK_START_RELOC
)
1077 else if (kind
!= SWITCH_ALIGN_RELOC
)
1082 emit_switch_reloc (label
, state
)
1083 struct jcf_block
*label
;
1084 struct jcf_partial
*state
;
1086 emit_reloc (RELOCATION_VALUE_0
, BLOCK_START_RELOC
, label
, state
);
1089 /* Similar to emit_switch_reloc,
1090 but re-uses an existing case reloc. */
1093 emit_case_reloc (reloc
, state
)
1094 struct jcf_relocation
*reloc
;
1095 struct jcf_partial
*state
;
1097 struct jcf_block
*block
= state
->last_block
;
1098 reloc
->next
= block
->u
.relocations
;
1099 block
->u
.relocations
= reloc
;
1100 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1101 reloc
->kind
= BLOCK_START_RELOC
;
1105 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1106 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1109 emit_if (target
, opcode
, inv_opcode
, state
)
1110 struct jcf_block
*target
;
1111 int opcode
, inv_opcode
;
1112 struct jcf_partial
*state
;
1116 /* value is 1 byte from reloc back to start of instruction. */
1117 emit_reloc (RELOCATION_VALUE_1
, - inv_opcode
, target
, state
);
1121 emit_goto (target
, state
)
1122 struct jcf_block
*target
;
1123 struct jcf_partial
*state
;
1127 /* Value is 1 byte from reloc back to start of instruction. */
1128 emit_reloc (RELOCATION_VALUE_1
, OPCODE_goto_w
, target
, state
);
1132 emit_jsr (target
, state
)
1133 struct jcf_block
*target
;
1134 struct jcf_partial
*state
;
1138 /* Value is 1 byte from reloc back to start of instruction. */
1139 emit_reloc (RELOCATION_VALUE_1
, OPCODE_jsr_w
, target
, state
);
1142 /* Generate code to evaluate EXP. If the result is true,
1143 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1144 TRUE_BRANCH_FIRST is a code geneation hint that the
1145 TRUE_LABEL may follow right after this. (The idea is that we
1146 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1149 generate_bytecode_conditional (exp
, true_label
, false_label
,
1150 true_branch_first
, state
)
1152 struct jcf_block
*true_label
;
1153 struct jcf_block
*false_label
;
1154 int true_branch_first
;
1155 struct jcf_partial
*state
;
1157 tree exp0
, exp1
, type
;
1158 int save_SP
= state
->code_SP
;
1159 enum java_opcode op
, negop
;
1160 switch (TREE_CODE (exp
))
1163 emit_goto (integer_zerop (exp
) ? false_label
: true_label
, state
);
1167 struct jcf_block
*then_label
= gen_jcf_label (state
);
1168 struct jcf_block
*else_label
= gen_jcf_label (state
);
1169 int save_SP_before
, save_SP_after
;
1170 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1171 then_label
, else_label
, 1, state
);
1172 define_jcf_label (then_label
, state
);
1173 save_SP_before
= state
->code_SP
;
1174 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1175 true_label
, false_label
, 1, state
);
1176 save_SP_after
= state
->code_SP
;
1177 state
->code_SP
= save_SP_before
;
1178 define_jcf_label (else_label
, state
);
1179 generate_bytecode_conditional (TREE_OPERAND (exp
, 2),
1180 true_label
, false_label
,
1181 true_branch_first
, state
);
1182 if (state
->code_SP
!= save_SP_after
)
1186 case TRUTH_NOT_EXPR
:
1187 generate_bytecode_conditional (TREE_OPERAND (exp
, 0), false_label
,
1188 true_label
, ! true_branch_first
, state
);
1190 case TRUTH_ANDIF_EXPR
:
1192 struct jcf_block
*next_label
= gen_jcf_label (state
);
1193 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1194 next_label
, false_label
, 1, state
);
1195 define_jcf_label (next_label
, state
);
1196 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1197 true_label
, false_label
, 1, state
);
1200 case TRUTH_ORIF_EXPR
:
1202 struct jcf_block
*next_label
= gen_jcf_label (state
);
1203 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1204 true_label
, next_label
, 1, state
);
1205 define_jcf_label (next_label
, state
);
1206 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1207 true_label
, false_label
, 1, state
);
1211 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1212 set it to the corresponding 1-operand if<COND> instructions. */
1216 /* The opcodes with their inverses are allocated in pairs.
1217 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1218 negop
= (op
& 1) ? op
+ 1 : op
- 1;
1220 if (true_branch_first
)
1222 emit_if (false_label
, negop
, op
, state
);
1223 emit_goto (true_label
, state
);
1227 emit_if (true_label
, op
, negop
, state
);
1228 emit_goto (false_label
, state
);
1232 op
= OPCODE_if_icmpeq
;
1235 op
= OPCODE_if_icmpne
;
1238 op
= OPCODE_if_icmpgt
;
1241 op
= OPCODE_if_icmplt
;
1244 op
= OPCODE_if_icmpge
;
1247 op
= OPCODE_if_icmple
;
1250 exp0
= TREE_OPERAND (exp
, 0);
1251 exp1
= TREE_OPERAND (exp
, 1);
1252 type
= TREE_TYPE (exp0
);
1253 switch (TREE_CODE (type
))
1256 case POINTER_TYPE
: case RECORD_TYPE
:
1257 switch (TREE_CODE (exp
))
1259 case EQ_EXPR
: op
= OPCODE_if_acmpeq
; break;
1260 case NE_EXPR
: op
= OPCODE_if_acmpne
; break;
1263 if (integer_zerop (exp1
) || integer_zerop (exp0
))
1265 generate_bytecode_insns (integer_zerop (exp0
) ? exp1
: exp0
,
1266 STACK_TARGET
, state
);
1267 op
= op
+ (OPCODE_ifnull
- OPCODE_if_acmpeq
);
1268 negop
= (op
& 1) ? op
- 1 : op
+ 1;
1272 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1273 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1277 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1278 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1279 if (op
== OPCODE_if_icmplt
|| op
== OPCODE_if_icmple
)
1283 if (TYPE_PRECISION (type
) > 32)
1294 if (TYPE_PRECISION (type
) > 32)
1296 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1297 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1305 if (integer_zerop (exp1
))
1307 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1311 if (integer_zerop (exp0
))
1315 case OPCODE_if_icmplt
:
1316 case OPCODE_if_icmpge
:
1319 case OPCODE_if_icmpgt
:
1320 case OPCODE_if_icmple
:
1326 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1330 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1331 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1337 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1339 if (true_branch_first
)
1341 emit_if (false_label
, OPCODE_ifeq
, OPCODE_ifne
, state
);
1342 emit_goto (true_label
, state
);
1346 emit_if (true_label
, OPCODE_ifne
, OPCODE_ifeq
, state
);
1347 emit_goto (false_label
, state
);
1351 if (save_SP
!= state
->code_SP
)
1355 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1356 but only as far out as LIMIT (since we are about to jump to the
1357 emit label that is LIMIT). */
1360 call_cleanups (limit
, state
)
1361 struct jcf_block
*limit
;
1362 struct jcf_partial
*state
;
1364 struct jcf_block
*block
= state
->labeled_blocks
;
1365 for (; block
!= limit
; block
= block
->next
)
1367 if (block
->pc
== PENDING_CLEANUP_PC
)
1368 emit_jsr (block
, state
);
1373 generate_bytecode_return (exp
, state
)
1375 struct jcf_partial
*state
;
1377 tree return_type
= TREE_TYPE (TREE_TYPE (state
->current_method
));
1378 int returns_void
= TREE_CODE (return_type
) == VOID_TYPE
;
1383 switch (TREE_CODE (exp
))
1386 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
,
1388 exp
= TREE_OPERAND (exp
, 1);
1392 struct jcf_block
*then_label
= gen_jcf_label (state
);
1393 struct jcf_block
*else_label
= gen_jcf_label (state
);
1394 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1395 then_label
, else_label
, 1, state
);
1396 define_jcf_label (then_label
, state
);
1397 generate_bytecode_return (TREE_OPERAND (exp
, 1), state
);
1398 define_jcf_label (else_label
, state
);
1399 generate_bytecode_return (TREE_OPERAND (exp
, 2), state
);
1403 generate_bytecode_insns (exp
,
1404 returns_void
? IGNORE_TARGET
1405 : STACK_TARGET
, state
);
1411 call_cleanups (NULL
, state
);
1415 op
= OPCODE_ireturn
+ adjust_typed_op (return_type
, 4);
1416 if (state
->num_finalizers
> 0)
1418 if (state
->return_value_decl
== NULL_TREE
)
1420 state
->return_value_decl
1421 = build_decl (VAR_DECL
, NULL_TREE
, TREE_TYPE (exp
));
1422 localvar_alloc (state
->return_value_decl
, state
);
1424 emit_store (state
->return_value_decl
, state
);
1425 call_cleanups (NULL
, state
);
1426 emit_load (state
->return_value_decl
, state
);
1427 /* If we call localvar_free (state->return_value_decl, state),
1428 then we risk the save decl erroneously re-used in the
1429 finalizer. Instead, we keep the state->return_value_decl
1430 allocated through the rest of the method. This is not
1431 the greatest solution, but it is at least simple and safe. */
1438 /* Generate bytecode for sub-expression EXP of METHOD.
1439 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1442 generate_bytecode_insns (exp
, target
, state
)
1445 struct jcf_partial
*state
;
1448 enum java_opcode jopcode
;
1450 HOST_WIDE_INT value
;
1455 if (exp
== NULL
&& target
== IGNORE_TARGET
)
1458 type
= TREE_TYPE (exp
);
1460 switch (TREE_CODE (exp
))
1463 if (BLOCK_EXPR_BODY (exp
))
1466 tree body
= BLOCK_EXPR_BODY (exp
);
1467 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1469 tree next
= TREE_CHAIN (local
);
1470 localvar_alloc (local
, state
);
1473 /* Avoid deep recursion for long blocks. */
1474 while (TREE_CODE (body
) == COMPOUND_EXPR
)
1476 generate_bytecode_insns (TREE_OPERAND (body
, 0), target
, state
);
1477 body
= TREE_OPERAND (body
, 1);
1479 generate_bytecode_insns (body
, target
, state
);
1480 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1482 tree next
= TREE_CHAIN (local
);
1483 localvar_free (local
, state
);
1489 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
1490 /* Normally the first operand to a COMPOUND_EXPR must complete
1491 normally. However, in the special case of a do-while
1492 statement this is not necessarily the case. */
1493 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 0)))
1494 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1496 case EXPR_WITH_FILE_LOCATION
:
1498 const char *saved_input_filename
= input_filename
;
1499 tree body
= EXPR_WFL_NODE (exp
);
1500 int saved_lineno
= lineno
;
1501 if (body
== empty_stmt_node
)
1503 input_filename
= EXPR_WFL_FILENAME (exp
);
1504 lineno
= EXPR_WFL_LINENO (exp
);
1505 if (EXPR_WFL_EMIT_LINE_NOTE (exp
) && lineno
> 0
1506 && debug_info_level
> DINFO_LEVEL_NONE
)
1507 put_linenumber (lineno
, state
);
1508 generate_bytecode_insns (body
, target
, state
);
1509 input_filename
= saved_input_filename
;
1510 lineno
= saved_lineno
;
1514 if (target
== IGNORE_TARGET
) ; /* do nothing */
1515 else if (TREE_CODE (type
) == POINTER_TYPE
)
1517 if (! integer_zerop (exp
))
1520 OP1 (OPCODE_aconst_null
);
1523 else if (TYPE_PRECISION (type
) <= 32)
1525 push_int_const (TREE_INT_CST_LOW (exp
), state
);
1530 push_long_const (TREE_INT_CST_LOW (exp
), TREE_INT_CST_HIGH (exp
),
1537 int prec
= TYPE_PRECISION (type
) >> 5;
1539 if (real_zerop (exp
))
1540 OP1 (prec
== 1 ? OPCODE_fconst_0
: OPCODE_dconst_0
);
1541 else if (real_onep (exp
))
1542 OP1 (prec
== 1 ? OPCODE_fconst_1
: OPCODE_dconst_1
);
1543 /* FIXME Should also use fconst_2 for 2.0f.
1544 Also, should use iconst_2/ldc followed by i2f/i2d
1545 for other float/double when the value is a small integer. */
1548 offset
= find_constant_index (exp
, state
);
1550 push_constant1 (offset
, state
);
1552 push_constant2 (offset
, state
);
1558 push_constant1 (find_string_constant (&state
->cpool
, exp
), state
);
1562 if (TREE_STATIC (exp
))
1564 field_op (exp
, OPCODE_getstatic
, state
);
1565 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1568 /* ... fall through ... */
1570 emit_load (exp
, state
);
1572 case NON_LVALUE_EXPR
:
1574 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1577 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1578 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1579 if (target
!= IGNORE_TARGET
)
1581 jopcode
= OPCODE_iaload
+ adjust_typed_op (type
, 7);
1584 if (! TYPE_IS_WIDE (type
))
1590 tree obj
= TREE_OPERAND (exp
, 0);
1591 tree field
= TREE_OPERAND (exp
, 1);
1592 int is_static
= FIELD_STATIC (field
);
1593 generate_bytecode_insns (obj
,
1594 is_static
? IGNORE_TARGET
: target
, state
);
1595 if (target
!= IGNORE_TARGET
)
1597 if (DECL_NAME (field
) == length_identifier_node
&& !is_static
1598 && TYPE_ARRAY_P (TREE_TYPE (obj
)))
1601 OP1 (OPCODE_arraylength
);
1605 field_op (field
, is_static
? OPCODE_getstatic
: OPCODE_getfield
,
1609 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1614 case TRUTH_ANDIF_EXPR
:
1615 case TRUTH_ORIF_EXPR
:
1623 struct jcf_block
*then_label
= gen_jcf_label (state
);
1624 struct jcf_block
*else_label
= gen_jcf_label (state
);
1625 struct jcf_block
*end_label
= gen_jcf_label (state
);
1626 generate_bytecode_conditional (exp
,
1627 then_label
, else_label
, 1, state
);
1628 define_jcf_label (then_label
, state
);
1629 push_int_const (1, state
);
1630 emit_goto (end_label
, state
);
1631 define_jcf_label (else_label
, state
);
1632 push_int_const (0, state
);
1633 define_jcf_label (end_label
, state
);
1639 struct jcf_block
*then_label
= gen_jcf_label (state
);
1640 struct jcf_block
*else_label
= gen_jcf_label (state
);
1641 struct jcf_block
*end_label
= gen_jcf_label (state
);
1642 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1643 then_label
, else_label
, 1, state
);
1644 define_jcf_label (then_label
, state
);
1645 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1646 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 1))
1647 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1648 || TREE_CODE (TREE_TYPE (exp
)) != VOID_TYPE
)
1649 emit_goto (end_label
, state
);
1650 define_jcf_label (else_label
, state
);
1651 generate_bytecode_insns (TREE_OPERAND (exp
, 2), target
, state
);
1652 define_jcf_label (end_label
, state
);
1653 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1654 if (TREE_TYPE (exp
) != void_type_node
)
1655 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1660 struct jcf_switch_state
*sw_state
= state
->sw_state
;
1661 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
1662 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1663 HOST_WIDE_INT case_value
= TREE_INT_CST_LOW (TREE_OPERAND (exp
, 0));
1665 reloc
->label
= get_jcf_label_here (state
);
1666 reloc
->offset
= case_value
;
1667 reloc
->next
= sw_state
->cases
;
1668 sw_state
->cases
= reloc
;
1669 if (sw_state
->num_cases
== 0)
1671 sw_state
->min_case
= case_value
;
1672 sw_state
->max_case
= case_value
;
1676 if (case_value
< sw_state
->min_case
)
1677 sw_state
->min_case
= case_value
;
1678 if (case_value
> sw_state
->max_case
)
1679 sw_state
->max_case
= case_value
;
1681 sw_state
->num_cases
++;
1685 state
->sw_state
->default_label
= get_jcf_label_here (state
);
1690 /* The SWITCH_EXPR has three parts, generated in the following order:
1691 1. the switch_expression (the value used to select the correct case);
1693 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1694 After code generation, we will re-order them in the order 1, 3, 2.
1695 This is to avoid any extra GOTOs. */
1696 struct jcf_switch_state sw_state
;
1697 struct jcf_block
*expression_last
; /* Last block of the switch_expression. */
1698 struct jcf_block
*body_last
; /* Last block of the switch_body. */
1699 struct jcf_block
*switch_instruction
; /* First block of switch_instruction. */
1700 struct jcf_block
*instruction_last
; /* Last block of the switch_instruction. */
1701 struct jcf_block
*body_block
;
1703 sw_state
.prev
= state
->sw_state
;
1704 state
->sw_state
= &sw_state
;
1705 sw_state
.cases
= NULL
;
1706 sw_state
.num_cases
= 0;
1707 sw_state
.default_label
= NULL
;
1708 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1709 expression_last
= state
->last_block
;
1710 /* Force a new block here. */
1711 body_block
= gen_jcf_label (state
);
1712 define_jcf_label (body_block
, state
);
1713 generate_bytecode_insns (TREE_OPERAND (exp
, 1), IGNORE_TARGET
, state
);
1714 body_last
= state
->last_block
;
1716 switch_instruction
= gen_jcf_label (state
);
1717 define_jcf_label (switch_instruction
, state
);
1718 if (sw_state
.default_label
== NULL
)
1719 sw_state
.default_label
= gen_jcf_label (state
);
1721 if (sw_state
.num_cases
<= 1)
1723 if (sw_state
.num_cases
== 0)
1725 emit_pop (1, state
);
1730 push_int_const (sw_state
.cases
->offset
, state
);
1732 emit_if (sw_state
.cases
->label
,
1733 OPCODE_if_icmpeq
, OPCODE_if_icmpne
, state
);
1735 emit_goto (sw_state
.default_label
, state
);
1740 /* Copy the chain of relocs into a sorted array. */
1741 struct jcf_relocation
**relocs
= (struct jcf_relocation
**)
1742 xmalloc (sw_state
.num_cases
* sizeof (struct jcf_relocation
*));
1743 /* The relocs arrays is a buffer with a gap.
1744 The assumption is that cases will normally come in "runs". */
1746 int gap_end
= sw_state
.num_cases
;
1747 struct jcf_relocation
*reloc
;
1748 for (reloc
= sw_state
.cases
; reloc
!= NULL
; reloc
= reloc
->next
)
1750 HOST_WIDE_INT case_value
= reloc
->offset
;
1751 while (gap_end
< sw_state
.num_cases
)
1753 struct jcf_relocation
*end
= relocs
[gap_end
];
1754 if (case_value
<= end
->offset
)
1756 relocs
[gap_start
++] = end
;
1759 while (gap_start
> 0)
1761 struct jcf_relocation
*before
= relocs
[gap_start
-1];
1762 if (case_value
>= before
->offset
)
1764 relocs
[--gap_end
] = before
;
1767 relocs
[gap_start
++] = reloc
;
1768 /* Note we don't check for duplicates. This is
1769 handled by the parser. */
1772 if (2 * sw_state
.num_cases
1773 >= sw_state
.max_case
- sw_state
.min_case
)
1774 { /* Use tableswitch. */
1776 RESERVE (13 + 4 * (sw_state
.max_case
- sw_state
.min_case
+ 1));
1777 OP1 (OPCODE_tableswitch
);
1778 emit_reloc (RELOCATION_VALUE_0
,
1779 SWITCH_ALIGN_RELOC
, NULL
, state
);
1780 emit_switch_reloc (sw_state
.default_label
, state
);
1781 OP4 (sw_state
.min_case
);
1782 OP4 (sw_state
.max_case
);
1783 for (i
= sw_state
.min_case
; ; )
1785 reloc
= relocs
[index
];
1786 if (i
== reloc
->offset
)
1788 emit_case_reloc (reloc
, state
);
1789 if (i
== sw_state
.max_case
)
1794 emit_switch_reloc (sw_state
.default_label
, state
);
1799 { /* Use lookupswitch. */
1800 RESERVE(9 + 8 * sw_state
.num_cases
);
1801 OP1 (OPCODE_lookupswitch
);
1802 emit_reloc (RELOCATION_VALUE_0
,
1803 SWITCH_ALIGN_RELOC
, NULL
, state
);
1804 emit_switch_reloc (sw_state
.default_label
, state
);
1805 OP4 (sw_state
.num_cases
);
1806 for (i
= 0; i
< sw_state
.num_cases
; i
++)
1808 struct jcf_relocation
*reloc
= relocs
[i
];
1809 OP4 (reloc
->offset
);
1810 emit_case_reloc (reloc
, state
);
1816 instruction_last
= state
->last_block
;
1817 if (sw_state
.default_label
->pc
< 0)
1818 define_jcf_label (sw_state
.default_label
, state
);
1819 else /* Force a new block. */
1820 sw_state
.default_label
= get_jcf_label_here (state
);
1821 /* Now re-arrange the blocks so the switch_instruction
1822 comes before the switch_body. */
1823 switch_length
= state
->code_length
- switch_instruction
->pc
;
1824 switch_instruction
->pc
= body_block
->pc
;
1825 instruction_last
->next
= body_block
;
1826 instruction_last
->v
.chunk
->next
= body_block
->v
.chunk
;
1827 expression_last
->next
= switch_instruction
;
1828 expression_last
->v
.chunk
->next
= switch_instruction
->v
.chunk
;
1829 body_last
->next
= sw_state
.default_label
;
1830 body_last
->v
.chunk
->next
= NULL
;
1831 state
->chunk
= body_last
->v
.chunk
;
1832 for (; body_block
!= sw_state
.default_label
; body_block
= body_block
->next
)
1833 body_block
->pc
+= switch_length
;
1835 state
->sw_state
= sw_state
.prev
;
1840 exp
= TREE_OPERAND (exp
, 0);
1841 if (exp
== NULL_TREE
)
1842 exp
= empty_stmt_node
;
1843 else if (TREE_CODE (exp
) != MODIFY_EXPR
)
1846 exp
= TREE_OPERAND (exp
, 1);
1847 generate_bytecode_return (exp
, state
);
1849 case LABELED_BLOCK_EXPR
:
1851 struct jcf_block
*end_label
= gen_jcf_label (state
);
1852 end_label
->next
= state
->labeled_blocks
;
1853 state
->labeled_blocks
= end_label
;
1854 end_label
->pc
= PENDING_EXIT_PC
;
1855 end_label
->u
.labeled_block
= exp
;
1856 if (LABELED_BLOCK_BODY (exp
))
1857 generate_bytecode_insns (LABELED_BLOCK_BODY (exp
), target
, state
);
1858 if (state
->labeled_blocks
!= end_label
)
1860 state
->labeled_blocks
= end_label
->next
;
1861 define_jcf_label (end_label
, state
);
1866 tree body
= TREE_OPERAND (exp
, 0);
1868 if (TREE_CODE (body
) == COMPOUND_EXPR
1869 && TREE_CODE (TREE_OPERAND (body
, 0)) == EXIT_EXPR
)
1871 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1872 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1873 struct jcf_block
*head_label
;
1874 struct jcf_block
*body_label
;
1875 struct jcf_block
*end_label
= gen_jcf_label (state
);
1876 struct jcf_block
*exit_label
= state
->labeled_blocks
;
1877 head_label
= gen_jcf_label (state
);
1878 emit_goto (head_label
, state
);
1879 body_label
= get_jcf_label_here (state
);
1880 generate_bytecode_insns (TREE_OPERAND (body
, 1), target
, state
);
1881 define_jcf_label (head_label
, state
);
1882 generate_bytecode_conditional (TREE_OPERAND (body
, 0),
1883 end_label
, body_label
, 1, state
);
1884 define_jcf_label (end_label
, state
);
1889 struct jcf_block
*head_label
= get_jcf_label_here (state
);
1890 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1891 if (CAN_COMPLETE_NORMALLY (body
))
1892 emit_goto (head_label
, state
);
1898 struct jcf_block
*label
= state
->labeled_blocks
;
1899 struct jcf_block
*end_label
= gen_jcf_label (state
);
1900 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1901 label
, end_label
, 0, state
);
1902 define_jcf_label (end_label
, state
);
1905 case EXIT_BLOCK_EXPR
:
1907 struct jcf_block
*label
= state
->labeled_blocks
;
1908 if (TREE_OPERAND (exp
, 1) != NULL
) goto notimpl
;
1909 while (label
->u
.labeled_block
!= TREE_OPERAND (exp
, 0))
1910 label
= label
->next
;
1911 call_cleanups (label
, state
);
1912 emit_goto (label
, state
);
1916 case PREDECREMENT_EXPR
: value
= -1; post_op
= 0; goto increment
;
1917 case PREINCREMENT_EXPR
: value
= 1; post_op
= 0; goto increment
;
1918 case POSTDECREMENT_EXPR
: value
= -1; post_op
= 1; goto increment
;
1919 case POSTINCREMENT_EXPR
: value
= 1; post_op
= 1; goto increment
;
1922 arg
= TREE_OPERAND (exp
, 1);
1923 exp
= TREE_OPERAND (exp
, 0);
1924 type
= TREE_TYPE (exp
);
1925 size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1926 if ((TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1927 && ! TREE_STATIC (exp
)
1928 && TREE_CODE (type
) == INTEGER_TYPE
1929 && TYPE_PRECISION (type
) == 32)
1931 if (target
!= IGNORE_TARGET
&& post_op
)
1932 emit_load (exp
, state
);
1933 emit_iinc (exp
, value
, state
);
1934 if (target
!= IGNORE_TARGET
&& ! post_op
)
1935 emit_load (exp
, state
);
1938 if (TREE_CODE (exp
) == COMPONENT_REF
)
1940 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1941 emit_dup (1, 0, state
);
1942 /* Stack: ..., objectref, objectref. */
1943 field_op (TREE_OPERAND (exp
, 1), OPCODE_getfield
, state
);
1945 /* Stack: ..., objectref, oldvalue. */
1948 else if (TREE_CODE (exp
) == ARRAY_REF
)
1950 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1951 generate_bytecode_insns (TREE_OPERAND (exp
, 1), STACK_TARGET
, state
);
1952 emit_dup (2, 0, state
);
1953 /* Stack: ..., array, index, array, index. */
1954 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (exp
), 7);
1958 /* Stack: ..., array, index, oldvalue. */
1961 else if (TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1963 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1964 /* Stack: ..., oldvalue. */
1970 if (target
!= IGNORE_TARGET
&& post_op
)
1971 emit_dup (size
, offset
, state
);
1972 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1973 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1974 /* Stack, otherwise: ..., [result, ] oldvalue. */
1975 generate_bytecode_insns (arg
, STACK_TARGET
, state
);
1976 emit_binop ((value
>= 0 ? OPCODE_iadd
: OPCODE_isub
)
1977 + adjust_typed_op (type
, 3),
1979 if (target
!= IGNORE_TARGET
&& ! post_op
)
1980 emit_dup (size
, offset
, state
);
1981 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1982 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1983 /* Stack, otherwise: ..., [result, ] newvalue. */
1984 goto finish_assignment
;
1988 tree lhs
= TREE_OPERAND (exp
, 0);
1989 tree rhs
= TREE_OPERAND (exp
, 1);
1992 /* See if we can use the iinc instruction. */
1993 if ((TREE_CODE (lhs
) == VAR_DECL
|| TREE_CODE (lhs
) == PARM_DECL
)
1994 && ! TREE_STATIC (lhs
)
1995 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
1996 && TYPE_PRECISION (TREE_TYPE (lhs
)) == 32
1997 && (TREE_CODE (rhs
) == PLUS_EXPR
|| TREE_CODE (rhs
) == MINUS_EXPR
))
1999 tree arg0
= TREE_OPERAND (rhs
, 0);
2000 tree arg1
= TREE_OPERAND (rhs
, 1);
2001 HOST_WIDE_INT min_value
= -32768;
2002 HOST_WIDE_INT max_value
= 32767;
2003 if (TREE_CODE (rhs
) == MINUS_EXPR
)
2008 else if (arg1
== lhs
)
2011 arg1
= TREE_OPERAND (rhs
, 0);
2013 if (lhs
== arg0
&& TREE_CODE (arg1
) == INTEGER_CST
)
2015 HOST_WIDE_INT hi_value
= TREE_INT_CST_HIGH (arg1
);
2016 value
= TREE_INT_CST_LOW (arg1
);
2017 if ((hi_value
== 0 && value
<= max_value
)
2018 || (hi_value
== -1 && value
>= min_value
))
2020 if (TREE_CODE (rhs
) == MINUS_EXPR
)
2022 emit_iinc (lhs
, value
, state
);
2023 if (target
!= IGNORE_TARGET
)
2024 emit_load (lhs
, state
);
2030 if (TREE_CODE (lhs
) == COMPONENT_REF
)
2032 generate_bytecode_insns (TREE_OPERAND (lhs
, 0),
2033 STACK_TARGET
, state
);
2036 else if (TREE_CODE (lhs
) == ARRAY_REF
)
2038 generate_bytecode_insns (TREE_OPERAND(lhs
, 0),
2039 STACK_TARGET
, state
);
2040 generate_bytecode_insns (TREE_OPERAND(lhs
, 1),
2041 STACK_TARGET
, state
);
2047 /* If the rhs is a binary expression and the left operand is
2048 `==' to the lhs then we have an OP= expression. In this
2049 case we must do some special processing. */
2050 if (TREE_CODE_CLASS (TREE_CODE (rhs
)) == '2'
2051 && lhs
== TREE_OPERAND (rhs
, 0))
2053 if (TREE_CODE (lhs
) == COMPONENT_REF
)
2055 tree field
= TREE_OPERAND (lhs
, 1);
2056 if (! FIELD_STATIC (field
))
2058 /* Duplicate the object reference so we can get
2060 emit_dup (TYPE_IS_WIDE (field
) ? 2 : 1, 0, state
);
2063 field_op (field
, (FIELD_STATIC (field
)
2068 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
2070 else if (TREE_CODE (lhs
) == VAR_DECL
2071 || TREE_CODE (lhs
) == PARM_DECL
)
2073 if (FIELD_STATIC (lhs
))
2075 field_op (lhs
, OPCODE_getstatic
, state
);
2076 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs
)) ? 2 : 1);
2079 emit_load (lhs
, state
);
2081 else if (TREE_CODE (lhs
) == ARRAY_REF
)
2083 /* Duplicate the array and index, which are on the
2084 stack, so that we can load the old value. */
2085 emit_dup (2, 0, state
);
2087 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (lhs
), 7);
2090 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs
)) ? 2 : 1);
2095 /* This function correctly handles the case where the LHS
2096 of a binary expression is NULL_TREE. */
2097 rhs
= build (TREE_CODE (rhs
), TREE_TYPE (rhs
),
2098 NULL_TREE
, TREE_OPERAND (rhs
, 1));
2101 generate_bytecode_insns (rhs
, STACK_TARGET
, state
);
2102 if (target
!= IGNORE_TARGET
)
2103 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1 , offset
, state
);
2109 if (TREE_CODE (exp
) == COMPONENT_REF
)
2111 tree field
= TREE_OPERAND (exp
, 1);
2112 if (! FIELD_STATIC (field
))
2115 FIELD_STATIC (field
) ? OPCODE_putstatic
: OPCODE_putfield
,
2118 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
2120 else if (TREE_CODE (exp
) == VAR_DECL
2121 || TREE_CODE (exp
) == PARM_DECL
)
2123 if (FIELD_STATIC (exp
))
2125 field_op (exp
, OPCODE_putstatic
, state
);
2126 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
2129 emit_store (exp
, state
);
2131 else if (TREE_CODE (exp
) == ARRAY_REF
)
2133 jopcode
= OPCODE_iastore
+ adjust_typed_op (TREE_TYPE (exp
), 7);
2136 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 4 : 3);
2142 jopcode
= OPCODE_iadd
;
2145 jopcode
= OPCODE_isub
;
2148 jopcode
= OPCODE_imul
;
2150 case TRUNC_DIV_EXPR
:
2152 jopcode
= OPCODE_idiv
;
2154 case TRUNC_MOD_EXPR
:
2155 jopcode
= OPCODE_irem
;
2157 case LSHIFT_EXPR
: jopcode
= OPCODE_ishl
; goto binop
;
2158 case RSHIFT_EXPR
: jopcode
= OPCODE_ishr
; goto binop
;
2159 case URSHIFT_EXPR
: jopcode
= OPCODE_iushr
; goto binop
;
2160 case TRUTH_AND_EXPR
:
2161 case BIT_AND_EXPR
: jopcode
= OPCODE_iand
; goto binop
;
2163 case BIT_IOR_EXPR
: jopcode
= OPCODE_ior
; goto binop
;
2164 case TRUTH_XOR_EXPR
:
2165 case BIT_XOR_EXPR
: jopcode
= OPCODE_ixor
; goto binop
;
2168 tree arg0
= TREE_OPERAND (exp
, 0);
2169 tree arg1
= TREE_OPERAND (exp
, 1);
2170 jopcode
+= adjust_typed_op (type
, 3);
2171 if (arg0
== arg1
&& TREE_CODE (arg0
) == SAVE_EXPR
)
2173 /* fold may (e.g) convert 2*x to x+x. */
2174 generate_bytecode_insns (TREE_OPERAND (arg0
, 0), target
, state
);
2175 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0
)) > 32 ? 2 : 1, 0, state
);
2179 /* ARG0 will be NULL_TREE if we're handling an `OP='
2180 expression. In this case the stack already holds the
2181 LHS. See the MODIFY_EXPR case. */
2182 if (arg0
!= NULL_TREE
)
2183 generate_bytecode_insns (arg0
, target
, state
);
2184 if (jopcode
>= OPCODE_lshl
&& jopcode
<= OPCODE_lushr
)
2185 arg1
= convert (int_type_node
, arg1
);
2186 generate_bytecode_insns (arg1
, target
, state
);
2188 /* For most binary operations, both operands and the result have the
2189 same type. Shift operations are different. Using arg1's type
2190 gets us the correct SP adjustment in all cases. */
2191 if (target
== STACK_TARGET
)
2192 emit_binop (jopcode
, TREE_TYPE (arg1
), state
);
2195 case TRUTH_NOT_EXPR
:
2197 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2198 if (target
== STACK_TARGET
)
2200 int is_long
= TYPE_PRECISION (TREE_TYPE (exp
)) > 32;
2201 push_int_const (TREE_CODE (exp
) == BIT_NOT_EXPR
? -1 : 1, state
);
2205 NOTE_PUSH (1 + is_long
);
2206 OP1 (OPCODE_ixor
+ is_long
);
2207 NOTE_POP (1 + is_long
);
2211 jopcode
= OPCODE_ineg
;
2212 jopcode
+= adjust_typed_op (type
, 3);
2213 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2214 if (target
== STACK_TARGET
)
2215 emit_unop (jopcode
, type
, state
);
2217 case INSTANCEOF_EXPR
:
2219 int index
= find_class_constant (&state
->cpool
, TREE_OPERAND (exp
, 1));
2220 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2222 OP1 (OPCODE_instanceof
);
2227 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
2232 case FIX_TRUNC_EXPR
:
2234 tree src
= TREE_OPERAND (exp
, 0);
2235 tree src_type
= TREE_TYPE (src
);
2236 tree dst_type
= TREE_TYPE (exp
);
2237 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2238 if (target
== IGNORE_TARGET
|| src_type
== dst_type
)
2240 if (TREE_CODE (dst_type
) == POINTER_TYPE
)
2242 if (TREE_CODE (exp
) == CONVERT_EXPR
)
2244 int index
= find_class_constant (&state
->cpool
,
2245 TREE_TYPE (dst_type
));
2247 OP1 (OPCODE_checkcast
);
2251 else /* Convert numeric types. */
2253 int wide_src
= TYPE_PRECISION (src_type
) > 32;
2254 int wide_dst
= TYPE_PRECISION (dst_type
) > 32;
2255 NOTE_POP (1 + wide_src
);
2257 if (TREE_CODE (dst_type
) == REAL_TYPE
)
2259 if (TREE_CODE (src_type
) == REAL_TYPE
)
2260 OP1 (wide_dst
? OPCODE_f2d
: OPCODE_d2f
);
2261 else if (TYPE_PRECISION (src_type
) == 64)
2262 OP1 (OPCODE_l2f
+ wide_dst
);
2264 OP1 (OPCODE_i2f
+ wide_dst
);
2266 else /* Convert to integral type. */
2268 if (TREE_CODE (src_type
) == REAL_TYPE
)
2269 OP1 (OPCODE_f2i
+ wide_dst
+ 3 * wide_src
);
2274 if (TYPE_PRECISION (dst_type
) < 32)
2277 /* Already converted to int, if needed. */
2278 if (TYPE_PRECISION (dst_type
) <= 8)
2280 else if (TREE_UNSIGNED (dst_type
))
2286 NOTE_PUSH (1 + wide_dst
);
2293 tree try_clause
= TREE_OPERAND (exp
, 0);
2294 struct jcf_block
*start_label
= get_jcf_label_here (state
);
2295 struct jcf_block
*end_label
; /* End of try clause. */
2296 struct jcf_block
*finished_label
= gen_jcf_label (state
);
2297 tree clause
= TREE_OPERAND (exp
, 1);
2298 if (target
!= IGNORE_TARGET
)
2300 generate_bytecode_insns (try_clause
, IGNORE_TARGET
, state
);
2301 end_label
= get_jcf_label_here (state
);
2302 if (end_label
== start_label
)
2304 if (CAN_COMPLETE_NORMALLY (try_clause
))
2305 emit_goto (finished_label
, state
);
2306 while (clause
!= NULL_TREE
)
2308 tree catch_clause
= TREE_OPERAND (clause
, 0);
2309 tree exception_decl
= BLOCK_EXPR_DECLS (catch_clause
);
2310 struct jcf_handler
*handler
= alloc_handler (start_label
,
2312 if (exception_decl
== NULL_TREE
)
2313 handler
->type
= NULL_TREE
;
2315 handler
->type
= TREE_TYPE (TREE_TYPE (exception_decl
));
2316 generate_bytecode_insns (catch_clause
, IGNORE_TARGET
, state
);
2317 clause
= TREE_CHAIN (clause
);
2318 if (CAN_COMPLETE_NORMALLY (catch_clause
) && clause
!= NULL_TREE
)
2319 emit_goto (finished_label
, state
);
2321 define_jcf_label (finished_label
, state
);
2325 case TRY_FINALLY_EXPR
:
2327 struct jcf_block
*finished_label
= NULL
;
2328 struct jcf_block
*finally_label
, *start_label
, *end_label
;
2329 struct jcf_handler
*handler
;
2330 tree try_block
= TREE_OPERAND (exp
, 0);
2331 tree finally
= TREE_OPERAND (exp
, 1);
2332 tree return_link
= NULL_TREE
, exception_decl
= NULL_TREE
;
2334 tree exception_type
;
2336 finally_label
= gen_jcf_label (state
);
2337 start_label
= get_jcf_label_here (state
);
2338 /* If the `finally' clause can complete normally, we emit it
2339 as a subroutine and let the other clauses call it via
2340 `jsr'. If it can't complete normally, then we simply emit
2341 `goto's directly to it. */
2342 if (CAN_COMPLETE_NORMALLY (finally
))
2344 finally_label
->pc
= PENDING_CLEANUP_PC
;
2345 finally_label
->next
= state
->labeled_blocks
;
2346 state
->labeled_blocks
= finally_label
;
2347 state
->num_finalizers
++;
2350 generate_bytecode_insns (try_block
, target
, state
);
2352 if (CAN_COMPLETE_NORMALLY (finally
))
2354 if (state
->labeled_blocks
!= finally_label
)
2356 state
->labeled_blocks
= finally_label
->next
;
2358 end_label
= get_jcf_label_here (state
);
2360 if (end_label
== start_label
)
2362 state
->num_finalizers
--;
2363 define_jcf_label (finally_label
, state
);
2364 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2368 if (CAN_COMPLETE_NORMALLY (finally
))
2370 return_link
= build_decl (VAR_DECL
, NULL_TREE
,
2371 return_address_type_node
);
2372 finished_label
= gen_jcf_label (state
);
2375 if (CAN_COMPLETE_NORMALLY (try_block
))
2377 if (CAN_COMPLETE_NORMALLY (finally
))
2379 emit_jsr (finally_label
, state
);
2380 emit_goto (finished_label
, state
);
2383 emit_goto (finally_label
, state
);
2386 /* Handle exceptions. */
2388 exception_type
= build_pointer_type (throwable_type_node
);
2389 if (CAN_COMPLETE_NORMALLY (finally
))
2391 /* We're going to generate a subroutine, so we'll need to
2392 save and restore the exception around the `jsr'. */
2393 exception_decl
= build_decl (VAR_DECL
, NULL_TREE
, exception_type
);
2394 localvar_alloc (return_link
, state
);
2396 handler
= alloc_handler (start_label
, end_label
, state
);
2397 handler
->type
= NULL_TREE
;
2398 if (CAN_COMPLETE_NORMALLY (finally
))
2400 localvar_alloc (exception_decl
, state
);
2402 emit_store (exception_decl
, state
);
2403 emit_jsr (finally_label
, state
);
2404 emit_load (exception_decl
, state
);
2406 OP1 (OPCODE_athrow
);
2411 /* We're not generating a subroutine. In this case we can
2412 simply have the exception handler pop the exception and
2413 then fall through to the `finally' block. */
2415 emit_pop (1, state
);
2419 /* The finally block. If we're generating a subroutine, first
2420 save return PC into return_link. Otherwise, just generate
2421 the code for the `finally' block. */
2422 define_jcf_label (finally_label
, state
);
2423 if (CAN_COMPLETE_NORMALLY (finally
))
2426 emit_store (return_link
, state
);
2429 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2430 if (CAN_COMPLETE_NORMALLY (finally
))
2432 maybe_wide (OPCODE_ret
, DECL_LOCAL_INDEX (return_link
), state
);
2433 localvar_free (exception_decl
, state
);
2434 localvar_free (return_link
, state
);
2435 define_jcf_label (finished_label
, state
);
2440 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
2442 OP1 (OPCODE_athrow
);
2444 case NEW_ARRAY_INIT
:
2446 tree values
= CONSTRUCTOR_ELTS (TREE_OPERAND (exp
, 0));
2447 tree array_type
= TREE_TYPE (TREE_TYPE (exp
));
2448 tree element_type
= TYPE_ARRAY_ELEMENT (array_type
);
2449 HOST_WIDE_INT length
= java_array_type_length (array_type
);
2450 if (target
== IGNORE_TARGET
)
2452 for ( ; values
!= NULL_TREE
; values
= TREE_CHAIN (values
))
2453 generate_bytecode_insns (TREE_VALUE (values
), target
, state
);
2456 push_int_const (length
, state
);
2459 if (JPRIMITIVE_TYPE_P (element_type
))
2461 int atype
= encode_newarray_type (element_type
);
2462 OP1 (OPCODE_newarray
);
2467 int index
= find_class_constant (&state
->cpool
,
2468 TREE_TYPE (element_type
));
2469 OP1 (OPCODE_anewarray
);
2473 jopcode
= OPCODE_iastore
+ adjust_typed_op (element_type
, 7);
2474 for ( ; values
!= NULL_TREE
; values
= TREE_CHAIN (values
), offset
++)
2476 int save_SP
= state
->code_SP
;
2477 emit_dup (1, 0, state
);
2478 push_int_const (offset
, state
);
2480 generate_bytecode_insns (TREE_VALUE (values
), STACK_TARGET
, state
);
2483 state
->code_SP
= save_SP
;
2487 case JAVA_EXC_OBJ_EXPR
:
2488 NOTE_PUSH (1); /* Pushed by exception system. */
2490 case NEW_CLASS_EXPR
:
2492 tree
class = TREE_TYPE (TREE_TYPE (exp
));
2493 int need_result
= target
!= IGNORE_TARGET
;
2494 int index
= find_class_constant (&state
->cpool
, class);
2500 NOTE_PUSH (1 + need_result
);
2502 /* ... fall though ... */
2505 tree f
= TREE_OPERAND (exp
, 0);
2506 tree x
= TREE_OPERAND (exp
, 1);
2507 int save_SP
= state
->code_SP
;
2509 if (TREE_CODE (f
) == ADDR_EXPR
)
2510 f
= TREE_OPERAND (f
, 0);
2511 if (f
== soft_newarray_node
)
2513 int type_code
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2514 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x
)),
2515 STACK_TARGET
, state
);
2517 OP1 (OPCODE_newarray
);
2521 else if (f
== soft_multianewarray_node
)
2525 int index
= find_class_constant (&state
->cpool
,
2526 TREE_TYPE (TREE_TYPE (exp
)));
2527 x
= TREE_CHAIN (x
); /* Skip class argument. */
2528 ndims
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2529 for (idim
= ndims
; --idim
>= 0; )
2532 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2535 OP1 (OPCODE_multianewarray
);
2540 else if (f
== soft_anewarray_node
)
2542 tree cl
= TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp
)));
2543 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (cl
));
2544 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2546 OP1 (OPCODE_anewarray
);
2550 else if (f
== soft_monitorenter_node
2551 || f
== soft_monitorexit_node
2554 if (f
== soft_monitorenter_node
)
2555 op
= OPCODE_monitorenter
;
2556 else if (f
== soft_monitorexit_node
)
2557 op
= OPCODE_monitorexit
;
2560 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2566 for ( ; x
!= NULL_TREE
; x
= TREE_CHAIN (x
))
2568 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2570 nargs
= state
->code_SP
- save_SP
;
2571 state
->code_SP
= save_SP
;
2572 if (f
== soft_fmod_node
)
2579 if (TREE_CODE (exp
) == NEW_CLASS_EXPR
)
2580 NOTE_POP (1); /* Pop implicit this. */
2581 if (TREE_CODE (f
) == FUNCTION_DECL
&& DECL_CONTEXT (f
) != NULL_TREE
)
2583 tree context
= DECL_CONTEXT (f
);
2584 int index
, interface
= 0;
2586 if (METHOD_STATIC (f
))
2587 OP1 (OPCODE_invokestatic
);
2588 else if (DECL_CONSTRUCTOR_P (f
) || CALL_USING_SUPER (exp
)
2589 || METHOD_PRIVATE (f
))
2590 OP1 (OPCODE_invokespecial
);
2593 if (CLASS_INTERFACE (TYPE_NAME (context
)))
2595 tree arg1
= TREE_VALUE (TREE_OPERAND (exp
, 1));
2596 context
= TREE_TYPE (TREE_TYPE (arg1
));
2597 if (CLASS_INTERFACE (TYPE_NAME (context
)))
2601 OP1 (OPCODE_invokeinterface
);
2603 OP1 (OPCODE_invokevirtual
);
2605 index
= find_methodref_with_class_index (&state
->cpool
, f
, context
);
2615 f
= TREE_TYPE (TREE_TYPE (f
));
2616 if (TREE_CODE (f
) != VOID_TYPE
)
2618 int size
= TYPE_IS_WIDE (f
) ? 2 : 1;
2619 if (target
== IGNORE_TARGET
)
2620 emit_pop (size
, state
);
2630 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2631 tree_code_name
[(int) TREE_CODE (exp
)]);
2636 perform_relocations (state
)
2637 struct jcf_partial
*state
;
2639 struct jcf_block
*block
;
2640 struct jcf_relocation
*reloc
;
2644 /* Before we start, the pc field of each block is an upper bound on
2645 the block's start pc (it may be less, if previous blocks need less
2646 than their maximum).
2648 The minimum size of each block is in the block's chunk->size. */
2650 /* First, figure out the actual locations of each block. */
2653 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2655 int block_size
= block
->v
.chunk
->size
;
2659 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2660 Assumes relocations are in reverse order. */
2661 reloc
= block
->u
.relocations
;
2662 while (reloc
!= NULL
2663 && reloc
->kind
== OPCODE_goto_w
2664 && reloc
->label
->pc
== block
->next
->pc
2665 && reloc
->offset
+ 2 == block_size
)
2667 reloc
= reloc
->next
;
2668 block
->u
.relocations
= reloc
;
2669 block
->v
.chunk
->size
-= 3;
2674 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
2676 if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2678 /* We assume this is the first relocation in this block,
2679 so we know its final pc. */
2680 int where
= pc
+ reloc
->offset
;
2681 int pad
= ((where
+ 3) & ~3) - where
;
2684 else if (reloc
->kind
< -1 || reloc
->kind
> BLOCK_START_RELOC
)
2686 int delta
= reloc
->label
->pc
- (pc
+ reloc
->offset
- 1);
2687 int expand
= reloc
->kind
> 0 ? 2 : 5;
2691 if (delta
>= -32768 && delta
<= 32767)
2697 block_size
+= expand
;
2703 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2705 struct chunk
*chunk
= block
->v
.chunk
;
2706 int old_size
= chunk
->size
;
2707 int next_pc
= block
->next
== NULL
? pc
: block
->next
->pc
;
2708 int new_size
= next_pc
- block
->pc
;
2709 unsigned char *new_ptr
;
2710 unsigned char *old_buffer
= chunk
->data
;
2711 unsigned char *old_ptr
= old_buffer
+ old_size
;
2712 if (new_size
!= old_size
)
2714 chunk
->data
= (unsigned char *)
2715 obstack_alloc (state
->chunk_obstack
, new_size
);
2716 chunk
->size
= new_size
;
2718 new_ptr
= chunk
->data
+ new_size
;
2720 /* We do the relocations from back to front, because
2721 the relocations are in reverse order. */
2722 for (reloc
= block
->u
.relocations
; ; reloc
= reloc
->next
)
2724 /* new_ptr and old_ptr point into the old and new buffers,
2725 respectively. (If no relocations cause the buffer to
2726 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2727 The bytes at higher address have been copied and relocations
2728 handled; those at lower addresses remain to process. */
2730 /* Lower old index of piece to be copied with no relocation.
2731 I.e. high index of the first piece that does need relocation. */
2732 int start
= reloc
== NULL
? 0
2733 : reloc
->kind
== SWITCH_ALIGN_RELOC
? reloc
->offset
2734 : (reloc
->kind
== 0 || reloc
->kind
== BLOCK_START_RELOC
)
2736 : reloc
->offset
+ 2;
2739 int n
= (old_ptr
- old_buffer
) - start
;
2743 memcpy (new_ptr
, old_ptr
, n
);
2744 if (old_ptr
== old_buffer
)
2747 new_offset
= new_ptr
- chunk
->data
;
2748 new_offset
-= (reloc
->kind
== -1 ? 2 : 4);
2749 if (reloc
->kind
== 0)
2752 value
= GET_u4 (old_ptr
);
2754 else if (reloc
->kind
== BLOCK_START_RELOC
)
2760 else if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2762 int where
= block
->pc
+ reloc
->offset
;
2763 int pad
= ((where
+ 3) & ~3) - where
;
2771 value
= GET_u2 (old_ptr
);
2773 value
+= reloc
->label
->pc
- (block
->pc
+ new_offset
);
2774 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2775 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2776 if (reloc
->kind
!= -1)
2778 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2779 *--new_ptr
= (unsigned char) value
;
2781 if (reloc
->kind
> BLOCK_START_RELOC
)
2783 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2785 *--new_ptr
= reloc
->kind
;
2787 else if (reloc
->kind
< -1)
2789 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2791 *--new_ptr
= OPCODE_goto_w
;
2794 *--new_ptr
= - reloc
->kind
;
2797 if (new_ptr
!= chunk
->data
)
2800 state
->code_length
= pc
;
2804 init_jcf_state (state
, work
)
2805 struct jcf_partial
*state
;
2806 struct obstack
*work
;
2808 state
->chunk_obstack
= work
;
2809 state
->first
= state
->chunk
= NULL
;
2810 CPOOL_INIT (&state
->cpool
);
2811 BUFFER_INIT (&state
->localvars
);
2812 BUFFER_INIT (&state
->bytecode
);
2816 init_jcf_method (state
, method
)
2817 struct jcf_partial
*state
;
2820 state
->current_method
= method
;
2821 state
->blocks
= state
->last_block
= NULL
;
2822 state
->linenumber_count
= 0;
2823 state
->first_lvar
= state
->last_lvar
= NULL
;
2824 state
->lvar_count
= 0;
2825 state
->labeled_blocks
= NULL
;
2826 state
->code_length
= 0;
2827 BUFFER_RESET (&state
->bytecode
);
2828 BUFFER_RESET (&state
->localvars
);
2830 state
->code_SP_max
= 0;
2831 state
->handlers
= NULL
;
2832 state
->last_handler
= NULL
;
2833 state
->num_handlers
= 0;
2834 state
->num_finalizers
= 0;
2835 state
->return_value_decl
= NULL_TREE
;
2839 release_jcf_state (state
)
2840 struct jcf_partial
*state
;
2842 CPOOL_FINISH (&state
->cpool
);
2843 obstack_free (state
->chunk_obstack
, state
->first
);
2846 /* Generate and return a list of chunks containing the class CLAS
2847 in the .class file representation. The list can be written to a
2848 .class file using write_chunks. Allocate chunks from obstack WORK. */
2850 static struct chunk
*
2851 generate_classfile (clas
, state
)
2853 struct jcf_partial
*state
;
2855 struct chunk
*cpool_chunk
;
2856 const char *source_file
, *s
;
2859 char *fields_count_ptr
;
2860 int fields_count
= 0;
2861 char *methods_count_ptr
;
2862 int methods_count
= 0;
2863 static tree SourceFile_node
= NULL_TREE
;
2866 = clas
== object_type_node
? 0
2867 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas
));
2869 ptr
= append_chunk (NULL
, 8, state
);
2870 PUT4 (0xCafeBabe); /* Magic number */
2871 PUT2 (3); /* Minor version */
2872 PUT2 (45); /* Major version */
2874 append_chunk (NULL
, 0, state
);
2875 cpool_chunk
= state
->chunk
;
2877 /* Next allocate the chunk containing acces_flags through fields_counr. */
2878 if (clas
== object_type_node
)
2881 i
= 8 + 2 * total_supers
;
2882 ptr
= append_chunk (NULL
, i
, state
);
2883 i
= get_access_flags (TYPE_NAME (clas
));
2884 if (! (i
& ACC_INTERFACE
))
2886 PUT2 (i
); /* acces_flags */
2887 i
= find_class_constant (&state
->cpool
, clas
); PUT2 (i
); /* this_class */
2888 if (clas
== object_type_node
)
2890 PUT2(0); /* super_class */
2891 PUT2(0); /* interfaces_count */
2895 tree basetypes
= TYPE_BINFO_BASETYPES (clas
);
2896 tree base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, 0));
2897 int j
= find_class_constant (&state
->cpool
, base
);
2898 PUT2 (j
); /* super_class */
2899 PUT2 (total_supers
- 1); /* interfaces_count */
2900 for (i
= 1; i
< total_supers
; i
++)
2902 base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, i
));
2903 j
= find_class_constant (&state
->cpool
, base
);
2907 fields_count_ptr
= ptr
;
2909 for (part
= TYPE_FIELDS (clas
); part
; part
= TREE_CHAIN (part
))
2911 int have_value
, attr_count
= 0;
2912 if (DECL_NAME (part
) == NULL_TREE
|| DECL_ARTIFICIAL (part
))
2914 ptr
= append_chunk (NULL
, 8, state
);
2915 i
= get_access_flags (part
); PUT2 (i
);
2916 i
= find_utf8_constant (&state
->cpool
, DECL_NAME (part
)); PUT2 (i
);
2917 i
= find_utf8_constant (&state
->cpool
,
2918 build_java_signature (TREE_TYPE (part
)));
2920 have_value
= DECL_INITIAL (part
) != NULL_TREE
2921 && FIELD_STATIC (part
) && CONSTANT_VALUE_P (DECL_INITIAL (part
))
2922 && FIELD_FINAL (part
)
2923 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part
))
2924 || TREE_TYPE (part
) == string_ptr_type_node
);
2928 if (FIELD_THISN (part
) || FIELD_LOCAL_ALIAS (part
))
2931 PUT2 (attr_count
); /* attributes_count */
2934 tree init
= DECL_INITIAL (part
);
2935 static tree ConstantValue_node
= NULL_TREE
;
2936 if (TREE_TYPE (part
) != TREE_TYPE (init
))
2937 fatal_error ("field initializer type mismatch");
2938 ptr
= append_chunk (NULL
, 8, state
);
2939 if (ConstantValue_node
== NULL_TREE
)
2940 ConstantValue_node
= get_identifier ("ConstantValue");
2941 i
= find_utf8_constant (&state
->cpool
, ConstantValue_node
);
2942 PUT2 (i
); /* attribute_name_index */
2943 PUT4 (2); /* attribute_length */
2944 i
= find_constant_index (init
, state
); PUT2 (i
);
2946 /* Emit the "Synthetic" attribute for val$<x> and this$<n> fields. */
2947 if (FIELD_THISN (part
) || FIELD_LOCAL_ALIAS (part
))
2948 ptr
= append_synthetic_attribute (state
);
2951 ptr
= fields_count_ptr
; UNSAFE_PUT2 (fields_count
);
2953 ptr
= methods_count_ptr
= append_chunk (NULL
, 2, state
);
2956 for (part
= TYPE_METHODS (clas
); part
; part
= TREE_CHAIN (part
))
2958 struct jcf_block
*block
;
2959 tree function_body
= DECL_FUNCTION_BODY (part
);
2960 tree body
= function_body
== NULL_TREE
? NULL_TREE
2961 : BLOCK_EXPR_BODY (function_body
);
2962 tree name
= DECL_CONSTRUCTOR_P (part
) ? init_identifier_node
2964 tree type
= TREE_TYPE (part
);
2965 tree save_function
= current_function_decl
;
2966 int synthetic_p
= 0;
2967 current_function_decl
= part
;
2968 ptr
= append_chunk (NULL
, 8, state
);
2969 i
= get_access_flags (part
); PUT2 (i
);
2970 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
2971 i
= find_utf8_constant (&state
->cpool
, build_java_signature (type
));
2973 i
= (body
!= NULL_TREE
) + (DECL_FUNCTION_THROWS (part
) != NULL_TREE
);
2975 /* Make room for the Synthetic attribute (of zero length.) */
2976 if (DECL_FINIT_P (part
)
2977 || DECL_INSTINIT_P (part
)
2978 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part
))
2979 || TYPE_DOT_CLASS (clas
) == part
)
2985 PUT2 (i
); /* attributes_count */
2988 ptr
= append_synthetic_attribute (state
);
2990 if (body
!= NULL_TREE
)
2992 int code_attributes_count
= 0;
2993 static tree Code_node
= NULL_TREE
;
2996 struct jcf_handler
*handler
;
2997 if (Code_node
== NULL_TREE
)
2998 Code_node
= get_identifier ("Code");
2999 ptr
= append_chunk (NULL
, 14, state
);
3000 i
= find_utf8_constant (&state
->cpool
, Code_node
); PUT2 (i
);
3002 init_jcf_method (state
, part
);
3003 get_jcf_label_here (state
); /* Force a first block. */
3004 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3005 localvar_alloc (t
, state
);
3006 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
3007 if (CAN_COMPLETE_NORMALLY (body
))
3009 if (TREE_CODE (TREE_TYPE (type
)) != VOID_TYPE
)
3012 OP1 (OPCODE_return
);
3014 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3015 localvar_free (t
, state
);
3016 if (state
->return_value_decl
!= NULL_TREE
)
3017 localvar_free (state
->return_value_decl
, state
);
3018 finish_jcf_block (state
);
3019 perform_relocations (state
);
3022 i
= 8 + state
->code_length
+ 4 + 8 * state
->num_handlers
;
3023 if (state
->linenumber_count
> 0)
3025 code_attributes_count
++;
3026 i
+= 8 + 4 * state
->linenumber_count
;
3028 if (state
->lvar_count
> 0)
3030 code_attributes_count
++;
3031 i
+= 8 + 10 * state
->lvar_count
;
3033 UNSAFE_PUT4 (i
); /* attribute_length */
3034 UNSAFE_PUT2 (state
->code_SP_max
); /* max_stack */
3035 UNSAFE_PUT2 (localvar_max
); /* max_locals */
3036 UNSAFE_PUT4 (state
->code_length
);
3038 /* Emit the exception table. */
3039 ptr
= append_chunk (NULL
, 2 + 8 * state
->num_handlers
, state
);
3040 PUT2 (state
->num_handlers
); /* exception_table_length */
3041 handler
= state
->handlers
;
3042 for (; handler
!= NULL
; handler
= handler
->next
)
3045 PUT2 (handler
->start_label
->pc
);
3046 PUT2 (handler
->end_label
->pc
);
3047 PUT2 (handler
->handler_label
->pc
);
3048 if (handler
->type
== NULL_TREE
)
3051 type_index
= find_class_constant (&state
->cpool
,
3056 ptr
= append_chunk (NULL
, 2, state
);
3057 PUT2 (code_attributes_count
);
3059 /* Write the LineNumberTable attribute. */
3060 if (state
->linenumber_count
> 0)
3062 static tree LineNumberTable_node
= NULL_TREE
;
3063 ptr
= append_chunk (NULL
,
3064 8 + 4 * state
->linenumber_count
, state
);
3065 if (LineNumberTable_node
== NULL_TREE
)
3066 LineNumberTable_node
= get_identifier ("LineNumberTable");
3067 i
= find_utf8_constant (&state
->cpool
, LineNumberTable_node
);
3068 PUT2 (i
); /* attribute_name_index */
3069 i
= 2+4*state
->linenumber_count
; PUT4(i
); /* attribute_length */
3070 i
= state
->linenumber_count
; PUT2 (i
);
3071 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
3073 int line
= block
->linenumber
;
3082 /* Write the LocalVariableTable attribute. */
3083 if (state
->lvar_count
> 0)
3085 static tree LocalVariableTable_node
= NULL_TREE
;
3086 struct localvar_info
*lvar
= state
->first_lvar
;
3087 ptr
= append_chunk (NULL
, 8 + 10 * state
->lvar_count
, state
);
3088 if (LocalVariableTable_node
== NULL_TREE
)
3089 LocalVariableTable_node
= get_identifier("LocalVariableTable");
3090 i
= find_utf8_constant (&state
->cpool
, LocalVariableTable_node
);
3091 PUT2 (i
); /* attribute_name_index */
3092 i
= 2 + 10 * state
->lvar_count
; PUT4 (i
); /* attribute_length */
3093 i
= state
->lvar_count
; PUT2 (i
);
3094 for ( ; lvar
!= NULL
; lvar
= lvar
->next
)
3096 tree name
= DECL_NAME (lvar
->decl
);
3097 tree sig
= build_java_signature (TREE_TYPE (lvar
->decl
));
3098 i
= lvar
->start_label
->pc
; PUT2 (i
);
3099 i
= lvar
->end_label
->pc
- i
; PUT2 (i
);
3100 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
3101 i
= find_utf8_constant (&state
->cpool
, sig
); PUT2 (i
);
3102 i
= DECL_LOCAL_INDEX (lvar
->decl
); PUT2 (i
);
3106 if (DECL_FUNCTION_THROWS (part
) != NULL_TREE
)
3108 tree t
= DECL_FUNCTION_THROWS (part
);
3109 int throws_count
= list_length (t
);
3110 static tree Exceptions_node
= NULL_TREE
;
3111 if (Exceptions_node
== NULL_TREE
)
3112 Exceptions_node
= get_identifier ("Exceptions");
3113 ptr
= append_chunk (NULL
, 8 + 2 * throws_count
, state
);
3114 i
= find_utf8_constant (&state
->cpool
, Exceptions_node
);
3115 PUT2 (i
); /* attribute_name_index */
3116 i
= 2 + 2 * throws_count
; PUT4(i
); /* attribute_length */
3117 i
= throws_count
; PUT2 (i
);
3118 for (; t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
3120 i
= find_class_constant (&state
->cpool
, TREE_VALUE (t
));
3125 current_function_decl
= save_function
;
3127 ptr
= methods_count_ptr
; UNSAFE_PUT2 (methods_count
);
3129 source_file
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3130 for (s
= source_file
; ; s
++)
3135 if (ch
== '/' || ch
== '\\')
3138 ptr
= append_chunk (NULL
, 10, state
);
3140 i
= 1; /* Source file always exists as an attribute */
3141 if (INNER_CLASS_TYPE_P (clas
) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas
)))
3143 if (clas
== object_type_node
)
3145 PUT2 (i
); /* attributes_count */
3147 /* generate the SourceFile attribute. */
3148 if (SourceFile_node
== NULL_TREE
)
3150 SourceFile_node
= get_identifier ("SourceFile");
3151 ggc_add_tree_root (&SourceFile_node
, 1);
3154 i
= find_utf8_constant (&state
->cpool
, SourceFile_node
);
3155 PUT2 (i
); /* attribute_name_index */
3157 i
= find_utf8_constant (&state
->cpool
, get_identifier (source_file
));
3159 append_gcj_attribute (state
, clas
);
3160 append_innerclasses_attribute (state
, clas
);
3162 /* New finally generate the contents of the constant pool chunk. */
3163 i
= count_constant_pool_bytes (&state
->cpool
);
3164 ptr
= obstack_alloc (state
->chunk_obstack
, i
);
3165 cpool_chunk
->data
= ptr
;
3166 cpool_chunk
->size
= i
;
3167 write_constant_pool (&state
->cpool
, ptr
, i
);
3168 return state
->first
;
3171 static unsigned char *
3172 append_synthetic_attribute (state
)
3173 struct jcf_partial
*state
;
3175 static tree Synthetic_node
= NULL_TREE
;
3176 unsigned char *ptr
= append_chunk (NULL
, 6, state
);
3179 if (Synthetic_node
== NULL_TREE
)
3181 Synthetic_node
= get_identifier ("Synthetic");
3182 ggc_add_tree_root (&Synthetic_node
, 1);
3184 i
= find_utf8_constant (&state
->cpool
, Synthetic_node
);
3185 PUT2 (i
); /* Attribute string index */
3186 PUT4 (0); /* Attribute length */
3192 append_gcj_attribute (state
, class)
3193 struct jcf_partial
*state
;
3199 if (class != object_type_node
)
3202 ptr
= append_chunk (NULL
, 6, state
); /* 2+4 */
3203 i
= find_utf8_constant (&state
->cpool
,
3204 get_identifier ("gnu.gcj.gcj-compiled"));
3205 PUT2 (i
); /* Attribute string index */
3206 PUT4 (0); /* Attribute length */
3210 append_innerclasses_attribute (state
, class)
3211 struct jcf_partial
*state
;
3214 static tree InnerClasses_node
= NULL_TREE
;
3215 tree orig_decl
= TYPE_NAME (class);
3218 unsigned char *ptr
, *length_marker
, *number_marker
;
3220 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl
))
3223 ptr
= append_chunk (NULL
, 8, state
); /* 2+4+2 */
3225 if (InnerClasses_node
== NULL_TREE
)
3227 InnerClasses_node
= get_identifier ("InnerClasses");
3228 ggc_add_tree_root (&InnerClasses_node
, 1);
3230 i
= find_utf8_constant (&state
->cpool
, InnerClasses_node
);
3232 length_marker
= ptr
; PUT4 (0); /* length, to be later patched */
3233 number_marker
= ptr
; PUT2 (0); /* number of classes, tblp */
3235 /* Generate the entries: all inner classes visible from the one we
3236 process: itself, up and down. */
3237 while (class && INNER_CLASS_TYPE_P (class))
3241 decl
= TYPE_NAME (class);
3242 n
= IDENTIFIER_POINTER (DECL_NAME (decl
)) +
3243 IDENTIFIER_LENGTH (DECL_NAME (decl
));
3245 while (n
[-1] != '$')
3247 append_innerclasses_attribute_entry (state
, decl
, get_identifier (n
));
3250 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3254 for (current
= DECL_INNER_CLASS_LIST (decl
);
3255 current
; current
= TREE_CHAIN (current
))
3257 append_innerclasses_attribute_entry (state
, TREE_PURPOSE (current
),
3258 TREE_VALUE (current
));
3262 ptr
= length_marker
; PUT4 (8*length
+2);
3263 ptr
= number_marker
; PUT2 (length
);
3267 append_innerclasses_attribute_entry (state
, decl
, name
)
3268 struct jcf_partial
*state
;
3272 int ocii
= 0, ini
= 0;
3273 unsigned char *ptr
= append_chunk (NULL
, 8, state
);
3275 icii
= find_class_constant (&state
->cpool
, TREE_TYPE (decl
));
3277 /* Sun's implementation seems to generate ocii to 0 for inner
3278 classes (which aren't considered members of the class they're
3279 in.) The specs are saying that if the class is anonymous,
3280 inner_name_index must be zero. */
3281 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl
)))
3283 ocii
= find_class_constant (&state
->cpool
,
3284 TREE_TYPE (DECL_CONTEXT (decl
)));
3285 ini
= find_utf8_constant (&state
->cpool
, name
);
3287 icaf
= get_access_flags (decl
);
3289 PUT2 (icii
); PUT2 (ocii
); PUT2 (ini
); PUT2 (icaf
);
3293 make_class_file_name (clas
)
3296 const char *dname
, *cname
, *slash
;
3300 cname
= IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas
)),
3301 "", '.', DIR_SEPARATOR
,
3303 if (jcf_write_base_directory
== NULL
)
3305 /* Make sure we put the class file into the .java file's
3306 directory, and not into some subdirectory thereof. */
3308 dname
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3309 slash
= strrchr (dname
, DIR_SEPARATOR
);
3315 t
= strrchr (cname
, DIR_SEPARATOR
);
3321 dname
= jcf_write_base_directory
;
3322 slash
= dname
+ strlen (dname
);
3325 r
= xmalloc (slash
- dname
+ strlen (cname
) + 2);
3326 strncpy (r
, dname
, slash
- dname
);
3327 r
[slash
- dname
] = DIR_SEPARATOR
;
3328 strcpy (&r
[slash
- dname
+ 1], cname
);
3330 /* We try to make new directories when we need them. We only do
3331 this for directories which "might not" exist. For instance, we
3332 assume the `-d' directory exists, but we don't assume that any
3333 subdirectory below it exists. It might be worthwhile to keep
3334 track of which directories we've created to avoid gratuitous
3336 dname
= r
+ (slash
- dname
) + 1;
3339 char *s
= strchr (dname
, DIR_SEPARATOR
);
3343 if (stat (r
, &sb
) == -1
3344 /* Try to make it. */
3345 && mkdir (r
, 0755) == -1)
3346 fatal_io_error ("can't create directory %s", r
);
3349 /* Skip consecutive separators. */
3350 for (dname
= s
+ 1; *dname
&& *dname
== DIR_SEPARATOR
; ++dname
)
3357 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
3358 The output .class file name is make_class_file_name(CLAS). */
3361 write_classfile (clas
)
3364 struct obstack
*work
= &temporary_obstack
;
3365 struct jcf_partial state
[1];
3366 char *class_file_name
= make_class_file_name (clas
);
3367 struct chunk
*chunks
;
3369 if (class_file_name
!= NULL
)
3371 FILE *stream
= fopen (class_file_name
, "wb");
3373 fatal_io_error ("can't to open %s", class_file_name
);
3375 jcf_dependency_add_target (class_file_name
);
3376 init_jcf_state (state
, work
);
3377 chunks
= generate_classfile (clas
, state
);
3378 write_chunks (stream
, chunks
);
3379 if (fclose (stream
))
3380 fatal_io_error ("can't close %s", class_file_name
);
3381 free (class_file_name
);
3383 release_jcf_state (state
);
3387 string concatenation
3388 synchronized statement