1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
27 #include "coretypes.h"
32 #include "java-tree.h"
36 #include "java-opcodes.h"
37 #include "parse.h" /* for BLOCK_EXPR_BODY */
43 extern struct obstack temporary_obstack;
45 /* Base directory in which `.class' files should be written.
46 NULL means to put the file into the same directory as the
47 corresponding .java file. */
48 const char *jcf_write_base_directory = NULL;
50 /* Make sure bytecode.data is big enough for at least N more bytes. */
53 do { CHECK_OP(state); \
54 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
55 buffer_grow (&state->bytecode, N); } while (0)
57 /* Add a 1-byte instruction/operand I to bytecode.data,
58 assuming space has already been RESERVE'd. */
60 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
62 /* Like OP1, but I is a 2-byte big endian integer. */
65 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
67 /* Like OP1, but I is a 4-byte big endian integer. */
70 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
71 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
73 /* Macro to call each time we push I words on the JVM stack. */
75 #define NOTE_PUSH(I) \
76 do { state->code_SP += (I); \
77 if (state->code_SP > state->code_SP_max) \
78 state->code_SP_max = state->code_SP; } while (0)
80 /* Macro to call each time we pop I words from the JVM stack. */
83 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
85 /* A chunk or segment of a .class file. */
89 /* The next segment of this .class file. */
92 /* The actual data in this segment to be written to the .class file. */
95 /* The size of the segment to be written to the .class file. */
99 #define PENDING_CLEANUP_PC (-3)
100 #define PENDING_EXIT_PC (-2)
101 #define UNDEFINED_PC (-1)
103 /* Each "block" represents a label plus the bytecode instructions following.
104 There may be branches out of the block, but no incoming jumps, except
105 to the beginning of the block.
107 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
108 associated code yet), but it is an undefined label.
113 /* For blocks that that are defined, the next block (in pc order).
114 For blocks that are not-yet-defined the end label of a LABELED_BLOCK_EXPR
115 or a cleanup expression (from a TRY_FINALLY_EXPR),
116 this is the next (outer) such end label, in a stack headed by
117 labeled_blocks in jcf_partial. */
118 struct jcf_block *next;
120 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
121 pc is PENDING_EXIT_PC.
122 In the not-yet-defined end label for pending cleanup subroutine,
123 pc is PENDING_CLEANUP_PC.
124 For other not-yet-defined labels, pc is UNDEFINED_PC.
126 If the label has been defined:
127 Until perform_relocations is finished, this is the maximum possible
128 value of the bytecode offset at the beginning of this block.
129 After perform_relocations, it is the actual offset (pc). */
134 /* After finish_jcf_block is called, the actual instructions
135 contained in this block. Before that NULL, and the instructions
136 are in state->bytecode. */
140 /* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
141 covered by the cleanup. */
142 struct jcf_block *start_label;
146 /* Set of relocations (in reverse offset order) for this block. */
147 struct jcf_relocation *relocations;
149 /* If this block is that of the not-yet-defined end label of
150 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR.
151 If pc==PENDING_CLEANUP_PC, the cleanup that needs to be run. */
156 /* A "relocation" type for the 0-3 bytes of padding at the start
157 of a tableswitch or a lookupswitch. */
158 #define SWITCH_ALIGN_RELOC 4
160 /* A relocation type for the labels in a tableswitch or a lookupswitch;
161 these are relative to the start of the instruction, but (due to
162 th 0-3 bytes of padding), we don't know the offset before relocation. */
163 #define BLOCK_START_RELOC 1
165 struct jcf_relocation
167 /* Next relocation for the current jcf_block. */
168 struct jcf_relocation *next;
170 /* The (byte) offset within the current block that needs to be relocated. */
171 HOST_WIDE_INT offset;
173 /* 0 if offset is a 4-byte relative offset.
174 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
175 for proper alignment in tableswitch/lookupswitch instructions.
176 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
177 to the start of the containing block.
178 -1 if offset is a 2-byte relative offset.
179 < -1 if offset is the address of an instruction with a 2-byte offset
180 that does not have a corresponding 4-byte offset version, in which
181 case the absolute value of kind is the inverted opcode.
182 > 4 if offset is the address of an instruction (such as jsr) with a
183 2-byte offset that does have a corresponding 4-byte offset version,
184 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
187 /* The label the relocation wants to actually transfer to. */
188 struct jcf_block *label;
191 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
192 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
194 /* State for single catch clause. */
198 struct jcf_handler *next;
200 struct jcf_block *start_label;
201 struct jcf_block *end_label;
202 struct jcf_block *handler_label;
204 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
208 /* State for the current switch statement. */
210 struct jcf_switch_state
212 struct jcf_switch_state *prev;
213 struct jcf_block *default_label;
215 struct jcf_relocation *cases;
217 HOST_WIDE_INT min_case, max_case;
220 /* This structure is used to contain the various pieces that will
221 become a .class file. */
227 struct obstack *chunk_obstack;
230 /* List of basic blocks for the current method. */
231 struct jcf_block *blocks;
232 struct jcf_block *last_block;
234 struct localvar_info *first_lvar;
235 struct localvar_info *last_lvar;
240 int linenumber_count;
242 /* Until perform_relocations, this is a upper bound on the number
243 of bytes (so far) in the instructions for the current method. */
246 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
247 struct jcf_block *labeled_blocks;
249 /* The current stack size (stack pointer) in the current method. */
252 /* The largest extent of stack size (stack pointer) in the current method. */
255 /* Contains a mapping from local var slot number to localvar_info. */
256 struct buffer localvars;
258 /* The buffer allocated for bytecode for the current jcf_block. */
259 struct buffer bytecode;
261 /* Chain of exception handlers for the current method. */
262 struct jcf_handler *handlers;
264 /* Last element in handlers chain. */
265 struct jcf_handler *last_handler;
267 /* Number of exception handlers for the current method. */
270 /* Number of finalizers we are currently nested within. */
273 /* If non-NULL, use this for the return value. */
274 tree return_value_decl;
276 /* Information about the current switch statement. */
277 struct jcf_switch_state *sw_state;
279 /* The count of jsr instructions that have been emitted. */
283 static void generate_bytecode_insns (tree, int, struct jcf_partial *);
284 static struct chunk * alloc_chunk (struct chunk *, unsigned char *,
285 int, struct obstack *);
286 static unsigned char * append_chunk (unsigned char *, int,
287 struct jcf_partial *);
288 static void append_chunk_copy (unsigned char *, int, struct jcf_partial *);
289 static struct jcf_block * gen_jcf_label (struct jcf_partial *);
290 static void finish_jcf_block (struct jcf_partial *);
291 static void define_jcf_label (struct jcf_block *, struct jcf_partial *);
292 static struct jcf_block * get_jcf_label_here (struct jcf_partial *);
293 static void put_linenumber (int, struct jcf_partial *);
294 static void localvar_alloc (tree, struct jcf_partial *);
295 static void maybe_free_localvar (tree, struct jcf_partial *, int);
296 static int get_access_flags (tree);
297 static void write_chunks (FILE *, struct chunk *);
298 static int adjust_typed_op (tree, int);
299 static void generate_bytecode_conditional (tree, struct jcf_block *,
300 struct jcf_block *, int,
301 struct jcf_partial *);
302 static void generate_bytecode_return (tree, struct jcf_partial *);
303 static void perform_relocations (struct jcf_partial *);
304 static void init_jcf_state (struct jcf_partial *, struct obstack *);
305 static void init_jcf_method (struct jcf_partial *, tree);
306 static void release_jcf_state (struct jcf_partial *);
307 static struct chunk * generate_classfile (tree, struct jcf_partial *);
308 static struct jcf_handler *alloc_handler (struct jcf_block *,
310 struct jcf_partial *);
311 static void emit_iinc (tree, HOST_WIDE_INT, struct jcf_partial *);
312 static void emit_reloc (HOST_WIDE_INT, int, struct jcf_block *,
313 struct jcf_partial *);
314 static void push_constant1 (HOST_WIDE_INT, struct jcf_partial *);
315 static void push_constant2 (HOST_WIDE_INT, struct jcf_partial *);
316 static void push_int_const (HOST_WIDE_INT, struct jcf_partial *);
317 static int find_constant_wide (HOST_WIDE_INT, HOST_WIDE_INT,
318 struct jcf_partial *);
319 static void push_long_const (HOST_WIDE_INT, HOST_WIDE_INT,
320 struct jcf_partial *);
321 static int find_constant_index (tree, struct jcf_partial *);
322 static void push_long_const (HOST_WIDE_INT, HOST_WIDE_INT,
323 struct jcf_partial *);
324 static void field_op (tree, int, struct jcf_partial *);
325 static void maybe_wide (int, int, struct jcf_partial *);
326 static void emit_dup (int, int, struct jcf_partial *);
327 static void emit_pop (int, struct jcf_partial *);
328 static void emit_load_or_store (tree, int, struct jcf_partial *);
329 static void emit_load (tree, struct jcf_partial *);
330 static void emit_store (tree, struct jcf_partial *);
331 static void emit_unop (enum java_opcode, tree, struct jcf_partial *);
332 static void emit_binop (enum java_opcode, tree, struct jcf_partial *);
333 static void emit_reloc (HOST_WIDE_INT, int, struct jcf_block *,
334 struct jcf_partial *);
335 static void emit_switch_reloc (struct jcf_block *, struct jcf_partial *);
336 static void emit_case_reloc (struct jcf_relocation *, struct jcf_partial *);
337 static void emit_if (struct jcf_block *, int, int, struct jcf_partial *);
338 static void emit_goto (struct jcf_block *, struct jcf_partial *);
339 static void emit_jsr (struct jcf_block *, struct jcf_partial *);
340 static void call_cleanups (struct jcf_block *, struct jcf_partial *);
341 static char *make_class_file_name (tree);
342 static unsigned char *append_synthetic_attribute (struct jcf_partial *);
343 static void append_deprecated_attribute (struct jcf_partial *);
344 static void append_innerclasses_attribute (struct jcf_partial *, tree);
345 static void append_innerclasses_attribute_entry (struct jcf_partial *, tree, tree);
346 static void append_gcj_attribute (struct jcf_partial *, tree);
348 /* Utility macros for appending (big-endian) data to a buffer.
349 We assume a local variable 'ptr' points into where we want to
350 write next, and we assume enough space has been allocated. */
352 #ifdef ENABLE_JC1_CHECKING
353 static int CHECK_PUT (void *, struct jcf_partial *, int);
356 CHECK_PUT (void *ptr, struct jcf_partial *state, int i)
358 if ((unsigned char *) ptr < state->chunk->data
359 || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
365 #define CHECK_PUT(PTR, STATE, I) ((void)0)
368 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
369 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
370 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
371 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
373 /* There are some cases below where CHECK_PUT is guaranteed to fail.
374 Use the following macros in those specific cases. */
375 #define UNSAFE_PUT1(X) (*ptr++ = (X))
376 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
377 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
378 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
381 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
382 Set the data and size fields to DATA and SIZE, respectively.
383 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
385 static struct chunk *
386 alloc_chunk (struct chunk *last, unsigned char *data,
387 int size, struct obstack *work)
389 struct chunk *chunk = obstack_alloc (work, sizeof(struct chunk));
391 if (data == NULL && size > 0)
392 data = obstack_alloc (work, size);
402 #ifdef ENABLE_JC1_CHECKING
403 static int CHECK_OP (struct jcf_partial *);
406 CHECK_OP (struct jcf_partial *state)
408 if (state->bytecode.ptr > state->bytecode.limit)
414 #define CHECK_OP(STATE) ((void) 0)
417 static unsigned char *
418 append_chunk (unsigned char *data, int size, struct jcf_partial *state)
420 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
421 if (state->first == NULL)
422 state->first = state->chunk;
423 return state->chunk->data;
427 append_chunk_copy (unsigned char *data, int size, struct jcf_partial *state)
429 unsigned char *ptr = append_chunk (NULL, size, state);
430 memcpy (ptr, data, size);
433 static struct jcf_block *
434 gen_jcf_label (struct jcf_partial *state)
436 struct jcf_block *block
437 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
439 block->linenumber = -1;
440 block->pc = UNDEFINED_PC;
445 finish_jcf_block (struct jcf_partial *state)
447 struct jcf_block *block = state->last_block;
448 struct jcf_relocation *reloc;
449 int code_length = BUFFER_LENGTH (&state->bytecode);
450 int pc = state->code_length;
451 append_chunk_copy (state->bytecode.data, code_length, state);
452 BUFFER_RESET (&state->bytecode);
453 block->v.chunk = state->chunk;
455 /* Calculate code_length to the maximum value it can have. */
456 pc += block->v.chunk->size;
457 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
459 int kind = reloc->kind;
460 if (kind == SWITCH_ALIGN_RELOC)
462 else if (kind > BLOCK_START_RELOC)
463 pc += 2; /* 2-byte offset may grow to 4-byte offset */
465 pc += 5; /* May need to add a goto_w. */
467 state->code_length = pc;
471 define_jcf_label (struct jcf_block *label, struct jcf_partial *state)
473 if (state->last_block != NULL)
474 finish_jcf_block (state);
475 label->pc = state->code_length;
476 if (state->blocks == NULL)
477 state->blocks = label;
479 state->last_block->next = label;
480 state->last_block = label;
482 label->u.relocations = NULL;
485 static struct jcf_block *
486 get_jcf_label_here (struct jcf_partial *state)
488 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
489 return state->last_block;
492 struct jcf_block *label = gen_jcf_label (state);
493 define_jcf_label (label, state);
498 /* Note a line number entry for the current PC and given LINE. */
501 put_linenumber (int line, struct jcf_partial *state)
503 struct jcf_block *label = get_jcf_label_here (state);
504 if (label->linenumber > 0)
506 label = gen_jcf_label (state);
507 define_jcf_label (label, state);
509 label->linenumber = line;
510 state->linenumber_count++;
513 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
514 in the range (START_LABEL, END_LABEL). */
516 static struct jcf_handler *
517 alloc_handler (struct jcf_block *start_label, struct jcf_block *end_label,
518 struct jcf_partial *state)
520 struct jcf_handler *handler
521 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
522 handler->start_label = start_label;
523 handler->end_label = end_label;
524 handler->handler_label = get_jcf_label_here (state);
525 if (state->handlers == NULL)
526 state->handlers = handler;
528 state->last_handler->next = handler;
529 state->last_handler = handler;
530 handler->next = NULL;
531 state->num_handlers++;
536 /* The index of jvm local variable allocated for this DECL.
537 This is assigned when generating .class files;
538 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
539 (We don't allocate DECL_LANG_SPECIFIC for locals from Java source code.) */
541 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
545 struct localvar_info *next;
548 struct jcf_block *start_label;
549 struct jcf_block *end_label;
552 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
553 #define localvar_max \
554 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
557 localvar_alloc (tree decl, struct jcf_partial *state)
559 struct jcf_block *start_label = get_jcf_label_here (state);
560 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
562 struct localvar_info *info;
563 struct localvar_info **ptr = localvar_buffer;
564 struct localvar_info **limit
565 = (struct localvar_info**) state->localvars.ptr;
566 for (index = 0; ptr < limit; index++, ptr++)
569 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
574 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
575 ptr = (struct localvar_info**) state->localvars.data + index;
576 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
578 info = obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
581 ptr[1] = (struct localvar_info *)(~0);
582 DECL_LOCAL_INDEX (decl) = index;
584 info->start_label = start_label;
586 if (debug_info_level > DINFO_LEVEL_TERSE
587 && DECL_NAME (decl) != NULL_TREE)
589 /* Generate debugging info. */
591 if (state->last_lvar != NULL)
592 state->last_lvar->next = info;
594 state->first_lvar = info;
595 state->last_lvar = info;
601 maybe_free_localvar (tree decl, struct jcf_partial *state, int really)
603 struct jcf_block *end_label = get_jcf_label_here (state);
604 int index = DECL_LOCAL_INDEX (decl);
605 struct localvar_info **ptr = &localvar_buffer [index];
606 struct localvar_info *info = *ptr;
607 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
609 info->end_label = end_label;
611 if (info->decl != decl)
618 if (ptr[1] != (struct localvar_info *)(~0))
625 #define STACK_TARGET 1
626 #define IGNORE_TARGET 2
628 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
629 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
632 get_access_flags (tree decl)
635 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
637 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
639 if (TREE_PROTECTED (decl))
640 flags |= ACC_PROTECTED;
641 if (TREE_PRIVATE (decl))
642 flags |= ACC_PRIVATE;
644 else if (TREE_CODE (decl) == TYPE_DECL)
646 if (CLASS_PUBLIC (decl))
648 if (CLASS_FINAL (decl))
650 if (CLASS_SUPER (decl))
652 if (CLASS_ABSTRACT (decl))
653 flags |= ACC_ABSTRACT;
654 if (CLASS_INTERFACE (decl))
655 flags |= ACC_INTERFACE;
656 if (CLASS_STATIC (decl))
658 if (CLASS_PRIVATE (decl))
659 flags |= ACC_PRIVATE;
660 if (CLASS_PROTECTED (decl))
661 flags |= ACC_PROTECTED;
662 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
663 || LOCAL_CLASS_P (TREE_TYPE (decl)))
664 flags |= ACC_PRIVATE;
665 if (CLASS_STRICTFP (decl))
671 if (TREE_CODE (decl) == FUNCTION_DECL)
673 if (METHOD_PUBLIC (decl))
675 if (METHOD_FINAL (decl))
677 if (METHOD_NATIVE (decl))
679 if (METHOD_STATIC (decl))
681 if (METHOD_SYNCHRONIZED (decl))
682 flags |= ACC_SYNCHRONIZED;
683 if (METHOD_ABSTRACT (decl))
684 flags |= ACC_ABSTRACT;
685 if (METHOD_STRICTFP (decl))
690 if (FIELD_PUBLIC (decl))
692 if (FIELD_FINAL (decl))
694 if (FIELD_STATIC (decl))
696 if (FIELD_VOLATILE (decl))
697 flags |= ACC_VOLATILE;
698 if (FIELD_TRANSIENT (decl))
699 flags |= ACC_TRANSIENT;
704 /* Write the list of segments starting at CHUNKS to STREAM. */
707 write_chunks (FILE* stream, struct chunk *chunks)
709 for (; chunks != NULL; chunks = chunks->next)
710 fwrite (chunks->data, chunks->size, 1, stream);
713 /* Push a 1-word constant in the constant pool at the given INDEX.
714 (Caller is responsible for doing NOTE_PUSH.) */
717 push_constant1 (HOST_WIDE_INT index, struct jcf_partial *state)
732 /* Push a 2-word constant in the constant pool at the given INDEX.
733 (Caller is responsible for doing NOTE_PUSH.) */
736 push_constant2 (HOST_WIDE_INT index, struct jcf_partial *state)
743 /* Push 32-bit integer constant on VM stack.
744 Caller is responsible for doing NOTE_PUSH. */
747 push_int_const (HOST_WIDE_INT i, struct jcf_partial *state)
750 if (i >= -1 && i <= 5)
751 OP1(OPCODE_iconst_0 + i);
752 else if (i >= -128 && i < 128)
757 else if (i >= -32768 && i < 32768)
764 i = find_constant1 (&state->cpool, CONSTANT_Integer,
765 (jword)(i & 0xFFFFFFFF));
766 push_constant1 (i, state);
771 find_constant_wide (HOST_WIDE_INT lo, HOST_WIDE_INT hi,
772 struct jcf_partial *state)
774 HOST_WIDE_INT w1, w2;
775 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
776 return find_constant2 (&state->cpool, CONSTANT_Long,
777 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
780 /* Find or allocate a constant pool entry for the given VALUE.
781 Return the index in the constant pool. */
784 find_constant_index (tree value, struct jcf_partial *state)
786 if (TREE_CODE (value) == INTEGER_CST)
788 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
789 return find_constant1 (&state->cpool, CONSTANT_Integer,
790 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
792 return find_constant_wide (TREE_INT_CST_LOW (value),
793 TREE_INT_CST_HIGH (value), state);
795 else if (TREE_CODE (value) == REAL_CST)
799 real_to_target (words, &TREE_REAL_CST (value),
800 TYPE_MODE (TREE_TYPE (value)));
801 words[0] &= 0xffffffff;
802 words[1] &= 0xffffffff;
804 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
805 return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
807 return find_constant2 (&state->cpool, CONSTANT_Double,
808 (jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
809 (jword)words[FLOAT_WORDS_BIG_ENDIAN]);
811 else if (TREE_CODE (value) == STRING_CST)
812 return find_string_constant (&state->cpool, value);
818 /* Push 64-bit long constant on VM stack.
819 Caller is responsible for doing NOTE_PUSH. */
822 push_long_const (HOST_WIDE_INT lo, HOST_WIDE_INT hi, struct jcf_partial *state)
824 HOST_WIDE_INT highpart, dummy;
825 jint lowpart = WORD_TO_INT (lo);
827 rshift_double (lo, hi, 32, 64, &highpart, &dummy, 1);
829 if (highpart == 0 && (lowpart == 0 || lowpart == 1))
832 OP1(OPCODE_lconst_0 + lowpart);
834 else if ((highpart == 0 && lowpart > 0 && lowpart < 32768)
835 || (highpart == -1 && lowpart < 0 && lowpart >= -32768))
837 push_int_const (lowpart, state);
842 push_constant2 (find_constant_wide (lo, hi, state), state);
846 field_op (tree field, int opcode, struct jcf_partial *state)
848 int index = find_fieldref_index (&state->cpool, field);
854 /* Returns an integer in the range 0 (for 'int') through 4 (for object
855 reference) to 7 (for 'short') which matches the pattern of how JVM
856 opcodes typically depend on the operand type. */
859 adjust_typed_op (tree type, int max)
861 switch (TREE_CODE (type))
864 case RECORD_TYPE: return 4;
866 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
868 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
870 switch (TYPE_PRECISION (type))
872 case 8: return max < 5 ? 0 : 5;
873 case 16: return max < 7 ? 0 : 7;
879 switch (TYPE_PRECISION (type))
892 maybe_wide (int opcode, int index, struct jcf_partial *state)
909 /* Compile code to duplicate with offset, where
910 SIZE is the size of the stack item to duplicate (1 or 2), abd
911 OFFSET is where to insert the result (must be 0, 1, or 2).
912 (The new words get inserted at stack[SP-size-offset].) */
915 emit_dup (int size, int offset, struct jcf_partial *state)
922 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
923 else if (offset == 1)
924 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
925 else if (offset == 2)
926 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
934 emit_pop (int size, struct jcf_partial *state)
937 OP1 (OPCODE_pop - 1 + size);
941 emit_iinc (tree var, HOST_WIDE_INT value, struct jcf_partial *state)
943 int slot = DECL_LOCAL_INDEX (var);
945 if (value < -128 || value > 127 || slot >= 256)
963 emit_load_or_store (tree var, /* Variable to load from or store into. */
964 int opcode, /* Either OPCODE_iload or OPCODE_istore. */
965 struct jcf_partial *state)
967 tree type = TREE_TYPE (var);
968 int kind = adjust_typed_op (type, 4);
969 int index = DECL_LOCAL_INDEX (var);
973 OP1 (opcode + 5 + 4 * kind + index); /* [ilfda]{load,store}_[0123] */
976 maybe_wide (opcode + kind, index, state); /* [ilfda]{load,store} */
980 emit_load (tree var, struct jcf_partial *state)
982 emit_load_or_store (var, OPCODE_iload, state);
983 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
987 emit_store (tree var, struct jcf_partial *state)
989 emit_load_or_store (var, OPCODE_istore, state);
990 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
994 emit_unop (enum java_opcode opcode, tree type ATTRIBUTE_UNUSED,
995 struct jcf_partial *state)
1002 emit_binop (enum java_opcode opcode, tree type, struct jcf_partial *state)
1004 int size = TYPE_IS_WIDE (type) ? 2 : 1;
1011 emit_reloc (HOST_WIDE_INT value, int kind,
1012 struct jcf_block *target, struct jcf_partial *state)
1014 struct jcf_relocation *reloc
1015 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1016 struct jcf_block *block = state->last_block;
1017 reloc->next = block->u.relocations;
1018 block->u.relocations = reloc;
1019 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1020 reloc->label = target;
1022 if (kind == 0 || kind == BLOCK_START_RELOC)
1024 else if (kind != SWITCH_ALIGN_RELOC)
1029 emit_switch_reloc (struct jcf_block *label, struct jcf_partial *state)
1031 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1034 /* Similar to emit_switch_reloc,
1035 but re-uses an existing case reloc. */
1038 emit_case_reloc (struct jcf_relocation *reloc, struct jcf_partial *state)
1040 struct jcf_block *block = state->last_block;
1041 reloc->next = block->u.relocations;
1042 block->u.relocations = reloc;
1043 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1044 reloc->kind = BLOCK_START_RELOC;
1048 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1049 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1052 emit_if (struct jcf_block *target, int opcode, int inv_opcode,
1053 struct jcf_partial *state)
1057 /* value is 1 byte from reloc back to start of instruction. */
1058 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1062 emit_goto (struct jcf_block *target, struct jcf_partial *state)
1066 /* Value is 1 byte from reloc back to start of instruction. */
1067 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1071 emit_jsr (struct jcf_block *target, struct jcf_partial *state)
1075 /* Value is 1 byte from reloc back to start of instruction. */
1076 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1080 /* Generate code to evaluate EXP. If the result is true,
1081 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1082 TRUE_BRANCH_FIRST is a code generation hint that the
1083 TRUE_LABEL may follow right after this. (The idea is that we
1084 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1087 generate_bytecode_conditional (tree exp,
1088 struct jcf_block *true_label,
1089 struct jcf_block *false_label,
1090 int true_branch_first,
1091 struct jcf_partial *state)
1093 tree exp0, exp1, type;
1094 int save_SP = state->code_SP;
1095 enum java_opcode op, negop;
1098 switch (TREE_CODE (exp))
1101 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1105 struct jcf_block *then_label = gen_jcf_label (state);
1106 struct jcf_block *else_label = gen_jcf_label (state);
1107 int save_SP_before, save_SP_after;
1108 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1109 then_label, else_label, 1, state);
1110 define_jcf_label (then_label, state);
1111 save_SP_before = state->code_SP;
1112 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1113 true_label, false_label, 1, state);
1114 save_SP_after = state->code_SP;
1115 state->code_SP = save_SP_before;
1116 define_jcf_label (else_label, state);
1117 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1118 true_label, false_label,
1119 true_branch_first, state);
1120 if (state->code_SP != save_SP_after)
1124 case TRUTH_NOT_EXPR:
1125 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
1126 true_label, ! true_branch_first, state);
1128 case TRUTH_ANDIF_EXPR:
1130 struct jcf_block *next_label = gen_jcf_label (state);
1131 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1132 next_label, false_label, 1, state);
1133 define_jcf_label (next_label, state);
1134 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1135 true_label, false_label, 1, state);
1138 case TRUTH_ORIF_EXPR:
1140 struct jcf_block *next_label = gen_jcf_label (state);
1141 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1142 true_label, next_label, 1, state);
1143 define_jcf_label (next_label, state);
1144 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1145 true_label, false_label, 1, state);
1149 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1150 set it to the corresponding 1-operand if<COND> instructions. */
1154 /* The opcodes with their inverses are allocated in pairs.
1155 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1156 negop = (op & 1) ? op + 1 : op - 1;
1158 if (true_branch_first)
1160 emit_if (false_label, negop, op, state);
1161 emit_goto (true_label, state);
1165 emit_if (true_label, op, negop, state);
1166 emit_goto (false_label, state);
1173 op = OPCODE_if_icmpeq;
1179 op = OPCODE_if_icmpne;
1185 op = OPCODE_if_icmpgt;
1191 op = OPCODE_if_icmplt;
1197 op = OPCODE_if_icmpge;
1203 op = OPCODE_if_icmple;
1209 /* UNLT_EXPR(a, b) means 'a < b || unordered(a, b)'. This is
1210 the same as the Java source expression '!(a >= b)', so handle
1212 struct jcf_block *tmp = true_label;
1213 true_label = false_label;
1215 true_branch_first = !true_branch_first;
1218 exp0 = TREE_OPERAND (exp, 0);
1219 exp1 = TREE_OPERAND (exp, 1);
1220 type = TREE_TYPE (exp0);
1221 switch (TREE_CODE (type))
1224 case POINTER_TYPE: case RECORD_TYPE:
1225 switch (TREE_CODE (exp))
1227 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
1228 case NE_EXPR: op = OPCODE_if_acmpne; break;
1231 if (integer_zerop (exp1) || integer_zerop (exp0))
1233 generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
1234 STACK_TARGET, state);
1235 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1236 negop = (op & 1) ? op - 1 : op + 1;
1240 generate_bytecode_insns (exp0, STACK_TARGET, state);
1241 generate_bytecode_insns (exp1, STACK_TARGET, state);
1245 generate_bytecode_insns (exp0, STACK_TARGET, state);
1246 generate_bytecode_insns (exp1, STACK_TARGET, state);
1247 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1251 if (TYPE_PRECISION (type) > 32)
1262 if (TYPE_PRECISION (type) > 32)
1264 generate_bytecode_insns (exp0, STACK_TARGET, state);
1265 generate_bytecode_insns (exp1, STACK_TARGET, state);
1273 if (integer_zerop (exp1))
1275 generate_bytecode_insns (exp0, STACK_TARGET, state);
1279 if (integer_zerop (exp0))
1283 case OPCODE_if_icmplt:
1284 case OPCODE_if_icmpge:
1287 case OPCODE_if_icmpgt:
1288 case OPCODE_if_icmple:
1294 generate_bytecode_insns (exp1, STACK_TARGET, state);
1298 generate_bytecode_insns (exp0, STACK_TARGET, state);
1299 generate_bytecode_insns (exp1, STACK_TARGET, state);
1305 generate_bytecode_insns (exp, STACK_TARGET, state);
1307 if (true_branch_first)
1309 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1310 emit_goto (true_label, state);
1314 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1315 emit_goto (false_label, state);
1319 if (save_SP != state->code_SP)
1323 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1324 but only as far out as LIMIT (since we are about to jump to the
1325 emit label that is LIMIT). */
1328 call_cleanups (struct jcf_block *limit, struct jcf_partial *state)
1330 struct jcf_block *block = state->labeled_blocks;
1331 for (; block != limit; block = block->next)
1333 if (block->pc == PENDING_CLEANUP_PC)
1334 emit_jsr (block, state);
1339 generate_bytecode_return (tree exp, struct jcf_partial *state)
1341 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1342 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1347 switch (TREE_CODE (exp))
1350 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1352 exp = TREE_OPERAND (exp, 1);
1356 struct jcf_block *then_label = gen_jcf_label (state);
1357 struct jcf_block *else_label = gen_jcf_label (state);
1358 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1359 then_label, else_label, 1, state);
1360 define_jcf_label (then_label, state);
1361 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1362 define_jcf_label (else_label, state);
1363 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1367 generate_bytecode_insns (exp,
1368 returns_void ? IGNORE_TARGET
1369 : STACK_TARGET, state);
1375 call_cleanups (NULL, state);
1379 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1380 if (state->num_finalizers > 0)
1382 if (state->return_value_decl == NULL_TREE)
1384 state->return_value_decl
1385 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1386 localvar_alloc (state->return_value_decl, state);
1388 emit_store (state->return_value_decl, state);
1389 call_cleanups (NULL, state);
1390 emit_load (state->return_value_decl, state);
1391 /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
1392 then we risk the save decl erroneously re-used in the
1393 finalizer. Instead, we keep the state->return_value_decl
1394 allocated through the rest of the method. This is not
1395 the greatest solution, but it is at least simple and safe. */
1402 /* Generate bytecode for sub-expression EXP of METHOD.
1403 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1406 generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
1409 enum java_opcode jopcode;
1411 HOST_WIDE_INT value;
1416 if (exp == NULL && target == IGNORE_TARGET)
1419 type = TREE_TYPE (exp);
1421 switch (TREE_CODE (exp))
1424 if (BLOCK_EXPR_BODY (exp))
1427 tree body = BLOCK_EXPR_BODY (exp);
1428 long jsrs = state->num_jsrs;
1429 for (local = BLOCK_EXPR_DECLS (exp); local; )
1431 tree next = TREE_CHAIN (local);
1432 localvar_alloc (local, state);
1435 /* Avoid deep recursion for long blocks. */
1436 while (TREE_CODE (body) == COMPOUND_EXPR)
1438 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1439 body = TREE_OPERAND (body, 1);
1441 generate_bytecode_insns (body, target, state);
1443 for (local = BLOCK_EXPR_DECLS (exp); local; )
1445 tree next = TREE_CHAIN (local);
1446 maybe_free_localvar (local, state, state->num_jsrs <= jsrs);
1452 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1453 /* Normally the first operand to a COMPOUND_EXPR must complete
1454 normally. However, in the special case of a do-while
1455 statement this is not necessarily the case. */
1456 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0)))
1457 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1459 case EXPR_WITH_FILE_LOCATION:
1461 location_t saved_location = input_location;
1462 tree body = EXPR_WFL_NODE (exp);
1463 if (IS_EMPTY_STMT (body))
1465 input_filename = EXPR_WFL_FILENAME (exp);
1466 input_line = EXPR_WFL_LINENO (exp);
1467 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && input_line > 0
1468 && debug_info_level > DINFO_LEVEL_NONE)
1469 put_linenumber (input_line, state);
1470 generate_bytecode_insns (body, target, state);
1471 input_location = saved_location;
1475 if (target == IGNORE_TARGET) ; /* do nothing */
1476 else if (TREE_CODE (type) == POINTER_TYPE)
1478 if (! integer_zerop (exp))
1481 OP1 (OPCODE_aconst_null);
1484 else if (TYPE_PRECISION (type) <= 32)
1486 push_int_const (TREE_INT_CST_LOW (exp), state);
1491 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1498 int prec = TYPE_PRECISION (type) >> 5;
1500 if (real_zerop (exp) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp)))
1501 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1502 else if (real_onep (exp))
1503 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1504 else if (prec == 1 && real_twop (exp))
1505 OP1 (OPCODE_fconst_2);
1506 /* ??? We could also use iconst_3/ldc followed by i2f/i2d
1507 for other float/double when the value is a small integer. */
1510 offset = find_constant_index (exp, state);
1512 push_constant1 (offset, state);
1514 push_constant2 (offset, state);
1520 push_constant1 (find_string_constant (&state->cpool, exp), state);
1524 if (TREE_STATIC (exp))
1526 field_op (exp, OPCODE_getstatic, state);
1527 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1530 /* ... fall through ... */
1532 emit_load (exp, state);
1534 case NON_LVALUE_EXPR:
1536 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1539 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1540 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1541 if (target != IGNORE_TARGET)
1543 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1546 if (! TYPE_IS_WIDE (type))
1552 tree obj = TREE_OPERAND (exp, 0);
1553 tree field = TREE_OPERAND (exp, 1);
1554 int is_static = FIELD_STATIC (field);
1555 generate_bytecode_insns (obj,
1556 is_static ? IGNORE_TARGET : target, state);
1557 if (target != IGNORE_TARGET)
1559 if (DECL_NAME (field) == length_identifier_node && !is_static
1560 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1563 OP1 (OPCODE_arraylength);
1567 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1571 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1576 case TRUTH_ANDIF_EXPR:
1577 case TRUTH_ORIF_EXPR:
1591 struct jcf_block *then_label = gen_jcf_label (state);
1592 struct jcf_block *else_label = gen_jcf_label (state);
1593 struct jcf_block *end_label = gen_jcf_label (state);
1594 generate_bytecode_conditional (exp,
1595 then_label, else_label, 1, state);
1596 define_jcf_label (then_label, state);
1597 push_int_const (1, state);
1598 emit_goto (end_label, state);
1599 define_jcf_label (else_label, state);
1600 push_int_const (0, state);
1601 define_jcf_label (end_label, state);
1607 struct jcf_block *then_label = gen_jcf_label (state);
1608 struct jcf_block *else_label = gen_jcf_label (state);
1609 struct jcf_block *end_label = gen_jcf_label (state);
1610 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1611 then_label, else_label, 1, state);
1612 define_jcf_label (then_label, state);
1613 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1614 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1615 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1616 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1617 emit_goto (end_label, state);
1618 define_jcf_label (else_label, state);
1619 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1620 define_jcf_label (end_label, state);
1621 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1622 if (TREE_TYPE (exp) != void_type_node)
1623 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1628 struct jcf_switch_state *sw_state = state->sw_state;
1629 struct jcf_relocation *reloc
1630 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1631 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1633 reloc->label = get_jcf_label_here (state);
1634 reloc->offset = case_value;
1635 reloc->next = sw_state->cases;
1636 sw_state->cases = reloc;
1637 if (sw_state->num_cases == 0)
1639 sw_state->min_case = case_value;
1640 sw_state->max_case = case_value;
1644 if (case_value < sw_state->min_case)
1645 sw_state->min_case = case_value;
1646 if (case_value > sw_state->max_case)
1647 sw_state->max_case = case_value;
1649 sw_state->num_cases++;
1653 state->sw_state->default_label = get_jcf_label_here (state);
1658 /* The SWITCH_EXPR has three parts, generated in the following order:
1659 1. the switch_expression (the value used to select the correct case);
1661 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1662 After code generation, we will re-order them in the order 1, 3, 2.
1663 This is to avoid any extra GOTOs. */
1664 struct jcf_switch_state sw_state;
1665 struct jcf_block *expression_last; /* Last block of the switch_expression. */
1666 struct jcf_block *body_last; /* Last block of the switch_body. */
1667 struct jcf_block *switch_instruction; /* First block of switch_instruction. */
1668 struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1669 struct jcf_block *body_block;
1671 sw_state.prev = state->sw_state;
1672 state->sw_state = &sw_state;
1673 sw_state.cases = NULL;
1674 sw_state.num_cases = 0;
1675 sw_state.default_label = NULL;
1676 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1677 expression_last = state->last_block;
1678 /* Force a new block here. */
1679 body_block = gen_jcf_label (state);
1680 define_jcf_label (body_block, state);
1681 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1682 body_last = state->last_block;
1684 switch_instruction = gen_jcf_label (state);
1685 define_jcf_label (switch_instruction, state);
1686 if (sw_state.default_label == NULL)
1687 sw_state.default_label = gen_jcf_label (state);
1689 if (sw_state.num_cases <= 1)
1691 if (sw_state.num_cases == 0)
1693 emit_pop (1, state);
1698 push_int_const (sw_state.cases->offset, state);
1700 emit_if (sw_state.cases->label,
1701 OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1703 emit_goto (sw_state.default_label, state);
1708 unsigned HOST_WIDE_INT delta;
1709 /* Copy the chain of relocs into a sorted array. */
1710 struct jcf_relocation **relocs
1711 = xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1712 /* The relocs arrays is a buffer with a gap.
1713 The assumption is that cases will normally come in "runs". */
1715 int gap_end = sw_state.num_cases;
1716 struct jcf_relocation *reloc;
1717 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
1719 HOST_WIDE_INT case_value = reloc->offset;
1720 while (gap_end < sw_state.num_cases)
1722 struct jcf_relocation *end = relocs[gap_end];
1723 if (case_value <= end->offset)
1725 relocs[gap_start++] = end;
1728 while (gap_start > 0)
1730 struct jcf_relocation *before = relocs[gap_start-1];
1731 if (case_value >= before->offset)
1733 relocs[--gap_end] = before;
1736 relocs[gap_start++] = reloc;
1737 /* Note we don't check for duplicates. This is
1738 handled by the parser. */
1741 /* We could have DELTA < 0 if sw_state.min_case is
1742 something like Integer.MIN_VALUE. That is why delta is
1744 delta = sw_state.max_case - sw_state.min_case;
1745 if (2 * (unsigned) sw_state.num_cases >= delta)
1746 { /* Use tableswitch. */
1748 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1749 OP1 (OPCODE_tableswitch);
1750 emit_reloc (RELOCATION_VALUE_0,
1751 SWITCH_ALIGN_RELOC, NULL, state);
1752 emit_switch_reloc (sw_state.default_label, state);
1753 OP4 (sw_state.min_case);
1754 OP4 (sw_state.max_case);
1755 for (i = sw_state.min_case; ; )
1757 reloc = relocs[index];
1758 if (i == reloc->offset)
1760 emit_case_reloc (reloc, state);
1761 if (i == sw_state.max_case)
1766 emit_switch_reloc (sw_state.default_label, state);
1771 { /* Use lookupswitch. */
1772 RESERVE(9 + 8 * sw_state.num_cases);
1773 OP1 (OPCODE_lookupswitch);
1774 emit_reloc (RELOCATION_VALUE_0,
1775 SWITCH_ALIGN_RELOC, NULL, state);
1776 emit_switch_reloc (sw_state.default_label, state);
1777 OP4 (sw_state.num_cases);
1778 for (i = 0; i < sw_state.num_cases; i++)
1780 struct jcf_relocation *reloc = relocs[i];
1781 OP4 (reloc->offset);
1782 emit_case_reloc (reloc, state);
1788 instruction_last = state->last_block;
1789 if (sw_state.default_label->pc < 0)
1790 define_jcf_label (sw_state.default_label, state);
1791 else /* Force a new block. */
1792 sw_state.default_label = get_jcf_label_here (state);
1793 /* Now re-arrange the blocks so the switch_instruction
1794 comes before the switch_body. */
1795 switch_length = state->code_length - switch_instruction->pc;
1796 switch_instruction->pc = body_block->pc;
1797 instruction_last->next = body_block;
1798 instruction_last->v.chunk->next = body_block->v.chunk;
1799 expression_last->next = switch_instruction;
1800 expression_last->v.chunk->next = switch_instruction->v.chunk;
1801 body_last->next = sw_state.default_label;
1802 body_last->v.chunk->next = NULL;
1803 state->chunk = body_last->v.chunk;
1804 for (; body_block != sw_state.default_label; body_block = body_block->next)
1805 body_block->pc += switch_length;
1807 state->sw_state = sw_state.prev;
1812 exp = TREE_OPERAND (exp, 0);
1813 if (exp == NULL_TREE)
1814 exp = build_java_empty_stmt ();
1815 else if (TREE_CODE (exp) != MODIFY_EXPR)
1818 exp = TREE_OPERAND (exp, 1);
1819 generate_bytecode_return (exp, state);
1821 case LABELED_BLOCK_EXPR:
1823 struct jcf_block *end_label = gen_jcf_label (state);
1824 end_label->next = state->labeled_blocks;
1825 state->labeled_blocks = end_label;
1826 end_label->pc = PENDING_EXIT_PC;
1827 end_label->u.labeled_block = exp;
1828 if (LABELED_BLOCK_BODY (exp))
1829 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1830 if (state->labeled_blocks != end_label)
1832 state->labeled_blocks = end_label->next;
1833 define_jcf_label (end_label, state);
1838 tree body = TREE_OPERAND (exp, 0);
1840 if (TREE_CODE (body) == COMPOUND_EXPR
1841 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1843 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1844 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1845 struct jcf_block *head_label;
1846 struct jcf_block *body_label;
1847 struct jcf_block *end_label = gen_jcf_label (state);
1848 struct jcf_block *exit_label = state->labeled_blocks;
1849 head_label = gen_jcf_label (state);
1850 emit_goto (head_label, state);
1851 body_label = get_jcf_label_here (state);
1852 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1853 define_jcf_label (head_label, state);
1854 generate_bytecode_conditional (TREE_OPERAND (body, 0),
1855 end_label, body_label, 1, state);
1856 define_jcf_label (end_label, state);
1861 struct jcf_block *head_label = get_jcf_label_here (state);
1862 generate_bytecode_insns (body, IGNORE_TARGET, state);
1863 if (CAN_COMPLETE_NORMALLY (body))
1864 emit_goto (head_label, state);
1870 struct jcf_block *label = state->labeled_blocks;
1871 struct jcf_block *end_label = gen_jcf_label (state);
1872 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1873 label, end_label, 0, state);
1874 define_jcf_label (end_label, state);
1877 case EXIT_BLOCK_EXPR:
1879 struct jcf_block *label = state->labeled_blocks;
1880 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1881 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1882 label = label->next;
1883 call_cleanups (label, state);
1884 emit_goto (label, state);
1888 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
1889 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
1890 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
1891 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
1894 arg = TREE_OPERAND (exp, 1);
1895 exp = TREE_OPERAND (exp, 0);
1896 type = TREE_TYPE (exp);
1897 size = TYPE_IS_WIDE (type) ? 2 : 1;
1898 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1899 && ! TREE_STATIC (exp)
1900 && TREE_CODE (type) == INTEGER_TYPE
1901 && TYPE_PRECISION (type) == 32)
1903 if (target != IGNORE_TARGET && post_op)
1904 emit_load (exp, state);
1905 emit_iinc (exp, value, state);
1906 if (target != IGNORE_TARGET && ! post_op)
1907 emit_load (exp, state);
1910 if (TREE_CODE (exp) == COMPONENT_REF)
1912 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1913 emit_dup (1, 0, state);
1914 /* Stack: ..., objectref, objectref. */
1915 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1917 /* Stack: ..., objectref, oldvalue. */
1920 else if (TREE_CODE (exp) == ARRAY_REF)
1922 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1923 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1924 emit_dup (2, 0, state);
1925 /* Stack: ..., array, index, array, index. */
1926 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1930 /* Stack: ..., array, index, oldvalue. */
1933 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1935 generate_bytecode_insns (exp, STACK_TARGET, state);
1936 /* Stack: ..., oldvalue. */
1942 if (target != IGNORE_TARGET && post_op)
1943 emit_dup (size, offset, state);
1944 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1945 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1946 /* Stack, otherwise: ..., [result, ] oldvalue. */
1947 generate_bytecode_insns (arg, STACK_TARGET, state);
1948 emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
1949 + adjust_typed_op (type, 3),
1951 if (target != IGNORE_TARGET && ! post_op)
1952 emit_dup (size, offset, state);
1953 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1954 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1955 /* Stack, otherwise: ..., [result, ] newvalue. */
1956 goto finish_assignment;
1960 tree lhs = TREE_OPERAND (exp, 0);
1961 tree rhs = TREE_OPERAND (exp, 1);
1964 /* See if we can use the iinc instruction. */
1965 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
1966 && ! TREE_STATIC (lhs)
1967 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
1968 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
1969 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
1971 tree arg0 = TREE_OPERAND (rhs, 0);
1972 tree arg1 = TREE_OPERAND (rhs, 1);
1973 HOST_WIDE_INT min_value = -32768;
1974 HOST_WIDE_INT max_value = 32767;
1975 if (TREE_CODE (rhs) == MINUS_EXPR)
1980 else if (arg1 == lhs)
1983 arg1 = TREE_OPERAND (rhs, 0);
1985 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
1987 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
1988 value = TREE_INT_CST_LOW (arg1);
1989 if ((hi_value == 0 && value <= max_value)
1990 || (hi_value == -1 && value >= min_value))
1992 if (TREE_CODE (rhs) == MINUS_EXPR)
1994 emit_iinc (lhs, value, state);
1995 if (target != IGNORE_TARGET)
1996 emit_load (lhs, state);
2002 if (TREE_CODE (lhs) == COMPONENT_REF)
2004 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
2005 STACK_TARGET, state);
2008 else if (TREE_CODE (lhs) == ARRAY_REF)
2010 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
2011 STACK_TARGET, state);
2012 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
2013 STACK_TARGET, state);
2019 /* If the rhs is a binary expression and the left operand is
2020 `==' to the lhs then we have an OP= expression. In this
2021 case we must do some special processing. */
2022 if (TREE_CODE_CLASS (TREE_CODE (rhs)) == '2'
2023 && lhs == TREE_OPERAND (rhs, 0))
2025 if (TREE_CODE (lhs) == COMPONENT_REF)
2027 tree field = TREE_OPERAND (lhs, 1);
2028 if (! FIELD_STATIC (field))
2030 /* Duplicate the object reference so we can get
2032 emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
2035 field_op (field, (FIELD_STATIC (field)
2040 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2042 else if (TREE_CODE (lhs) == VAR_DECL
2043 || TREE_CODE (lhs) == PARM_DECL)
2045 if (FIELD_STATIC (lhs))
2047 field_op (lhs, OPCODE_getstatic, state);
2048 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2051 emit_load (lhs, state);
2053 else if (TREE_CODE (lhs) == ARRAY_REF)
2055 /* Duplicate the array and index, which are on the
2056 stack, so that we can load the old value. */
2057 emit_dup (2, 0, state);
2059 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
2062 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2067 /* This function correctly handles the case where the LHS
2068 of a binary expression is NULL_TREE. */
2069 rhs = build (TREE_CODE (rhs), TREE_TYPE (rhs),
2070 NULL_TREE, TREE_OPERAND (rhs, 1));
2073 generate_bytecode_insns (rhs, STACK_TARGET, state);
2074 if (target != IGNORE_TARGET)
2075 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2081 if (TREE_CODE (exp) == COMPONENT_REF)
2083 tree field = TREE_OPERAND (exp, 1);
2084 if (! FIELD_STATIC (field))
2087 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2090 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2092 else if (TREE_CODE (exp) == VAR_DECL
2093 || TREE_CODE (exp) == PARM_DECL)
2095 if (FIELD_STATIC (exp))
2097 field_op (exp, OPCODE_putstatic, state);
2098 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2101 emit_store (exp, state);
2103 else if (TREE_CODE (exp) == ARRAY_REF)
2105 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2108 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2114 jopcode = OPCODE_iadd;
2117 jopcode = OPCODE_isub;
2120 jopcode = OPCODE_imul;
2122 case TRUNC_DIV_EXPR:
2124 jopcode = OPCODE_idiv;
2126 case TRUNC_MOD_EXPR:
2127 jopcode = OPCODE_irem;
2129 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
2130 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
2131 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
2132 case TRUTH_AND_EXPR:
2133 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
2135 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
2136 case TRUTH_XOR_EXPR:
2137 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
2140 tree arg0 = TREE_OPERAND (exp, 0);
2141 tree arg1 = TREE_OPERAND (exp, 1);
2142 jopcode += adjust_typed_op (type, 3);
2143 if (arg0 != NULL_TREE && operand_equal_p (arg0, arg1, 0))
2145 /* fold may (e.g) convert 2*x to x+x. */
2146 generate_bytecode_insns (arg0, target, state);
2147 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2151 /* ARG0 will be NULL_TREE if we're handling an `OP='
2152 expression. In this case the stack already holds the
2153 LHS. See the MODIFY_EXPR case. */
2154 if (arg0 != NULL_TREE)
2155 generate_bytecode_insns (arg0, target, state);
2156 if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2157 arg1 = convert (int_type_node, arg1);
2158 generate_bytecode_insns (arg1, target, state);
2160 /* For most binary operations, both operands and the result have the
2161 same type. Shift operations are different. Using arg1's type
2162 gets us the correct SP adjustment in all cases. */
2163 if (target == STACK_TARGET)
2164 emit_binop (jopcode, TREE_TYPE (arg1), state);
2167 case TRUTH_NOT_EXPR:
2169 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2170 if (target == STACK_TARGET)
2172 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2173 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
2177 NOTE_PUSH (1 + is_long);
2178 OP1 (OPCODE_ixor + is_long);
2179 NOTE_POP (1 + is_long);
2183 jopcode = OPCODE_ineg;
2184 jopcode += adjust_typed_op (type, 3);
2185 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2186 if (target == STACK_TARGET)
2187 emit_unop (jopcode, type, state);
2189 case INSTANCEOF_EXPR:
2191 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2192 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2194 OP1 (OPCODE_instanceof);
2199 /* Because the state associated with a SAVE_EXPR tree node must
2200 be a RTL expression, we use it to store the DECL_LOCAL_INDEX
2201 of a temporary variable in a CONST_INT. */
2202 if (! SAVE_EXPR_RTL (exp))
2204 tree type = TREE_TYPE (exp);
2205 tree decl = build_decl (VAR_DECL, NULL_TREE, type);
2206 generate_bytecode_insns (TREE_OPERAND (exp, 0),
2207 STACK_TARGET, state);
2208 localvar_alloc (decl, state);
2209 SAVE_EXPR_RTL (exp) = GEN_INT (DECL_LOCAL_INDEX (decl));
2210 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1, 0, state);
2211 emit_store (decl, state);
2215 /* The following code avoids creating a temporary DECL just
2216 to pass to emit_load. This code could be factored with
2217 the similar implementation in emit_load_or_store. */
2218 tree type = TREE_TYPE (exp);
2219 int kind = adjust_typed_op (type, 4);
2220 int index = (int) INTVAL (SAVE_EXPR_RTL (exp));
2223 RESERVE (1); /* [ilfda]load_[0123] */
2224 OP1 (OPCODE_iload + 5 + 4*kind + index);
2226 else /* [ilfda]load */
2227 maybe_wide (OPCODE_iload + kind, index, state);
2228 NOTE_PUSH (TYPE_IS_WIDE (type) ? 2 : 1);
2234 case FIX_TRUNC_EXPR:
2236 tree src = TREE_OPERAND (exp, 0);
2237 tree src_type = TREE_TYPE (src);
2238 tree dst_type = TREE_TYPE (exp);
2239 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2240 if (target == IGNORE_TARGET || src_type == dst_type)
2242 if (TREE_CODE (dst_type) == POINTER_TYPE)
2244 if (TREE_CODE (exp) == CONVERT_EXPR)
2246 int index = find_class_constant (&state->cpool,
2247 TREE_TYPE (dst_type));
2249 OP1 (OPCODE_checkcast);
2253 else /* Convert numeric types. */
2255 int wide_src = TYPE_PRECISION (src_type) > 32;
2256 int wide_dst = TYPE_PRECISION (dst_type) > 32;
2257 NOTE_POP (1 + wide_src);
2259 if (TREE_CODE (dst_type) == REAL_TYPE)
2261 if (TREE_CODE (src_type) == REAL_TYPE)
2262 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2263 else if (TYPE_PRECISION (src_type) == 64)
2264 OP1 (OPCODE_l2f + wide_dst);
2266 OP1 (OPCODE_i2f + wide_dst);
2268 else /* Convert to integral type. */
2270 if (TREE_CODE (src_type) == REAL_TYPE)
2271 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2276 if (TYPE_PRECISION (dst_type) < 32)
2279 /* Already converted to int, if needed. */
2280 if (TYPE_PRECISION (dst_type) <= 8)
2282 else if (TYPE_UNSIGNED (dst_type))
2288 NOTE_PUSH (1 + wide_dst);
2295 tree try_clause = TREE_OPERAND (exp, 0);
2296 struct jcf_block *start_label = get_jcf_label_here (state);
2297 struct jcf_block *end_label; /* End of try clause. */
2298 struct jcf_block *finished_label = gen_jcf_label (state);
2299 tree clause = TREE_OPERAND (exp, 1);
2300 if (target != IGNORE_TARGET)
2302 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2303 end_label = get_jcf_label_here (state);
2304 if (end_label == start_label)
2306 if (CAN_COMPLETE_NORMALLY (try_clause))
2307 emit_goto (finished_label, state);
2308 while (clause != NULL_TREE)
2310 tree catch_clause = TREE_OPERAND (clause, 0);
2311 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2312 struct jcf_handler *handler = alloc_handler (start_label,
2314 if (exception_decl == NULL_TREE)
2315 handler->type = NULL_TREE;
2317 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2318 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2319 clause = TREE_CHAIN (clause);
2320 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2321 emit_goto (finished_label, state);
2323 define_jcf_label (finished_label, state);
2327 case TRY_FINALLY_EXPR:
2329 struct jcf_block *finished_label = NULL;
2330 struct jcf_block *finally_label, *start_label, *end_label;
2331 struct jcf_handler *handler;
2332 tree try_block = TREE_OPERAND (exp, 0);
2333 tree finally = TREE_OPERAND (exp, 1);
2334 tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2336 tree exception_type;
2338 finally_label = gen_jcf_label (state);
2339 start_label = get_jcf_label_here (state);
2340 /* If the `finally' clause can complete normally, we emit it
2341 as a subroutine and let the other clauses call it via
2342 `jsr'. If it can't complete normally, then we simply emit
2343 `goto's directly to it. */
2344 if (CAN_COMPLETE_NORMALLY (finally))
2346 finally_label->pc = PENDING_CLEANUP_PC;
2347 finally_label->next = state->labeled_blocks;
2348 state->labeled_blocks = finally_label;
2349 state->num_finalizers++;
2352 generate_bytecode_insns (try_block, target, state);
2354 if (CAN_COMPLETE_NORMALLY (finally))
2356 if (state->labeled_blocks != finally_label)
2358 state->labeled_blocks = finally_label->next;
2360 end_label = get_jcf_label_here (state);
2362 if (end_label == start_label)
2364 state->num_finalizers--;
2365 define_jcf_label (finally_label, state);
2366 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2370 if (CAN_COMPLETE_NORMALLY (finally))
2372 return_link = build_decl (VAR_DECL, NULL_TREE,
2373 return_address_type_node);
2374 finished_label = gen_jcf_label (state);
2377 if (CAN_COMPLETE_NORMALLY (try_block))
2379 if (CAN_COMPLETE_NORMALLY (finally))
2381 emit_jsr (finally_label, state);
2382 emit_goto (finished_label, state);
2385 emit_goto (finally_label, state);
2388 /* Handle exceptions. */
2390 exception_type = build_pointer_type (throwable_type_node);
2391 if (CAN_COMPLETE_NORMALLY (finally))
2393 /* We're going to generate a subroutine, so we'll need to
2394 save and restore the exception around the `jsr'. */
2395 exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2396 localvar_alloc (return_link, state);
2398 handler = alloc_handler (start_label, end_label, state);
2399 handler->type = NULL_TREE;
2400 if (CAN_COMPLETE_NORMALLY (finally))
2402 localvar_alloc (exception_decl, state);
2404 emit_store (exception_decl, state);
2405 emit_jsr (finally_label, state);
2406 emit_load (exception_decl, state);
2408 OP1 (OPCODE_athrow);
2413 /* We're not generating a subroutine. In this case we can
2414 simply have the exception handler pop the exception and
2415 then fall through to the `finally' block. */
2417 emit_pop (1, state);
2421 /* The finally block. If we're generating a subroutine, first
2422 save return PC into return_link. Otherwise, just generate
2423 the code for the `finally' block. */
2424 define_jcf_label (finally_label, state);
2425 if (CAN_COMPLETE_NORMALLY (finally))
2428 emit_store (return_link, state);
2431 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2432 if (CAN_COMPLETE_NORMALLY (finally))
2434 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2435 maybe_free_localvar (exception_decl, state, 1);
2436 maybe_free_localvar (return_link, state, 1);
2437 define_jcf_label (finished_label, state);
2442 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2444 OP1 (OPCODE_athrow);
2446 case NEW_ARRAY_INIT:
2448 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2449 tree array_type = TREE_TYPE (TREE_TYPE (exp));
2450 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2451 HOST_WIDE_INT length = java_array_type_length (array_type);
2452 if (target == IGNORE_TARGET)
2454 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
2455 generate_bytecode_insns (TREE_VALUE (values), target, state);
2458 push_int_const (length, state);
2461 if (JPRIMITIVE_TYPE_P (element_type))
2463 int atype = encode_newarray_type (element_type);
2464 OP1 (OPCODE_newarray);
2469 int index = find_class_constant (&state->cpool,
2470 TREE_TYPE (element_type));
2471 OP1 (OPCODE_anewarray);
2475 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2476 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
2478 int save_SP = state->code_SP;
2479 emit_dup (1, 0, state);
2480 push_int_const (offset, state);
2482 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2485 state->code_SP = save_SP;
2489 case JAVA_EXC_OBJ_EXPR:
2490 NOTE_PUSH (1); /* Pushed by exception system. */
2495 /* This copes with cases where fold() has created MIN or MAX
2496 from a conditional expression. */
2497 enum tree_code code = TREE_CODE (exp) == MIN_EXPR ? LT_EXPR : GT_EXPR;
2498 tree op0 = TREE_OPERAND (exp, 0);
2499 tree op1 = TREE_OPERAND (exp, 1);
2501 if (TREE_SIDE_EFFECTS (op0) || TREE_SIDE_EFFECTS (op1))
2503 x = build (COND_EXPR, TREE_TYPE (exp),
2504 build (code, boolean_type_node, op0, op1),
2506 generate_bytecode_insns (x, target, state);
2509 case NEW_CLASS_EXPR:
2511 tree class = TREE_TYPE (TREE_TYPE (exp));
2512 int need_result = target != IGNORE_TARGET;
2513 int index = find_class_constant (&state->cpool, class);
2519 NOTE_PUSH (1 + need_result);
2521 /* ... fall though ... */
2524 tree f = TREE_OPERAND (exp, 0);
2525 tree x = TREE_OPERAND (exp, 1);
2526 int save_SP = state->code_SP;
2528 if (TREE_CODE (f) == ADDR_EXPR)
2529 f = TREE_OPERAND (f, 0);
2530 if (f == soft_newarray_node)
2532 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2533 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2534 STACK_TARGET, state);
2536 OP1 (OPCODE_newarray);
2540 else if (f == soft_multianewarray_node)
2544 int index = find_class_constant (&state->cpool,
2545 TREE_TYPE (TREE_TYPE (exp)));
2546 x = TREE_CHAIN (x); /* Skip class argument. */
2547 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2548 for (idim = ndims; --idim >= 0; )
2551 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2554 OP1 (OPCODE_multianewarray);
2559 else if (f == soft_anewarray_node)
2561 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2562 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2563 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2565 OP1 (OPCODE_anewarray);
2569 else if (f == soft_monitorenter_node
2570 || f == soft_monitorexit_node
2573 if (f == soft_monitorenter_node)
2574 op = OPCODE_monitorenter;
2575 else if (f == soft_monitorexit_node)
2576 op = OPCODE_monitorexit;
2579 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2585 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
2587 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2589 nargs = state->code_SP - save_SP;
2590 state->code_SP = save_SP;
2591 if (f == soft_fmod_node)
2598 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2599 NOTE_POP (1); /* Pop implicit this. */
2600 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2602 tree context = DECL_CONTEXT (f);
2603 int index, interface = 0;
2605 if (METHOD_STATIC (f))
2606 OP1 (OPCODE_invokestatic);
2607 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2608 || METHOD_PRIVATE (f))
2609 OP1 (OPCODE_invokespecial);
2612 if (CLASS_INTERFACE (TYPE_NAME (context)))
2614 tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2615 context = TREE_TYPE (TREE_TYPE (arg1));
2616 if (CLASS_INTERFACE (TYPE_NAME (context)))
2620 OP1 (OPCODE_invokeinterface);
2622 OP1 (OPCODE_invokevirtual);
2624 index = find_methodref_with_class_index (&state->cpool, f, context);
2634 f = TREE_TYPE (TREE_TYPE (f));
2635 if (TREE_CODE (f) != VOID_TYPE)
2637 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2638 if (target == IGNORE_TARGET)
2639 emit_pop (size, state);
2649 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2650 tree_code_name [(int) TREE_CODE (exp)]);
2655 perform_relocations (struct jcf_partial *state)
2657 struct jcf_block *block;
2658 struct jcf_relocation *reloc;
2662 /* Before we start, the pc field of each block is an upper bound on
2663 the block's start pc (it may be less, if previous blocks need less
2664 than their maximum).
2666 The minimum size of each block is in the block's chunk->size. */
2668 /* First, figure out the actual locations of each block. */
2671 for (block = state->blocks; block != NULL; block = block->next)
2673 int block_size = block->v.chunk->size;
2677 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2678 Assumes relocations are in reverse order. */
2679 reloc = block->u.relocations;
2680 while (reloc != NULL
2681 && reloc->kind == OPCODE_goto_w
2682 && reloc->label->pc == block->next->pc
2683 && reloc->offset + 2 == block_size)
2685 reloc = reloc->next;
2686 block->u.relocations = reloc;
2687 block->v.chunk->size -= 3;
2692 /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2693 jump directly to X. We're careful here to avoid an infinite
2694 loop if the `goto's themselves form one. We do this
2695 optimization because we can generate a goto-to-goto for some
2696 try/finally blocks. */
2697 while (reloc != NULL
2698 && reloc->kind == OPCODE_goto_w
2699 && reloc->label != block
2700 && reloc->label->v.chunk->data != NULL
2701 && reloc->label->v.chunk->data[0] == OPCODE_goto)
2703 /* Find the reloc for the first instruction of the
2704 destination block. */
2705 struct jcf_relocation *first_reloc;
2706 for (first_reloc = reloc->label->u.relocations;
2708 first_reloc = first_reloc->next)
2710 if (first_reloc->offset == 1
2711 && first_reloc->kind == OPCODE_goto_w)
2713 reloc->label = first_reloc->label;
2718 /* If we didn't do anything, exit the loop. */
2719 if (first_reloc == NULL)
2723 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
2725 if (reloc->kind == SWITCH_ALIGN_RELOC)
2727 /* We assume this is the first relocation in this block,
2728 so we know its final pc. */
2729 int where = pc + reloc->offset;
2730 int pad = ((where + 3) & ~3) - where;
2733 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2735 int delta = reloc->label->pc - (pc + reloc->offset - 1);
2736 int expand = reloc->kind > 0 ? 2 : 5;
2740 if (delta >= -32768 && delta <= 32767)
2746 block_size += expand;
2752 for (block = state->blocks; block != NULL; block = block->next)
2754 struct chunk *chunk = block->v.chunk;
2755 int old_size = chunk->size;
2756 int next_pc = block->next == NULL ? pc : block->next->pc;
2757 int new_size = next_pc - block->pc;
2758 unsigned char *new_ptr;
2759 unsigned char *old_buffer = chunk->data;
2760 unsigned char *old_ptr = old_buffer + old_size;
2761 if (new_size != old_size)
2763 chunk->data = obstack_alloc (state->chunk_obstack, new_size);
2764 chunk->size = new_size;
2766 new_ptr = chunk->data + new_size;
2768 /* We do the relocations from back to front, because
2769 the relocations are in reverse order. */
2770 for (reloc = block->u.relocations; ; reloc = reloc->next)
2772 /* new_ptr and old_ptr point into the old and new buffers,
2773 respectively. (If no relocations cause the buffer to
2774 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2775 The bytes at higher address have been copied and relocations
2776 handled; those at lower addresses remain to process. */
2778 /* Lower old index of piece to be copied with no relocation.
2779 I.e. high index of the first piece that does need relocation. */
2780 int start = reloc == NULL ? 0
2781 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2782 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2784 : reloc->offset + 2;
2787 int n = (old_ptr - old_buffer) - start;
2791 memcpy (new_ptr, old_ptr, n);
2792 if (old_ptr == old_buffer)
2795 new_offset = new_ptr - chunk->data;
2796 new_offset -= (reloc->kind == -1 ? 2 : 4);
2797 if (reloc->kind == 0)
2800 value = GET_u4 (old_ptr);
2802 else if (reloc->kind == BLOCK_START_RELOC)
2808 else if (reloc->kind == SWITCH_ALIGN_RELOC)
2810 int where = block->pc + reloc->offset;
2811 int pad = ((where + 3) & ~3) - where;
2819 value = GET_u2 (old_ptr);
2821 value += reloc->label->pc - (block->pc + new_offset);
2822 *--new_ptr = (unsigned char) value; value >>= 8;
2823 *--new_ptr = (unsigned char) value; value >>= 8;
2824 if (reloc->kind != -1)
2826 *--new_ptr = (unsigned char) value; value >>= 8;
2827 *--new_ptr = (unsigned char) value;
2829 if (reloc->kind > BLOCK_START_RELOC)
2831 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2833 *--new_ptr = reloc->kind;
2835 else if (reloc->kind < -1)
2837 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2839 *--new_ptr = OPCODE_goto_w;
2842 *--new_ptr = - reloc->kind;
2845 if (new_ptr != chunk->data)
2848 state->code_length = pc;
2852 init_jcf_state (struct jcf_partial *state, struct obstack *work)
2854 state->chunk_obstack = work;
2855 state->first = state->chunk = NULL;
2856 CPOOL_INIT (&state->cpool);
2857 BUFFER_INIT (&state->localvars);
2858 BUFFER_INIT (&state->bytecode);
2862 init_jcf_method (struct jcf_partial *state, tree method)
2864 state->current_method = method;
2865 state->blocks = state->last_block = NULL;
2866 state->linenumber_count = 0;
2867 state->first_lvar = state->last_lvar = NULL;
2868 state->lvar_count = 0;
2869 state->labeled_blocks = NULL;
2870 state->code_length = 0;
2871 BUFFER_RESET (&state->bytecode);
2872 BUFFER_RESET (&state->localvars);
2874 state->code_SP_max = 0;
2875 state->handlers = NULL;
2876 state->last_handler = NULL;
2877 state->num_handlers = 0;
2878 state->num_finalizers = 0;
2879 state->return_value_decl = NULL_TREE;
2883 release_jcf_state (struct jcf_partial *state)
2885 CPOOL_FINISH (&state->cpool);
2886 obstack_free (state->chunk_obstack, state->first);
2889 /* Generate and return a list of chunks containing the class CLAS
2890 in the .class file representation. The list can be written to a
2891 .class file using write_chunks. Allocate chunks from obstack WORK. */
2893 static GTY(()) tree SourceFile_node;
2894 static struct chunk *
2895 generate_classfile (tree clas, struct jcf_partial *state)
2897 struct chunk *cpool_chunk;
2898 const char *source_file, *s;
2901 char *fields_count_ptr;
2902 int fields_count = 0;
2903 char *methods_count_ptr;
2904 int methods_count = 0;
2907 = clas == object_type_node ? 0
2908 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2910 ptr = append_chunk (NULL, 8, state);
2911 PUT4 (0xCafeBabe); /* Magic number */
2912 PUT2 (3); /* Minor version */
2913 PUT2 (45); /* Major version */
2915 append_chunk (NULL, 0, state);
2916 cpool_chunk = state->chunk;
2918 /* Next allocate the chunk containing access_flags through fields_count. */
2919 if (clas == object_type_node)
2922 i = 8 + 2 * total_supers;
2923 ptr = append_chunk (NULL, i, state);
2924 i = get_access_flags (TYPE_NAME (clas));
2925 if (! (i & ACC_INTERFACE))
2927 PUT2 (i); /* access_flags */
2928 i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
2929 if (clas == object_type_node)
2931 PUT2(0); /* super_class */
2932 PUT2(0); /* interfaces_count */
2936 tree basetypes = TYPE_BINFO_BASETYPES (clas);
2937 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2938 int j = find_class_constant (&state->cpool, base);
2939 PUT2 (j); /* super_class */
2940 PUT2 (total_supers - 1); /* interfaces_count */
2941 for (i = 1; i < total_supers; i++)
2943 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2944 j = find_class_constant (&state->cpool, base);
2948 fields_count_ptr = ptr;
2950 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
2952 int have_value, attr_count = 0;
2953 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2955 ptr = append_chunk (NULL, 8, state);
2956 i = get_access_flags (part); PUT2 (i);
2957 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
2958 i = find_utf8_constant (&state->cpool,
2959 build_java_signature (TREE_TYPE (part)));
2961 have_value = DECL_INITIAL (part) != NULL_TREE
2962 && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
2963 && FIELD_FINAL (part)
2964 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
2965 || TREE_TYPE (part) == string_ptr_type_node);
2969 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2970 || FIELD_SYNTHETIC (part))
2972 if (FIELD_DEPRECATED (part))
2975 PUT2 (attr_count); /* attributes_count */
2978 tree init = DECL_INITIAL (part);
2979 static tree ConstantValue_node = NULL_TREE;
2980 if (TREE_TYPE (part) != TREE_TYPE (init))
2981 fatal_error ("field initializer type mismatch");
2982 ptr = append_chunk (NULL, 8, state);
2983 if (ConstantValue_node == NULL_TREE)
2984 ConstantValue_node = get_identifier ("ConstantValue");
2985 i = find_utf8_constant (&state->cpool, ConstantValue_node);
2986 PUT2 (i); /* attribute_name_index */
2987 PUT4 (2); /* attribute_length */
2988 i = find_constant_index (init, state); PUT2 (i);
2990 /* Emit the "Synthetic" attribute for val$<x> and this$<n>
2991 fields and other fields which need it. */
2992 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2993 || FIELD_SYNTHETIC (part))
2994 ptr = append_synthetic_attribute (state);
2995 if (FIELD_DEPRECATED (part))
2996 append_deprecated_attribute (state);
2999 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
3001 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
3004 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
3006 struct jcf_block *block;
3007 tree function_body = DECL_FUNCTION_BODY (part);
3008 tree body = function_body == NULL_TREE ? NULL_TREE
3009 : BLOCK_EXPR_BODY (function_body);
3010 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
3012 tree type = TREE_TYPE (part);
3013 tree save_function = current_function_decl;
3014 int synthetic_p = 0;
3016 /* Invisible Miranda methods shouldn't end up in the .class
3018 if (METHOD_INVISIBLE (part))
3021 current_function_decl = part;
3022 ptr = append_chunk (NULL, 8, state);
3023 i = get_access_flags (part); PUT2 (i);
3024 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3025 i = find_utf8_constant (&state->cpool, build_java_signature (type));
3027 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
3029 /* Make room for the Synthetic attribute (of zero length.) */
3030 if (DECL_FINIT_P (part)
3031 || DECL_INSTINIT_P (part)
3032 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
3033 || TYPE_DOT_CLASS (clas) == part)
3038 /* Make room for Deprecated attribute. */
3039 if (METHOD_DEPRECATED (part))
3042 PUT2 (i); /* attributes_count */
3045 ptr = append_synthetic_attribute (state);
3047 if (body != NULL_TREE)
3049 int code_attributes_count = 0;
3050 static tree Code_node = NULL_TREE;
3053 struct jcf_handler *handler;
3054 if (Code_node == NULL_TREE)
3055 Code_node = get_identifier ("Code");
3056 ptr = append_chunk (NULL, 14, state);
3057 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
3059 init_jcf_method (state, part);
3060 get_jcf_label_here (state); /* Force a first block. */
3061 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3062 localvar_alloc (t, state);
3063 state->num_jsrs = 0;
3064 generate_bytecode_insns (body, IGNORE_TARGET, state);
3065 if (CAN_COMPLETE_NORMALLY (body))
3067 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
3070 OP1 (OPCODE_return);
3072 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3073 maybe_free_localvar (t, state, 1);
3074 if (state->return_value_decl != NULL_TREE)
3075 maybe_free_localvar (state->return_value_decl, state, 1);
3076 finish_jcf_block (state);
3077 perform_relocations (state);
3080 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
3081 if (state->linenumber_count > 0)
3083 code_attributes_count++;
3084 i += 8 + 4 * state->linenumber_count;
3086 if (state->lvar_count > 0)
3088 code_attributes_count++;
3089 i += 8 + 10 * state->lvar_count;
3091 UNSAFE_PUT4 (i); /* attribute_length */
3092 UNSAFE_PUT2 (state->code_SP_max); /* max_stack */
3093 UNSAFE_PUT2 (localvar_max); /* max_locals */
3094 UNSAFE_PUT4 (state->code_length);
3096 /* Emit the exception table. */
3097 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3098 PUT2 (state->num_handlers); /* exception_table_length */
3099 handler = state->handlers;
3100 for (; handler != NULL; handler = handler->next)
3103 PUT2 (handler->start_label->pc);
3104 PUT2 (handler->end_label->pc);
3105 PUT2 (handler->handler_label->pc);
3106 if (handler->type == NULL_TREE)
3109 type_index = find_class_constant (&state->cpool,
3114 ptr = append_chunk (NULL, 2, state);
3115 PUT2 (code_attributes_count);
3117 /* Write the LineNumberTable attribute. */
3118 if (state->linenumber_count > 0)
3120 static tree LineNumberTable_node = NULL_TREE;
3121 ptr = append_chunk (NULL,
3122 8 + 4 * state->linenumber_count, state);
3123 if (LineNumberTable_node == NULL_TREE)
3124 LineNumberTable_node = get_identifier ("LineNumberTable");
3125 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3126 PUT2 (i); /* attribute_name_index */
3127 i = 2+4*state->linenumber_count; PUT4(i); /* attribute_length */
3128 i = state->linenumber_count; PUT2 (i);
3129 for (block = state->blocks; block != NULL; block = block->next)
3131 int line = block->linenumber;
3140 /* Write the LocalVariableTable attribute. */
3141 if (state->lvar_count > 0)
3143 static tree LocalVariableTable_node = NULL_TREE;
3144 struct localvar_info *lvar = state->first_lvar;
3145 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3146 if (LocalVariableTable_node == NULL_TREE)
3147 LocalVariableTable_node = get_identifier("LocalVariableTable");
3148 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3149 PUT2 (i); /* attribute_name_index */
3150 i = 2 + 10 * state->lvar_count; PUT4 (i); /* attribute_length */
3151 i = state->lvar_count; PUT2 (i);
3152 for ( ; lvar != NULL; lvar = lvar->next)
3154 tree name = DECL_NAME (lvar->decl);
3155 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3156 i = lvar->start_label->pc; PUT2 (i);
3157 i = lvar->end_label->pc - i; PUT2 (i);
3158 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3159 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
3160 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
3164 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3166 tree t = DECL_FUNCTION_THROWS (part);
3167 int throws_count = list_length (t);
3168 static tree Exceptions_node = NULL_TREE;
3169 if (Exceptions_node == NULL_TREE)
3170 Exceptions_node = get_identifier ("Exceptions");
3171 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3172 i = find_utf8_constant (&state->cpool, Exceptions_node);
3173 PUT2 (i); /* attribute_name_index */
3174 i = 2 + 2 * throws_count; PUT4(i); /* attribute_length */
3175 i = throws_count; PUT2 (i);
3176 for (; t != NULL_TREE; t = TREE_CHAIN (t))
3178 i = find_class_constant (&state->cpool, TREE_VALUE (t));
3183 if (METHOD_DEPRECATED (part))
3184 append_deprecated_attribute (state);
3187 current_function_decl = save_function;
3189 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
3191 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3192 for (s = source_file; ; s++)
3197 if (ch == '/' || ch == '\\')
3200 ptr = append_chunk (NULL, 10, state);
3202 i = 1; /* Source file always exists as an attribute */
3203 if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3205 if (clas == object_type_node)
3207 if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3210 PUT2 (i); /* attributes_count */
3212 /* generate the SourceFile attribute. */
3213 if (SourceFile_node == NULL_TREE)
3215 SourceFile_node = get_identifier ("SourceFile");
3218 i = find_utf8_constant (&state->cpool, SourceFile_node);
3219 PUT2 (i); /* attribute_name_index */
3221 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3223 append_gcj_attribute (state, clas);
3224 append_innerclasses_attribute (state, clas);
3225 if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3226 append_deprecated_attribute (state);
3228 /* New finally generate the contents of the constant pool chunk. */
3229 i = count_constant_pool_bytes (&state->cpool);
3230 ptr = obstack_alloc (state->chunk_obstack, i);
3231 cpool_chunk->data = ptr;
3232 cpool_chunk->size = i;
3233 write_constant_pool (&state->cpool, ptr, i);
3234 return state->first;
3237 static GTY(()) tree Synthetic_node;
3238 static unsigned char *
3239 append_synthetic_attribute (struct jcf_partial *state)
3241 unsigned char *ptr = append_chunk (NULL, 6, state);
3244 if (Synthetic_node == NULL_TREE)
3246 Synthetic_node = get_identifier ("Synthetic");
3248 i = find_utf8_constant (&state->cpool, Synthetic_node);
3249 PUT2 (i); /* Attribute string index */
3250 PUT4 (0); /* Attribute length */
3256 append_deprecated_attribute (struct jcf_partial *state)
3258 unsigned char *ptr = append_chunk (NULL, 6, state);
3261 i = find_utf8_constant (&state->cpool, get_identifier ("Deprecated"));
3262 PUT2 (i); /* Attribute string index */
3263 PUT4 (0); /* Attribute length */
3267 append_gcj_attribute (struct jcf_partial *state, tree class)
3272 if (class != object_type_node)
3275 ptr = append_chunk (NULL, 6, state); /* 2+4 */
3276 i = find_utf8_constant (&state->cpool,
3277 get_identifier ("gnu.gcj.gcj-compiled"));
3278 PUT2 (i); /* Attribute string index */
3279 PUT4 (0); /* Attribute length */
3282 static tree InnerClasses_node;
3284 append_innerclasses_attribute (struct jcf_partial *state, tree class)
3286 tree orig_decl = TYPE_NAME (class);
3289 unsigned char *ptr, *length_marker, *number_marker;
3291 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3294 ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3296 if (InnerClasses_node == NULL_TREE)
3298 InnerClasses_node = get_identifier ("InnerClasses");
3300 i = find_utf8_constant (&state->cpool, InnerClasses_node);
3302 length_marker = ptr; PUT4 (0); /* length, to be later patched */
3303 number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3305 /* Generate the entries: all inner classes visible from the one we
3306 process: itself, up and down. */
3307 while (class && INNER_CLASS_TYPE_P (class))
3311 decl = TYPE_NAME (class);
3312 n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
3313 IDENTIFIER_LENGTH (DECL_NAME (decl));
3315 while (n[-1] != '$')
3317 append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3320 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3324 for (current = DECL_INNER_CLASS_LIST (decl);
3325 current; current = TREE_CHAIN (current))
3327 append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3328 TREE_VALUE (current));
3332 ptr = length_marker; PUT4 (8*length+2);
3333 ptr = number_marker; PUT2 (length);
3337 append_innerclasses_attribute_entry (struct jcf_partial *state,
3338 tree decl, tree name)
3341 int ocii = 0, ini = 0;
3342 unsigned char *ptr = append_chunk (NULL, 8, state);
3344 icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3346 /* Sun's implementation seems to generate ocii to 0 for inner
3347 classes (which aren't considered members of the class they're
3348 in.) The specs are saying that if the class is anonymous,
3349 inner_name_index must be zero. */
3350 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3352 ocii = find_class_constant (&state->cpool,
3353 TREE_TYPE (DECL_CONTEXT (decl)));
3354 ini = find_utf8_constant (&state->cpool, name);
3356 icaf = get_access_flags (decl);
3358 PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
3362 make_class_file_name (tree clas)
3364 const char *dname, *cname, *slash;
3369 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3370 "", '.', DIR_SEPARATOR,
3372 if (jcf_write_base_directory == NULL)
3374 /* Make sure we put the class file into the .java file's
3375 directory, and not into some subdirectory thereof. */
3377 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3378 slash = strrchr (dname, DIR_SEPARATOR);
3379 #ifdef DIR_SEPARATOR_2
3381 slash = strrchr (dname, DIR_SEPARATOR_2);
3387 sep = DIR_SEPARATOR;
3392 t = strrchr (cname, DIR_SEPARATOR);
3400 dname = jcf_write_base_directory;
3402 s = strrchr (dname, DIR_SEPARATOR);
3403 #ifdef DIR_SEPARATOR_2
3405 s = strrchr (dname, DIR_SEPARATOR_2);
3410 sep = DIR_SEPARATOR;
3412 slash = dname + strlen (dname);
3415 r = xmalloc (slash - dname + strlen (cname) + 2);
3416 strncpy (r, dname, slash - dname);
3417 r[slash - dname] = sep;
3418 strcpy (&r[slash - dname + 1], cname);
3420 /* We try to make new directories when we need them. We only do
3421 this for directories which "might not" exist. For instance, we
3422 assume the `-d' directory exists, but we don't assume that any
3423 subdirectory below it exists. It might be worthwhile to keep
3424 track of which directories we've created to avoid gratuitous
3426 dname = r + (slash - dname) + 1;
3429 char *s = strchr (dname, sep);
3433 /* Try to make directory if it doesn't already exist. */
3434 if (stat (r, &sb) == -1
3435 && mkdir (r, 0755) == -1
3436 /* The directory might have been made by another process. */
3438 fatal_error ("can't create directory %s: %m", r);
3441 /* Skip consecutive separators. */
3442 for (dname = s + 1; *dname && *dname == sep; ++dname)
3449 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3450 The output .class file name is make_class_file_name(CLAS). */
3453 write_classfile (tree clas)
3455 struct obstack *work = &temporary_obstack;
3456 struct jcf_partial state[1];
3457 char *class_file_name = make_class_file_name (clas);
3458 struct chunk *chunks;
3460 if (class_file_name != NULL)
3463 char *temporary_file_name;
3465 /* The .class file is initially written to a ".tmp" file so that
3466 if multiple instances of the compiler are running at once
3467 they do not see partially formed class files. */
3468 temporary_file_name = concat (class_file_name, ".tmp", NULL);
3469 stream = fopen (temporary_file_name, "wb");
3471 fatal_error ("can't open %s for writing: %m", temporary_file_name);
3473 jcf_dependency_add_target (class_file_name);
3474 init_jcf_state (state, work);
3475 chunks = generate_classfile (clas, state);
3476 write_chunks (stream, chunks);
3477 if (fclose (stream))
3478 fatal_error ("error closing %s: %m", temporary_file_name);
3480 /* If a file named by the string pointed to by `new' exists
3481 prior to the call to the `rename' function, the behavior
3482 is implementation-defined. ISO 9899-1990 7.9.4.2.
3484 For example, on Win32 with MSVCRT, it is an error. */
3486 unlink (class_file_name);
3488 if (rename (temporary_file_name, class_file_name) == -1)
3490 remove (temporary_file_name);
3491 fatal_error ("can't create %s: %m", class_file_name);
3493 free (temporary_file_name);
3494 free (class_file_name);
3496 release_jcf_state (state);
3500 string concatenation
3501 synchronized statement
3504 #include "gt-java-jcf-write.h"