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. */
26 #include "coretypes.h"
31 #include "java-tree.h"
36 #include "java-opcodes.h"
37 #include "parse.h" /* for BLOCK_EXPR_BODY */
43 #define DIR_SEPARATOR '/'
46 extern struct obstack temporary_obstack;
48 /* Base directory in which `.class' files should be written.
49 NULL means to put the file into the same directory as the
50 corresponding .java file. */
51 char *jcf_write_base_directory = NULL;
53 /* Make sure bytecode.data is big enough for at least N more bytes. */
56 do { CHECK_OP(state); \
57 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
58 buffer_grow (&state->bytecode, N); } while (0)
60 /* Add a 1-byte instruction/operand I to bytecode.data,
61 assuming space has already been RESERVE'd. */
63 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
65 /* Like OP1, but I is a 2-byte big endian integer. */
68 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
70 /* Like OP1, but I is a 4-byte big endian integer. */
73 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
74 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
76 /* Macro to call each time we push I words on the JVM stack. */
78 #define NOTE_PUSH(I) \
79 do { state->code_SP += (I); \
80 if (state->code_SP > state->code_SP_max) \
81 state->code_SP_max = state->code_SP; } while (0)
83 /* Macro to call each time we pop I words from the JVM stack. */
86 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
88 /* A chunk or segment of a .class file. */
92 /* The next segment of this .class file. */
95 /* The actual data in this segment to be written to the .class file. */
98 /* The size of the segment to be written to the .class file. */
102 #define PENDING_CLEANUP_PC (-3)
103 #define PENDING_EXIT_PC (-2)
104 #define UNDEFINED_PC (-1)
106 /* Each "block" represents a label plus the bytecode instructions following.
107 There may be branches out of the block, but no incoming jumps, except
108 to the beginning of the block.
110 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
111 associated code yet), but it is an undefined label.
116 /* For blocks that that are defined, the next block (in pc order).
117 For blocks that are not-yet-defined the end label of a LABELED_BLOCK_EXPR
118 or a cleanup expression (from a TRY_FINALLY_EXPR),
119 this is the next (outer) such end label, in a stack headed by
120 labeled_blocks in jcf_partial. */
121 struct jcf_block *next;
123 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
124 pc is PENDING_EXIT_PC.
125 In the not-yet-defined end label for pending cleanup subroutine,
126 pc is PENDING_CLEANUP_PC.
127 For other not-yet-defined labels, pc is UNDEFINED_PC.
129 If the label has been defined:
130 Until perform_relocations is finished, this is the maximum possible
131 value of the bytecode offset at the begnning of this block.
132 After perform_relocations, it is the actual offset (pc). */
137 /* After finish_jcf_block is called, the actual instructions
138 contained in this block. Before that NULL, and the instructions
139 are in state->bytecode. */
143 /* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
144 covered by the cleanup. */
145 struct jcf_block *start_label;
149 /* Set of relocations (in reverse offset order) for this block. */
150 struct jcf_relocation *relocations;
152 /* If this block is that of the not-yet-defined end label of
153 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR.
154 If pc==PENDING_CLEANUP_PC, the cleanup that needs to be run. */
159 /* A "relocation" type for the 0-3 bytes of padding at the start
160 of a tableswitch or a lookupswitch. */
161 #define SWITCH_ALIGN_RELOC 4
163 /* A relocation type for the labels in a tableswitch or a lookupswitch;
164 these are relative to the start of the instruction, but (due to
165 th 0-3 bytes of padding), we don't know the offset before relocation. */
166 #define BLOCK_START_RELOC 1
168 struct jcf_relocation
170 /* Next relocation for the current jcf_block. */
171 struct jcf_relocation *next;
173 /* The (byte) offset within the current block that needs to be relocated. */
174 HOST_WIDE_INT offset;
176 /* 0 if offset is a 4-byte relative offset.
177 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
178 for proper alignment in tableswitch/lookupswitch instructions.
179 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
180 to the start of the containing block.
181 -1 if offset is a 2-byte relative offset.
182 < -1 if offset is the address of an instruction with a 2-byte offset
183 that does not have a corresponding 4-byte offset version, in which
184 case the absolute value of kind is the inverted opcode.
185 > 4 if offset is the address of an instruction (such as jsr) with a
186 2-byte offset that does have a corresponding 4-byte offset version,
187 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
190 /* The label the relocation wants to actually transfer to. */
191 struct jcf_block *label;
194 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
195 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
197 /* State for single catch clause. */
201 struct jcf_handler *next;
203 struct jcf_block *start_label;
204 struct jcf_block *end_label;
205 struct jcf_block *handler_label;
207 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
211 /* State for the current switch statement. */
213 struct jcf_switch_state
215 struct jcf_switch_state *prev;
216 struct jcf_block *default_label;
218 struct jcf_relocation *cases;
220 HOST_WIDE_INT min_case, max_case;
223 /* This structure is used to contain the various pieces that will
224 become a .class file. */
230 struct obstack *chunk_obstack;
233 /* List of basic blocks for the current method. */
234 struct jcf_block *blocks;
235 struct jcf_block *last_block;
237 struct localvar_info *first_lvar;
238 struct localvar_info *last_lvar;
243 int linenumber_count;
245 /* Until perform_relocations, this is a upper bound on the number
246 of bytes (so far) in the instructions for the current method. */
249 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
250 struct jcf_block *labeled_blocks;
252 /* The current stack size (stack pointer) in the current method. */
255 /* The largest extent of stack size (stack pointer) in the current method. */
258 /* Contains a mapping from local var slot number to localvar_info. */
259 struct buffer localvars;
261 /* The buffer allocated for bytecode for the current jcf_block. */
262 struct buffer bytecode;
264 /* Chain of exception handlers for the current method. */
265 struct jcf_handler *handlers;
267 /* Last element in handlers chain. */
268 struct jcf_handler *last_handler;
270 /* Number of exception handlers for the current method. */
273 /* Number of finalizers we are currently nested within. */
276 /* If non-NULL, use this for the return value. */
277 tree return_value_decl;
279 /* Information about the current switch statement. */
280 struct jcf_switch_state *sw_state;
283 static void generate_bytecode_insns PARAMS ((tree, int, struct jcf_partial *));
284 static struct chunk * alloc_chunk PARAMS ((struct chunk *, unsigned char *,
285 int, struct obstack *));
286 static unsigned char * append_chunk PARAMS ((unsigned char *, int,
287 struct jcf_partial *));
288 static void append_chunk_copy PARAMS ((unsigned char *, int,
289 struct jcf_partial *));
290 static struct jcf_block * gen_jcf_label PARAMS ((struct jcf_partial *));
291 static void finish_jcf_block PARAMS ((struct jcf_partial *));
292 static void define_jcf_label PARAMS ((struct jcf_block *,
293 struct jcf_partial *));
294 static struct jcf_block * get_jcf_label_here PARAMS ((struct jcf_partial *));
295 static void put_linenumber PARAMS ((int, struct jcf_partial *));
296 static void localvar_alloc PARAMS ((tree, struct jcf_partial *));
297 static void localvar_free PARAMS ((tree, struct jcf_partial *));
298 static int get_access_flags PARAMS ((tree));
299 static void write_chunks PARAMS ((FILE *, struct chunk *));
300 static int adjust_typed_op PARAMS ((tree, int));
301 static void generate_bytecode_conditional PARAMS ((tree, struct jcf_block *,
302 struct jcf_block *, int,
303 struct jcf_partial *));
304 static void generate_bytecode_return PARAMS ((tree, struct jcf_partial *));
305 static void perform_relocations PARAMS ((struct jcf_partial *));
306 static void init_jcf_state PARAMS ((struct jcf_partial *, struct obstack *));
307 static void init_jcf_method PARAMS ((struct jcf_partial *, tree));
308 static void release_jcf_state PARAMS ((struct jcf_partial *));
309 static struct chunk * generate_classfile PARAMS ((tree, struct jcf_partial *));
310 static struct jcf_handler *alloc_handler PARAMS ((struct jcf_block *,
312 struct jcf_partial *));
313 static void emit_iinc PARAMS ((tree, HOST_WIDE_INT, struct jcf_partial *));
314 static void emit_reloc PARAMS ((HOST_WIDE_INT, int, struct jcf_block *,
315 struct jcf_partial *));
316 static void push_constant1 PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
317 static void push_constant2 PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
318 static void push_int_const PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
319 static int find_constant_wide PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
320 struct jcf_partial *));
321 static void push_long_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
322 struct jcf_partial *));
323 static int find_constant_index PARAMS ((tree, struct jcf_partial *));
324 static void push_long_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
325 struct jcf_partial *));
326 static void field_op PARAMS ((tree, int, struct jcf_partial *));
327 static void maybe_wide PARAMS ((int, int, struct jcf_partial *));
328 static void emit_dup PARAMS ((int, int, struct jcf_partial *));
329 static void emit_pop PARAMS ((int, struct jcf_partial *));
330 static void emit_load_or_store PARAMS ((tree, int, struct jcf_partial *));
331 static void emit_load PARAMS ((tree, struct jcf_partial *));
332 static void emit_store PARAMS ((tree, struct jcf_partial *));
333 static void emit_unop PARAMS ((enum java_opcode, tree, struct jcf_partial *));
334 static void emit_binop PARAMS ((enum java_opcode, tree, struct jcf_partial *));
335 static void emit_reloc PARAMS ((HOST_WIDE_INT, int, struct jcf_block *,
336 struct jcf_partial *));
337 static void emit_switch_reloc PARAMS ((struct jcf_block *,
338 struct jcf_partial *));
339 static void emit_case_reloc PARAMS ((struct jcf_relocation *,
340 struct jcf_partial *));
341 static void emit_if PARAMS ((struct jcf_block *, int, int,
342 struct jcf_partial *));
343 static void emit_goto PARAMS ((struct jcf_block *, struct jcf_partial *));
344 static void emit_jsr PARAMS ((struct jcf_block *, struct jcf_partial *));
345 static void call_cleanups PARAMS ((struct jcf_block *, struct jcf_partial *));
346 static char *make_class_file_name PARAMS ((tree));
347 static unsigned char *append_synthetic_attribute PARAMS ((struct jcf_partial *));
348 static void append_innerclasses_attribute PARAMS ((struct jcf_partial *, tree));
349 static void append_innerclasses_attribute_entry PARAMS ((struct jcf_partial *, tree, tree));
350 static void append_gcj_attribute PARAMS ((struct jcf_partial *, tree));
352 /* Utility macros for appending (big-endian) data to a buffer.
353 We assume a local variable 'ptr' points into where we want to
354 write next, and we assume enough space has been allocated. */
356 #ifdef ENABLE_JC1_CHECKING
357 static int CHECK_PUT PARAMS ((void *, struct jcf_partial *, int));
360 CHECK_PUT (ptr, state, i)
362 struct jcf_partial *state;
365 if ((unsigned char *) ptr < state->chunk->data
366 || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
372 #define CHECK_PUT(PTR, STATE, I) ((void)0)
375 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
376 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
377 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
378 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
380 /* There are some cases below where CHECK_PUT is guaranteed to fail.
381 Use the following macros in those specific cases. */
382 #define UNSAFE_PUT1(X) (*ptr++ = (X))
383 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
384 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
385 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
388 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
389 Set the data and size fields to DATA and SIZE, respectively.
390 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
392 static struct chunk *
393 alloc_chunk (last, data, size, work)
397 struct obstack *work;
399 struct chunk *chunk = (struct chunk *)
400 obstack_alloc (work, sizeof(struct chunk));
402 if (data == NULL && size > 0)
403 data = obstack_alloc (work, size);
413 #ifdef ENABLE_JC1_CHECKING
414 static int CHECK_OP PARAMS ((struct jcf_partial *));
418 struct jcf_partial *state;
420 if (state->bytecode.ptr > state->bytecode.limit)
426 #define CHECK_OP(STATE) ((void) 0)
429 static unsigned char *
430 append_chunk (data, size, state)
433 struct jcf_partial *state;
435 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
436 if (state->first == NULL)
437 state->first = state->chunk;
438 return state->chunk->data;
442 append_chunk_copy (data, size, state)
445 struct jcf_partial *state;
447 unsigned char *ptr = append_chunk (NULL, size, state);
448 memcpy (ptr, data, size);
451 static struct jcf_block *
452 gen_jcf_label (state)
453 struct jcf_partial *state;
455 struct jcf_block *block = (struct jcf_block *)
456 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
458 block->linenumber = -1;
459 block->pc = UNDEFINED_PC;
464 finish_jcf_block (state)
465 struct jcf_partial *state;
467 struct jcf_block *block = state->last_block;
468 struct jcf_relocation *reloc;
469 int code_length = BUFFER_LENGTH (&state->bytecode);
470 int pc = state->code_length;
471 append_chunk_copy (state->bytecode.data, code_length, state);
472 BUFFER_RESET (&state->bytecode);
473 block->v.chunk = state->chunk;
475 /* Calculate code_length to the maximum value it can have. */
476 pc += block->v.chunk->size;
477 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
479 int kind = reloc->kind;
480 if (kind == SWITCH_ALIGN_RELOC)
482 else if (kind > BLOCK_START_RELOC)
483 pc += 2; /* 2-byte offset may grow to 4-byte offset */
485 pc += 5; /* May need to add a goto_w. */
487 state->code_length = pc;
491 define_jcf_label (label, state)
492 struct jcf_block *label;
493 struct jcf_partial *state;
495 if (state->last_block != NULL)
496 finish_jcf_block (state);
497 label->pc = state->code_length;
498 if (state->blocks == NULL)
499 state->blocks = label;
501 state->last_block->next = label;
502 state->last_block = label;
504 label->u.relocations = NULL;
507 static struct jcf_block *
508 get_jcf_label_here (state)
509 struct jcf_partial *state;
511 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
512 return state->last_block;
515 struct jcf_block *label = gen_jcf_label (state);
516 define_jcf_label (label, state);
521 /* Note a line number entry for the current PC and given LINE. */
524 put_linenumber (line, state)
526 struct jcf_partial *state;
528 struct jcf_block *label = get_jcf_label_here (state);
529 if (label->linenumber > 0)
531 label = gen_jcf_label (state);
532 define_jcf_label (label, state);
534 label->linenumber = line;
535 state->linenumber_count++;
538 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
539 in the range (START_LABEL, END_LABEL). */
541 static struct jcf_handler *
542 alloc_handler (start_label, end_label, state)
543 struct jcf_block *start_label;
544 struct jcf_block *end_label;
545 struct jcf_partial *state;
547 struct jcf_handler *handler = (struct jcf_handler *)
548 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
549 handler->start_label = start_label;
550 handler->end_label = end_label;
551 handler->handler_label = get_jcf_label_here (state);
552 if (state->handlers == NULL)
553 state->handlers = handler;
555 state->last_handler->next = handler;
556 state->last_handler = handler;
557 handler->next = NULL;
558 state->num_handlers++;
563 /* The index of jvm local variable allocated for this DECL.
564 This is assigned when generating .class files;
565 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
566 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
568 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
572 struct localvar_info *next;
575 struct jcf_block *start_label;
576 struct jcf_block *end_label;
579 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
580 #define localvar_max \
581 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
584 localvar_alloc (decl, state)
586 struct jcf_partial *state;
588 struct jcf_block *start_label = get_jcf_label_here (state);
589 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
591 register struct localvar_info *info;
592 register struct localvar_info **ptr = localvar_buffer;
593 register struct localvar_info **limit
594 = (struct localvar_info**) state->localvars.ptr;
595 for (index = 0; ptr < limit; index++, ptr++)
598 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
603 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
604 ptr = (struct localvar_info**) state->localvars.data + index;
605 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
607 info = (struct localvar_info *)
608 obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
611 ptr[1] = (struct localvar_info *)(~0);
612 DECL_LOCAL_INDEX (decl) = index;
614 info->start_label = start_label;
616 if (debug_info_level > DINFO_LEVEL_TERSE
617 && DECL_NAME (decl) != NULL_TREE)
619 /* Generate debugging info. */
621 if (state->last_lvar != NULL)
622 state->last_lvar->next = info;
624 state->first_lvar = info;
625 state->last_lvar = info;
631 localvar_free (decl, state)
633 struct jcf_partial *state;
635 struct jcf_block *end_label = get_jcf_label_here (state);
636 int index = DECL_LOCAL_INDEX (decl);
637 register struct localvar_info **ptr = &localvar_buffer [index];
638 register struct localvar_info *info = *ptr;
639 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
641 info->end_label = end_label;
643 if (info->decl != decl)
648 if (ptr[1] != (struct localvar_info *)(~0))
655 #define STACK_TARGET 1
656 #define IGNORE_TARGET 2
658 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
659 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
662 get_access_flags (decl)
666 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
667 if (CLASS_PUBLIC (decl)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
669 if (CLASS_FINAL (decl)) /* same as FIELD_FINAL and METHOD_FINAL */
671 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
673 if (TREE_PROTECTED (decl))
674 flags |= ACC_PROTECTED;
675 if (TREE_PRIVATE (decl))
676 flags |= ACC_PRIVATE;
678 else if (TREE_CODE (decl) == TYPE_DECL)
680 if (CLASS_SUPER (decl))
682 if (CLASS_ABSTRACT (decl))
683 flags |= ACC_ABSTRACT;
684 if (CLASS_INTERFACE (decl))
685 flags |= ACC_INTERFACE;
686 if (CLASS_STATIC (decl))
688 if (CLASS_PRIVATE (decl))
689 flags |= ACC_PRIVATE;
690 if (CLASS_PROTECTED (decl))
691 flags |= ACC_PROTECTED;
692 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
693 || LOCAL_CLASS_P (TREE_TYPE (decl)))
694 flags |= ACC_PRIVATE;
695 if (CLASS_STRICTFP (decl))
701 if (TREE_CODE (decl) == FUNCTION_DECL)
703 if (METHOD_NATIVE (decl))
705 if (METHOD_STATIC (decl))
707 if (METHOD_SYNCHRONIZED (decl))
708 flags |= ACC_SYNCHRONIZED;
709 if (METHOD_ABSTRACT (decl))
710 flags |= ACC_ABSTRACT;
711 if (METHOD_STRICTFP (decl))
716 if (FIELD_STATIC (decl))
718 if (FIELD_VOLATILE (decl))
719 flags |= ACC_VOLATILE;
720 if (FIELD_TRANSIENT (decl))
721 flags |= ACC_TRANSIENT;
726 /* Write the list of segments starting at CHUNKS to STREAM. */
729 write_chunks (stream, chunks)
731 struct chunk *chunks;
733 for (; chunks != NULL; chunks = chunks->next)
734 fwrite (chunks->data, chunks->size, 1, stream);
737 /* Push a 1-word constant in the constant pool at the given INDEX.
738 (Caller is responsible for doing NOTE_PUSH.) */
741 push_constant1 (index, state)
743 struct jcf_partial *state;
758 /* Push a 2-word constant in the constant pool at the given INDEX.
759 (Caller is responsible for doing NOTE_PUSH.) */
762 push_constant2 (index, state)
764 struct jcf_partial *state;
771 /* Push 32-bit integer constant on VM stack.
772 Caller is responsible for doing NOTE_PUSH. */
775 push_int_const (i, state)
777 struct jcf_partial *state;
780 if (i >= -1 && i <= 5)
781 OP1(OPCODE_iconst_0 + i);
782 else if (i >= -128 && i < 128)
787 else if (i >= -32768 && i < 32768)
794 i = find_constant1 (&state->cpool, CONSTANT_Integer,
795 (jword)(i & 0xFFFFFFFF));
796 push_constant1 (i, state);
801 find_constant_wide (lo, hi, state)
802 HOST_WIDE_INT lo, hi;
803 struct jcf_partial *state;
805 HOST_WIDE_INT w1, w2;
806 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
807 return find_constant2 (&state->cpool, CONSTANT_Long,
808 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
811 /* Find or allocate a constant pool entry for the given VALUE.
812 Return the index in the constant pool. */
815 find_constant_index (value, state)
817 struct jcf_partial *state;
819 if (TREE_CODE (value) == INTEGER_CST)
821 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
822 return find_constant1 (&state->cpool, CONSTANT_Integer,
823 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
825 return find_constant_wide (TREE_INT_CST_LOW (value),
826 TREE_INT_CST_HIGH (value), state);
828 else if (TREE_CODE (value) == REAL_CST)
832 real_to_target (words, &TREE_REAL_CST (value),
833 TYPE_MODE (TREE_TYPE (value)));
834 words[0] &= 0xffffffff;
835 words[1] &= 0xffffffff;
837 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
838 return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
840 return find_constant2 (&state->cpool, CONSTANT_Double,
841 (jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
842 (jword)words[FLOAT_WORDS_BIG_ENDIAN]);
844 else if (TREE_CODE (value) == STRING_CST)
845 return find_string_constant (&state->cpool, value);
851 /* Push 64-bit long constant on VM stack.
852 Caller is responsible for doing NOTE_PUSH. */
855 push_long_const (lo, hi, state)
856 HOST_WIDE_INT lo, hi;
857 struct jcf_partial *state;
859 HOST_WIDE_INT highpart, dummy;
860 jint lowpart = WORD_TO_INT (lo);
862 rshift_double (lo, hi, 32, 64, &highpart, &dummy, 1);
864 if (highpart == 0 && (lowpart == 0 || lowpart == 1))
867 OP1(OPCODE_lconst_0 + lowpart);
869 else if ((highpart == 0 && lowpart > 0 && lowpart < 32768)
870 || (highpart == -1 && lowpart < 0 && lowpart >= -32768))
872 push_int_const (lowpart, state);
877 push_constant2 (find_constant_wide (lo, hi, state), state);
881 field_op (field, opcode, state)
884 struct jcf_partial *state;
886 int index = find_fieldref_index (&state->cpool, field);
892 /* Returns an integer in the range 0 (for 'int') through 4 (for object
893 reference) to 7 (for 'short') which matches the pattern of how JVM
894 opcodes typically depend on the operand type. */
897 adjust_typed_op (type, max)
901 switch (TREE_CODE (type))
904 case RECORD_TYPE: return 4;
906 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
908 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
910 switch (TYPE_PRECISION (type))
912 case 8: return max < 5 ? 0 : 5;
913 case 16: return max < 7 ? 0 : 7;
919 switch (TYPE_PRECISION (type))
932 maybe_wide (opcode, index, state)
934 struct jcf_partial *state;
951 /* Compile code to duplicate with offset, where
952 SIZE is the size of the stack item to duplicate (1 or 2), abd
953 OFFSET is where to insert the result (must be 0, 1, or 2).
954 (The new words get inserted at stack[SP-size-offset].) */
957 emit_dup (size, offset, state)
959 struct jcf_partial *state;
966 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
967 else if (offset == 1)
968 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
969 else if (offset == 2)
970 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
978 emit_pop (size, state)
980 struct jcf_partial *state;
983 OP1 (OPCODE_pop - 1 + size);
987 emit_iinc (var, value, state)
990 struct jcf_partial *state;
992 int slot = DECL_LOCAL_INDEX (var);
994 if (value < -128 || value > 127 || slot >= 256)
1012 emit_load_or_store (var, opcode, state)
1013 tree var; /* Variable to load from or store into. */
1014 int opcode; /* Either OPCODE_iload or OPCODE_istore. */
1015 struct jcf_partial *state;
1017 tree type = TREE_TYPE (var);
1018 int kind = adjust_typed_op (type, 4);
1019 int index = DECL_LOCAL_INDEX (var);
1023 OP1 (opcode + 5 + 4 * kind + index); /* [ilfda]{load,store}_[0123] */
1026 maybe_wide (opcode + kind, index, state); /* [ilfda]{load,store} */
1030 emit_load (var, state)
1032 struct jcf_partial *state;
1034 emit_load_or_store (var, OPCODE_iload, state);
1035 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1039 emit_store (var, state)
1041 struct jcf_partial *state;
1043 emit_load_or_store (var, OPCODE_istore, state);
1044 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1048 emit_unop (opcode, type, state)
1049 enum java_opcode opcode;
1050 tree type ATTRIBUTE_UNUSED;
1051 struct jcf_partial *state;
1058 emit_binop (opcode, type, state)
1059 enum java_opcode opcode;
1061 struct jcf_partial *state;
1063 int size = TYPE_IS_WIDE (type) ? 2 : 1;
1070 emit_reloc (value, kind, target, state)
1071 HOST_WIDE_INT value;
1073 struct jcf_block *target;
1074 struct jcf_partial *state;
1076 struct jcf_relocation *reloc = (struct jcf_relocation *)
1077 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1078 struct jcf_block *block = state->last_block;
1079 reloc->next = block->u.relocations;
1080 block->u.relocations = reloc;
1081 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1082 reloc->label = target;
1084 if (kind == 0 || kind == BLOCK_START_RELOC)
1086 else if (kind != SWITCH_ALIGN_RELOC)
1091 emit_switch_reloc (label, state)
1092 struct jcf_block *label;
1093 struct jcf_partial *state;
1095 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1098 /* Similar to emit_switch_reloc,
1099 but re-uses an existing case reloc. */
1102 emit_case_reloc (reloc, state)
1103 struct jcf_relocation *reloc;
1104 struct jcf_partial *state;
1106 struct jcf_block *block = state->last_block;
1107 reloc->next = block->u.relocations;
1108 block->u.relocations = reloc;
1109 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1110 reloc->kind = BLOCK_START_RELOC;
1114 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1115 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1118 emit_if (target, opcode, inv_opcode, state)
1119 struct jcf_block *target;
1120 int opcode, inv_opcode;
1121 struct jcf_partial *state;
1125 /* value is 1 byte from reloc back to start of instruction. */
1126 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1130 emit_goto (target, state)
1131 struct jcf_block *target;
1132 struct jcf_partial *state;
1136 /* Value is 1 byte from reloc back to start of instruction. */
1137 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1141 emit_jsr (target, state)
1142 struct jcf_block *target;
1143 struct jcf_partial *state;
1147 /* Value is 1 byte from reloc back to start of instruction. */
1148 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1151 /* Generate code to evaluate EXP. If the result is true,
1152 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1153 TRUE_BRANCH_FIRST is a code geneation hint that the
1154 TRUE_LABEL may follow right after this. (The idea is that we
1155 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1158 generate_bytecode_conditional (exp, true_label, false_label,
1159 true_branch_first, state)
1161 struct jcf_block *true_label;
1162 struct jcf_block *false_label;
1163 int true_branch_first;
1164 struct jcf_partial *state;
1166 tree exp0, exp1, type;
1167 int save_SP = state->code_SP;
1168 enum java_opcode op, negop;
1169 switch (TREE_CODE (exp))
1172 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1176 struct jcf_block *then_label = gen_jcf_label (state);
1177 struct jcf_block *else_label = gen_jcf_label (state);
1178 int save_SP_before, save_SP_after;
1179 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1180 then_label, else_label, 1, state);
1181 define_jcf_label (then_label, state);
1182 save_SP_before = state->code_SP;
1183 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1184 true_label, false_label, 1, state);
1185 save_SP_after = state->code_SP;
1186 state->code_SP = save_SP_before;
1187 define_jcf_label (else_label, state);
1188 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1189 true_label, false_label,
1190 true_branch_first, state);
1191 if (state->code_SP != save_SP_after)
1195 case TRUTH_NOT_EXPR:
1196 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
1197 true_label, ! true_branch_first, state);
1199 case TRUTH_ANDIF_EXPR:
1201 struct jcf_block *next_label = gen_jcf_label (state);
1202 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1203 next_label, false_label, 1, state);
1204 define_jcf_label (next_label, state);
1205 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1206 true_label, false_label, 1, state);
1209 case TRUTH_ORIF_EXPR:
1211 struct jcf_block *next_label = gen_jcf_label (state);
1212 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1213 true_label, next_label, 1, state);
1214 define_jcf_label (next_label, state);
1215 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1216 true_label, false_label, 1, state);
1220 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1221 set it to the corresponding 1-operand if<COND> instructions. */
1225 /* The opcodes with their inverses are allocated in pairs.
1226 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1227 negop = (op & 1) ? op + 1 : op - 1;
1229 if (true_branch_first)
1231 emit_if (false_label, negop, op, state);
1232 emit_goto (true_label, state);
1236 emit_if (true_label, op, negop, state);
1237 emit_goto (false_label, state);
1241 op = OPCODE_if_icmpeq;
1244 op = OPCODE_if_icmpne;
1247 op = OPCODE_if_icmpgt;
1250 op = OPCODE_if_icmplt;
1253 op = OPCODE_if_icmpge;
1256 op = OPCODE_if_icmple;
1259 exp0 = TREE_OPERAND (exp, 0);
1260 exp1 = TREE_OPERAND (exp, 1);
1261 type = TREE_TYPE (exp0);
1262 switch (TREE_CODE (type))
1265 case POINTER_TYPE: case RECORD_TYPE:
1266 switch (TREE_CODE (exp))
1268 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
1269 case NE_EXPR: op = OPCODE_if_acmpne; break;
1272 if (integer_zerop (exp1) || integer_zerop (exp0))
1274 generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
1275 STACK_TARGET, state);
1276 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1277 negop = (op & 1) ? op - 1 : op + 1;
1281 generate_bytecode_insns (exp0, STACK_TARGET, state);
1282 generate_bytecode_insns (exp1, STACK_TARGET, state);
1286 generate_bytecode_insns (exp0, STACK_TARGET, state);
1287 generate_bytecode_insns (exp1, STACK_TARGET, state);
1288 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1292 if (TYPE_PRECISION (type) > 32)
1303 if (TYPE_PRECISION (type) > 32)
1305 generate_bytecode_insns (exp0, STACK_TARGET, state);
1306 generate_bytecode_insns (exp1, STACK_TARGET, state);
1314 if (integer_zerop (exp1))
1316 generate_bytecode_insns (exp0, STACK_TARGET, state);
1320 if (integer_zerop (exp0))
1324 case OPCODE_if_icmplt:
1325 case OPCODE_if_icmpge:
1328 case OPCODE_if_icmpgt:
1329 case OPCODE_if_icmple:
1335 generate_bytecode_insns (exp1, STACK_TARGET, state);
1339 generate_bytecode_insns (exp0, STACK_TARGET, state);
1340 generate_bytecode_insns (exp1, STACK_TARGET, state);
1346 generate_bytecode_insns (exp, STACK_TARGET, state);
1348 if (true_branch_first)
1350 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1351 emit_goto (true_label, state);
1355 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1356 emit_goto (false_label, state);
1360 if (save_SP != state->code_SP)
1364 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1365 but only as far out as LIMIT (since we are about to jump to the
1366 emit label that is LIMIT). */
1369 call_cleanups (limit, state)
1370 struct jcf_block *limit;
1371 struct jcf_partial *state;
1373 struct jcf_block *block = state->labeled_blocks;
1374 for (; block != limit; block = block->next)
1376 if (block->pc == PENDING_CLEANUP_PC)
1377 emit_jsr (block, state);
1382 generate_bytecode_return (exp, state)
1384 struct jcf_partial *state;
1386 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1387 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1392 switch (TREE_CODE (exp))
1395 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1397 exp = TREE_OPERAND (exp, 1);
1401 struct jcf_block *then_label = gen_jcf_label (state);
1402 struct jcf_block *else_label = gen_jcf_label (state);
1403 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1404 then_label, else_label, 1, state);
1405 define_jcf_label (then_label, state);
1406 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1407 define_jcf_label (else_label, state);
1408 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1412 generate_bytecode_insns (exp,
1413 returns_void ? IGNORE_TARGET
1414 : STACK_TARGET, state);
1420 call_cleanups (NULL, state);
1424 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1425 if (state->num_finalizers > 0)
1427 if (state->return_value_decl == NULL_TREE)
1429 state->return_value_decl
1430 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1431 localvar_alloc (state->return_value_decl, state);
1433 emit_store (state->return_value_decl, state);
1434 call_cleanups (NULL, state);
1435 emit_load (state->return_value_decl, state);
1436 /* If we call localvar_free (state->return_value_decl, state),
1437 then we risk the save decl erroneously re-used in the
1438 finalizer. Instead, we keep the state->return_value_decl
1439 allocated through the rest of the method. This is not
1440 the greatest solution, but it is at least simple and safe. */
1447 /* Generate bytecode for sub-expression EXP of METHOD.
1448 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1451 generate_bytecode_insns (exp, target, state)
1454 struct jcf_partial *state;
1457 enum java_opcode jopcode;
1459 HOST_WIDE_INT value;
1464 if (exp == NULL && target == IGNORE_TARGET)
1467 type = TREE_TYPE (exp);
1469 switch (TREE_CODE (exp))
1472 if (BLOCK_EXPR_BODY (exp))
1475 tree body = BLOCK_EXPR_BODY (exp);
1476 for (local = BLOCK_EXPR_DECLS (exp); local; )
1478 tree next = TREE_CHAIN (local);
1479 localvar_alloc (local, state);
1482 /* Avoid deep recursion for long blocks. */
1483 while (TREE_CODE (body) == COMPOUND_EXPR)
1485 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1486 body = TREE_OPERAND (body, 1);
1488 generate_bytecode_insns (body, target, state);
1489 for (local = BLOCK_EXPR_DECLS (exp); local; )
1491 tree next = TREE_CHAIN (local);
1492 localvar_free (local, state);
1498 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1499 /* Normally the first operand to a COMPOUND_EXPR must complete
1500 normally. However, in the special case of a do-while
1501 statement this is not necessarily the case. */
1502 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0)))
1503 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1505 case EXPR_WITH_FILE_LOCATION:
1507 const char *saved_input_filename = input_filename;
1508 tree body = EXPR_WFL_NODE (exp);
1509 int saved_lineno = lineno;
1510 if (body == empty_stmt_node)
1512 input_filename = EXPR_WFL_FILENAME (exp);
1513 lineno = EXPR_WFL_LINENO (exp);
1514 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && lineno > 0
1515 && debug_info_level > DINFO_LEVEL_NONE)
1516 put_linenumber (lineno, state);
1517 generate_bytecode_insns (body, target, state);
1518 input_filename = saved_input_filename;
1519 lineno = saved_lineno;
1523 if (target == IGNORE_TARGET) ; /* do nothing */
1524 else if (TREE_CODE (type) == POINTER_TYPE)
1526 if (! integer_zerop (exp))
1529 OP1 (OPCODE_aconst_null);
1532 else if (TYPE_PRECISION (type) <= 32)
1534 push_int_const (TREE_INT_CST_LOW (exp), state);
1539 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1546 int prec = TYPE_PRECISION (type) >> 5;
1548 if (real_zerop (exp) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp)))
1549 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1550 else if (real_onep (exp))
1551 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1552 /* FIXME Should also use fconst_2 for 2.0f.
1553 Also, should use iconst_2/ldc followed by i2f/i2d
1554 for other float/double when the value is a small integer. */
1557 offset = find_constant_index (exp, state);
1559 push_constant1 (offset, state);
1561 push_constant2 (offset, state);
1567 push_constant1 (find_string_constant (&state->cpool, exp), state);
1571 if (TREE_STATIC (exp))
1573 field_op (exp, OPCODE_getstatic, state);
1574 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1577 /* ... fall through ... */
1579 emit_load (exp, state);
1581 case NON_LVALUE_EXPR:
1583 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1586 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1587 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1588 if (target != IGNORE_TARGET)
1590 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1593 if (! TYPE_IS_WIDE (type))
1599 tree obj = TREE_OPERAND (exp, 0);
1600 tree field = TREE_OPERAND (exp, 1);
1601 int is_static = FIELD_STATIC (field);
1602 generate_bytecode_insns (obj,
1603 is_static ? IGNORE_TARGET : target, state);
1604 if (target != IGNORE_TARGET)
1606 if (DECL_NAME (field) == length_identifier_node && !is_static
1607 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1610 OP1 (OPCODE_arraylength);
1614 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1618 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1623 case TRUTH_ANDIF_EXPR:
1624 case TRUTH_ORIF_EXPR:
1632 struct jcf_block *then_label = gen_jcf_label (state);
1633 struct jcf_block *else_label = gen_jcf_label (state);
1634 struct jcf_block *end_label = gen_jcf_label (state);
1635 generate_bytecode_conditional (exp,
1636 then_label, else_label, 1, state);
1637 define_jcf_label (then_label, state);
1638 push_int_const (1, state);
1639 emit_goto (end_label, state);
1640 define_jcf_label (else_label, state);
1641 push_int_const (0, state);
1642 define_jcf_label (end_label, state);
1648 struct jcf_block *then_label = gen_jcf_label (state);
1649 struct jcf_block *else_label = gen_jcf_label (state);
1650 struct jcf_block *end_label = gen_jcf_label (state);
1651 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1652 then_label, else_label, 1, state);
1653 define_jcf_label (then_label, state);
1654 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1655 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1656 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1657 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1658 emit_goto (end_label, state);
1659 define_jcf_label (else_label, state);
1660 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1661 define_jcf_label (end_label, state);
1662 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1663 if (TREE_TYPE (exp) != void_type_node)
1664 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1669 struct jcf_switch_state *sw_state = state->sw_state;
1670 struct jcf_relocation *reloc = (struct jcf_relocation *)
1671 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1672 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1674 reloc->label = get_jcf_label_here (state);
1675 reloc->offset = case_value;
1676 reloc->next = sw_state->cases;
1677 sw_state->cases = reloc;
1678 if (sw_state->num_cases == 0)
1680 sw_state->min_case = case_value;
1681 sw_state->max_case = case_value;
1685 if (case_value < sw_state->min_case)
1686 sw_state->min_case = case_value;
1687 if (case_value > sw_state->max_case)
1688 sw_state->max_case = case_value;
1690 sw_state->num_cases++;
1694 state->sw_state->default_label = get_jcf_label_here (state);
1699 /* The SWITCH_EXPR has three parts, generated in the following order:
1700 1. the switch_expression (the value used to select the correct case);
1702 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1703 After code generation, we will re-order them in the order 1, 3, 2.
1704 This is to avoid any extra GOTOs. */
1705 struct jcf_switch_state sw_state;
1706 struct jcf_block *expression_last; /* Last block of the switch_expression. */
1707 struct jcf_block *body_last; /* Last block of the switch_body. */
1708 struct jcf_block *switch_instruction; /* First block of switch_instruction. */
1709 struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1710 struct jcf_block *body_block;
1712 sw_state.prev = state->sw_state;
1713 state->sw_state = &sw_state;
1714 sw_state.cases = NULL;
1715 sw_state.num_cases = 0;
1716 sw_state.default_label = NULL;
1717 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1718 expression_last = state->last_block;
1719 /* Force a new block here. */
1720 body_block = gen_jcf_label (state);
1721 define_jcf_label (body_block, state);
1722 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1723 body_last = state->last_block;
1725 switch_instruction = gen_jcf_label (state);
1726 define_jcf_label (switch_instruction, state);
1727 if (sw_state.default_label == NULL)
1728 sw_state.default_label = gen_jcf_label (state);
1730 if (sw_state.num_cases <= 1)
1732 if (sw_state.num_cases == 0)
1734 emit_pop (1, state);
1739 push_int_const (sw_state.cases->offset, state);
1741 emit_if (sw_state.cases->label,
1742 OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1744 emit_goto (sw_state.default_label, state);
1749 /* Copy the chain of relocs into a sorted array. */
1750 struct jcf_relocation **relocs = (struct jcf_relocation **)
1751 xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1752 /* The relocs arrays is a buffer with a gap.
1753 The assumption is that cases will normally come in "runs". */
1755 int gap_end = sw_state.num_cases;
1756 struct jcf_relocation *reloc;
1757 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
1759 HOST_WIDE_INT case_value = reloc->offset;
1760 while (gap_end < sw_state.num_cases)
1762 struct jcf_relocation *end = relocs[gap_end];
1763 if (case_value <= end->offset)
1765 relocs[gap_start++] = end;
1768 while (gap_start > 0)
1770 struct jcf_relocation *before = relocs[gap_start-1];
1771 if (case_value >= before->offset)
1773 relocs[--gap_end] = before;
1776 relocs[gap_start++] = reloc;
1777 /* Note we don't check for duplicates. This is
1778 handled by the parser. */
1781 if (2 * sw_state.num_cases
1782 >= sw_state.max_case - sw_state.min_case)
1783 { /* Use tableswitch. */
1785 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1786 OP1 (OPCODE_tableswitch);
1787 emit_reloc (RELOCATION_VALUE_0,
1788 SWITCH_ALIGN_RELOC, NULL, state);
1789 emit_switch_reloc (sw_state.default_label, state);
1790 OP4 (sw_state.min_case);
1791 OP4 (sw_state.max_case);
1792 for (i = sw_state.min_case; ; )
1794 reloc = relocs[index];
1795 if (i == reloc->offset)
1797 emit_case_reloc (reloc, state);
1798 if (i == sw_state.max_case)
1803 emit_switch_reloc (sw_state.default_label, state);
1808 { /* Use lookupswitch. */
1809 RESERVE(9 + 8 * sw_state.num_cases);
1810 OP1 (OPCODE_lookupswitch);
1811 emit_reloc (RELOCATION_VALUE_0,
1812 SWITCH_ALIGN_RELOC, NULL, state);
1813 emit_switch_reloc (sw_state.default_label, state);
1814 OP4 (sw_state.num_cases);
1815 for (i = 0; i < sw_state.num_cases; i++)
1817 struct jcf_relocation *reloc = relocs[i];
1818 OP4 (reloc->offset);
1819 emit_case_reloc (reloc, state);
1825 instruction_last = state->last_block;
1826 if (sw_state.default_label->pc < 0)
1827 define_jcf_label (sw_state.default_label, state);
1828 else /* Force a new block. */
1829 sw_state.default_label = get_jcf_label_here (state);
1830 /* Now re-arrange the blocks so the switch_instruction
1831 comes before the switch_body. */
1832 switch_length = state->code_length - switch_instruction->pc;
1833 switch_instruction->pc = body_block->pc;
1834 instruction_last->next = body_block;
1835 instruction_last->v.chunk->next = body_block->v.chunk;
1836 expression_last->next = switch_instruction;
1837 expression_last->v.chunk->next = switch_instruction->v.chunk;
1838 body_last->next = sw_state.default_label;
1839 body_last->v.chunk->next = NULL;
1840 state->chunk = body_last->v.chunk;
1841 for (; body_block != sw_state.default_label; body_block = body_block->next)
1842 body_block->pc += switch_length;
1844 state->sw_state = sw_state.prev;
1849 exp = TREE_OPERAND (exp, 0);
1850 if (exp == NULL_TREE)
1851 exp = empty_stmt_node;
1852 else if (TREE_CODE (exp) != MODIFY_EXPR)
1855 exp = TREE_OPERAND (exp, 1);
1856 generate_bytecode_return (exp, state);
1858 case LABELED_BLOCK_EXPR:
1860 struct jcf_block *end_label = gen_jcf_label (state);
1861 end_label->next = state->labeled_blocks;
1862 state->labeled_blocks = end_label;
1863 end_label->pc = PENDING_EXIT_PC;
1864 end_label->u.labeled_block = exp;
1865 if (LABELED_BLOCK_BODY (exp))
1866 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1867 if (state->labeled_blocks != end_label)
1869 state->labeled_blocks = end_label->next;
1870 define_jcf_label (end_label, state);
1875 tree body = TREE_OPERAND (exp, 0);
1877 if (TREE_CODE (body) == COMPOUND_EXPR
1878 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1880 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1881 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1882 struct jcf_block *head_label;
1883 struct jcf_block *body_label;
1884 struct jcf_block *end_label = gen_jcf_label (state);
1885 struct jcf_block *exit_label = state->labeled_blocks;
1886 head_label = gen_jcf_label (state);
1887 emit_goto (head_label, state);
1888 body_label = get_jcf_label_here (state);
1889 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1890 define_jcf_label (head_label, state);
1891 generate_bytecode_conditional (TREE_OPERAND (body, 0),
1892 end_label, body_label, 1, state);
1893 define_jcf_label (end_label, state);
1898 struct jcf_block *head_label = get_jcf_label_here (state);
1899 generate_bytecode_insns (body, IGNORE_TARGET, state);
1900 if (CAN_COMPLETE_NORMALLY (body))
1901 emit_goto (head_label, state);
1907 struct jcf_block *label = state->labeled_blocks;
1908 struct jcf_block *end_label = gen_jcf_label (state);
1909 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1910 label, end_label, 0, state);
1911 define_jcf_label (end_label, state);
1914 case EXIT_BLOCK_EXPR:
1916 struct jcf_block *label = state->labeled_blocks;
1917 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1918 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1919 label = label->next;
1920 call_cleanups (label, state);
1921 emit_goto (label, state);
1925 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
1926 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
1927 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
1928 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
1931 arg = TREE_OPERAND (exp, 1);
1932 exp = TREE_OPERAND (exp, 0);
1933 type = TREE_TYPE (exp);
1934 size = TYPE_IS_WIDE (type) ? 2 : 1;
1935 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1936 && ! TREE_STATIC (exp)
1937 && TREE_CODE (type) == INTEGER_TYPE
1938 && TYPE_PRECISION (type) == 32)
1940 if (target != IGNORE_TARGET && post_op)
1941 emit_load (exp, state);
1942 emit_iinc (exp, value, state);
1943 if (target != IGNORE_TARGET && ! post_op)
1944 emit_load (exp, state);
1947 if (TREE_CODE (exp) == COMPONENT_REF)
1949 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1950 emit_dup (1, 0, state);
1951 /* Stack: ..., objectref, objectref. */
1952 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1954 /* Stack: ..., objectref, oldvalue. */
1957 else if (TREE_CODE (exp) == ARRAY_REF)
1959 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1960 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1961 emit_dup (2, 0, state);
1962 /* Stack: ..., array, index, array, index. */
1963 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1967 /* Stack: ..., array, index, oldvalue. */
1970 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1972 generate_bytecode_insns (exp, STACK_TARGET, state);
1973 /* Stack: ..., oldvalue. */
1979 if (target != IGNORE_TARGET && post_op)
1980 emit_dup (size, offset, state);
1981 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1982 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1983 /* Stack, otherwise: ..., [result, ] oldvalue. */
1984 generate_bytecode_insns (arg, STACK_TARGET, state);
1985 emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
1986 + adjust_typed_op (type, 3),
1988 if (target != IGNORE_TARGET && ! post_op)
1989 emit_dup (size, offset, state);
1990 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1991 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1992 /* Stack, otherwise: ..., [result, ] newvalue. */
1993 goto finish_assignment;
1997 tree lhs = TREE_OPERAND (exp, 0);
1998 tree rhs = TREE_OPERAND (exp, 1);
2001 /* See if we can use the iinc instruction. */
2002 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
2003 && ! TREE_STATIC (lhs)
2004 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
2005 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
2006 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
2008 tree arg0 = TREE_OPERAND (rhs, 0);
2009 tree arg1 = TREE_OPERAND (rhs, 1);
2010 HOST_WIDE_INT min_value = -32768;
2011 HOST_WIDE_INT max_value = 32767;
2012 if (TREE_CODE (rhs) == MINUS_EXPR)
2017 else if (arg1 == lhs)
2020 arg1 = TREE_OPERAND (rhs, 0);
2022 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
2024 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
2025 value = TREE_INT_CST_LOW (arg1);
2026 if ((hi_value == 0 && value <= max_value)
2027 || (hi_value == -1 && value >= min_value))
2029 if (TREE_CODE (rhs) == MINUS_EXPR)
2031 emit_iinc (lhs, value, state);
2032 if (target != IGNORE_TARGET)
2033 emit_load (lhs, state);
2039 if (TREE_CODE (lhs) == COMPONENT_REF)
2041 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
2042 STACK_TARGET, state);
2045 else if (TREE_CODE (lhs) == ARRAY_REF)
2047 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
2048 STACK_TARGET, state);
2049 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
2050 STACK_TARGET, state);
2056 /* If the rhs is a binary expression and the left operand is
2057 `==' to the lhs then we have an OP= expression. In this
2058 case we must do some special processing. */
2059 if (TREE_CODE_CLASS (TREE_CODE (rhs)) == '2'
2060 && lhs == TREE_OPERAND (rhs, 0))
2062 if (TREE_CODE (lhs) == COMPONENT_REF)
2064 tree field = TREE_OPERAND (lhs, 1);
2065 if (! FIELD_STATIC (field))
2067 /* Duplicate the object reference so we can get
2069 emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
2072 field_op (field, (FIELD_STATIC (field)
2077 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2079 else if (TREE_CODE (lhs) == VAR_DECL
2080 || TREE_CODE (lhs) == PARM_DECL)
2082 if (FIELD_STATIC (lhs))
2084 field_op (lhs, OPCODE_getstatic, state);
2085 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2088 emit_load (lhs, state);
2090 else if (TREE_CODE (lhs) == ARRAY_REF)
2092 /* Duplicate the array and index, which are on the
2093 stack, so that we can load the old value. */
2094 emit_dup (2, 0, state);
2096 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
2099 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2104 /* This function correctly handles the case where the LHS
2105 of a binary expression is NULL_TREE. */
2106 rhs = build (TREE_CODE (rhs), TREE_TYPE (rhs),
2107 NULL_TREE, TREE_OPERAND (rhs, 1));
2110 generate_bytecode_insns (rhs, STACK_TARGET, state);
2111 if (target != IGNORE_TARGET)
2112 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2118 if (TREE_CODE (exp) == COMPONENT_REF)
2120 tree field = TREE_OPERAND (exp, 1);
2121 if (! FIELD_STATIC (field))
2124 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2127 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2129 else if (TREE_CODE (exp) == VAR_DECL
2130 || TREE_CODE (exp) == PARM_DECL)
2132 if (FIELD_STATIC (exp))
2134 field_op (exp, OPCODE_putstatic, state);
2135 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2138 emit_store (exp, state);
2140 else if (TREE_CODE (exp) == ARRAY_REF)
2142 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2145 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2151 jopcode = OPCODE_iadd;
2154 jopcode = OPCODE_isub;
2157 jopcode = OPCODE_imul;
2159 case TRUNC_DIV_EXPR:
2161 jopcode = OPCODE_idiv;
2163 case TRUNC_MOD_EXPR:
2164 jopcode = OPCODE_irem;
2166 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
2167 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
2168 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
2169 case TRUTH_AND_EXPR:
2170 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
2172 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
2173 case TRUTH_XOR_EXPR:
2174 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
2177 tree arg0 = TREE_OPERAND (exp, 0);
2178 tree arg1 = TREE_OPERAND (exp, 1);
2179 jopcode += adjust_typed_op (type, 3);
2180 if (arg0 == arg1 && TREE_CODE (arg0) == SAVE_EXPR)
2182 /* fold may (e.g) convert 2*x to x+x. */
2183 generate_bytecode_insns (TREE_OPERAND (arg0, 0), target, state);
2184 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2188 /* ARG0 will be NULL_TREE if we're handling an `OP='
2189 expression. In this case the stack already holds the
2190 LHS. See the MODIFY_EXPR case. */
2191 if (arg0 != NULL_TREE)
2192 generate_bytecode_insns (arg0, target, state);
2193 if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2194 arg1 = convert (int_type_node, arg1);
2195 generate_bytecode_insns (arg1, target, state);
2197 /* For most binary operations, both operands and the result have the
2198 same type. Shift operations are different. Using arg1's type
2199 gets us the correct SP adjustment in all cases. */
2200 if (target == STACK_TARGET)
2201 emit_binop (jopcode, TREE_TYPE (arg1), state);
2204 case TRUTH_NOT_EXPR:
2206 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2207 if (target == STACK_TARGET)
2209 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2210 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
2214 NOTE_PUSH (1 + is_long);
2215 OP1 (OPCODE_ixor + is_long);
2216 NOTE_POP (1 + is_long);
2220 jopcode = OPCODE_ineg;
2221 jopcode += adjust_typed_op (type, 3);
2222 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2223 if (target == STACK_TARGET)
2224 emit_unop (jopcode, type, state);
2226 case INSTANCEOF_EXPR:
2228 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2229 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2231 OP1 (OPCODE_instanceof);
2236 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2241 case FIX_TRUNC_EXPR:
2243 tree src = TREE_OPERAND (exp, 0);
2244 tree src_type = TREE_TYPE (src);
2245 tree dst_type = TREE_TYPE (exp);
2246 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2247 if (target == IGNORE_TARGET || src_type == dst_type)
2249 if (TREE_CODE (dst_type) == POINTER_TYPE)
2251 if (TREE_CODE (exp) == CONVERT_EXPR)
2253 int index = find_class_constant (&state->cpool,
2254 TREE_TYPE (dst_type));
2256 OP1 (OPCODE_checkcast);
2260 else /* Convert numeric types. */
2262 int wide_src = TYPE_PRECISION (src_type) > 32;
2263 int wide_dst = TYPE_PRECISION (dst_type) > 32;
2264 NOTE_POP (1 + wide_src);
2266 if (TREE_CODE (dst_type) == REAL_TYPE)
2268 if (TREE_CODE (src_type) == REAL_TYPE)
2269 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2270 else if (TYPE_PRECISION (src_type) == 64)
2271 OP1 (OPCODE_l2f + wide_dst);
2273 OP1 (OPCODE_i2f + wide_dst);
2275 else /* Convert to integral type. */
2277 if (TREE_CODE (src_type) == REAL_TYPE)
2278 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2283 if (TYPE_PRECISION (dst_type) < 32)
2286 /* Already converted to int, if needed. */
2287 if (TYPE_PRECISION (dst_type) <= 8)
2289 else if (TREE_UNSIGNED (dst_type))
2295 NOTE_PUSH (1 + wide_dst);
2302 tree try_clause = TREE_OPERAND (exp, 0);
2303 struct jcf_block *start_label = get_jcf_label_here (state);
2304 struct jcf_block *end_label; /* End of try clause. */
2305 struct jcf_block *finished_label = gen_jcf_label (state);
2306 tree clause = TREE_OPERAND (exp, 1);
2307 if (target != IGNORE_TARGET)
2309 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2310 end_label = get_jcf_label_here (state);
2311 if (end_label == start_label)
2313 if (CAN_COMPLETE_NORMALLY (try_clause))
2314 emit_goto (finished_label, state);
2315 while (clause != NULL_TREE)
2317 tree catch_clause = TREE_OPERAND (clause, 0);
2318 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2319 struct jcf_handler *handler = alloc_handler (start_label,
2321 if (exception_decl == NULL_TREE)
2322 handler->type = NULL_TREE;
2324 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2325 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2326 clause = TREE_CHAIN (clause);
2327 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2328 emit_goto (finished_label, state);
2330 define_jcf_label (finished_label, state);
2334 case TRY_FINALLY_EXPR:
2336 struct jcf_block *finished_label = NULL;
2337 struct jcf_block *finally_label, *start_label, *end_label;
2338 struct jcf_handler *handler;
2339 tree try_block = TREE_OPERAND (exp, 0);
2340 tree finally = TREE_OPERAND (exp, 1);
2341 tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2343 tree exception_type;
2345 finally_label = gen_jcf_label (state);
2346 start_label = get_jcf_label_here (state);
2347 /* If the `finally' clause can complete normally, we emit it
2348 as a subroutine and let the other clauses call it via
2349 `jsr'. If it can't complete normally, then we simply emit
2350 `goto's directly to it. */
2351 if (CAN_COMPLETE_NORMALLY (finally))
2353 finally_label->pc = PENDING_CLEANUP_PC;
2354 finally_label->next = state->labeled_blocks;
2355 state->labeled_blocks = finally_label;
2356 state->num_finalizers++;
2359 generate_bytecode_insns (try_block, target, state);
2361 if (CAN_COMPLETE_NORMALLY (finally))
2363 if (state->labeled_blocks != finally_label)
2365 state->labeled_blocks = finally_label->next;
2367 end_label = get_jcf_label_here (state);
2369 if (end_label == start_label)
2371 state->num_finalizers--;
2372 define_jcf_label (finally_label, state);
2373 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2377 if (CAN_COMPLETE_NORMALLY (finally))
2379 return_link = build_decl (VAR_DECL, NULL_TREE,
2380 return_address_type_node);
2381 finished_label = gen_jcf_label (state);
2384 if (CAN_COMPLETE_NORMALLY (try_block))
2386 if (CAN_COMPLETE_NORMALLY (finally))
2388 emit_jsr (finally_label, state);
2389 emit_goto (finished_label, state);
2392 emit_goto (finally_label, state);
2395 /* Handle exceptions. */
2397 exception_type = build_pointer_type (throwable_type_node);
2398 if (CAN_COMPLETE_NORMALLY (finally))
2400 /* We're going to generate a subroutine, so we'll need to
2401 save and restore the exception around the `jsr'. */
2402 exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2403 localvar_alloc (return_link, state);
2405 handler = alloc_handler (start_label, end_label, state);
2406 handler->type = NULL_TREE;
2407 if (CAN_COMPLETE_NORMALLY (finally))
2409 localvar_alloc (exception_decl, state);
2411 emit_store (exception_decl, state);
2412 emit_jsr (finally_label, state);
2413 emit_load (exception_decl, state);
2415 OP1 (OPCODE_athrow);
2420 /* We're not generating a subroutine. In this case we can
2421 simply have the exception handler pop the exception and
2422 then fall through to the `finally' block. */
2424 emit_pop (1, state);
2428 /* The finally block. If we're generating a subroutine, first
2429 save return PC into return_link. Otherwise, just generate
2430 the code for the `finally' block. */
2431 define_jcf_label (finally_label, state);
2432 if (CAN_COMPLETE_NORMALLY (finally))
2435 emit_store (return_link, state);
2438 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2439 if (CAN_COMPLETE_NORMALLY (finally))
2441 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2442 localvar_free (exception_decl, state);
2443 localvar_free (return_link, state);
2444 define_jcf_label (finished_label, state);
2449 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2451 OP1 (OPCODE_athrow);
2453 case NEW_ARRAY_INIT:
2455 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2456 tree array_type = TREE_TYPE (TREE_TYPE (exp));
2457 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2458 HOST_WIDE_INT length = java_array_type_length (array_type);
2459 if (target == IGNORE_TARGET)
2461 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
2462 generate_bytecode_insns (TREE_VALUE (values), target, state);
2465 push_int_const (length, state);
2468 if (JPRIMITIVE_TYPE_P (element_type))
2470 int atype = encode_newarray_type (element_type);
2471 OP1 (OPCODE_newarray);
2476 int index = find_class_constant (&state->cpool,
2477 TREE_TYPE (element_type));
2478 OP1 (OPCODE_anewarray);
2482 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2483 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
2485 int save_SP = state->code_SP;
2486 emit_dup (1, 0, state);
2487 push_int_const (offset, state);
2489 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2492 state->code_SP = save_SP;
2496 case JAVA_EXC_OBJ_EXPR:
2497 NOTE_PUSH (1); /* Pushed by exception system. */
2499 case NEW_CLASS_EXPR:
2501 tree class = TREE_TYPE (TREE_TYPE (exp));
2502 int need_result = target != IGNORE_TARGET;
2503 int index = find_class_constant (&state->cpool, class);
2509 NOTE_PUSH (1 + need_result);
2511 /* ... fall though ... */
2514 tree f = TREE_OPERAND (exp, 0);
2515 tree x = TREE_OPERAND (exp, 1);
2516 int save_SP = state->code_SP;
2518 if (TREE_CODE (f) == ADDR_EXPR)
2519 f = TREE_OPERAND (f, 0);
2520 if (f == soft_newarray_node)
2522 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2523 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2524 STACK_TARGET, state);
2526 OP1 (OPCODE_newarray);
2530 else if (f == soft_multianewarray_node)
2534 int index = find_class_constant (&state->cpool,
2535 TREE_TYPE (TREE_TYPE (exp)));
2536 x = TREE_CHAIN (x); /* Skip class argument. */
2537 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2538 for (idim = ndims; --idim >= 0; )
2541 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2544 OP1 (OPCODE_multianewarray);
2549 else if (f == soft_anewarray_node)
2551 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2552 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2553 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2555 OP1 (OPCODE_anewarray);
2559 else if (f == soft_monitorenter_node
2560 || f == soft_monitorexit_node
2563 if (f == soft_monitorenter_node)
2564 op = OPCODE_monitorenter;
2565 else if (f == soft_monitorexit_node)
2566 op = OPCODE_monitorexit;
2569 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2575 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
2577 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2579 nargs = state->code_SP - save_SP;
2580 state->code_SP = save_SP;
2581 if (f == soft_fmod_node)
2588 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2589 NOTE_POP (1); /* Pop implicit this. */
2590 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2592 tree context = DECL_CONTEXT (f);
2593 int index, interface = 0;
2595 if (METHOD_STATIC (f))
2596 OP1 (OPCODE_invokestatic);
2597 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2598 || METHOD_PRIVATE (f))
2599 OP1 (OPCODE_invokespecial);
2602 if (CLASS_INTERFACE (TYPE_NAME (context)))
2604 tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2605 context = TREE_TYPE (TREE_TYPE (arg1));
2606 if (CLASS_INTERFACE (TYPE_NAME (context)))
2610 OP1 (OPCODE_invokeinterface);
2612 OP1 (OPCODE_invokevirtual);
2614 index = find_methodref_with_class_index (&state->cpool, f, context);
2624 f = TREE_TYPE (TREE_TYPE (f));
2625 if (TREE_CODE (f) != VOID_TYPE)
2627 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2628 if (target == IGNORE_TARGET)
2629 emit_pop (size, state);
2639 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2640 tree_code_name [(int) TREE_CODE (exp)]);
2645 perform_relocations (state)
2646 struct jcf_partial *state;
2648 struct jcf_block *block;
2649 struct jcf_relocation *reloc;
2653 /* Before we start, the pc field of each block is an upper bound on
2654 the block's start pc (it may be less, if previous blocks need less
2655 than their maximum).
2657 The minimum size of each block is in the block's chunk->size. */
2659 /* First, figure out the actual locations of each block. */
2662 for (block = state->blocks; block != NULL; block = block->next)
2664 int block_size = block->v.chunk->size;
2668 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2669 Assumes relocations are in reverse order. */
2670 reloc = block->u.relocations;
2671 while (reloc != NULL
2672 && reloc->kind == OPCODE_goto_w
2673 && reloc->label->pc == block->next->pc
2674 && reloc->offset + 2 == block_size)
2676 reloc = reloc->next;
2677 block->u.relocations = reloc;
2678 block->v.chunk->size -= 3;
2683 /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2684 jump directly to X. We're careful here to avoid an infinite
2685 loop if the `goto's themselves form one. We do this
2686 optimization because we can generate a goto-to-goto for some
2687 try/finally blocks. */
2688 while (reloc != NULL
2689 && reloc->kind == OPCODE_goto_w
2690 && reloc->label != block
2691 && reloc->label->v.chunk->data != NULL
2692 && reloc->label->v.chunk->data[0] == OPCODE_goto)
2694 /* Find the reloc for the first instruction of the
2695 destination block. */
2696 struct jcf_relocation *first_reloc;
2697 for (first_reloc = reloc->label->u.relocations;
2699 first_reloc = first_reloc->next)
2701 if (first_reloc->offset == 1
2702 && first_reloc->kind == OPCODE_goto_w)
2704 reloc->label = first_reloc->label;
2709 /* If we didn't do anything, exit the loop. */
2710 if (first_reloc == NULL)
2714 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
2716 if (reloc->kind == SWITCH_ALIGN_RELOC)
2718 /* We assume this is the first relocation in this block,
2719 so we know its final pc. */
2720 int where = pc + reloc->offset;
2721 int pad = ((where + 3) & ~3) - where;
2724 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2726 int delta = reloc->label->pc - (pc + reloc->offset - 1);
2727 int expand = reloc->kind > 0 ? 2 : 5;
2731 if (delta >= -32768 && delta <= 32767)
2737 block_size += expand;
2743 for (block = state->blocks; block != NULL; block = block->next)
2745 struct chunk *chunk = block->v.chunk;
2746 int old_size = chunk->size;
2747 int next_pc = block->next == NULL ? pc : block->next->pc;
2748 int new_size = next_pc - block->pc;
2749 unsigned char *new_ptr;
2750 unsigned char *old_buffer = chunk->data;
2751 unsigned char *old_ptr = old_buffer + old_size;
2752 if (new_size != old_size)
2754 chunk->data = (unsigned char *)
2755 obstack_alloc (state->chunk_obstack, new_size);
2756 chunk->size = new_size;
2758 new_ptr = chunk->data + new_size;
2760 /* We do the relocations from back to front, because
2761 the relocations are in reverse order. */
2762 for (reloc = block->u.relocations; ; reloc = reloc->next)
2764 /* new_ptr and old_ptr point into the old and new buffers,
2765 respectively. (If no relocations cause the buffer to
2766 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2767 The bytes at higher address have been copied and relocations
2768 handled; those at lower addresses remain to process. */
2770 /* Lower old index of piece to be copied with no relocation.
2771 I.e. high index of the first piece that does need relocation. */
2772 int start = reloc == NULL ? 0
2773 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2774 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2776 : reloc->offset + 2;
2779 int n = (old_ptr - old_buffer) - start;
2783 memcpy (new_ptr, old_ptr, n);
2784 if (old_ptr == old_buffer)
2787 new_offset = new_ptr - chunk->data;
2788 new_offset -= (reloc->kind == -1 ? 2 : 4);
2789 if (reloc->kind == 0)
2792 value = GET_u4 (old_ptr);
2794 else if (reloc->kind == BLOCK_START_RELOC)
2800 else if (reloc->kind == SWITCH_ALIGN_RELOC)
2802 int where = block->pc + reloc->offset;
2803 int pad = ((where + 3) & ~3) - where;
2811 value = GET_u2 (old_ptr);
2813 value += reloc->label->pc - (block->pc + new_offset);
2814 *--new_ptr = (unsigned char) value; value >>= 8;
2815 *--new_ptr = (unsigned char) value; value >>= 8;
2816 if (reloc->kind != -1)
2818 *--new_ptr = (unsigned char) value; value >>= 8;
2819 *--new_ptr = (unsigned char) value;
2821 if (reloc->kind > BLOCK_START_RELOC)
2823 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2825 *--new_ptr = reloc->kind;
2827 else if (reloc->kind < -1)
2829 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2831 *--new_ptr = OPCODE_goto_w;
2834 *--new_ptr = - reloc->kind;
2837 if (new_ptr != chunk->data)
2840 state->code_length = pc;
2844 init_jcf_state (state, work)
2845 struct jcf_partial *state;
2846 struct obstack *work;
2848 state->chunk_obstack = work;
2849 state->first = state->chunk = NULL;
2850 CPOOL_INIT (&state->cpool);
2851 BUFFER_INIT (&state->localvars);
2852 BUFFER_INIT (&state->bytecode);
2856 init_jcf_method (state, method)
2857 struct jcf_partial *state;
2860 state->current_method = method;
2861 state->blocks = state->last_block = NULL;
2862 state->linenumber_count = 0;
2863 state->first_lvar = state->last_lvar = NULL;
2864 state->lvar_count = 0;
2865 state->labeled_blocks = NULL;
2866 state->code_length = 0;
2867 BUFFER_RESET (&state->bytecode);
2868 BUFFER_RESET (&state->localvars);
2870 state->code_SP_max = 0;
2871 state->handlers = NULL;
2872 state->last_handler = NULL;
2873 state->num_handlers = 0;
2874 state->num_finalizers = 0;
2875 state->return_value_decl = NULL_TREE;
2879 release_jcf_state (state)
2880 struct jcf_partial *state;
2882 CPOOL_FINISH (&state->cpool);
2883 obstack_free (state->chunk_obstack, state->first);
2886 /* Generate and return a list of chunks containing the class CLAS
2887 in the .class file representation. The list can be written to a
2888 .class file using write_chunks. Allocate chunks from obstack WORK. */
2890 static GTY(()) tree SourceFile_node;
2891 static struct chunk *
2892 generate_classfile (clas, state)
2894 struct jcf_partial *state;
2896 struct chunk *cpool_chunk;
2897 const char *source_file, *s;
2900 char *fields_count_ptr;
2901 int fields_count = 0;
2902 char *methods_count_ptr;
2903 int methods_count = 0;
2906 = clas == object_type_node ? 0
2907 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2909 ptr = append_chunk (NULL, 8, state);
2910 PUT4 (0xCafeBabe); /* Magic number */
2911 PUT2 (3); /* Minor version */
2912 PUT2 (45); /* Major version */
2914 append_chunk (NULL, 0, state);
2915 cpool_chunk = state->chunk;
2917 /* Next allocate the chunk containing acces_flags through fields_counr. */
2918 if (clas == object_type_node)
2921 i = 8 + 2 * total_supers;
2922 ptr = append_chunk (NULL, i, state);
2923 i = get_access_flags (TYPE_NAME (clas));
2924 if (! (i & ACC_INTERFACE))
2926 PUT2 (i); /* acces_flags */
2927 i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
2928 if (clas == object_type_node)
2930 PUT2(0); /* super_class */
2931 PUT2(0); /* interfaces_count */
2935 tree basetypes = TYPE_BINFO_BASETYPES (clas);
2936 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2937 int j = find_class_constant (&state->cpool, base);
2938 PUT2 (j); /* super_class */
2939 PUT2 (total_supers - 1); /* interfaces_count */
2940 for (i = 1; i < total_supers; i++)
2942 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2943 j = find_class_constant (&state->cpool, base);
2947 fields_count_ptr = ptr;
2949 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
2951 int have_value, attr_count = 0;
2952 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2954 ptr = append_chunk (NULL, 8, state);
2955 i = get_access_flags (part); PUT2 (i);
2956 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
2957 i = find_utf8_constant (&state->cpool,
2958 build_java_signature (TREE_TYPE (part)));
2960 have_value = DECL_INITIAL (part) != NULL_TREE
2961 && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
2962 && FIELD_FINAL (part)
2963 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
2964 || TREE_TYPE (part) == string_ptr_type_node);
2968 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part) || FIELD_SYNTHETIC (part))
2971 PUT2 (attr_count); /* attributes_count */
2974 tree init = DECL_INITIAL (part);
2975 static tree ConstantValue_node = NULL_TREE;
2976 if (TREE_TYPE (part) != TREE_TYPE (init))
2977 fatal_error ("field initializer type mismatch");
2978 ptr = append_chunk (NULL, 8, state);
2979 if (ConstantValue_node == NULL_TREE)
2980 ConstantValue_node = get_identifier ("ConstantValue");
2981 i = find_utf8_constant (&state->cpool, ConstantValue_node);
2982 PUT2 (i); /* attribute_name_index */
2983 PUT4 (2); /* attribute_length */
2984 i = find_constant_index (init, state); PUT2 (i);
2986 /* Emit the "Synthetic" attribute for val$<x> and this$<n>
2987 fields and other fields which need it. */
2988 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2989 || FIELD_SYNTHETIC (part))
2990 ptr = append_synthetic_attribute (state);
2993 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
2995 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
2998 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
3000 struct jcf_block *block;
3001 tree function_body = DECL_FUNCTION_BODY (part);
3002 tree body = function_body == NULL_TREE ? NULL_TREE
3003 : BLOCK_EXPR_BODY (function_body);
3004 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
3006 tree type = TREE_TYPE (part);
3007 tree save_function = current_function_decl;
3008 int synthetic_p = 0;
3009 current_function_decl = part;
3010 ptr = append_chunk (NULL, 8, state);
3011 i = get_access_flags (part); PUT2 (i);
3012 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3013 i = find_utf8_constant (&state->cpool, build_java_signature (type));
3015 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
3017 /* Make room for the Synthetic attribute (of zero length.) */
3018 if (DECL_FINIT_P (part)
3019 || DECL_INSTINIT_P (part)
3020 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
3021 || TYPE_DOT_CLASS (clas) == part)
3027 PUT2 (i); /* attributes_count */
3030 ptr = append_synthetic_attribute (state);
3032 if (body != NULL_TREE)
3034 int code_attributes_count = 0;
3035 static tree Code_node = NULL_TREE;
3038 struct jcf_handler *handler;
3039 if (Code_node == NULL_TREE)
3040 Code_node = get_identifier ("Code");
3041 ptr = append_chunk (NULL, 14, state);
3042 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
3044 init_jcf_method (state, part);
3045 get_jcf_label_here (state); /* Force a first block. */
3046 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3047 localvar_alloc (t, state);
3048 generate_bytecode_insns (body, IGNORE_TARGET, state);
3049 if (CAN_COMPLETE_NORMALLY (body))
3051 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
3054 OP1 (OPCODE_return);
3056 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3057 localvar_free (t, state);
3058 if (state->return_value_decl != NULL_TREE)
3059 localvar_free (state->return_value_decl, state);
3060 finish_jcf_block (state);
3061 perform_relocations (state);
3064 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
3065 if (state->linenumber_count > 0)
3067 code_attributes_count++;
3068 i += 8 + 4 * state->linenumber_count;
3070 if (state->lvar_count > 0)
3072 code_attributes_count++;
3073 i += 8 + 10 * state->lvar_count;
3075 UNSAFE_PUT4 (i); /* attribute_length */
3076 UNSAFE_PUT2 (state->code_SP_max); /* max_stack */
3077 UNSAFE_PUT2 (localvar_max); /* max_locals */
3078 UNSAFE_PUT4 (state->code_length);
3080 /* Emit the exception table. */
3081 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3082 PUT2 (state->num_handlers); /* exception_table_length */
3083 handler = state->handlers;
3084 for (; handler != NULL; handler = handler->next)
3087 PUT2 (handler->start_label->pc);
3088 PUT2 (handler->end_label->pc);
3089 PUT2 (handler->handler_label->pc);
3090 if (handler->type == NULL_TREE)
3093 type_index = find_class_constant (&state->cpool,
3098 ptr = append_chunk (NULL, 2, state);
3099 PUT2 (code_attributes_count);
3101 /* Write the LineNumberTable attribute. */
3102 if (state->linenumber_count > 0)
3104 static tree LineNumberTable_node = NULL_TREE;
3105 ptr = append_chunk (NULL,
3106 8 + 4 * state->linenumber_count, state);
3107 if (LineNumberTable_node == NULL_TREE)
3108 LineNumberTable_node = get_identifier ("LineNumberTable");
3109 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3110 PUT2 (i); /* attribute_name_index */
3111 i = 2+4*state->linenumber_count; PUT4(i); /* attribute_length */
3112 i = state->linenumber_count; PUT2 (i);
3113 for (block = state->blocks; block != NULL; block = block->next)
3115 int line = block->linenumber;
3124 /* Write the LocalVariableTable attribute. */
3125 if (state->lvar_count > 0)
3127 static tree LocalVariableTable_node = NULL_TREE;
3128 struct localvar_info *lvar = state->first_lvar;
3129 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3130 if (LocalVariableTable_node == NULL_TREE)
3131 LocalVariableTable_node = get_identifier("LocalVariableTable");
3132 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3133 PUT2 (i); /* attribute_name_index */
3134 i = 2 + 10 * state->lvar_count; PUT4 (i); /* attribute_length */
3135 i = state->lvar_count; PUT2 (i);
3136 for ( ; lvar != NULL; lvar = lvar->next)
3138 tree name = DECL_NAME (lvar->decl);
3139 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3140 i = lvar->start_label->pc; PUT2 (i);
3141 i = lvar->end_label->pc - i; PUT2 (i);
3142 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3143 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
3144 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
3148 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3150 tree t = DECL_FUNCTION_THROWS (part);
3151 int throws_count = list_length (t);
3152 static tree Exceptions_node = NULL_TREE;
3153 if (Exceptions_node == NULL_TREE)
3154 Exceptions_node = get_identifier ("Exceptions");
3155 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3156 i = find_utf8_constant (&state->cpool, Exceptions_node);
3157 PUT2 (i); /* attribute_name_index */
3158 i = 2 + 2 * throws_count; PUT4(i); /* attribute_length */
3159 i = throws_count; PUT2 (i);
3160 for (; t != NULL_TREE; t = TREE_CHAIN (t))
3162 i = find_class_constant (&state->cpool, TREE_VALUE (t));
3167 current_function_decl = save_function;
3169 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
3171 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3172 for (s = source_file; ; s++)
3177 if (ch == '/' || ch == '\\')
3180 ptr = append_chunk (NULL, 10, state);
3182 i = 1; /* Source file always exists as an attribute */
3183 if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3185 if (clas == object_type_node)
3187 PUT2 (i); /* attributes_count */
3189 /* generate the SourceFile attribute. */
3190 if (SourceFile_node == NULL_TREE)
3192 SourceFile_node = get_identifier ("SourceFile");
3195 i = find_utf8_constant (&state->cpool, SourceFile_node);
3196 PUT2 (i); /* attribute_name_index */
3198 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3200 append_gcj_attribute (state, clas);
3201 append_innerclasses_attribute (state, clas);
3203 /* New finally generate the contents of the constant pool chunk. */
3204 i = count_constant_pool_bytes (&state->cpool);
3205 ptr = obstack_alloc (state->chunk_obstack, i);
3206 cpool_chunk->data = ptr;
3207 cpool_chunk->size = i;
3208 write_constant_pool (&state->cpool, ptr, i);
3209 return state->first;
3212 static GTY(()) tree Synthetic_node;
3213 static unsigned char *
3214 append_synthetic_attribute (state)
3215 struct jcf_partial *state;
3217 unsigned char *ptr = append_chunk (NULL, 6, state);
3220 if (Synthetic_node == NULL_TREE)
3222 Synthetic_node = get_identifier ("Synthetic");
3224 i = find_utf8_constant (&state->cpool, Synthetic_node);
3225 PUT2 (i); /* Attribute string index */
3226 PUT4 (0); /* Attribute length */
3232 append_gcj_attribute (state, class)
3233 struct jcf_partial *state;
3239 if (class != object_type_node)
3242 ptr = append_chunk (NULL, 6, state); /* 2+4 */
3243 i = find_utf8_constant (&state->cpool,
3244 get_identifier ("gnu.gcj.gcj-compiled"));
3245 PUT2 (i); /* Attribute string index */
3246 PUT4 (0); /* Attribute length */
3249 static tree InnerClasses_node;
3251 append_innerclasses_attribute (state, class)
3252 struct jcf_partial *state;
3255 tree orig_decl = TYPE_NAME (class);
3258 unsigned char *ptr, *length_marker, *number_marker;
3260 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3263 ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3265 if (InnerClasses_node == NULL_TREE)
3267 InnerClasses_node = get_identifier ("InnerClasses");
3269 i = find_utf8_constant (&state->cpool, InnerClasses_node);
3271 length_marker = ptr; PUT4 (0); /* length, to be later patched */
3272 number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3274 /* Generate the entries: all inner classes visible from the one we
3275 process: itself, up and down. */
3276 while (class && INNER_CLASS_TYPE_P (class))
3280 decl = TYPE_NAME (class);
3281 n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
3282 IDENTIFIER_LENGTH (DECL_NAME (decl));
3284 while (n[-1] != '$')
3286 append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3289 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3293 for (current = DECL_INNER_CLASS_LIST (decl);
3294 current; current = TREE_CHAIN (current))
3296 append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3297 TREE_VALUE (current));
3301 ptr = length_marker; PUT4 (8*length+2);
3302 ptr = number_marker; PUT2 (length);
3306 append_innerclasses_attribute_entry (state, decl, name)
3307 struct jcf_partial *state;
3311 int ocii = 0, ini = 0;
3312 unsigned char *ptr = append_chunk (NULL, 8, state);
3314 icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3316 /* Sun's implementation seems to generate ocii to 0 for inner
3317 classes (which aren't considered members of the class they're
3318 in.) The specs are saying that if the class is anonymous,
3319 inner_name_index must be zero. */
3320 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3322 ocii = find_class_constant (&state->cpool,
3323 TREE_TYPE (DECL_CONTEXT (decl)));
3324 ini = find_utf8_constant (&state->cpool, name);
3326 icaf = get_access_flags (decl);
3328 PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
3332 make_class_file_name (clas)
3335 const char *dname, *cname, *slash;
3339 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3340 "", '.', DIR_SEPARATOR,
3342 if (jcf_write_base_directory == NULL)
3344 /* Make sure we put the class file into the .java file's
3345 directory, and not into some subdirectory thereof. */
3347 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3348 slash = strrchr (dname, DIR_SEPARATOR);
3354 t = strrchr (cname, DIR_SEPARATOR);
3360 dname = jcf_write_base_directory;
3361 slash = dname + strlen (dname);
3364 r = xmalloc (slash - dname + strlen (cname) + 2);
3365 strncpy (r, dname, slash - dname);
3366 r[slash - dname] = DIR_SEPARATOR;
3367 strcpy (&r[slash - dname + 1], cname);
3369 /* We try to make new directories when we need them. We only do
3370 this for directories which "might not" exist. For instance, we
3371 assume the `-d' directory exists, but we don't assume that any
3372 subdirectory below it exists. It might be worthwhile to keep
3373 track of which directories we've created to avoid gratuitous
3375 dname = r + (slash - dname) + 1;
3378 char *s = strchr (dname, DIR_SEPARATOR);
3382 if (stat (r, &sb) == -1
3383 /* Try to make it. */
3384 && mkdir (r, 0755) == -1)
3385 fatal_io_error ("can't create directory %s", r);
3388 /* Skip consecutive separators. */
3389 for (dname = s + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
3396 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
3397 The output .class file name is make_class_file_name(CLAS). */
3400 write_classfile (clas)
3403 struct obstack *work = &temporary_obstack;
3404 struct jcf_partial state[1];
3405 char *class_file_name = make_class_file_name (clas);
3406 struct chunk *chunks;
3408 if (class_file_name != NULL)
3411 char *temporary_file_name;
3413 /* The .class file is initially written to a ".tmp" file so that
3414 if multiple instances of the compiler are running at once
3415 they do not see partially formed class files. */
3416 temporary_file_name = concat (class_file_name, ".tmp", NULL);
3417 stream = fopen (temporary_file_name, "wb");
3419 fatal_io_error ("can't open %s for writing", temporary_file_name);
3421 jcf_dependency_add_target (class_file_name);
3422 init_jcf_state (state, work);
3423 chunks = generate_classfile (clas, state);
3424 write_chunks (stream, chunks);
3425 if (fclose (stream))
3426 fatal_io_error ("error closing %s", temporary_file_name);
3428 /* If a file named by the string pointed to by `new' exists
3429 prior to the call to the `rename' function, the bahaviour
3430 is implementation-defined. ISO 9899-1990 7.9.4.2.
3432 For example, on Win32 with MSVCRT, it is an error. */
3434 unlink (class_file_name);
3436 if (rename (temporary_file_name, class_file_name) == -1)
3438 remove (temporary_file_name);
3439 fatal_io_error ("can't create %s", class_file_name);
3441 free (temporary_file_name);
3442 free (class_file_name);
3444 release_jcf_state (state);
3448 string concatenation
3449 synchronized statement
3452 #include "gt-java-jcf-write.h"