OSDN Git Service

gcc/java:
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-write.c
1 /* Write out a Java(TM) class file.
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3    Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
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)
10 any later version.
11
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. 
20
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.  */
24
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "jcf.h"
30 #include "tree.h"
31 #include "real.h"
32 #include "java-tree.h"
33 #include "obstack.h"
34 #include "rtl.h"
35 #include "flags.h"
36 #include "java-opcodes.h"
37 #include "parse.h" /* for BLOCK_EXPR_BODY */
38 #include "buffer.h"
39 #include "toplev.h"
40 #include "ggc.h"
41 #include "tm_p.h"
42
43 extern struct obstack temporary_obstack;
44
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;
49
50 /* Make sure bytecode.data is big enough for at least N more bytes. */
51
52 #define RESERVE(N) \
53   do { CHECK_OP(state); \
54     if (state->bytecode.ptr + (N) > state->bytecode.limit) \
55     buffer_grow (&state->bytecode, N); } while (0)
56
57 /* Add a 1-byte instruction/operand I to bytecode.data,
58    assuming space has already been RESERVE'd. */
59
60 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
61
62 /* Like OP1, but I is a 2-byte big endian integer. */
63
64 #define OP2(I) \
65   do { int _i = (I); OP1 (_i >> 8);  OP1 (_i); CHECK_OP(state); } while (0)
66
67 /* Like OP1, but I is a 4-byte big endian integer. */
68
69 #define OP4(I) \
70   do { int _i = (I);  OP1 (_i >> 24);  OP1 (_i >> 16); \
71        OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
72
73 /* Macro to call each time we push I words on the JVM stack. */
74
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)
79
80 /* Macro to call each time we pop I words from the JVM stack. */
81
82 #define NOTE_POP(I) \
83   do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
84
85 /* A chunk or segment of a .class file. */
86
87 struct chunk
88 {
89   /* The next segment of this .class file. */
90   struct chunk *next;
91
92   /* The actual data in this segment to be written to the .class file. */
93   unsigned char *data;
94
95   /* The size of the segment to be written to the .class file. */
96   int size;
97 };
98
99 #define PENDING_CLEANUP_PC (-3)
100 #define PENDING_EXIT_PC (-2)
101 #define UNDEFINED_PC (-1)
102
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.
106
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.
109 */
110
111 struct jcf_block
112 {
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;
119
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.
125
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). */
130   int pc;
131
132   int linenumber;
133
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. */
137   union {
138     struct chunk *chunk;
139
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;
143   } v;
144
145   union {
146     /* Set of relocations (in reverse offset order) for this block. */
147     struct jcf_relocation *relocations;
148
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. */
152     tree labeled_block;
153   } u;
154 };
155
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
159
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
164
165 struct jcf_relocation
166 {
167   /* Next relocation for the current jcf_block. */
168   struct jcf_relocation *next;
169
170   /* The (byte) offset within the current block that needs to be relocated. */
171   HOST_WIDE_INT offset;
172
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). */
185   int kind;
186
187   /* The label the relocation wants to actually transfer to. */
188   struct jcf_block *label;
189 };
190
191 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
192 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
193
194 /* State for single catch clause. */
195
196 struct jcf_handler
197 {
198   struct jcf_handler *next;
199
200   struct jcf_block *start_label;
201   struct jcf_block *end_label;
202   struct jcf_block *handler_label;
203
204   /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
205   tree type;
206 };
207
208 /* State for the current switch statement. */
209
210 struct jcf_switch_state
211 {
212   struct jcf_switch_state *prev;
213   struct jcf_block *default_label;
214
215   struct jcf_relocation *cases;
216   int num_cases;
217   HOST_WIDE_INT min_case, max_case;
218 };
219
220 /* This structure is used to contain the various pieces that will
221    become a .class file. */
222
223 struct jcf_partial
224 {
225   struct chunk *first;
226   struct chunk *chunk;
227   struct obstack *chunk_obstack;
228   tree current_method;
229
230   /* List of basic blocks for the current method. */
231   struct jcf_block *blocks;
232   struct jcf_block *last_block;
233
234   struct localvar_info *first_lvar;
235   struct localvar_info *last_lvar;
236   int lvar_count;
237
238   CPool cpool;
239
240   int linenumber_count;
241
242   /* Until perform_relocations, this is a upper bound on the number
243      of bytes (so far) in the instructions for the current method. */
244   int code_length;
245
246   /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
247   struct jcf_block *labeled_blocks;
248   
249   /* The current stack size (stack pointer) in the current method. */
250   int code_SP;
251
252   /* The largest extent of stack size (stack pointer) in the current method. */
253   int code_SP_max;
254
255   /* Contains a mapping from local var slot number to localvar_info. */
256   struct buffer localvars;
257
258   /* The buffer allocated for bytecode for the current jcf_block. */
259   struct buffer bytecode;
260
261   /* Chain of exception handlers for the current method. */
262   struct jcf_handler *handlers;
263
264   /* Last element in handlers chain. */
265   struct jcf_handler *last_handler;
266
267   /* Number of exception handlers for the current method. */
268   int num_handlers;
269
270   /* Number of finalizers we are currently nested within. */
271   int num_finalizers;
272
273   /* If non-NULL, use this for the return value. */
274   tree return_value_decl;
275
276   /* Information about the current switch statement. */
277   struct jcf_switch_state *sw_state;
278
279   /* The count of jsr instructions that have been emitted.  */
280   long num_jsrs;
281 };
282
283 static void generate_bytecode_insns (tree, int, struct jcf_partial *);
284 static struct chunk * alloc_chunk (struct chunk *, unsigned char *,
285                                    int, struct obstack *);
286 static unsigned char * append_chunk (unsigned char *, int,
287                                      struct jcf_partial *);
288 static void append_chunk_copy (unsigned char *, int, struct jcf_partial *);
289 static struct jcf_block * gen_jcf_label (struct jcf_partial *);
290 static void finish_jcf_block (struct jcf_partial *);
291 static void define_jcf_label (struct jcf_block *, struct jcf_partial *);
292 static struct jcf_block * get_jcf_label_here (struct jcf_partial *);
293 static void put_linenumber (int, struct jcf_partial *);
294 static void localvar_alloc (tree, struct jcf_partial *);
295 static void maybe_free_localvar (tree, struct jcf_partial *, int);
296 static int get_access_flags (tree);
297 static void write_chunks (FILE *, struct chunk *);
298 static int adjust_typed_op (tree, int);
299 static void generate_bytecode_conditional (tree, struct jcf_block *,
300                                            struct jcf_block *, int,
301                                            struct jcf_partial *);
302 static void generate_bytecode_return (tree, struct jcf_partial *);
303 static void perform_relocations (struct jcf_partial *);
304 static void init_jcf_state (struct jcf_partial *, struct obstack *);
305 static void init_jcf_method (struct jcf_partial *, tree);
306 static void release_jcf_state (struct jcf_partial *);
307 static int get_classfile_modifiers (tree class);
308 static struct chunk * generate_classfile (tree, struct jcf_partial *);
309 static struct jcf_handler *alloc_handler (struct jcf_block *,
310                                           struct jcf_block *,
311                                           struct jcf_partial *);
312 static void emit_iinc (tree, HOST_WIDE_INT, struct jcf_partial *);
313 static void emit_reloc (HOST_WIDE_INT, int, struct jcf_block *, 
314                         struct jcf_partial *);
315 static void push_constant1 (HOST_WIDE_INT, struct jcf_partial *);
316 static void push_constant2 (HOST_WIDE_INT, struct jcf_partial *);
317 static void push_int_const (HOST_WIDE_INT, struct jcf_partial *);
318 static int find_constant_wide (HOST_WIDE_INT, HOST_WIDE_INT,
319                                struct jcf_partial *);
320 static void push_long_const (HOST_WIDE_INT, HOST_WIDE_INT,
321                              struct jcf_partial *);
322 static int find_constant_index (tree, struct jcf_partial *);
323 static void push_long_const (HOST_WIDE_INT, HOST_WIDE_INT,
324                              struct jcf_partial *);
325 static void field_op (tree, int, struct jcf_partial *);
326 static void maybe_wide (int, int, struct jcf_partial *);
327 static void emit_dup (int, int, struct jcf_partial *);
328 static void emit_pop (int, struct jcf_partial *);
329 static void emit_load_or_store (tree, int, struct jcf_partial *);
330 static void emit_load (tree, struct jcf_partial *);
331 static void emit_store (tree, struct jcf_partial *);
332 static void emit_unop (enum java_opcode, tree, struct jcf_partial *);
333 static void emit_binop (enum java_opcode, tree, struct jcf_partial *);
334 static void emit_reloc (HOST_WIDE_INT, int, struct jcf_block *,
335                         struct jcf_partial *);
336 static void emit_switch_reloc (struct jcf_block *, struct jcf_partial *);
337 static void emit_case_reloc (struct jcf_relocation *, struct jcf_partial *);
338 static void emit_if (struct jcf_block *, int, int, struct jcf_partial *);
339 static void emit_goto (struct jcf_block *, struct jcf_partial *);
340 static void emit_jsr (struct jcf_block *, struct jcf_partial *);
341 static void call_cleanups (struct jcf_block *, struct jcf_partial *);
342 static char *make_class_file_name (tree);
343 static unsigned char *append_synthetic_attribute (struct jcf_partial *);
344 static void append_deprecated_attribute (struct jcf_partial *);
345 static void append_innerclasses_attribute (struct jcf_partial *, tree);
346 static void append_innerclasses_attribute_entry (struct jcf_partial *, tree, tree);
347 static void append_gcj_attribute (struct jcf_partial *, tree);
348
349 /* Utility macros for appending (big-endian) data to a buffer.
350    We assume a local variable 'ptr' points into where we want to
351    write next, and we assume enough space has been allocated. */
352
353 #ifdef ENABLE_JC1_CHECKING
354 static int CHECK_PUT (void *, struct jcf_partial *, int);
355
356 static int
357 CHECK_PUT (void *ptr, struct jcf_partial *state, int i)
358 {
359   if ((unsigned char *) ptr < state->chunk->data
360       || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
361     abort ();
362
363   return 0;
364 }
365 #else
366 #define CHECK_PUT(PTR, STATE, I) ((void)0)
367 #endif
368
369 #define PUT1(X)  (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
370 #define PUT2(X)  (PUT1((X) >> 8), PUT1((X) & 0xFF))
371 #define PUT4(X)  (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
372 #define PUTN(P, N)  (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
373
374 /* There are some cases below where CHECK_PUT is guaranteed to fail.
375    Use the following macros in those specific cases.  */
376 #define UNSAFE_PUT1(X)  (*ptr++ = (X))
377 #define UNSAFE_PUT2(X)  (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
378 #define UNSAFE_PUT4(X)  (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
379 #define UNSAFE_PUTN(P, N)  (memcpy(ptr, P, N), ptr += (N))
380
381 \f
382 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
383    Set the data and size fields to DATA and SIZE, respectively.
384    However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
385
386 static struct chunk *
387 alloc_chunk (struct chunk *last, unsigned char *data,
388              int size, struct obstack *work)
389 {
390   struct chunk *chunk = obstack_alloc (work, sizeof(struct chunk));
391
392   if (data == NULL && size > 0)
393     data = obstack_alloc (work, size);
394
395   chunk->next = NULL;
396   chunk->data = data;
397   chunk->size = size;
398   if (last != NULL)
399     last->next = chunk;
400   return chunk;
401 }
402
403 #ifdef ENABLE_JC1_CHECKING
404 static int CHECK_OP (struct jcf_partial *);
405
406 static int
407 CHECK_OP (struct jcf_partial *state)
408 {
409   if (state->bytecode.ptr > state->bytecode.limit)
410     abort ();
411
412   return 0;
413 }
414 #else
415 #define CHECK_OP(STATE) ((void) 0)
416 #endif
417
418 static unsigned char *
419 append_chunk (unsigned char *data, int size, struct jcf_partial *state)
420 {
421   state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
422   if (state->first == NULL)
423     state->first = state->chunk;
424   return state->chunk->data;
425 }
426
427 static void
428 append_chunk_copy (unsigned char *data, int size, struct jcf_partial *state)
429 {
430   unsigned char *ptr = append_chunk (NULL, size, state);
431   memcpy (ptr, data, size);
432 }
433 \f
434 static struct jcf_block *
435 gen_jcf_label (struct jcf_partial *state)
436 {
437   struct jcf_block *block
438     = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
439   block->next = NULL;
440   block->linenumber = -1;
441   block->pc = UNDEFINED_PC;
442   return block;
443 }
444
445 static void
446 finish_jcf_block (struct jcf_partial *state)
447 {
448   struct jcf_block *block = state->last_block;
449   struct jcf_relocation *reloc;
450   int code_length = BUFFER_LENGTH (&state->bytecode);
451   int pc = state->code_length;
452   append_chunk_copy (state->bytecode.data, code_length, state);
453   BUFFER_RESET (&state->bytecode);
454   block->v.chunk = state->chunk;
455
456   /* Calculate code_length to the maximum value it can have. */
457   pc += block->v.chunk->size;
458   for (reloc = block->u.relocations;  reloc != NULL;  reloc = reloc->next)
459     {
460       int kind = reloc->kind;
461       if (kind == SWITCH_ALIGN_RELOC)
462         pc += 3;
463       else if (kind > BLOCK_START_RELOC)
464         pc += 2; /* 2-byte offset may grow to 4-byte offset */
465       else if (kind < -1)
466         pc += 5; /* May need to add a goto_w. */
467     }
468   state->code_length = pc;
469 }
470
471 static void
472 define_jcf_label (struct jcf_block *label, struct jcf_partial *state)
473 {
474   if (state->last_block != NULL)
475     finish_jcf_block (state);
476   label->pc = state->code_length;
477   if (state->blocks == NULL)
478     state->blocks = label;
479   else
480     state->last_block->next = label;
481   state->last_block = label;
482   label->next = NULL;
483   label->u.relocations = NULL;
484 }
485
486 static struct jcf_block *
487 get_jcf_label_here (struct jcf_partial *state)
488 {
489   if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
490     return state->last_block;
491   else
492     {
493       struct jcf_block *label = gen_jcf_label (state);
494       define_jcf_label (label, state);
495       return label;
496     }
497 }
498
499 /* Note a line number entry for the current PC and given LINE. */
500
501 static void
502 put_linenumber (int line, struct jcf_partial *state)
503 {
504   struct jcf_block *label = get_jcf_label_here (state);
505   if (label->linenumber > 0)
506     {
507       label = gen_jcf_label (state);
508       define_jcf_label (label, state);
509     }
510   label->linenumber = line;
511   state->linenumber_count++;
512 }
513
514 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
515    in the range (START_LABEL, END_LABEL). */
516
517 static struct jcf_handler *
518 alloc_handler (struct jcf_block *start_label, struct jcf_block *end_label,
519                struct jcf_partial *state)
520 {
521   struct jcf_handler *handler
522     = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
523   handler->start_label = start_label;
524   handler->end_label = end_label;
525   handler->handler_label = get_jcf_label_here (state);
526   if (state->handlers == NULL)
527     state->handlers = handler;
528   else
529     state->last_handler->next = handler;
530   state->last_handler = handler;
531   handler->next = NULL;
532   state->num_handlers++;
533   return handler;
534 }
535
536 \f
537 /* The index of jvm local variable allocated for this DECL.
538    This is assigned when generating .class files;
539    contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
540    (We don't allocate DECL_LANG_SPECIFIC for locals from Java source code.) */
541
542 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
543
544 struct localvar_info
545 {
546   struct localvar_info *next;
547
548   tree decl;
549   struct jcf_block *start_label;
550   struct jcf_block *end_label;
551 };
552
553 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
554 #define localvar_max \
555   ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
556
557 static void
558 localvar_alloc (tree decl, struct jcf_partial *state)
559 {
560   struct jcf_block *start_label = get_jcf_label_here (state);
561   int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
562   int index;
563   struct localvar_info *info;
564   struct localvar_info **ptr = localvar_buffer;
565   struct localvar_info **limit
566     = (struct localvar_info**) state->localvars.ptr;
567   for (index = 0;  ptr < limit;  index++, ptr++)
568     {
569       if (ptr[0] == NULL
570           && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
571         break;
572     }
573   if (ptr == limit)
574     {
575       buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
576       ptr = (struct localvar_info**) state->localvars.data + index;
577       state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
578     }
579   info = obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
580   ptr[0] = info;
581   if (wide)
582     ptr[1] = (struct localvar_info *)(~0);
583   DECL_LOCAL_INDEX (decl) = index;
584   info->decl = decl;
585   info->start_label = start_label;
586
587   if (debug_info_level > DINFO_LEVEL_TERSE
588       && DECL_NAME (decl) != NULL_TREE)
589     {
590       /* Generate debugging info. */
591       info->next = NULL;
592       if (state->last_lvar != NULL)
593         state->last_lvar->next = info;
594       else
595         state->first_lvar = info;
596       state->last_lvar = info;
597       state->lvar_count++;
598     }
599 }
600
601 static void
602 maybe_free_localvar (tree decl, struct jcf_partial *state, int really)
603 {
604   struct jcf_block *end_label = get_jcf_label_here (state);
605   int index = DECL_LOCAL_INDEX (decl);
606   struct localvar_info **ptr = &localvar_buffer [index];
607   struct localvar_info *info = *ptr;
608   int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
609
610   info->end_label = end_label;
611
612   if (info->decl != decl)
613     abort ();
614   if (! really)
615     return;
616   ptr[0] = NULL;
617   if (wide)
618     {
619       if (ptr[1] !=  (struct localvar_info *)(~0))
620         abort ();
621       ptr[1] = NULL;
622     }
623 }
624
625 \f
626 #define STACK_TARGET 1
627 #define IGNORE_TARGET 2
628
629 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
630    a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
631
632 static int
633 get_access_flags (tree decl)
634 {
635   int flags = 0;
636   int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
637
638   if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
639     {
640       if (TREE_PROTECTED (decl))
641         flags |= ACC_PROTECTED;
642       if (TREE_PRIVATE (decl))
643         flags |= ACC_PRIVATE;
644     }
645   else if (TREE_CODE (decl) == TYPE_DECL)
646     {
647       if (CLASS_PUBLIC (decl))
648         flags |= ACC_PUBLIC;
649       if (CLASS_FINAL (decl))
650         flags |= ACC_FINAL;
651       if (CLASS_SUPER (decl))
652         flags |= ACC_SUPER;
653       if (CLASS_ABSTRACT (decl))
654         flags |= ACC_ABSTRACT;
655       if (CLASS_INTERFACE (decl))
656         flags |= ACC_INTERFACE;
657       if (CLASS_STATIC (decl))
658         flags |= ACC_STATIC;
659       if (CLASS_PRIVATE (decl))
660         flags |= ACC_PRIVATE;
661       if (CLASS_PROTECTED (decl))
662         flags |= ACC_PROTECTED;
663       if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
664           || LOCAL_CLASS_P (TREE_TYPE (decl)))
665         flags |= ACC_PRIVATE;
666       if (CLASS_STRICTFP (decl))
667         flags |= ACC_STRICT;
668     }
669   else
670     abort ();
671
672   if (TREE_CODE (decl) == FUNCTION_DECL)
673     {
674       if (METHOD_PUBLIC (decl))
675         flags |= ACC_PUBLIC;
676       if (METHOD_FINAL (decl))
677         flags |= ACC_FINAL;
678       if (METHOD_NATIVE (decl))
679         flags |= ACC_NATIVE;
680       if (METHOD_STATIC (decl))
681         flags |= ACC_STATIC;
682       if (METHOD_SYNCHRONIZED (decl))
683         flags |= ACC_SYNCHRONIZED;
684       if (METHOD_ABSTRACT (decl))
685         flags |= ACC_ABSTRACT;
686       if (METHOD_STRICTFP (decl))
687         flags |= ACC_STRICT;
688     }
689   if (isfield)
690     {
691       if (FIELD_PUBLIC (decl))
692         flags |= ACC_PUBLIC;
693       if (FIELD_FINAL (decl))
694         flags |= ACC_FINAL;
695       if (FIELD_STATIC (decl))
696         flags |= ACC_STATIC;
697       if (FIELD_VOLATILE (decl))
698         flags |= ACC_VOLATILE;
699       if (FIELD_TRANSIENT (decl))
700         flags |= ACC_TRANSIENT;
701     }
702   return flags;
703 }
704
705 /* Write the list of segments starting at CHUNKS to STREAM. */
706
707 static void
708 write_chunks (FILE* stream, struct chunk *chunks)
709 {
710   for (;  chunks != NULL;  chunks = chunks->next)
711     fwrite (chunks->data, chunks->size, 1, stream);
712 }
713
714 /* Push a 1-word constant in the constant pool at the given INDEX.
715    (Caller is responsible for doing NOTE_PUSH.) */
716
717 static void
718 push_constant1 (HOST_WIDE_INT index, struct jcf_partial *state)
719 {
720   RESERVE (3);
721   if (index < 256)
722     {
723       OP1 (OPCODE_ldc);
724       OP1 (index);
725     }
726   else
727     {
728       OP1 (OPCODE_ldc_w);
729       OP2 (index);
730     }
731 }
732
733 /* Push a 2-word constant in the constant pool at the given INDEX.
734    (Caller is responsible for doing NOTE_PUSH.) */
735
736 static void
737 push_constant2 (HOST_WIDE_INT index, struct jcf_partial *state)
738 {
739   RESERVE (3);
740   OP1 (OPCODE_ldc2_w);
741   OP2 (index);
742 }
743
744 /* Push 32-bit integer constant on VM stack.
745    Caller is responsible for doing NOTE_PUSH. */
746
747 static void
748 push_int_const (HOST_WIDE_INT i, struct jcf_partial *state)
749 {
750   RESERVE(3);
751   if (i >= -1 && i <= 5)
752     OP1(OPCODE_iconst_0 + i);
753   else if (i >= -128 && i < 128)
754     {
755       OP1(OPCODE_bipush);
756       OP1(i);
757     }
758   else if (i >= -32768 && i < 32768)
759     {
760       OP1(OPCODE_sipush);
761       OP2(i);
762     }
763   else
764     {
765       i = find_constant1 (&state->cpool, CONSTANT_Integer, 
766                           (jword)(i & 0xFFFFFFFF));
767       push_constant1 (i, state);
768     }
769 }
770
771 static int
772 find_constant_wide (HOST_WIDE_INT lo, HOST_WIDE_INT hi,
773                     struct jcf_partial *state)
774 {
775   unsigned HOST_WIDE_INT w1;
776   HOST_WIDE_INT w2;
777   lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
778   return find_constant2 (&state->cpool, CONSTANT_Long,
779                          (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
780 }
781
782 /* Find or allocate a constant pool entry for the given VALUE.
783    Return the index in the constant pool. */
784
785 static int
786 find_constant_index (tree value, struct jcf_partial *state)
787 {
788   if (TREE_CODE (value) == INTEGER_CST)
789     {
790       if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
791         return find_constant1 (&state->cpool, CONSTANT_Integer,
792                                (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
793       else
794         return find_constant_wide (TREE_INT_CST_LOW (value),
795                                    TREE_INT_CST_HIGH (value), state);
796     }
797   else if (TREE_CODE (value) == REAL_CST)
798     {
799       long words[2];
800
801       /* IEEE NaN can have many values, but the Java VM spec defines a
802          canonical NaN.  */      
803       if (flag_emit_class_files
804           && REAL_VALUE_ISNAN (TREE_REAL_CST (value)))
805         {
806           if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
807             return find_constant1 (&state->cpool, CONSTANT_Float,
808                                    0x7fc00000);
809           else
810             return find_constant2 (&state->cpool, CONSTANT_Double,
811                                    0x7ff80000, 0x00000000);
812         }           
813       
814       real_to_target (words, &TREE_REAL_CST (value),
815                       TYPE_MODE (TREE_TYPE (value)));
816       words[0] &= 0xffffffff;
817       words[1] &= 0xffffffff;
818
819       if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
820         return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
821       else
822         return find_constant2 (&state->cpool, CONSTANT_Double,
823                                (jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
824                                (jword)words[FLOAT_WORDS_BIG_ENDIAN]);
825     }
826   else if (TREE_CODE (value) == STRING_CST)
827     return find_string_constant (&state->cpool, value);
828
829   else
830     abort ();
831 }
832
833 /* Push 64-bit long constant on VM stack.
834    Caller is responsible for doing NOTE_PUSH. */
835
836 static void
837 push_long_const (HOST_WIDE_INT lo, HOST_WIDE_INT hi, struct jcf_partial *state)
838 {
839   unsigned HOST_WIDE_INT highpart;
840   HOST_WIDE_INT dummy;
841   jint lowpart = WORD_TO_INT (lo);
842
843   rshift_double (lo, hi, 32, 64, &highpart, &dummy, 1);
844
845   if (highpart == 0 && (lowpart == 0 || lowpart == 1))
846     {
847       RESERVE(1);
848       OP1(OPCODE_lconst_0 + lowpart);
849     }
850   else if ((highpart == 0 && lowpart > 0 && lowpart < 32768) 
851            || (highpart == (unsigned HOST_WIDE_INT)-1
852                && lowpart < 0 && lowpart >= -32768))
853       {
854         push_int_const (lowpart, state);
855         RESERVE (1);
856         OP1 (OPCODE_i2l);
857       }
858   else
859     push_constant2 (find_constant_wide (lo, hi, state), state);
860 }
861
862 static void
863 field_op (tree field, int opcode, struct jcf_partial *state)
864 {
865   int index = find_fieldref_index (&state->cpool, field);
866   RESERVE (3);
867   OP1 (opcode);
868   OP2 (index);
869 }
870
871 /* Returns an integer in the range 0 (for 'int') through 4 (for object
872    reference) to 7 (for 'short') which matches the pattern of how JVM
873    opcodes typically depend on the operand type. */
874
875 static int
876 adjust_typed_op (tree type, int max)
877 {
878   switch (TREE_CODE (type))
879     {
880     case POINTER_TYPE:
881     case RECORD_TYPE:   return 4;
882     case BOOLEAN_TYPE:
883       return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
884     case CHAR_TYPE:
885       return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
886     case INTEGER_TYPE:
887       switch (TYPE_PRECISION (type))
888         {
889         case  8:       return max < 5 ? 0 : 5;
890         case 16:       return max < 7 ? 0 : 7;
891         case 32:       return 0;
892         case 64:       return 1;
893         }
894       break;
895     case REAL_TYPE:
896       switch (TYPE_PRECISION (type))
897         {
898         case 32:       return 2;
899         case 64:       return 3;
900         }
901       break;
902     default:
903       break;
904     }
905   abort ();
906 }
907
908 static void
909 maybe_wide (int opcode, int index, struct jcf_partial *state)
910 {
911   if (index >= 256)
912     {
913       RESERVE (4);
914       OP1 (OPCODE_wide);
915       OP1 (opcode);
916       OP2 (index);
917     }
918   else
919     {
920       RESERVE (2);
921       OP1 (opcode);
922       OP1 (index);
923     }
924 }
925
926 /* Compile code to duplicate with offset, where
927    SIZE is the size of the stack item to duplicate (1 or 2), abd
928    OFFSET is where to insert the result (must be 0, 1, or 2).
929    (The new words get inserted at stack[SP-size-offset].) */
930
931 static void
932 emit_dup (int size, int offset, struct jcf_partial *state)
933 {
934   int kind;
935   if (size == 0)
936     return;
937   RESERVE(1);
938   if (offset == 0)
939     kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
940   else if (offset == 1)
941     kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
942   else if (offset == 2)
943     kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
944   else
945     abort();
946   OP1 (kind);
947   NOTE_PUSH (size);
948 }
949
950 static void
951 emit_pop (int size, struct jcf_partial *state)
952 {
953   RESERVE (1);
954   OP1 (OPCODE_pop - 1 + size);
955 }
956
957 static void
958 emit_iinc (tree var, HOST_WIDE_INT value, struct jcf_partial *state)
959 {
960   int slot = DECL_LOCAL_INDEX (var);
961
962   if (value < -128 || value > 127 || slot >= 256)
963     {
964       RESERVE (6);
965       OP1 (OPCODE_wide);
966       OP1 (OPCODE_iinc);
967       OP2 (slot);
968       OP2 (value);
969     }
970   else
971     {
972       RESERVE (3);
973       OP1 (OPCODE_iinc);
974       OP1 (slot);
975       OP1 (value);
976     }
977 }
978
979 static void
980 emit_load_or_store (tree var,    /* Variable to load from or store into. */
981                     int opcode,  /* Either OPCODE_iload or OPCODE_istore. */
982                     struct jcf_partial *state)
983 {
984   tree type = TREE_TYPE (var);
985   int kind = adjust_typed_op (type, 4);
986   int index = DECL_LOCAL_INDEX (var);
987   if (index <= 3)
988     {
989       RESERVE (1);
990       OP1 (opcode + 5 + 4 * kind + index);    /* [ilfda]{load,store}_[0123] */
991     }
992   else
993     maybe_wide (opcode + kind, index, state);  /* [ilfda]{load,store} */
994 }
995
996 static void
997 emit_load (tree var, struct jcf_partial *state)
998 {
999   emit_load_or_store (var, OPCODE_iload, state);
1000   NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1001 }
1002
1003 static void
1004 emit_store (tree var, struct jcf_partial *state)
1005 {
1006   emit_load_or_store (var, OPCODE_istore, state);
1007   NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1008 }
1009
1010 static void
1011 emit_unop (enum java_opcode opcode, tree type ATTRIBUTE_UNUSED,
1012            struct jcf_partial *state)
1013 {
1014   RESERVE(1);
1015   OP1 (opcode);
1016 }
1017
1018 static void
1019 emit_binop (enum java_opcode opcode, tree type, struct jcf_partial *state)
1020 {
1021   int size = TYPE_IS_WIDE (type) ? 2 : 1;
1022   RESERVE(1);
1023   OP1 (opcode);
1024   NOTE_POP (size);
1025 }
1026
1027 static void
1028 emit_reloc (HOST_WIDE_INT value, int kind,
1029             struct jcf_block *target, struct jcf_partial *state)
1030 {
1031   struct jcf_relocation *reloc
1032     = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1033   struct jcf_block *block = state->last_block;
1034   reloc->next = block->u.relocations;
1035   block->u.relocations = reloc;
1036   reloc->offset = BUFFER_LENGTH (&state->bytecode);
1037   reloc->label = target;
1038   reloc->kind = kind;
1039   if (kind == 0 || kind == BLOCK_START_RELOC)
1040     OP4 (value);
1041   else if (kind != SWITCH_ALIGN_RELOC)
1042     OP2 (value);
1043 }
1044
1045 static void
1046 emit_switch_reloc (struct jcf_block *label, struct jcf_partial *state)
1047 {
1048   emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1049 }
1050
1051 /* Similar to emit_switch_reloc,
1052    but re-uses an existing case reloc. */
1053
1054 static void
1055 emit_case_reloc (struct jcf_relocation *reloc, struct jcf_partial *state)
1056 {
1057   struct jcf_block *block = state->last_block;
1058   reloc->next = block->u.relocations;
1059   block->u.relocations = reloc;
1060   reloc->offset = BUFFER_LENGTH (&state->bytecode);
1061   reloc->kind = BLOCK_START_RELOC;
1062   OP4 (0);
1063 }
1064
1065 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1066    The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1067
1068 static void
1069 emit_if (struct jcf_block *target, int opcode, int inv_opcode,
1070          struct jcf_partial *state)
1071 {
1072   RESERVE(3);
1073   OP1 (opcode);
1074   /* value is 1 byte from reloc back to start of instruction.  */
1075   emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1076 }
1077
1078 static void
1079 emit_goto (struct jcf_block *target, struct jcf_partial *state)
1080 {
1081   RESERVE(3);
1082   OP1 (OPCODE_goto);
1083   /* Value is 1 byte from reloc back to start of instruction.  */
1084   emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1085 }
1086
1087 static void
1088 emit_jsr (struct jcf_block *target, struct jcf_partial *state)
1089 {
1090   RESERVE(3);
1091   OP1 (OPCODE_jsr);
1092   /* Value is 1 byte from reloc back to start of instruction.  */
1093   emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1094   state->num_jsrs++;
1095 }
1096
1097 /* Generate code to evaluate EXP.  If the result is true,
1098    branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1099    TRUE_BRANCH_FIRST is a code generation hint that the
1100    TRUE_LABEL may follow right after this. (The idea is that we
1101    may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1102
1103 static void
1104 generate_bytecode_conditional (tree exp,
1105                                struct jcf_block *true_label,
1106                                struct jcf_block *false_label,
1107                                int true_branch_first,
1108                                struct jcf_partial *state)
1109 {
1110   tree exp0, exp1, type;
1111   int save_SP = state->code_SP;
1112   enum java_opcode op, negop;
1113   bool unordered = 0;
1114   
1115   switch (TREE_CODE (exp))
1116     {
1117     case INTEGER_CST:
1118       emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1119       break;
1120     case COND_EXPR:
1121       {
1122         struct jcf_block *then_label = gen_jcf_label (state);
1123         struct jcf_block *else_label = gen_jcf_label (state);
1124         int save_SP_before, save_SP_after;
1125         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1126                                        then_label, else_label, 1, state);
1127         define_jcf_label (then_label, state);
1128         save_SP_before = state->code_SP;
1129         generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1130                                        true_label, false_label, 1, state);
1131         save_SP_after = state->code_SP;
1132         state->code_SP = save_SP_before;
1133         define_jcf_label (else_label, state);
1134         generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1135                                        true_label, false_label,
1136                                        true_branch_first, state);
1137         if (state->code_SP != save_SP_after)
1138           abort ();
1139       }
1140       break;
1141     case TRUTH_NOT_EXPR:
1142       generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
1143                                      true_label, ! true_branch_first, state);
1144       break;
1145     case TRUTH_ANDIF_EXPR:
1146       {
1147         struct jcf_block *next_label = gen_jcf_label (state);
1148         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1149                                        next_label, false_label, 1, state);
1150         define_jcf_label (next_label, state);
1151         generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1152                                        true_label, false_label, 1, state);
1153       }
1154       break;
1155     case TRUTH_ORIF_EXPR:
1156       {
1157         struct jcf_block *next_label = gen_jcf_label (state);
1158         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1159                                        true_label, next_label, 1, state);
1160         define_jcf_label (next_label, state);
1161         generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1162                                        true_label, false_label, 1, state);
1163       }
1164       break;
1165     compare_1:
1166       /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1167          set it to the corresponding 1-operand if<COND> instructions. */
1168       op = op - 6;
1169       /* FALLTHROUGH */
1170     compare_2:
1171       /* The opcodes with their inverses are allocated in pairs.
1172          E.g.  The inverse of if_icmplt (161) is if_icmpge (162). */
1173       negop = (op & 1) ? op + 1 : op - 1;
1174     compare_2_ptr:
1175       if (true_branch_first)
1176         {
1177           emit_if (false_label, negop, op, state);
1178           emit_goto (true_label, state);
1179         }
1180       else
1181         {
1182           emit_if (true_label, op, negop, state);
1183           emit_goto (false_label, state);
1184         }
1185       break;
1186
1187     case UNEQ_EXPR:
1188       unordered = 1;
1189     case EQ_EXPR:
1190       op = OPCODE_if_icmpeq;
1191       goto compare;
1192
1193     case LTGT_EXPR:
1194       unordered = 1;
1195     case NE_EXPR:
1196       op = OPCODE_if_icmpne;
1197       goto compare;
1198
1199     case UNLE_EXPR:
1200       unordered = 1;
1201     case GT_EXPR:
1202       op = OPCODE_if_icmpgt;
1203       goto compare;
1204
1205     case UNGE_EXPR:
1206       unordered = 1;
1207     case LT_EXPR:
1208       op = OPCODE_if_icmplt;
1209       goto compare;
1210
1211     case UNLT_EXPR:
1212       unordered = 1;
1213     case GE_EXPR:
1214       op = OPCODE_if_icmpge;
1215       goto compare;
1216
1217     case UNGT_EXPR:
1218       unordered = 1;
1219     case LE_EXPR:
1220       op = OPCODE_if_icmple;
1221       goto compare;
1222
1223     compare:
1224       if (unordered)
1225         {
1226           /* UNLT_EXPR(a, b) means 'a < b || unordered(a, b)'.  This is 
1227           the same as the Java source expression '!(a >= b)', so handle 
1228           it that way.  */
1229           struct jcf_block *tmp = true_label;
1230           true_label = false_label;
1231           false_label = tmp;
1232           true_branch_first = !true_branch_first;
1233         }
1234         
1235       exp0 = TREE_OPERAND (exp, 0);
1236       exp1 = TREE_OPERAND (exp, 1);
1237       type = TREE_TYPE (exp0);
1238       switch (TREE_CODE (type))
1239         {
1240           int opf;
1241         case POINTER_TYPE:  case RECORD_TYPE:
1242           switch (TREE_CODE (exp))
1243             {
1244             case EQ_EXPR:  op = OPCODE_if_acmpeq;  break;
1245             case NE_EXPR:  op = OPCODE_if_acmpne;  break;
1246             default:  abort();
1247             }
1248           if (integer_zerop (exp1) || integer_zerop (exp0))
1249             {
1250               generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
1251                                        STACK_TARGET, state);
1252               op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1253               negop = (op & 1) ? op - 1 : op + 1;
1254               NOTE_POP (1);
1255               goto compare_2_ptr;
1256             }
1257           generate_bytecode_insns (exp0, STACK_TARGET, state);
1258           generate_bytecode_insns (exp1, STACK_TARGET, state);
1259           NOTE_POP (2);
1260           goto compare_2;
1261         case REAL_TYPE:
1262           generate_bytecode_insns (exp0, STACK_TARGET, state);
1263           generate_bytecode_insns (exp1, STACK_TARGET, state);
1264           if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1265             opf = OPCODE_fcmpg;
1266           else
1267             opf = OPCODE_fcmpl;
1268           if (TYPE_PRECISION (type) > 32)
1269             {
1270               opf += 2;
1271               NOTE_POP (4);
1272             }
1273           else
1274             NOTE_POP (2);
1275           RESERVE (1);
1276           OP1 (opf);
1277           goto compare_1;
1278         case INTEGER_TYPE:
1279           if (TYPE_PRECISION (type) > 32)
1280             {
1281               generate_bytecode_insns (exp0, STACK_TARGET, state);
1282               generate_bytecode_insns (exp1, STACK_TARGET, state);
1283               NOTE_POP (4);
1284               RESERVE (1);
1285               OP1 (OPCODE_lcmp);
1286               goto compare_1;
1287             }
1288           /* FALLTHROUGH */
1289         default:
1290           if (integer_zerop (exp1))
1291             {
1292               generate_bytecode_insns (exp0, STACK_TARGET, state);
1293               NOTE_POP (1);
1294               goto compare_1;
1295             }
1296           if (integer_zerop (exp0))
1297             {
1298               switch (op)
1299                 {
1300                 case OPCODE_if_icmplt:
1301                 case OPCODE_if_icmpge:
1302                   op += 2;
1303                   break;
1304                 case OPCODE_if_icmpgt:
1305                 case OPCODE_if_icmple:
1306                   op -= 2;
1307                   break;
1308                 default:
1309                   break;
1310                 }
1311               generate_bytecode_insns (exp1, STACK_TARGET, state);
1312               NOTE_POP (1);
1313               goto compare_1;
1314             }
1315           generate_bytecode_insns (exp0, STACK_TARGET, state);
1316           generate_bytecode_insns (exp1, STACK_TARGET, state);
1317           NOTE_POP (2);
1318           goto compare_2;
1319         }
1320
1321     default:
1322       generate_bytecode_insns (exp, STACK_TARGET, state);
1323       NOTE_POP (1);
1324       if (true_branch_first)
1325         {
1326           emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1327           emit_goto (true_label, state);
1328         }
1329       else
1330         {
1331           emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1332           emit_goto (false_label, state);
1333         }
1334       break;
1335     }
1336   if (save_SP != state->code_SP)
1337     abort ();
1338 }
1339
1340 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1341    but only as far out as LIMIT (since we are about to jump to the
1342    emit label that is LIMIT). */
1343
1344 static void
1345 call_cleanups (struct jcf_block *limit, struct jcf_partial *state)
1346 {
1347   struct jcf_block *block = state->labeled_blocks;
1348   for (;  block != limit;  block = block->next)
1349     {
1350       if (block->pc == PENDING_CLEANUP_PC)
1351         emit_jsr (block, state);
1352     }
1353 }
1354
1355 static void
1356 generate_bytecode_return (tree exp, struct jcf_partial *state)
1357 {
1358   tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1359   int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1360   int op;
1361  again:
1362   if (exp != NULL)
1363     {
1364       switch (TREE_CODE (exp))
1365         {
1366         case COMPOUND_EXPR:     
1367           generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1368                                    state);
1369           exp = TREE_OPERAND (exp, 1);
1370           goto again;
1371         case COND_EXPR:
1372           {
1373             struct jcf_block *then_label = gen_jcf_label (state);
1374             struct jcf_block *else_label = gen_jcf_label (state);
1375             generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1376                                            then_label, else_label, 1, state);
1377             define_jcf_label (then_label, state);
1378             generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1379             define_jcf_label (else_label, state);
1380             generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1381           }
1382           return;
1383         default:
1384           generate_bytecode_insns (exp,
1385                                    returns_void ? IGNORE_TARGET
1386                                    : STACK_TARGET, state);
1387         }
1388     }
1389   if (returns_void)
1390     {
1391       op = OPCODE_return;
1392       call_cleanups (NULL, state);
1393     }
1394   else
1395     {
1396       op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1397       if (state->num_finalizers > 0)
1398         {
1399           if (state->return_value_decl == NULL_TREE)
1400             {
1401               state->return_value_decl
1402                 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1403               localvar_alloc (state->return_value_decl, state);
1404             }
1405           emit_store (state->return_value_decl, state);
1406           call_cleanups (NULL, state);
1407           emit_load (state->return_value_decl, state);
1408           /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
1409              then we risk the save decl erroneously re-used in the
1410              finalizer.  Instead, we keep the state->return_value_decl
1411              allocated through the rest of the method.  This is not
1412              the greatest solution, but it is at least simple and safe. */
1413         }
1414     }
1415   RESERVE (1);
1416   OP1 (op);
1417 }
1418
1419 /* Generate bytecode for sub-expression EXP of METHOD.
1420    TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1421
1422 static void
1423 generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
1424 {
1425   tree type, arg;
1426   enum java_opcode jopcode;
1427   int op;
1428   HOST_WIDE_INT value;
1429   int post_op;
1430   int size;
1431   int offset;
1432
1433   if (exp == NULL && target == IGNORE_TARGET)
1434     return;
1435
1436   type = TREE_TYPE (exp);
1437
1438   switch (TREE_CODE (exp))
1439     {
1440     case BLOCK:
1441       if (BLOCK_EXPR_BODY (exp))
1442         {
1443           tree local;
1444           tree body = BLOCK_EXPR_BODY (exp);
1445           long jsrs = state->num_jsrs;
1446           for (local = BLOCK_EXPR_DECLS (exp); local; )
1447             {
1448               tree next = TREE_CHAIN (local);
1449               localvar_alloc (local, state);
1450               local = next;
1451             }
1452           /* Avoid deep recursion for long blocks. */
1453           while (TREE_CODE (body) == COMPOUND_EXPR)
1454             {
1455               generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1456               body = TREE_OPERAND (body, 1);
1457             }
1458           generate_bytecode_insns (body, target, state);
1459           
1460           for (local = BLOCK_EXPR_DECLS (exp); local; )
1461             {
1462               tree next = TREE_CHAIN (local);
1463               maybe_free_localvar (local, state, state->num_jsrs <= jsrs);
1464               local = next;
1465             }
1466         }
1467       break;
1468     case COMPOUND_EXPR: 
1469       generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1470       /* Normally the first operand to a COMPOUND_EXPR must complete
1471          normally.  However, in the special case of a do-while
1472          statement this is not necessarily the case.  */
1473       if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0)))
1474         generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1475       break;
1476     case EXPR_WITH_FILE_LOCATION:
1477       {
1478         location_t saved_location = input_location;
1479         tree body = EXPR_WFL_NODE (exp);
1480         if (IS_EMPTY_STMT (body))
1481           break;
1482 #ifdef USE_MAPPED_LOCATION
1483         input_location = EXPR_LOCATION (exp);
1484 #else
1485         input_filename = EXPR_WFL_FILENAME (exp);
1486         input_line = EXPR_WFL_LINENO (exp);
1487 #endif
1488         if (EXPR_WFL_EMIT_LINE_NOTE (exp) && input_line > 0
1489             && debug_info_level > DINFO_LEVEL_NONE)
1490           put_linenumber (input_line, state);
1491         generate_bytecode_insns (body, target, state);
1492         input_location = saved_location;
1493       }
1494       break;
1495     case INTEGER_CST:
1496       if (target == IGNORE_TARGET) ; /* do nothing */
1497       else if (TREE_CODE (type) == POINTER_TYPE)
1498         {
1499           if (! integer_zerop (exp))
1500             abort();
1501           RESERVE(1);
1502           OP1 (OPCODE_aconst_null);
1503           NOTE_PUSH (1);
1504         }
1505       else if (TYPE_PRECISION (type) <= 32)
1506         {
1507           push_int_const (TREE_INT_CST_LOW (exp), state);
1508           NOTE_PUSH (1);
1509         }
1510       else
1511         {
1512           push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1513                            state);
1514           NOTE_PUSH (2);
1515         }
1516       break;
1517     case REAL_CST:
1518       {
1519         int prec = TYPE_PRECISION (type) >> 5;
1520         RESERVE(1);
1521         if (real_zerop (exp) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp)))
1522           OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1523         else if (real_onep (exp))
1524           OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1525         else if (prec == 1 && real_twop (exp))
1526           OP1 (OPCODE_fconst_2);
1527         /* ??? We could also use iconst_3/ldc followed by i2f/i2d
1528            for other float/double when the value is a small integer. */
1529         else
1530           {
1531             offset = find_constant_index (exp, state);
1532             if (prec == 1)
1533               push_constant1 (offset, state);
1534             else
1535               push_constant2 (offset, state);
1536           }
1537         NOTE_PUSH (prec);
1538       }
1539       break;
1540     case STRING_CST:
1541       push_constant1 (find_string_constant (&state->cpool, exp), state);
1542       NOTE_PUSH (1);
1543       break;
1544     case VAR_DECL:
1545       if (TREE_STATIC (exp))
1546         {
1547           field_op (exp, OPCODE_getstatic, state);
1548           NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1549           break;
1550         }
1551       /* ... fall through ... */
1552     case PARM_DECL:
1553       emit_load (exp, state);
1554       break;
1555     case NON_LVALUE_EXPR:
1556     case INDIRECT_REF:
1557       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1558       break;
1559     case ARRAY_REF:
1560       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1561       generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1562       if (target != IGNORE_TARGET)
1563         {
1564           jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1565           RESERVE(1);
1566           OP1 (jopcode);
1567           if (! TYPE_IS_WIDE (type))
1568             NOTE_POP (1);
1569         }
1570       break;
1571     case COMPONENT_REF:
1572       {
1573         tree obj = TREE_OPERAND (exp, 0);
1574         tree field = TREE_OPERAND (exp, 1);
1575         int is_static = FIELD_STATIC (field);
1576         generate_bytecode_insns (obj,
1577                                  is_static ? IGNORE_TARGET : target, state);
1578         if (target != IGNORE_TARGET)
1579           {
1580             if (DECL_NAME (field) == length_identifier_node && !is_static
1581                 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1582               {
1583                 RESERVE (1);
1584                 OP1 (OPCODE_arraylength);
1585               }
1586             else
1587               {
1588                 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1589                           state);
1590                 if (! is_static)
1591                   NOTE_POP (1);
1592                 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1593               }
1594           }
1595       }
1596       break;
1597     case TRUTH_ANDIF_EXPR:
1598     case TRUTH_ORIF_EXPR:
1599     case EQ_EXPR:
1600     case NE_EXPR:
1601     case GT_EXPR:
1602     case LT_EXPR:
1603     case GE_EXPR:
1604     case LE_EXPR:
1605     case UNLT_EXPR:
1606     case UNLE_EXPR:
1607     case UNGT_EXPR:
1608     case UNGE_EXPR:
1609     case UNEQ_EXPR:
1610     case LTGT_EXPR:
1611       {
1612         struct jcf_block *then_label = gen_jcf_label (state);
1613         struct jcf_block *else_label = gen_jcf_label (state);
1614         struct jcf_block *end_label = gen_jcf_label (state);
1615         generate_bytecode_conditional (exp,
1616                                        then_label, else_label, 1, state);
1617         define_jcf_label (then_label, state);
1618         push_int_const (1, state);
1619         emit_goto (end_label, state);
1620         define_jcf_label (else_label, state);
1621         push_int_const (0, state);
1622         define_jcf_label (end_label, state);
1623         NOTE_PUSH (1);
1624       }
1625       break;
1626     case COND_EXPR:
1627       {
1628         struct jcf_block *then_label = gen_jcf_label (state);
1629         struct jcf_block *else_label = gen_jcf_label (state);
1630         struct jcf_block *end_label = gen_jcf_label (state);
1631         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1632                                        then_label, else_label, 1, state);
1633         define_jcf_label (then_label, state);
1634         generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1635         if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1636             /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1637             || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1638           emit_goto (end_label, state);
1639         define_jcf_label (else_label, state);
1640         generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1641         define_jcf_label (end_label, state);
1642         /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1643         if (TREE_TYPE (exp) != void_type_node)
1644           NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1645       }
1646       break;
1647     case CASE_EXPR:
1648       {
1649         struct jcf_switch_state *sw_state = state->sw_state;
1650         struct jcf_relocation *reloc
1651           = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1652         HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1653         reloc->kind = 0;
1654         reloc->label = get_jcf_label_here (state);
1655         reloc->offset = case_value;
1656         reloc->next = sw_state->cases;
1657         sw_state->cases = reloc;
1658         if (sw_state->num_cases == 0)
1659           {
1660             sw_state->min_case = case_value;
1661             sw_state->max_case = case_value;
1662           }
1663         else
1664           {
1665             if (case_value < sw_state->min_case)
1666               sw_state->min_case = case_value;
1667             if (case_value > sw_state->max_case)
1668               sw_state->max_case = case_value;
1669           }
1670         sw_state->num_cases++;
1671       }
1672       break;
1673     case DEFAULT_EXPR:
1674       state->sw_state->default_label = get_jcf_label_here (state);
1675       break;
1676
1677     case SWITCH_EXPR:
1678       {
1679         /* The SWITCH_EXPR has three parts, generated in the following order:
1680            1.  the switch_expression (the value used to select the correct case);
1681            2.  the switch_body;
1682            3.  the switch_instruction (the tableswitch/loopupswitch instruction.).
1683            After code generation, we will re-order them in the order 1, 3, 2.
1684            This is to avoid any extra GOTOs. */
1685         struct jcf_switch_state sw_state;
1686         struct jcf_block *expression_last; /* Last block of the switch_expression. */
1687         struct jcf_block *body_last; /* Last block of the switch_body. */
1688         struct jcf_block *switch_instruction;  /* First block of switch_instruction. */
1689         struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1690         struct jcf_block *body_block;
1691         int switch_length;
1692         sw_state.prev = state->sw_state;
1693         state->sw_state = &sw_state;
1694         sw_state.cases = NULL;
1695         sw_state.num_cases = 0;
1696         sw_state.default_label = NULL;
1697         generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1698         expression_last = state->last_block;
1699         /* Force a new block here.  */
1700         body_block = gen_jcf_label (state);
1701         define_jcf_label (body_block, state);
1702         generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1703         body_last = state->last_block;
1704
1705         switch_instruction = gen_jcf_label (state);
1706         define_jcf_label (switch_instruction, state);
1707         if (sw_state.default_label == NULL)
1708           sw_state.default_label = gen_jcf_label (state);
1709
1710         if (sw_state.num_cases <= 1)
1711           {
1712             if (sw_state.num_cases == 0)
1713               {
1714                 emit_pop (1, state);
1715                 NOTE_POP (1);
1716               }
1717             else
1718               {
1719                 push_int_const (sw_state.cases->offset, state);
1720                 NOTE_PUSH (1);
1721                 emit_if (sw_state.cases->label,
1722                          OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1723               }
1724             emit_goto (sw_state.default_label, state);
1725           }
1726         else
1727           {
1728             HOST_WIDE_INT i;
1729             unsigned HOST_WIDE_INT delta;
1730             /* Copy the chain of relocs into a sorted array. */
1731             struct jcf_relocation **relocs
1732               = xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1733             /* The relocs arrays is a buffer with a gap.
1734                The assumption is that cases will normally come in "runs". */
1735             int gap_start = 0;
1736             int gap_end = sw_state.num_cases;
1737             struct jcf_relocation *reloc;
1738             for (reloc = sw_state.cases;  reloc != NULL;  reloc = reloc->next)
1739               {
1740                 HOST_WIDE_INT case_value = reloc->offset;
1741                 while (gap_end < sw_state.num_cases)
1742                   {
1743                     struct jcf_relocation *end = relocs[gap_end];
1744                     if (case_value <= end->offset)
1745                       break;
1746                     relocs[gap_start++] = end;
1747                     gap_end++;
1748                   }
1749                 while (gap_start > 0)
1750                   {
1751                     struct jcf_relocation *before = relocs[gap_start-1];
1752                     if (case_value >= before->offset)
1753                       break;
1754                     relocs[--gap_end] = before;
1755                     gap_start--;
1756                   }
1757                 relocs[gap_start++] = reloc;
1758                 /* Note we don't check for duplicates.  This is
1759                    handled by the parser.  */
1760               }
1761
1762             /* We could have DELTA < 0 if sw_state.min_case is
1763                something like Integer.MIN_VALUE.  That is why delta is
1764                unsigned.  */
1765             delta = sw_state.max_case - sw_state.min_case;
1766             if (2 * (unsigned) sw_state.num_cases >= delta)
1767               { /* Use tableswitch. */
1768                 int index = 0;
1769                 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1770                 OP1 (OPCODE_tableswitch);
1771                 emit_reloc (RELOCATION_VALUE_0, 
1772                             SWITCH_ALIGN_RELOC, NULL, state);
1773                 emit_switch_reloc (sw_state.default_label, state);
1774                 OP4 (sw_state.min_case);
1775                 OP4 (sw_state.max_case);
1776                 for (i = sw_state.min_case; ; )
1777                   {
1778                     reloc = relocs[index];
1779                     if (i == reloc->offset)
1780                       {
1781                         emit_case_reloc (reloc, state);
1782                         if (i == sw_state.max_case)
1783                           break;
1784                         index++;
1785                       }
1786                     else
1787                       emit_switch_reloc (sw_state.default_label, state);
1788                     i++;
1789                   }
1790               }
1791             else
1792               { /* Use lookupswitch. */
1793                 RESERVE(9 + 8 * sw_state.num_cases);
1794                 OP1 (OPCODE_lookupswitch);
1795                 emit_reloc (RELOCATION_VALUE_0,
1796                             SWITCH_ALIGN_RELOC, NULL, state);
1797                 emit_switch_reloc (sw_state.default_label, state);
1798                 OP4 (sw_state.num_cases);
1799                 for (i = 0;  i < sw_state.num_cases;  i++)
1800                   {
1801                     struct jcf_relocation *reloc = relocs[i];
1802                     OP4 (reloc->offset);
1803                     emit_case_reloc (reloc, state);
1804                   }
1805               }
1806             free (relocs);
1807           }
1808
1809         instruction_last = state->last_block;
1810         if (sw_state.default_label->pc < 0)
1811           define_jcf_label (sw_state.default_label, state);
1812         else /* Force a new block. */
1813           sw_state.default_label = get_jcf_label_here (state);
1814         /* Now re-arrange the blocks so the switch_instruction
1815            comes before the switch_body. */
1816         switch_length = state->code_length - switch_instruction->pc;
1817         switch_instruction->pc = body_block->pc;
1818         instruction_last->next = body_block;
1819         instruction_last->v.chunk->next = body_block->v.chunk;
1820         expression_last->next = switch_instruction;
1821         expression_last->v.chunk->next = switch_instruction->v.chunk;
1822         body_last->next = sw_state.default_label;
1823         body_last->v.chunk->next = NULL;
1824         state->chunk = body_last->v.chunk;
1825         for (;  body_block != sw_state.default_label;  body_block = body_block->next)
1826           body_block->pc += switch_length;
1827
1828         state->sw_state = sw_state.prev;
1829         break;
1830       }
1831
1832     case RETURN_EXPR:
1833       exp = TREE_OPERAND (exp, 0);
1834       if (exp == NULL_TREE)
1835         exp = build_java_empty_stmt ();
1836       else if (TREE_CODE (exp) != MODIFY_EXPR) 
1837         abort ();
1838       else
1839         exp = TREE_OPERAND (exp, 1);
1840       generate_bytecode_return (exp, state);
1841       break;
1842     case LABELED_BLOCK_EXPR:
1843       {
1844         struct jcf_block *end_label = gen_jcf_label (state);
1845         end_label->next = state->labeled_blocks;
1846         state->labeled_blocks = end_label;
1847         end_label->pc = PENDING_EXIT_PC;
1848         end_label->u.labeled_block = exp;
1849         if (LABELED_BLOCK_BODY (exp))
1850           generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1851         if (state->labeled_blocks != end_label)
1852           abort();
1853         state->labeled_blocks = end_label->next;
1854         define_jcf_label (end_label, state);
1855       }
1856       break;
1857     case LOOP_EXPR:
1858       {
1859         tree body = TREE_OPERAND (exp, 0);
1860 #if 0
1861         if (TREE_CODE (body) == COMPOUND_EXPR
1862             && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1863           {
1864             /* Optimize:  H: if (TEST) GOTO L; BODY; GOTO H; L:
1865                to:  GOTO L;  BODY;  L:  if (!TEST) GOTO L; */
1866             struct jcf_block *head_label;
1867             struct jcf_block *body_label;
1868             struct jcf_block *end_label = gen_jcf_label (state);
1869             struct jcf_block *exit_label = state->labeled_blocks;
1870             head_label = gen_jcf_label (state);
1871             emit_goto (head_label, state);
1872             body_label = get_jcf_label_here (state);
1873             generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1874             define_jcf_label (head_label, state);
1875             generate_bytecode_conditional (TREE_OPERAND (body, 0),
1876                                            end_label, body_label, 1, state);
1877             define_jcf_label (end_label, state);
1878           }
1879         else
1880 #endif
1881           {
1882             struct jcf_block *head_label = get_jcf_label_here (state);
1883             generate_bytecode_insns (body, IGNORE_TARGET, state);
1884             if (CAN_COMPLETE_NORMALLY (body))
1885               emit_goto (head_label, state);
1886           }
1887       }
1888       break;
1889     case EXIT_EXPR:
1890       {
1891         struct jcf_block *label = state->labeled_blocks;
1892         struct jcf_block *end_label = gen_jcf_label (state);
1893         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1894                                        label, end_label, 0, state);
1895         define_jcf_label (end_label, state);
1896       }
1897       break;
1898     case EXIT_BLOCK_EXPR:
1899       {
1900         struct jcf_block *label = state->labeled_blocks;
1901         while (label->u.labeled_block != EXIT_BLOCK_LABELED_BLOCK (exp))
1902           label = label->next;
1903         call_cleanups (label, state);
1904         emit_goto (label, state);
1905       }
1906       break;
1907
1908     case PREDECREMENT_EXPR:  value = -1; post_op = 0;  goto increment;
1909     case PREINCREMENT_EXPR:  value =  1; post_op = 0;  goto increment;
1910     case POSTDECREMENT_EXPR: value = -1; post_op = 1;  goto increment;
1911     case POSTINCREMENT_EXPR: value =  1; post_op = 1;  goto increment;
1912     increment:
1913
1914       arg = TREE_OPERAND (exp, 1);
1915       exp = TREE_OPERAND (exp, 0);
1916       type = TREE_TYPE (exp);
1917       size = TYPE_IS_WIDE (type) ? 2 : 1;
1918       if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1919           && ! TREE_STATIC (exp)
1920           && TREE_CODE (type) == INTEGER_TYPE
1921           && TYPE_PRECISION (type) == 32)
1922         {
1923           if (target != IGNORE_TARGET && post_op)
1924             emit_load (exp, state);
1925           emit_iinc (exp, value, state);
1926           if (target != IGNORE_TARGET && ! post_op)
1927             emit_load (exp, state);
1928           break;
1929         }
1930       if (TREE_CODE (exp) == COMPONENT_REF)
1931         {
1932           generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1933           emit_dup (1, 0, state);
1934           /* Stack:  ..., objectref, objectref. */
1935           field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1936           NOTE_PUSH (size-1);
1937           /* Stack:  ..., objectref, oldvalue. */
1938           offset = 1;
1939         }
1940       else if (TREE_CODE (exp) == ARRAY_REF)
1941         {
1942           generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1943           generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1944           emit_dup (2, 0, state);
1945           /* Stack:  ..., array, index, array, index. */
1946           jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1947           RESERVE(1);
1948           OP1 (jopcode);
1949           NOTE_POP (2-size);
1950           /* Stack:  ..., array, index, oldvalue. */
1951           offset = 2;
1952         }
1953       else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1954         {
1955           generate_bytecode_insns (exp, STACK_TARGET, state);
1956           /* Stack:  ..., oldvalue. */
1957           offset = 0;
1958         }
1959       else
1960         abort ();
1961
1962       if (target != IGNORE_TARGET && post_op)
1963         emit_dup (size, offset, state);
1964       /* Stack, if ARRAY_REF:  ..., [result, ] array, index, oldvalue. */
1965       /* Stack, if COMPONENT_REF:  ..., [result, ] objectref, oldvalue. */
1966       /* Stack, otherwise:  ..., [result, ] oldvalue. */
1967       generate_bytecode_insns (arg, STACK_TARGET, state);
1968       emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
1969                   + adjust_typed_op (type, 3),
1970                   type, state);
1971       if (target != IGNORE_TARGET && ! post_op)
1972         emit_dup (size, offset, state);
1973       /* Stack, if ARRAY_REF:  ..., [result, ] array, index, newvalue. */
1974       /* Stack, if COMPONENT_REF:  ..., [result, ] objectref, newvalue. */
1975       /* Stack, otherwise:  ..., [result, ] newvalue. */
1976       goto finish_assignment;
1977
1978     case MODIFY_EXPR:
1979       {
1980         tree lhs = TREE_OPERAND (exp, 0);
1981         tree rhs = TREE_OPERAND (exp, 1);
1982         int offset = 0;
1983
1984         /* See if we can use the iinc instruction. */
1985         if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
1986             && ! TREE_STATIC (lhs)
1987             && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
1988             && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
1989             && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
1990           {
1991             tree arg0 = TREE_OPERAND (rhs, 0);
1992             tree arg1 = TREE_OPERAND (rhs, 1);
1993             HOST_WIDE_INT min_value = -32768;
1994             HOST_WIDE_INT max_value = 32767;
1995             if (TREE_CODE (rhs) == MINUS_EXPR)
1996               {
1997                 min_value++;
1998                 max_value++;
1999               }
2000             else if (arg1 == lhs)
2001               {
2002                 arg0 = arg1;
2003                 arg1 = TREE_OPERAND (rhs, 0);
2004               }
2005             if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
2006               {
2007                 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
2008                 value = TREE_INT_CST_LOW (arg1);
2009                 if ((hi_value == 0 && value <= max_value)
2010                     || (hi_value == -1 && value >= min_value))
2011                   {
2012                     if (TREE_CODE (rhs) == MINUS_EXPR)
2013                       value = -value;
2014                     emit_iinc (lhs, value, state);
2015                     if (target != IGNORE_TARGET)
2016                       emit_load (lhs, state);
2017                     break;
2018                   }
2019               }
2020           }
2021
2022         if (TREE_CODE (lhs) == COMPONENT_REF)
2023           {
2024             generate_bytecode_insns (TREE_OPERAND (lhs, 0),
2025                                      STACK_TARGET, state);
2026             offset = 1;
2027           }
2028         else if (TREE_CODE (lhs) == ARRAY_REF)
2029           {
2030             generate_bytecode_insns (TREE_OPERAND(lhs, 0),
2031                                      STACK_TARGET, state);
2032             generate_bytecode_insns (TREE_OPERAND(lhs, 1),
2033                                      STACK_TARGET, state);
2034             offset = 2;
2035           }
2036         else
2037           offset = 0;
2038
2039         /* If the rhs is a binary expression and the left operand is
2040            `==' to the lhs then we have an OP= expression.  In this
2041            case we must do some special processing.  */
2042         if (BINARY_CLASS_P (rhs) && lhs == TREE_OPERAND (rhs, 0))
2043           {
2044             if (TREE_CODE (lhs) == COMPONENT_REF)
2045               {
2046                 tree field = TREE_OPERAND (lhs, 1);
2047                 if (! FIELD_STATIC (field))
2048                   {
2049                     /* Duplicate the object reference so we can get
2050                        the field.  */
2051                     emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
2052                     NOTE_POP (1);
2053                   }
2054                 field_op (field, (FIELD_STATIC (field)
2055                                   ? OPCODE_getstatic
2056                                   : OPCODE_getfield),
2057                           state);
2058
2059                 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2060               }
2061             else if (TREE_CODE (lhs) == VAR_DECL
2062                      || TREE_CODE (lhs) == PARM_DECL)
2063               {
2064                 if (FIELD_STATIC (lhs))
2065                   {
2066                     field_op (lhs, OPCODE_getstatic, state);
2067                     NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2068                   }
2069                 else
2070                   emit_load (lhs, state);
2071               }
2072             else if (TREE_CODE (lhs) == ARRAY_REF)
2073               {
2074                 /* Duplicate the array and index, which are on the
2075                    stack, so that we can load the old value.  */
2076                 emit_dup (2, 0, state);
2077                 NOTE_POP (2);
2078                 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
2079                 RESERVE (1);
2080                 OP1 (jopcode);
2081                 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2082               }
2083             else
2084               abort ();
2085
2086             /* This function correctly handles the case where the LHS
2087                of a binary expression is NULL_TREE.  */
2088             rhs = build2 (TREE_CODE (rhs), TREE_TYPE (rhs),
2089                           NULL_TREE, TREE_OPERAND (rhs, 1));
2090           }
2091
2092         generate_bytecode_insns (rhs, STACK_TARGET, state);
2093         if (target != IGNORE_TARGET)
2094           emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2095         exp = lhs;
2096       }
2097       /* FALLTHROUGH */
2098
2099     finish_assignment:
2100       if (TREE_CODE (exp) == COMPONENT_REF)
2101         {
2102           tree field = TREE_OPERAND (exp, 1);
2103           if (! FIELD_STATIC (field))
2104             NOTE_POP (1);
2105           field_op (field,
2106                     FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2107                     state);
2108
2109           NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2110         }
2111       else if (TREE_CODE (exp) == VAR_DECL
2112                || TREE_CODE (exp) == PARM_DECL)
2113         {
2114           if (FIELD_STATIC (exp))
2115             {
2116               field_op (exp, OPCODE_putstatic, state);
2117               NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2118             }
2119           else
2120             emit_store (exp, state);
2121         }
2122       else if (TREE_CODE (exp) == ARRAY_REF)
2123         {
2124           jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2125           RESERVE (1);
2126           OP1 (jopcode);
2127           NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2128         }
2129       else
2130         abort ();
2131       break;
2132     case PLUS_EXPR:
2133       jopcode = OPCODE_iadd;
2134       goto binop;
2135     case MINUS_EXPR:
2136       jopcode = OPCODE_isub;
2137       goto binop;
2138     case MULT_EXPR:
2139       jopcode = OPCODE_imul;
2140       goto binop;
2141     case TRUNC_DIV_EXPR:
2142     case RDIV_EXPR:
2143       jopcode = OPCODE_idiv;
2144       goto binop;
2145     case TRUNC_MOD_EXPR:
2146       jopcode = OPCODE_irem;
2147       goto binop;
2148     case LSHIFT_EXPR:   jopcode = OPCODE_ishl;   goto binop;
2149     case RSHIFT_EXPR:
2150       jopcode = TYPE_UNSIGNED (type) ? OPCODE_iushr : OPCODE_ishr;
2151       goto binop;
2152     case URSHIFT_EXPR:  jopcode = OPCODE_iushr;  goto binop;
2153     case TRUTH_AND_EXPR:
2154     case BIT_AND_EXPR:  jopcode = OPCODE_iand;   goto binop;
2155     case TRUTH_OR_EXPR:
2156     case BIT_IOR_EXPR:  jopcode = OPCODE_ior;    goto binop;
2157     case TRUTH_XOR_EXPR:
2158     case BIT_XOR_EXPR:  jopcode = OPCODE_ixor;   goto binop;
2159     binop:
2160     {
2161       tree arg0 = TREE_OPERAND (exp, 0);
2162       tree arg1 = TREE_OPERAND (exp, 1);
2163       jopcode += adjust_typed_op (type, 3);
2164       if (arg0 != NULL_TREE && operand_equal_p (arg0, arg1, 0))
2165         {
2166           /* fold may (e.g) convert 2*x to x+x. */
2167           generate_bytecode_insns (arg0, target, state);
2168           emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2169         }
2170       else
2171         {
2172           /* ARG0 will be NULL_TREE if we're handling an `OP='
2173              expression.  In this case the stack already holds the
2174              LHS.  See the MODIFY_EXPR case.  */
2175           if (arg0 != NULL_TREE)
2176             generate_bytecode_insns (arg0, target, state);
2177           if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2178             arg1 = convert (int_type_node, arg1);
2179           generate_bytecode_insns (arg1, target, state);
2180         }
2181       /* For most binary operations, both operands and the result have the
2182          same type.  Shift operations are different.  Using arg1's type
2183          gets us the correct SP adjustment in all cases. */
2184       if (target == STACK_TARGET)
2185         emit_binop (jopcode, TREE_TYPE (arg1), state);
2186       break;
2187     }
2188     case TRUTH_NOT_EXPR:
2189     case BIT_NOT_EXPR:
2190       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2191       if (target == STACK_TARGET)
2192         {
2193           int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2194           push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state); 
2195           RESERVE (2);
2196           if (is_long)
2197             OP1 (OPCODE_i2l);
2198           NOTE_PUSH (1 + is_long);
2199           OP1 (OPCODE_ixor + is_long);
2200           NOTE_POP (1 + is_long);
2201         }
2202       break;
2203     case NEGATE_EXPR:
2204       jopcode = OPCODE_ineg;
2205       jopcode += adjust_typed_op (type, 3);
2206       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2207       if (target == STACK_TARGET)
2208         emit_unop (jopcode, type, state);
2209       break;
2210     case INSTANCEOF_EXPR:
2211       {
2212         int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2213         generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2214         RESERVE (3);
2215         OP1 (OPCODE_instanceof);
2216         OP2 (index);
2217       }
2218       break;
2219     case SAVE_EXPR:
2220       /* The first time through, the argument of the SAVE_EXPR will be
2221          something complex.  Evaluate it, and replace the argument with
2222          a VAR_DECL that holds the result.  */
2223       arg = TREE_OPERAND (exp, 0);
2224       if (TREE_CODE (arg) != VAR_DECL || DECL_NAME (arg))
2225         {
2226           tree type = TREE_TYPE (exp);
2227           tree decl = build_decl (VAR_DECL, NULL_TREE, type);
2228           generate_bytecode_insns (arg, STACK_TARGET, state);
2229           localvar_alloc (decl, state);
2230           TREE_OPERAND (exp, 0) = decl;
2231           emit_dup (TYPE_IS_WIDE (type) ? 2 : 1, 0, state);
2232           emit_store (decl, state);
2233         }
2234       else
2235         {
2236           tree type = TREE_TYPE (exp);
2237           emit_load (arg, state);
2238         }
2239       break;
2240     case CONVERT_EXPR:
2241     case NOP_EXPR:
2242     case FLOAT_EXPR:
2243     case FIX_TRUNC_EXPR:
2244       {
2245         tree src = TREE_OPERAND (exp, 0);
2246         tree src_type = TREE_TYPE (src);
2247         tree dst_type = TREE_TYPE (exp);
2248         generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2249         if (target == IGNORE_TARGET || src_type == dst_type)
2250           break;
2251         if (TREE_CODE (dst_type) == POINTER_TYPE)
2252           {
2253             if (TREE_CODE (exp) == CONVERT_EXPR)
2254               {
2255                 int index = find_class_constant (&state->cpool, 
2256                                                  TREE_TYPE (dst_type));
2257                 RESERVE (3);
2258                 OP1 (OPCODE_checkcast);
2259                 OP2 (index);
2260               }
2261           }
2262         else /* Convert numeric types. */
2263           {
2264             int src_prec = TYPE_PRECISION (src_type);
2265             int dst_prec = TYPE_PRECISION (dst_type);
2266             int wide_src = src_prec > 32;
2267             int wide_dst = dst_prec > 32;
2268             if (TREE_CODE (dst_type) == REAL_TYPE)
2269               {
2270                 NOTE_POP (1 + wide_src);
2271                 RESERVE (1);
2272                 if (TREE_CODE (src_type) == REAL_TYPE)
2273                   OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2274                 else if (src_prec == 64)
2275                   OP1 (OPCODE_l2f + wide_dst);
2276                 else
2277                   OP1 (OPCODE_i2f + wide_dst);
2278                 NOTE_PUSH (1 + wide_dst);
2279               }
2280             /* Convert to integral type (but ignore non-widening
2281                and non-narrowing integer type conversions).  */
2282             else if (TREE_CODE (src_type) == REAL_TYPE
2283                      || src_prec != dst_prec)
2284               {
2285                 NOTE_POP (1 + wide_src);
2286                 RESERVE (1);
2287                 if (TREE_CODE (src_type) == REAL_TYPE)
2288                   OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2289                 else if (wide_dst)
2290                   OP1 (OPCODE_i2l);
2291                 else if (wide_src)
2292                   OP1 (OPCODE_l2i);
2293                 if (dst_prec < 32)
2294                   {
2295                     RESERVE (1);
2296                     /* Already converted to int, if needed. */
2297                     if (dst_prec <= 8)
2298                       OP1 (OPCODE_i2b);
2299                     else if (TYPE_UNSIGNED (dst_type))
2300                       OP1 (OPCODE_i2c);
2301                     else
2302                       OP1 (OPCODE_i2s);
2303                   }
2304                 NOTE_PUSH (1 + wide_dst);
2305               }
2306           }
2307       }
2308       break;
2309
2310     case TRY_EXPR:
2311       {
2312         tree try_clause = TREE_OPERAND (exp, 0);
2313         struct jcf_block *start_label = get_jcf_label_here (state);
2314         struct jcf_block *end_label;  /* End of try clause. */
2315         struct jcf_block *finished_label = gen_jcf_label (state);
2316         tree clause = TREE_OPERAND (exp, 1);
2317         if (target != IGNORE_TARGET)
2318           abort ();
2319         generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2320         end_label = get_jcf_label_here (state);
2321         if (end_label == start_label)
2322           break;
2323         if (CAN_COMPLETE_NORMALLY (try_clause))
2324           emit_goto (finished_label, state);
2325         while (clause != NULL_TREE)
2326           {
2327             tree catch_clause = TREE_OPERAND (clause, 0);
2328             tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2329             struct jcf_handler *handler = alloc_handler (start_label,
2330                                                          end_label, state);
2331             if (exception_decl == NULL_TREE)
2332               handler->type = NULL_TREE;
2333             else
2334               handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2335             generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2336             clause = TREE_CHAIN (clause);
2337             if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2338               emit_goto (finished_label, state);
2339           }
2340         define_jcf_label (finished_label, state);
2341       }
2342       break;
2343
2344     case TRY_FINALLY_EXPR:
2345       {
2346         struct jcf_block *finished_label = NULL;
2347         struct jcf_block *finally_label, *start_label, *end_label;
2348         struct jcf_handler *handler;
2349         tree try_block = TREE_OPERAND (exp, 0);
2350         tree finally = TREE_OPERAND (exp, 1);
2351         tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2352
2353         tree exception_type;
2354
2355         finally_label = gen_jcf_label (state);
2356         start_label = get_jcf_label_here (state);
2357         /* If the `finally' clause can complete normally, we emit it
2358            as a subroutine and let the other clauses call it via
2359            `jsr'.  If it can't complete normally, then we simply emit
2360            `goto's directly to it.  */
2361         if (CAN_COMPLETE_NORMALLY (finally))
2362           {
2363             finally_label->pc = PENDING_CLEANUP_PC;
2364             finally_label->next = state->labeled_blocks;
2365             state->labeled_blocks = finally_label;
2366             state->num_finalizers++;
2367           }
2368
2369         generate_bytecode_insns (try_block, target, state);
2370
2371         if (CAN_COMPLETE_NORMALLY (finally))
2372           {
2373             if (state->labeled_blocks != finally_label)
2374               abort();
2375             state->labeled_blocks = finally_label->next;
2376           }
2377         end_label = get_jcf_label_here (state);
2378
2379         if (end_label == start_label)
2380           {
2381             state->num_finalizers--;
2382             define_jcf_label (finally_label, state);
2383             generate_bytecode_insns (finally, IGNORE_TARGET, state);
2384             break;
2385           }
2386
2387         if (CAN_COMPLETE_NORMALLY (finally))
2388           {
2389             return_link = build_decl (VAR_DECL, NULL_TREE,
2390                                       return_address_type_node);
2391             finished_label = gen_jcf_label (state);
2392           }
2393
2394         if (CAN_COMPLETE_NORMALLY (try_block))
2395           {
2396             if (CAN_COMPLETE_NORMALLY (finally))
2397               {
2398                 emit_jsr (finally_label, state);
2399                 emit_goto (finished_label, state);
2400               }
2401             else
2402               emit_goto (finally_label, state);
2403           }
2404
2405         /* Handle exceptions.  */
2406
2407         exception_type = build_pointer_type (throwable_type_node);
2408         if (CAN_COMPLETE_NORMALLY (finally))
2409           {
2410             /* We're going to generate a subroutine, so we'll need to
2411                save and restore the exception around the `jsr'.  */ 
2412             exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2413             localvar_alloc (return_link, state);
2414           }
2415         handler = alloc_handler (start_label, end_label, state);
2416         handler->type = NULL_TREE;
2417         if (CAN_COMPLETE_NORMALLY (finally))
2418           {
2419             localvar_alloc (exception_decl, state);
2420             NOTE_PUSH (1);
2421             emit_store (exception_decl, state);
2422             emit_jsr (finally_label, state);
2423             emit_load (exception_decl, state);
2424             RESERVE (1);
2425             OP1 (OPCODE_athrow);
2426             NOTE_POP (1);
2427           }
2428         else
2429           {
2430             /* We're not generating a subroutine.  In this case we can
2431                simply have the exception handler pop the exception and
2432                then fall through to the `finally' block.  */
2433             NOTE_PUSH (1);
2434             emit_pop (1, state);
2435             NOTE_POP (1);
2436           }
2437
2438         /* The finally block.  If we're generating a subroutine, first
2439            save return PC into return_link.  Otherwise, just generate
2440            the code for the `finally' block.  */
2441         define_jcf_label (finally_label, state);
2442         if (CAN_COMPLETE_NORMALLY (finally))
2443           {
2444             NOTE_PUSH (1);
2445             emit_store (return_link, state);
2446           }
2447
2448         generate_bytecode_insns (finally, IGNORE_TARGET, state);
2449         if (CAN_COMPLETE_NORMALLY (finally))
2450           {
2451             maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2452             maybe_free_localvar (exception_decl, state, 1);
2453             maybe_free_localvar (return_link, state, 1);
2454             define_jcf_label (finished_label, state);
2455           }
2456       }
2457       break;
2458     case THROW_EXPR:
2459       generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2460       RESERVE (1);
2461       OP1 (OPCODE_athrow);
2462       break;
2463     case NEW_ARRAY_INIT:
2464       {
2465         tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2466         tree array_type = TREE_TYPE (TREE_TYPE (exp));
2467         tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2468         HOST_WIDE_INT length = java_array_type_length (array_type);
2469         if (target == IGNORE_TARGET)
2470           {
2471             for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values))
2472               generate_bytecode_insns (TREE_VALUE (values), target, state);
2473             break;
2474           }
2475         push_int_const (length, state);
2476         NOTE_PUSH (1);
2477         RESERVE (3);
2478         if (JPRIMITIVE_TYPE_P (element_type))
2479           {
2480             int atype = encode_newarray_type (element_type);
2481             OP1 (OPCODE_newarray);
2482             OP1 (atype);
2483           }
2484         else
2485           {
2486             int index = find_class_constant (&state->cpool,
2487                                              TREE_TYPE (element_type));
2488             OP1 (OPCODE_anewarray);
2489             OP2 (index);
2490           }
2491         offset = 0;
2492         jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2493         for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values), offset++)
2494           {
2495             int save_SP = state->code_SP;
2496             emit_dup (1, 0, state);
2497             push_int_const (offset, state);
2498             NOTE_PUSH (1);
2499             generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2500             RESERVE (1);
2501             OP1 (jopcode);
2502             state->code_SP = save_SP;
2503           }
2504       }
2505       break;
2506     case JAVA_EXC_OBJ_EXPR:
2507       NOTE_PUSH (1);  /* Pushed by exception system. */
2508       break;
2509     case MIN_EXPR:
2510     case MAX_EXPR:
2511       {
2512         /* This copes with cases where fold() has created MIN or MAX
2513            from a conditional expression.  */
2514         enum tree_code code = TREE_CODE (exp) == MIN_EXPR ? LT_EXPR : GT_EXPR;
2515         tree op0 = TREE_OPERAND (exp, 0);
2516         tree op1 = TREE_OPERAND (exp, 1);
2517         tree x;
2518         if (TREE_SIDE_EFFECTS (op0) || TREE_SIDE_EFFECTS (op1))
2519           abort ();
2520         x = build3 (COND_EXPR, TREE_TYPE (exp), 
2521                     build2 (code, boolean_type_node, op0, op1), 
2522                     op0, op1);    
2523         generate_bytecode_insns (x, target, state);
2524         break;
2525       }                                      
2526     case NEW_CLASS_EXPR:
2527       {
2528         tree class = TREE_TYPE (TREE_TYPE (exp));
2529         int need_result = target != IGNORE_TARGET;
2530         int index = find_class_constant (&state->cpool, class);
2531         RESERVE (4);
2532         OP1 (OPCODE_new);
2533         OP2 (index);
2534         if (need_result)
2535           OP1 (OPCODE_dup);
2536         NOTE_PUSH (1 + need_result);
2537       }
2538       /* ... fall though ... */
2539     case CALL_EXPR:
2540       {
2541         tree f = TREE_OPERAND (exp, 0);
2542         tree x = TREE_OPERAND (exp, 1);
2543         int save_SP = state->code_SP;
2544         int nargs;
2545         if (TREE_CODE (f) == ADDR_EXPR)
2546           f = TREE_OPERAND (f, 0);
2547         if (f == soft_newarray_node)
2548           {
2549             int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2550             generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2551                                      STACK_TARGET, state);
2552             RESERVE (2);
2553             OP1 (OPCODE_newarray);
2554             OP1 (type_code);
2555             break;
2556           }
2557         else if (f == soft_multianewarray_node)
2558           {
2559             int ndims;
2560             int idim;
2561             int index = find_class_constant (&state->cpool,
2562                                              TREE_TYPE (TREE_TYPE (exp)));
2563             x = TREE_CHAIN (x);  /* Skip class argument. */
2564             ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2565             for (idim = ndims;  --idim >= 0; )
2566               {
2567                 x = TREE_CHAIN (x);
2568                 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2569               }
2570             RESERVE (4);
2571             OP1 (OPCODE_multianewarray);
2572             OP2 (index);
2573             OP1 (ndims);
2574             NOTE_POP (ndims - 1);
2575             break;
2576           }
2577         else if (f == soft_anewarray_node)
2578           {
2579             tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2580             int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2581             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2582             RESERVE (3);
2583             OP1 (OPCODE_anewarray);
2584             OP2 (index);
2585             break;
2586           }
2587         else if (f == soft_monitorenter_node
2588                  || f == soft_monitorexit_node
2589                  || f == throw_node)
2590           {
2591             if (f == soft_monitorenter_node)
2592               op = OPCODE_monitorenter;
2593             else if (f == soft_monitorexit_node)
2594               op = OPCODE_monitorexit;
2595             else
2596               op = OPCODE_athrow;
2597             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2598             RESERVE (1);
2599             OP1 (op);
2600             NOTE_POP (1);
2601             break;
2602           }
2603         for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
2604           {
2605             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2606           }
2607         nargs = state->code_SP - save_SP;
2608         state->code_SP = save_SP;
2609         if (f == soft_fmod_node)
2610           {
2611             RESERVE (1);
2612             OP1 (OPCODE_drem);
2613             NOTE_PUSH (2);
2614             break;
2615           }
2616         if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2617           NOTE_POP (1);  /* Pop implicit this. */
2618         if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2619           {
2620             tree context = DECL_CONTEXT (f);
2621             int index, interface = 0;
2622             RESERVE (5);
2623             if (METHOD_STATIC (f))
2624               OP1 (OPCODE_invokestatic);
2625             else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2626                 || METHOD_PRIVATE (f))
2627               OP1 (OPCODE_invokespecial);
2628             else
2629               {
2630                 if (CLASS_INTERFACE (TYPE_NAME (context)))
2631                   {
2632                     tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2633                     context = TREE_TYPE (TREE_TYPE (arg1));
2634                     if (CLASS_INTERFACE (TYPE_NAME (context)))
2635                       interface = 1;
2636                   }
2637                 if (interface)
2638                   OP1 (OPCODE_invokeinterface);
2639                 else
2640                   OP1 (OPCODE_invokevirtual);
2641               }
2642             index = find_methodref_with_class_index (&state->cpool, f, context);
2643             OP2 (index);
2644             if (interface)
2645               {
2646                 if (nargs <= 0)
2647                   abort ();
2648
2649                 OP1 (nargs);
2650                 OP1 (0);
2651               }
2652             f = TREE_TYPE (TREE_TYPE (f));
2653             if (TREE_CODE (f) != VOID_TYPE)
2654               {
2655                 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2656                 if (target == IGNORE_TARGET)
2657                   emit_pop (size, state);
2658                 else
2659                   NOTE_PUSH (size);
2660               }
2661             break;
2662           }
2663       }
2664       /* fall through */
2665     default:
2666       error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2667             tree_code_name [(int) TREE_CODE (exp)]);
2668     }
2669 }
2670
2671 static void
2672 perform_relocations (struct jcf_partial *state)
2673 {
2674   struct jcf_block *block;
2675   struct jcf_relocation *reloc;
2676   int pc;
2677   int shrink;
2678
2679   /* Before we start, the pc field of each block is an upper bound on
2680      the block's start pc (it may be less, if previous blocks need less
2681      than their maximum).
2682
2683      The minimum size of each block is in the block's chunk->size. */
2684
2685   /* First, figure out the actual locations of each block. */
2686   pc = 0;
2687   shrink = 0;
2688   for (block = state->blocks;  block != NULL;  block = block->next)
2689     {
2690       int block_size = block->v.chunk->size;
2691
2692       block->pc = pc;
2693
2694       /* Optimize GOTO L; L: by getting rid of the redundant goto.
2695          Assumes relocations are in reverse order. */
2696       reloc = block->u.relocations;
2697       while (reloc != NULL
2698              && reloc->kind == OPCODE_goto_w
2699              && reloc->label->pc == block->next->pc
2700              && reloc->offset + 2 == block_size)
2701         {
2702           reloc = reloc->next;
2703           block->u.relocations = reloc;
2704           block->v.chunk->size -= 3;
2705           block_size -= 3;
2706           shrink += 3;
2707         }
2708
2709       /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2710          jump directly to X.  We're careful here to avoid an infinite
2711          loop if the `goto's themselves form one.  We do this
2712          optimization because we can generate a goto-to-goto for some
2713          try/finally blocks.  */
2714       while (reloc != NULL
2715              && reloc->kind == OPCODE_goto_w
2716              && reloc->label != block
2717              && reloc->label->v.chunk->data != NULL
2718              && reloc->label->v.chunk->data[0] == OPCODE_goto)
2719         {
2720           /* Find the reloc for the first instruction of the
2721              destination block.  */
2722           struct jcf_relocation *first_reloc;
2723           for (first_reloc = reloc->label->u.relocations;
2724                first_reloc;
2725                first_reloc = first_reloc->next)
2726             {
2727               if (first_reloc->offset == 1
2728                   && first_reloc->kind == OPCODE_goto_w)
2729                 {
2730                   reloc->label = first_reloc->label;
2731                   break;
2732                 }
2733             }
2734
2735           /* If we didn't do anything, exit the loop.  */
2736           if (first_reloc == NULL)
2737             break;
2738         }
2739
2740       for (reloc = block->u.relocations;  reloc != NULL;  reloc = reloc->next)
2741         {
2742           if (reloc->kind == SWITCH_ALIGN_RELOC)
2743             {
2744               /* We assume this is the first relocation in this block,
2745                  so we know its final pc. */
2746               int where = pc + reloc->offset;
2747               int pad = ((where + 3) & ~3) - where;
2748               block_size += pad;
2749             }
2750           else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2751             {
2752               int delta = reloc->label->pc - (pc + reloc->offset - 1);
2753               int expand = reloc->kind > 0 ? 2 : 5;
2754
2755               if (delta > 0)
2756                 delta -= shrink;
2757               if (delta >= -32768 && delta <= 32767)
2758                 {
2759                   shrink += expand;
2760                   reloc->kind = -1;
2761                 }
2762               else
2763                 block_size += expand;
2764             }
2765         }
2766       pc += block_size;
2767     }
2768
2769   for (block = state->blocks;  block != NULL;  block = block->next)
2770     {
2771       struct chunk *chunk = block->v.chunk;
2772       int old_size = chunk->size;
2773       int next_pc = block->next == NULL ? pc : block->next->pc;
2774       int new_size = next_pc - block->pc;
2775       unsigned char *new_ptr;
2776       unsigned char *old_buffer = chunk->data;
2777       unsigned char *old_ptr = old_buffer + old_size;
2778       if (new_size != old_size)
2779         {
2780           chunk->data = obstack_alloc (state->chunk_obstack, new_size);
2781           chunk->size = new_size;
2782         }
2783       new_ptr = chunk->data + new_size;
2784
2785       /* We do the relocations from back to front, because
2786          the relocations are in reverse order. */
2787       for (reloc = block->u.relocations; ; reloc = reloc->next)
2788         {
2789           /* new_ptr and old_ptr point into the old and new buffers,
2790              respectively.  (If no relocations cause the buffer to
2791              grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2792              The bytes at higher address have been copied and relocations
2793              handled; those at lower addresses remain to process. */
2794
2795           /* Lower old index of piece to be copied with no relocation.
2796              I.e. high index of the first piece that does need relocation. */
2797           int start = reloc == NULL ? 0
2798             : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2799             : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2800             ? reloc->offset + 4
2801             : reloc->offset + 2;
2802           int32 value;
2803           int new_offset;
2804           int n = (old_ptr - old_buffer) - start;
2805           new_ptr -= n;
2806           old_ptr -= n;
2807           /* Don't "copy" bytes in place, this causes valgrind
2808              warnings.  */
2809           if (n > 0 && new_ptr != old_ptr)
2810             memcpy (new_ptr, old_ptr, n);
2811           if (old_ptr == old_buffer)
2812             break;
2813
2814           new_offset = new_ptr - chunk->data;
2815           new_offset -= (reloc->kind == -1 ? 2 : 4);
2816           if (reloc->kind == 0)
2817             {
2818               old_ptr -= 4;
2819               value = GET_u4 (old_ptr);
2820             }
2821           else if (reloc->kind == BLOCK_START_RELOC)
2822             {
2823               old_ptr -= 4;
2824               value = 0;
2825               new_offset = 0;
2826             }
2827           else if (reloc->kind == SWITCH_ALIGN_RELOC)
2828             {
2829               int where = block->pc + reloc->offset;
2830               int pad = ((where + 3) & ~3) - where;
2831               while (--pad >= 0)
2832                 *--new_ptr = 0;
2833               continue;
2834             }
2835           else
2836             {
2837               old_ptr -= 2;
2838               value = GET_u2 (old_ptr);
2839             }
2840           value += reloc->label->pc - (block->pc + new_offset);
2841           *--new_ptr = (unsigned char) value;  value >>= 8;
2842           *--new_ptr = (unsigned char) value;  value >>= 8;
2843           if (reloc->kind != -1)
2844             {
2845               *--new_ptr = (unsigned char) value;  value >>= 8;
2846               *--new_ptr = (unsigned char) value;
2847             }
2848           if (reloc->kind > BLOCK_START_RELOC)
2849             {
2850               /* Convert: OP TARGET to: OP_w TARGET;  (OP is goto or jsr). */
2851               --old_ptr;
2852               *--new_ptr = reloc->kind;
2853             }
2854           else if (reloc->kind < -1)
2855             {
2856               /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2857               --old_ptr;
2858               *--new_ptr = OPCODE_goto_w;
2859               *--new_ptr = 3;
2860               *--new_ptr = 0;
2861               *--new_ptr = - reloc->kind;
2862             }
2863         }
2864       if (new_ptr != chunk->data)
2865         abort ();
2866     }
2867   state->code_length = pc;
2868 }
2869
2870 static void
2871 init_jcf_state (struct jcf_partial *state, struct obstack *work)
2872 {
2873   state->chunk_obstack = work;
2874   state->first = state->chunk = NULL;
2875   CPOOL_INIT (&state->cpool);
2876   BUFFER_INIT (&state->localvars);
2877   BUFFER_INIT (&state->bytecode);
2878 }
2879
2880 static void
2881 init_jcf_method (struct jcf_partial *state, tree method)
2882 {
2883   state->current_method = method;
2884   state->blocks = state->last_block = NULL;
2885   state->linenumber_count = 0;
2886   state->first_lvar = state->last_lvar = NULL;
2887   state->lvar_count = 0;
2888   state->labeled_blocks = NULL;
2889   state->code_length = 0;
2890   BUFFER_RESET (&state->bytecode);
2891   BUFFER_RESET (&state->localvars);
2892   state->code_SP = 0;
2893   state->code_SP_max = 0;
2894   state->handlers = NULL;
2895   state->last_handler = NULL;
2896   state->num_handlers = 0;
2897   state->num_finalizers = 0;
2898   state->return_value_decl = NULL_TREE;
2899 }
2900
2901 static void
2902 release_jcf_state (struct jcf_partial *state)
2903 {
2904   CPOOL_FINISH (&state->cpool);
2905   obstack_free (state->chunk_obstack, state->first);
2906 }
2907
2908 /* Get the access flags (modifiers) of a class (TYPE_DECL) to be used in the
2909    access_flags field of the class file header.  */
2910
2911 static int
2912 get_classfile_modifiers (tree class)
2913 {
2914   /* These are the flags which are valid class file modifiers. 
2915      See JVMS2 S4.1.  */
2916   int valid_toplevel_class_flags = (ACC_PUBLIC | ACC_FINAL | ACC_SUPER | 
2917                                     ACC_INTERFACE | ACC_ABSTRACT);
2918   int flags = get_access_flags (class);
2919
2920   /* ACC_SUPER should always be set, except for interfaces.  */
2921   if (! (flags & ACC_INTERFACE))
2922     flags |= ACC_SUPER;
2923    
2924   /* A protected member class becomes public at the top level. */
2925   if (flags & ACC_PROTECTED)
2926     flags |= ACC_PUBLIC;
2927  
2928   /* Filter out flags that are not valid for a class or interface in the 
2929      top-level access_flags field.  */
2930   flags &= valid_toplevel_class_flags;
2931
2932   return flags;
2933 }
2934
2935 /* Get the access flags (modifiers) for a method to be used in the class 
2936    file.  */
2937
2938 static int
2939 get_method_access_flags (tree decl)
2940 {
2941   int flags = get_access_flags (decl);
2942
2943   /* Promote "private" inner-class constructors to package-private.  */
2944   if (DECL_CONSTRUCTOR_P (decl)
2945       && INNER_CLASS_DECL_P (TYPE_NAME (DECL_CONTEXT (decl))))
2946     flags &= ~(ACC_PRIVATE);
2947
2948   return flags;
2949 }
2950
2951 /* Generate and return a list of chunks containing the class CLAS
2952    in the .class file representation.  The list can be written to a
2953    .class file using write_chunks.  Allocate chunks from obstack WORK. */
2954
2955 static GTY(()) tree SourceFile_node;
2956 static struct chunk *
2957 generate_classfile (tree clas, struct jcf_partial *state)
2958 {
2959   struct chunk *cpool_chunk;
2960   const char *source_file, *s;
2961   unsigned char *ptr;
2962   int i;
2963   unsigned char *fields_count_ptr;
2964   int fields_count = 0;
2965   unsigned char *methods_count_ptr;
2966   int methods_count = 0;
2967   tree part;
2968   int total_supers
2969     = clas == object_type_node ? 0 : BINFO_N_BASE_BINFOS (TYPE_BINFO (clas));
2970   
2971   ptr = append_chunk (NULL, 8, state);
2972   PUT4 (0xCafeBabe);  /* Magic number */
2973   PUT2 (3);  /* Minor version */
2974   PUT2 (45);  /* Major version */
2975   
2976   append_chunk (NULL, 0, state);
2977   cpool_chunk = state->chunk;
2978
2979   /* Next allocate the chunk containing access_flags through fields_count. */
2980   if (clas == object_type_node)
2981     i = 10;
2982   else
2983     i = 8 + 2 * total_supers;
2984   ptr = append_chunk (NULL, i, state);
2985   i = get_classfile_modifiers (TYPE_NAME (clas));  
2986   PUT2 (i); /* access_flags */
2987   i = find_class_constant (&state->cpool, clas);  PUT2 (i);  /* this_class */
2988   if (clas == object_type_node)
2989     {
2990       PUT2(0);  /* super_class */
2991       PUT2(0);  /* interfaces_count */
2992     }
2993   else
2994     {
2995       tree binfo = TYPE_BINFO (clas);
2996       tree base_binfo = BINFO_BASE_BINFO (binfo, 0);
2997       int j = find_class_constant (&state->cpool, BINFO_TYPE (base_binfo));
2998       
2999       PUT2 (j);  /* super_class */
3000       PUT2 (total_supers - 1);  /* interfaces_count */
3001       for (i = 1; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
3002         {
3003           j = find_class_constant (&state->cpool, BINFO_TYPE (base_binfo));
3004           PUT2 (j);
3005         }
3006     }
3007   fields_count_ptr = ptr;
3008
3009   for (part = TYPE_FIELDS (clas);  part;  part = TREE_CHAIN (part))
3010     {
3011       int have_value, attr_count = 0;
3012       if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
3013         continue;
3014       ptr = append_chunk (NULL, 8, state);
3015       i = get_access_flags (part);  PUT2 (i);
3016       i = find_utf8_constant (&state->cpool, DECL_NAME (part));  PUT2 (i);
3017       i = find_utf8_constant (&state->cpool, 
3018                               build_java_signature (TREE_TYPE (part)));
3019       PUT2(i);
3020       have_value = DECL_INITIAL (part) != NULL_TREE 
3021         && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
3022         && FIELD_FINAL (part)
3023         && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
3024             || TREE_TYPE (part) == string_ptr_type_node);
3025       if (have_value)
3026         attr_count++;
3027
3028       if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
3029           || FIELD_SYNTHETIC (part))
3030         attr_count++;
3031       if (FIELD_DEPRECATED (part))
3032         attr_count++;
3033
3034       PUT2 (attr_count);  /* attributes_count */
3035       if (have_value)
3036         {
3037           tree init = DECL_INITIAL (part);
3038           static tree ConstantValue_node = NULL_TREE;
3039           if (TREE_TYPE (part) != TREE_TYPE (init))
3040             fatal_error ("field initializer type mismatch");
3041           ptr = append_chunk (NULL, 8, state);
3042           if (ConstantValue_node == NULL_TREE)
3043             ConstantValue_node = get_identifier ("ConstantValue");
3044           i = find_utf8_constant (&state->cpool, ConstantValue_node);
3045           PUT2 (i);  /* attribute_name_index */
3046           PUT4 (2); /* attribute_length */
3047           i = find_constant_index (init, state);  PUT2 (i);
3048         }
3049       /* Emit the "Synthetic" attribute for val$<x> and this$<n>
3050          fields and other fields which need it.  */
3051       if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
3052           || FIELD_SYNTHETIC (part))
3053         ptr = append_synthetic_attribute (state);
3054       if (FIELD_DEPRECATED (part))
3055         append_deprecated_attribute (state);
3056       fields_count++;
3057     }
3058   ptr = fields_count_ptr;  UNSAFE_PUT2 (fields_count);
3059
3060   ptr = methods_count_ptr = append_chunk (NULL, 2, state);
3061   PUT2 (0);
3062
3063   for (part = TYPE_METHODS (clas);  part;  part = TREE_CHAIN (part))
3064     {
3065       struct jcf_block *block;
3066       tree function_body = DECL_FUNCTION_BODY (part);
3067       tree body = function_body == NULL_TREE ? NULL_TREE
3068         : BLOCK_EXPR_BODY (function_body);
3069       tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
3070         : DECL_NAME (part);
3071       tree type = TREE_TYPE (part);
3072       tree save_function = current_function_decl;
3073       int synthetic_p = 0;
3074
3075       /* Invisible Miranda methods shouldn't end up in the .class
3076          file.  */
3077       if (METHOD_INVISIBLE (part))
3078         continue;
3079
3080       current_function_decl = part;
3081       ptr = append_chunk (NULL, 8, state);
3082       i = get_method_access_flags (part);  PUT2 (i);
3083       i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
3084       i = find_utf8_constant (&state->cpool, build_java_signature (type));
3085       PUT2 (i);
3086       i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
3087
3088       /* Make room for the Synthetic attribute (of zero length.)  */
3089       if (DECL_FINIT_P (part)
3090           || DECL_INSTINIT_P (part)
3091           || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
3092           || TYPE_DOT_CLASS (clas) == part)
3093         {
3094           i++;
3095           synthetic_p = 1;
3096         }
3097       /* Make room for Deprecated attribute.  */
3098       if (METHOD_DEPRECATED (part))
3099         i++;
3100
3101       PUT2 (i);   /* attributes_count */
3102
3103       if (synthetic_p)
3104         ptr = append_synthetic_attribute (state);
3105
3106       if (body != NULL_TREE)
3107         {
3108           int code_attributes_count = 0;
3109           static tree Code_node = NULL_TREE;
3110           tree t;
3111           unsigned char *attr_len_ptr;
3112           struct jcf_handler *handler;
3113           if (Code_node == NULL_TREE)
3114             Code_node = get_identifier ("Code");
3115           ptr = append_chunk (NULL, 14, state);
3116           i = find_utf8_constant (&state->cpool, Code_node);  PUT2 (i);
3117           attr_len_ptr = ptr;
3118           init_jcf_method (state, part);
3119           get_jcf_label_here (state);  /* Force a first block. */
3120           for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
3121             localvar_alloc (t, state);
3122           state->num_jsrs = 0;
3123           generate_bytecode_insns (body, IGNORE_TARGET, state);
3124           if (CAN_COMPLETE_NORMALLY (body))
3125             {
3126               if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
3127                 abort();
3128               RESERVE (1);
3129               OP1 (OPCODE_return);
3130             }
3131           for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
3132             maybe_free_localvar (t, state, 1);
3133           if (state->return_value_decl != NULL_TREE)
3134             maybe_free_localvar (state->return_value_decl, state, 1);
3135           finish_jcf_block (state);
3136           perform_relocations (state);
3137
3138           ptr = attr_len_ptr;
3139           i = 8 + state->code_length + 4 + 8 * state->num_handlers;
3140           if (state->linenumber_count > 0)
3141             {
3142               code_attributes_count++;
3143               i += 8 + 4 * state->linenumber_count;
3144             }
3145           if (state->lvar_count > 0)
3146             {
3147               code_attributes_count++;
3148               i += 8 + 10 * state->lvar_count;
3149             }
3150           UNSAFE_PUT4 (i); /* attribute_length */
3151           UNSAFE_PUT2 (state->code_SP_max);  /* max_stack */
3152           UNSAFE_PUT2 (localvar_max);  /* max_locals */
3153           UNSAFE_PUT4 (state->code_length);
3154
3155           /* Emit the exception table. */
3156           ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3157           PUT2 (state->num_handlers);  /* exception_table_length */
3158           handler = state->handlers;
3159           for (; handler != NULL;  handler = handler->next)
3160             {
3161               int type_index;
3162               PUT2 (handler->start_label->pc);
3163               PUT2 (handler->end_label->pc);
3164               PUT2 (handler->handler_label->pc);
3165               if (handler->type == NULL_TREE)
3166                 type_index = 0;
3167               else
3168                 type_index = find_class_constant (&state->cpool,
3169                                                   handler->type);
3170               PUT2 (type_index);
3171             }
3172
3173           ptr = append_chunk (NULL, 2, state);
3174           PUT2 (code_attributes_count);
3175
3176           /* Write the LineNumberTable attribute. */
3177           if (state->linenumber_count > 0)
3178             {
3179               static tree LineNumberTable_node = NULL_TREE;
3180               ptr = append_chunk (NULL, 
3181                                   8 + 4 * state->linenumber_count, state);
3182               if (LineNumberTable_node == NULL_TREE)
3183                 LineNumberTable_node = get_identifier ("LineNumberTable");
3184               i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3185               PUT2 (i);  /* attribute_name_index */
3186               i = 2+4*state->linenumber_count;  PUT4(i); /* attribute_length */
3187               i = state->linenumber_count;  PUT2 (i);
3188               for (block = state->blocks;  block != NULL;  block = block->next)
3189                 {
3190                   int line = block->linenumber;
3191                   if (line > 0)
3192                     {
3193                       PUT2 (block->pc);
3194                       PUT2 (line);
3195                     }
3196                 }
3197             }
3198
3199           /* Write the LocalVariableTable attribute. */
3200           if (state->lvar_count > 0)
3201             {
3202               static tree LocalVariableTable_node = NULL_TREE;
3203               struct localvar_info *lvar = state->first_lvar;
3204               ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3205               if (LocalVariableTable_node == NULL_TREE)
3206                 LocalVariableTable_node = get_identifier("LocalVariableTable");
3207               i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3208               PUT2 (i);  /* attribute_name_index */
3209               i = 2 + 10 * state->lvar_count;  PUT4 (i); /* attribute_length */
3210               i = state->lvar_count;  PUT2 (i);
3211               for ( ; lvar != NULL;  lvar = lvar->next)
3212                 {
3213                   tree name = DECL_NAME (lvar->decl);
3214                   tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3215                   i = lvar->start_label->pc;  PUT2 (i);
3216                   i = lvar->end_label->pc - i;  PUT2 (i);
3217                   i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
3218                   i = find_utf8_constant (&state->cpool, sig);  PUT2 (i);
3219                   i = DECL_LOCAL_INDEX (lvar->decl);  PUT2 (i);
3220                 }
3221             }
3222         }
3223       if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3224         {
3225           tree t = DECL_FUNCTION_THROWS (part);
3226           int throws_count = list_length (t);
3227           static tree Exceptions_node = NULL_TREE;
3228           if (Exceptions_node == NULL_TREE)
3229             Exceptions_node = get_identifier ("Exceptions");
3230           ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3231           i = find_utf8_constant (&state->cpool, Exceptions_node);
3232           PUT2 (i);  /* attribute_name_index */ 
3233           i = 2 + 2 * throws_count;  PUT4(i); /* attribute_length */ 
3234           i = throws_count;  PUT2 (i); 
3235           for (;  t != NULL_TREE;  t = TREE_CHAIN (t))
3236             {
3237               i = find_class_constant (&state->cpool, TREE_VALUE (t));
3238               PUT2 (i);
3239             }
3240         }
3241
3242       if (METHOD_DEPRECATED (part))
3243         append_deprecated_attribute (state);
3244  
3245       methods_count++;
3246       current_function_decl = save_function;
3247     }
3248   ptr = methods_count_ptr;  UNSAFE_PUT2 (methods_count);
3249
3250   source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3251   for (s = source_file; ; s++)
3252     {
3253       char ch = *s;
3254       if (ch == '\0')
3255         break;
3256       if (ch == '/' || ch == '\\')
3257         source_file = s+1;
3258     }
3259   ptr = append_chunk (NULL, 10, state);
3260
3261   i = 1;                /* Source file always exists as an attribute */
3262   if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3263     i++;
3264   if (clas == object_type_node)
3265     i++;
3266   if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3267     i++;
3268
3269   PUT2 (i);                     /* attributes_count */
3270
3271   /* generate the SourceFile attribute. */
3272   if (SourceFile_node == NULL_TREE) 
3273     {
3274       SourceFile_node = get_identifier ("SourceFile");
3275     }
3276
3277   i = find_utf8_constant (&state->cpool, SourceFile_node);
3278   PUT2 (i);  /* attribute_name_index */
3279   PUT4 (2);
3280   i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3281   PUT2 (i);
3282   append_gcj_attribute (state, clas);
3283   append_innerclasses_attribute (state, clas);
3284   if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3285     append_deprecated_attribute (state);
3286
3287   /* New finally generate the contents of the constant pool chunk. */
3288   i = count_constant_pool_bytes (&state->cpool);
3289   ptr = obstack_alloc (state->chunk_obstack, i);
3290   cpool_chunk->data = ptr;
3291   cpool_chunk->size = i;
3292   write_constant_pool (&state->cpool, ptr, i);
3293   return state->first;
3294 }
3295
3296 static GTY(()) tree Synthetic_node;
3297 static unsigned char *
3298 append_synthetic_attribute (struct jcf_partial *state)
3299 {
3300   unsigned char *ptr = append_chunk (NULL, 6, state);
3301   int i;
3302
3303   if (Synthetic_node == NULL_TREE)
3304     {
3305       Synthetic_node = get_identifier ("Synthetic");
3306     }
3307   i = find_utf8_constant (&state->cpool, Synthetic_node);
3308   PUT2 (i);             /* Attribute string index */
3309   PUT4 (0);             /* Attribute length */
3310
3311   return ptr;
3312 }
3313
3314 static void
3315 append_deprecated_attribute (struct jcf_partial *state)
3316 {
3317   unsigned char *ptr = append_chunk (NULL, 6, state);
3318   int i;
3319  
3320   i = find_utf8_constant (&state->cpool, get_identifier ("Deprecated"));
3321   PUT2 (i);             /* Attribute string index */
3322   PUT4 (0);             /* Attribute length */
3323 }
3324
3325 static void
3326 append_gcj_attribute (struct jcf_partial *state, tree class)
3327 {
3328   unsigned char *ptr;
3329   int i;
3330
3331   if (class != object_type_node)
3332     return;
3333
3334   ptr = append_chunk (NULL, 6, state); /* 2+4 */
3335   i = find_utf8_constant (&state->cpool, 
3336                           get_identifier ("gnu.gcj.gcj-compiled"));
3337   PUT2 (i);                     /* Attribute string index */
3338   PUT4 (0);                     /* Attribute length */
3339 }
3340
3341 static tree InnerClasses_node;
3342 static void
3343 append_innerclasses_attribute (struct jcf_partial *state, tree class)
3344 {
3345   tree orig_decl = TYPE_NAME (class);
3346   tree current, decl;
3347   int length = 0, i;
3348   unsigned char *ptr, *length_marker, *number_marker;
3349
3350   if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3351     return;
3352
3353   ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3354   
3355   if (InnerClasses_node == NULL_TREE) 
3356     {
3357       InnerClasses_node = get_identifier ("InnerClasses");
3358     }
3359   i = find_utf8_constant (&state->cpool, InnerClasses_node);
3360   PUT2 (i);
3361   length_marker = ptr; PUT4 (0); /* length, to be later patched */
3362   number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3363
3364   /* Generate the entries: all inner classes visible from the one we
3365      process: itself, up and down. */
3366   while (class && INNER_CLASS_TYPE_P (class))
3367     {
3368       const char *n;
3369
3370       decl = TYPE_NAME (class);
3371       n = IDENTIFIER_POINTER (DECL_NAME (decl)) + 
3372         IDENTIFIER_LENGTH (DECL_NAME (decl));
3373
3374       while (n[-1] != '$')
3375         n--;
3376       append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3377       length++;
3378
3379       class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3380     }
3381
3382   decl = orig_decl;
3383   for (current = DECL_INNER_CLASS_LIST (decl); 
3384        current; current = TREE_CHAIN (current))
3385     {
3386       append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3387                                            TREE_VALUE (current));
3388       length++;
3389     }
3390   
3391   ptr = length_marker; PUT4 (8*length+2);
3392   ptr = number_marker; PUT2 (length);
3393 }
3394
3395 static void
3396 append_innerclasses_attribute_entry (struct jcf_partial *state,
3397                                      tree decl, tree name)
3398 {
3399   int icii, icaf;
3400   int ocii = 0, ini = 0;
3401   unsigned char *ptr = append_chunk (NULL, 8, state);
3402
3403   icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3404
3405   /* Sun's implementation seems to generate ocii to 0 for inner
3406      classes (which aren't considered members of the class they're
3407      in.) The specs are saying that if the class is anonymous,
3408      inner_name_index must be zero. */
3409   if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3410     {
3411       ocii = find_class_constant (&state->cpool, 
3412                                   TREE_TYPE (DECL_CONTEXT (decl)));
3413       ini = find_utf8_constant (&state->cpool, name);
3414     }
3415   icaf = get_access_flags (decl);
3416
3417   PUT2 (icii); PUT2 (ocii); PUT2 (ini);  PUT2 (icaf);
3418 }
3419
3420 static char *
3421 make_class_file_name (tree clas)
3422 {
3423   const char *dname, *cname, *slash;
3424   char *r;
3425   struct stat sb;
3426   char sep;
3427
3428   cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3429                                                 "", '.', DIR_SEPARATOR,
3430                                                 ".class"));
3431   if (jcf_write_base_directory == NULL)
3432     {
3433       /* Make sure we put the class file into the .java file's
3434          directory, and not into some subdirectory thereof.  */
3435       char *t;
3436       dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3437       slash = strrchr (dname, DIR_SEPARATOR);
3438 #ifdef DIR_SEPARATOR_2
3439       if (! slash)
3440         slash = strrchr (dname, DIR_SEPARATOR_2);
3441 #endif
3442       if (! slash)
3443         {
3444           dname = ".";
3445           slash = dname + 1;
3446           sep = DIR_SEPARATOR;
3447         }
3448       else
3449         sep = *slash;
3450
3451       t = strrchr (cname, DIR_SEPARATOR);
3452       if (t)
3453         cname = t + 1;
3454     }
3455   else
3456     {
3457       char *s;
3458
3459       dname = jcf_write_base_directory;
3460
3461       s = strrchr (dname, DIR_SEPARATOR);
3462 #ifdef DIR_SEPARATOR_2
3463       if (! s)
3464         s = strrchr (dname, DIR_SEPARATOR_2);
3465 #endif
3466       if (s)
3467         sep = *s;
3468       else
3469         sep = DIR_SEPARATOR;
3470
3471       slash = dname + strlen (dname);
3472     }
3473
3474   r = xmalloc (slash - dname + strlen (cname) + 2);
3475   strncpy (r, dname, slash - dname);
3476   r[slash - dname] = sep;
3477   strcpy (&r[slash - dname + 1], cname);
3478
3479   /* We try to make new directories when we need them.  We only do
3480      this for directories which "might not" exist.  For instance, we
3481      assume the `-d' directory exists, but we don't assume that any
3482      subdirectory below it exists.  It might be worthwhile to keep
3483      track of which directories we've created to avoid gratuitous
3484      stat()s.  */
3485   dname = r + (slash - dname) + 1;
3486   while (1)
3487     {
3488       char *s = strchr (dname, sep);
3489       if (s == NULL)
3490         break;
3491       *s = '\0';
3492       /* Try to make directory if it doesn't already exist.  */
3493       if (stat (r, &sb) == -1
3494           && mkdir (r, 0755) == -1
3495           /* The directory might have been made by another process.  */
3496           && errno != EEXIST)
3497         fatal_error ("can't create directory %s: %m", r);
3498
3499       *s = sep;
3500       /* Skip consecutive separators.  */
3501       for (dname = s + 1; *dname && *dname == sep; ++dname)
3502         ;
3503     }
3504
3505   return r;
3506 }
3507
3508 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3509    The output .class file name is make_class_file_name(CLAS). */
3510
3511 void
3512 write_classfile (tree clas)
3513 {
3514   struct obstack *work = &temporary_obstack;
3515   struct jcf_partial state[1];
3516   char *class_file_name = make_class_file_name (clas);
3517   struct chunk *chunks;
3518
3519   if (class_file_name != NULL)
3520     {
3521       FILE *stream;
3522       char *temporary_file_name;
3523
3524       /* The .class file is initially written to a ".tmp" file so that
3525          if multiple instances of the compiler are running at once
3526          they do not see partially formed class files. */
3527       temporary_file_name = concat (class_file_name, ".tmp", NULL);
3528       stream = fopen (temporary_file_name, "wb");
3529       if (stream == NULL)
3530         fatal_error ("can't open %s for writing: %m", temporary_file_name);
3531
3532       jcf_dependency_add_target (class_file_name);
3533       init_jcf_state (state, work);
3534       chunks = generate_classfile (clas, state);
3535       write_chunks (stream, chunks);
3536       if (fclose (stream))
3537         fatal_error ("error closing %s: %m", temporary_file_name);
3538
3539       /* If a file named by the string pointed to by `new' exists
3540          prior to the call to the `rename' function, the behavior
3541          is implementation-defined.  ISO 9899-1990 7.9.4.2.
3542
3543          For example, on Win32 with MSVCRT, it is an error. */
3544
3545       unlink (class_file_name);
3546
3547       if (rename (temporary_file_name, class_file_name) == -1)
3548         {
3549           remove (temporary_file_name);
3550           fatal_error ("can't create %s: %m", class_file_name);
3551         }
3552       free (temporary_file_name);
3553       free (class_file_name);
3554     }
3555   release_jcf_state (state);
3556 }
3557
3558 /* TODO:
3559    string concatenation
3560    synchronized statement
3561    */
3562
3563 #include "gt-java-jcf-write.h"