OSDN Git Service

* decl.c (finish_method): Give methods once-only linkage.
[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           NOTE_PUSH (TYPE_IS_WIDE (type) ? 2 : 1);
2239         }
2240       break;
2241     case CONVERT_EXPR:
2242     case NOP_EXPR:
2243     case FLOAT_EXPR:
2244     case FIX_TRUNC_EXPR:
2245       {
2246         tree src = TREE_OPERAND (exp, 0);
2247         tree src_type = TREE_TYPE (src);
2248         tree dst_type = TREE_TYPE (exp);
2249         generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2250         if (target == IGNORE_TARGET || src_type == dst_type)
2251           break;
2252         if (TREE_CODE (dst_type) == POINTER_TYPE)
2253           {
2254             if (TREE_CODE (exp) == CONVERT_EXPR)
2255               {
2256                 int index = find_class_constant (&state->cpool, 
2257                                                  TREE_TYPE (dst_type));
2258                 RESERVE (3);
2259                 OP1 (OPCODE_checkcast);
2260                 OP2 (index);
2261               }
2262           }
2263         else /* Convert numeric types. */
2264           {
2265             int src_prec = TYPE_PRECISION (src_type);
2266             int dst_prec = TYPE_PRECISION (dst_type);
2267             int wide_src = src_prec > 32;
2268             int wide_dst = dst_prec > 32;
2269             if (TREE_CODE (dst_type) == REAL_TYPE)
2270               {
2271                 NOTE_POP (1 + wide_src);
2272                 RESERVE (1);
2273                 if (TREE_CODE (src_type) == REAL_TYPE)
2274                   OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2275                 else if (src_prec == 64)
2276                   OP1 (OPCODE_l2f + wide_dst);
2277                 else
2278                   OP1 (OPCODE_i2f + wide_dst);
2279                 NOTE_PUSH (1 + wide_dst);
2280               }
2281             /* Convert to integral type (but ignore non-widening
2282                and non-narrowing integer type conversions).  */
2283             else if (TREE_CODE (src_type) == REAL_TYPE
2284                      || src_prec != dst_prec)
2285               {
2286                 NOTE_POP (1 + wide_src);
2287                 RESERVE (1);
2288                 if (TREE_CODE (src_type) == REAL_TYPE)
2289                   OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2290                 else if (wide_dst)
2291                   OP1 (OPCODE_i2l);
2292                 else if (wide_src)
2293                   OP1 (OPCODE_l2i);
2294                 if (dst_prec < 32)
2295                   {
2296                     RESERVE (1);
2297                     /* Already converted to int, if needed. */
2298                     if (dst_prec <= 8)
2299                       OP1 (OPCODE_i2b);
2300                     else if (TYPE_UNSIGNED (dst_type))
2301                       OP1 (OPCODE_i2c);
2302                     else
2303                       OP1 (OPCODE_i2s);
2304                   }
2305                 NOTE_PUSH (1 + wide_dst);
2306               }
2307           }
2308       }
2309       break;
2310
2311     case TRY_EXPR:
2312       {
2313         tree try_clause = TREE_OPERAND (exp, 0);
2314         struct jcf_block *start_label = get_jcf_label_here (state);
2315         struct jcf_block *end_label;  /* End of try clause. */
2316         struct jcf_block *finished_label = gen_jcf_label (state);
2317         tree clause = TREE_OPERAND (exp, 1);
2318         if (target != IGNORE_TARGET)
2319           abort ();
2320         generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2321         end_label = get_jcf_label_here (state);
2322         if (end_label == start_label)
2323           break;
2324         if (CAN_COMPLETE_NORMALLY (try_clause))
2325           emit_goto (finished_label, state);
2326         while (clause != NULL_TREE)
2327           {
2328             tree catch_clause = TREE_OPERAND (clause, 0);
2329             tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2330             struct jcf_handler *handler = alloc_handler (start_label,
2331                                                          end_label, state);
2332             if (exception_decl == NULL_TREE)
2333               handler->type = NULL_TREE;
2334             else
2335               handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2336             generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2337             clause = TREE_CHAIN (clause);
2338             if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2339               emit_goto (finished_label, state);
2340           }
2341         define_jcf_label (finished_label, state);
2342       }
2343       break;
2344
2345     case TRY_FINALLY_EXPR:
2346       {
2347         struct jcf_block *finished_label = NULL;
2348         struct jcf_block *finally_label, *start_label, *end_label;
2349         struct jcf_handler *handler;
2350         tree try_block = TREE_OPERAND (exp, 0);
2351         tree finally = TREE_OPERAND (exp, 1);
2352         tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2353
2354         tree exception_type;
2355
2356         finally_label = gen_jcf_label (state);
2357         start_label = get_jcf_label_here (state);
2358         /* If the `finally' clause can complete normally, we emit it
2359            as a subroutine and let the other clauses call it via
2360            `jsr'.  If it can't complete normally, then we simply emit
2361            `goto's directly to it.  */
2362         if (CAN_COMPLETE_NORMALLY (finally))
2363           {
2364             finally_label->pc = PENDING_CLEANUP_PC;
2365             finally_label->next = state->labeled_blocks;
2366             state->labeled_blocks = finally_label;
2367             state->num_finalizers++;
2368           }
2369
2370         generate_bytecode_insns (try_block, target, state);
2371
2372         if (CAN_COMPLETE_NORMALLY (finally))
2373           {
2374             if (state->labeled_blocks != finally_label)
2375               abort();
2376             state->labeled_blocks = finally_label->next;
2377           }
2378         end_label = get_jcf_label_here (state);
2379
2380         if (end_label == start_label)
2381           {
2382             state->num_finalizers--;
2383             define_jcf_label (finally_label, state);
2384             generate_bytecode_insns (finally, IGNORE_TARGET, state);
2385             break;
2386           }
2387
2388         if (CAN_COMPLETE_NORMALLY (finally))
2389           {
2390             return_link = build_decl (VAR_DECL, NULL_TREE,
2391                                       return_address_type_node);
2392             finished_label = gen_jcf_label (state);
2393           }
2394
2395         if (CAN_COMPLETE_NORMALLY (try_block))
2396           {
2397             if (CAN_COMPLETE_NORMALLY (finally))
2398               {
2399                 emit_jsr (finally_label, state);
2400                 emit_goto (finished_label, state);
2401               }
2402             else
2403               emit_goto (finally_label, state);
2404           }
2405
2406         /* Handle exceptions.  */
2407
2408         exception_type = build_pointer_type (throwable_type_node);
2409         if (CAN_COMPLETE_NORMALLY (finally))
2410           {
2411             /* We're going to generate a subroutine, so we'll need to
2412                save and restore the exception around the `jsr'.  */ 
2413             exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2414             localvar_alloc (return_link, state);
2415           }
2416         handler = alloc_handler (start_label, end_label, state);
2417         handler->type = NULL_TREE;
2418         if (CAN_COMPLETE_NORMALLY (finally))
2419           {
2420             localvar_alloc (exception_decl, state);
2421             NOTE_PUSH (1);
2422             emit_store (exception_decl, state);
2423             emit_jsr (finally_label, state);
2424             emit_load (exception_decl, state);
2425             RESERVE (1);
2426             OP1 (OPCODE_athrow);
2427             NOTE_POP (1);
2428           }
2429         else
2430           {
2431             /* We're not generating a subroutine.  In this case we can
2432                simply have the exception handler pop the exception and
2433                then fall through to the `finally' block.  */
2434             NOTE_PUSH (1);
2435             emit_pop (1, state);
2436             NOTE_POP (1);
2437           }
2438
2439         /* The finally block.  If we're generating a subroutine, first
2440            save return PC into return_link.  Otherwise, just generate
2441            the code for the `finally' block.  */
2442         define_jcf_label (finally_label, state);
2443         if (CAN_COMPLETE_NORMALLY (finally))
2444           {
2445             NOTE_PUSH (1);
2446             emit_store (return_link, state);
2447           }
2448
2449         generate_bytecode_insns (finally, IGNORE_TARGET, state);
2450         if (CAN_COMPLETE_NORMALLY (finally))
2451           {
2452             maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2453             maybe_free_localvar (exception_decl, state, 1);
2454             maybe_free_localvar (return_link, state, 1);
2455             define_jcf_label (finished_label, state);
2456           }
2457       }
2458       break;
2459     case THROW_EXPR:
2460       generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2461       RESERVE (1);
2462       OP1 (OPCODE_athrow);
2463       break;
2464     case NEW_ARRAY_INIT:
2465       {
2466         tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2467         tree array_type = TREE_TYPE (TREE_TYPE (exp));
2468         tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2469         HOST_WIDE_INT length = java_array_type_length (array_type);
2470         if (target == IGNORE_TARGET)
2471           {
2472             for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values))
2473               generate_bytecode_insns (TREE_VALUE (values), target, state);
2474             break;
2475           }
2476         push_int_const (length, state);
2477         NOTE_PUSH (1);
2478         RESERVE (3);
2479         if (JPRIMITIVE_TYPE_P (element_type))
2480           {
2481             int atype = encode_newarray_type (element_type);
2482             OP1 (OPCODE_newarray);
2483             OP1 (atype);
2484           }
2485         else
2486           {
2487             int index = find_class_constant (&state->cpool,
2488                                              TREE_TYPE (element_type));
2489             OP1 (OPCODE_anewarray);
2490             OP2 (index);
2491           }
2492         offset = 0;
2493         jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2494         for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values), offset++)
2495           {
2496             int save_SP = state->code_SP;
2497             emit_dup (1, 0, state);
2498             push_int_const (offset, state);
2499             NOTE_PUSH (1);
2500             generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2501             RESERVE (1);
2502             OP1 (jopcode);
2503             state->code_SP = save_SP;
2504           }
2505       }
2506       break;
2507     case JAVA_EXC_OBJ_EXPR:
2508       NOTE_PUSH (1);  /* Pushed by exception system. */
2509       break;
2510     case MIN_EXPR:
2511     case MAX_EXPR:
2512       {
2513         /* This copes with cases where fold() has created MIN or MAX
2514            from a conditional expression.  */
2515         enum tree_code code = TREE_CODE (exp) == MIN_EXPR ? LT_EXPR : GT_EXPR;
2516         tree op0 = TREE_OPERAND (exp, 0);
2517         tree op1 = TREE_OPERAND (exp, 1);
2518         tree x;
2519         if (TREE_SIDE_EFFECTS (op0) || TREE_SIDE_EFFECTS (op1))
2520           abort ();
2521         x = build3 (COND_EXPR, TREE_TYPE (exp), 
2522                     build2 (code, boolean_type_node, op0, op1), 
2523                     op0, op1);    
2524         generate_bytecode_insns (x, target, state);
2525         break;
2526       }                                      
2527     case NEW_CLASS_EXPR:
2528       {
2529         tree class = TREE_TYPE (TREE_TYPE (exp));
2530         int need_result = target != IGNORE_TARGET;
2531         int index = find_class_constant (&state->cpool, class);
2532         RESERVE (4);
2533         OP1 (OPCODE_new);
2534         OP2 (index);
2535         if (need_result)
2536           OP1 (OPCODE_dup);
2537         NOTE_PUSH (1 + need_result);
2538       }
2539       /* ... fall though ... */
2540     case CALL_EXPR:
2541       {
2542         tree f = TREE_OPERAND (exp, 0);
2543         tree x = TREE_OPERAND (exp, 1);
2544         int save_SP = state->code_SP;
2545         int nargs;
2546         if (TREE_CODE (f) == ADDR_EXPR)
2547           f = TREE_OPERAND (f, 0);
2548         if (f == soft_newarray_node)
2549           {
2550             int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2551             generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2552                                      STACK_TARGET, state);
2553             RESERVE (2);
2554             OP1 (OPCODE_newarray);
2555             OP1 (type_code);
2556             break;
2557           }
2558         else if (f == soft_multianewarray_node)
2559           {
2560             int ndims;
2561             int idim;
2562             int index = find_class_constant (&state->cpool,
2563                                              TREE_TYPE (TREE_TYPE (exp)));
2564             x = TREE_CHAIN (x);  /* Skip class argument. */
2565             ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2566             for (idim = ndims;  --idim >= 0; )
2567               {
2568                 x = TREE_CHAIN (x);
2569                 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2570               }
2571             RESERVE (4);
2572             OP1 (OPCODE_multianewarray);
2573             OP2 (index);
2574             OP1 (ndims);
2575             NOTE_POP (ndims - 1);
2576             break;
2577           }
2578         else if (f == soft_anewarray_node)
2579           {
2580             tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2581             int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2582             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2583             RESERVE (3);
2584             OP1 (OPCODE_anewarray);
2585             OP2 (index);
2586             break;
2587           }
2588         else if (f == soft_monitorenter_node
2589                  || f == soft_monitorexit_node
2590                  || f == throw_node)
2591           {
2592             if (f == soft_monitorenter_node)
2593               op = OPCODE_monitorenter;
2594             else if (f == soft_monitorexit_node)
2595               op = OPCODE_monitorexit;
2596             else
2597               op = OPCODE_athrow;
2598             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2599             RESERVE (1);
2600             OP1 (op);
2601             NOTE_POP (1);
2602             break;
2603           }
2604         for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
2605           {
2606             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2607           }
2608         nargs = state->code_SP - save_SP;
2609         state->code_SP = save_SP;
2610         if (f == soft_fmod_node)
2611           {
2612             RESERVE (1);
2613             OP1 (OPCODE_drem);
2614             NOTE_PUSH (2);
2615             break;
2616           }
2617         if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2618           NOTE_POP (1);  /* Pop implicit this. */
2619         if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2620           {
2621             tree context = DECL_CONTEXT (f);
2622             int index, interface = 0;
2623             RESERVE (5);
2624             if (METHOD_STATIC (f))
2625               OP1 (OPCODE_invokestatic);
2626             else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2627                 || METHOD_PRIVATE (f))
2628               OP1 (OPCODE_invokespecial);
2629             else
2630               {
2631                 if (CLASS_INTERFACE (TYPE_NAME (context)))
2632                   {
2633                     tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2634                     context = TREE_TYPE (TREE_TYPE (arg1));
2635                     if (CLASS_INTERFACE (TYPE_NAME (context)))
2636                       interface = 1;
2637                   }
2638                 if (interface)
2639                   OP1 (OPCODE_invokeinterface);
2640                 else
2641                   OP1 (OPCODE_invokevirtual);
2642               }
2643             index = find_methodref_with_class_index (&state->cpool, f, context);
2644             OP2 (index);
2645             if (interface)
2646               {
2647                 if (nargs <= 0)
2648                   abort ();
2649
2650                 OP1 (nargs);
2651                 OP1 (0);
2652               }
2653             f = TREE_TYPE (TREE_TYPE (f));
2654             if (TREE_CODE (f) != VOID_TYPE)
2655               {
2656                 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2657                 if (target == IGNORE_TARGET)
2658                   emit_pop (size, state);
2659                 else
2660                   NOTE_PUSH (size);
2661               }
2662             break;
2663           }
2664       }
2665       /* fall through */
2666     default:
2667       error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2668             tree_code_name [(int) TREE_CODE (exp)]);
2669     }
2670 }
2671
2672 static void
2673 perform_relocations (struct jcf_partial *state)
2674 {
2675   struct jcf_block *block;
2676   struct jcf_relocation *reloc;
2677   int pc;
2678   int shrink;
2679
2680   /* Before we start, the pc field of each block is an upper bound on
2681      the block's start pc (it may be less, if previous blocks need less
2682      than their maximum).
2683
2684      The minimum size of each block is in the block's chunk->size. */
2685
2686   /* First, figure out the actual locations of each block. */
2687   pc = 0;
2688   shrink = 0;
2689   for (block = state->blocks;  block != NULL;  block = block->next)
2690     {
2691       int block_size = block->v.chunk->size;
2692
2693       block->pc = pc;
2694
2695       /* Optimize GOTO L; L: by getting rid of the redundant goto.
2696          Assumes relocations are in reverse order. */
2697       reloc = block->u.relocations;
2698       while (reloc != NULL
2699              && reloc->kind == OPCODE_goto_w
2700              && reloc->label->pc == block->next->pc
2701              && reloc->offset + 2 == block_size)
2702         {
2703           reloc = reloc->next;
2704           block->u.relocations = reloc;
2705           block->v.chunk->size -= 3;
2706           block_size -= 3;
2707           shrink += 3;
2708         }
2709
2710       /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2711          jump directly to X.  We're careful here to avoid an infinite
2712          loop if the `goto's themselves form one.  We do this
2713          optimization because we can generate a goto-to-goto for some
2714          try/finally blocks.  */
2715       while (reloc != NULL
2716              && reloc->kind == OPCODE_goto_w
2717              && reloc->label != block
2718              && reloc->label->v.chunk->data != NULL
2719              && reloc->label->v.chunk->data[0] == OPCODE_goto)
2720         {
2721           /* Find the reloc for the first instruction of the
2722              destination block.  */
2723           struct jcf_relocation *first_reloc;
2724           for (first_reloc = reloc->label->u.relocations;
2725                first_reloc;
2726                first_reloc = first_reloc->next)
2727             {
2728               if (first_reloc->offset == 1
2729                   && first_reloc->kind == OPCODE_goto_w)
2730                 {
2731                   reloc->label = first_reloc->label;
2732                   break;
2733                 }
2734             }
2735
2736           /* If we didn't do anything, exit the loop.  */
2737           if (first_reloc == NULL)
2738             break;
2739         }
2740
2741       for (reloc = block->u.relocations;  reloc != NULL;  reloc = reloc->next)
2742         {
2743           if (reloc->kind == SWITCH_ALIGN_RELOC)
2744             {
2745               /* We assume this is the first relocation in this block,
2746                  so we know its final pc. */
2747               int where = pc + reloc->offset;
2748               int pad = ((where + 3) & ~3) - where;
2749               block_size += pad;
2750             }
2751           else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2752             {
2753               int delta = reloc->label->pc - (pc + reloc->offset - 1);
2754               int expand = reloc->kind > 0 ? 2 : 5;
2755
2756               if (delta > 0)
2757                 delta -= shrink;
2758               if (delta >= -32768 && delta <= 32767)
2759                 {
2760                   shrink += expand;
2761                   reloc->kind = -1;
2762                 }
2763               else
2764                 block_size += expand;
2765             }
2766         }
2767       pc += block_size;
2768     }
2769
2770   for (block = state->blocks;  block != NULL;  block = block->next)
2771     {
2772       struct chunk *chunk = block->v.chunk;
2773       int old_size = chunk->size;
2774       int next_pc = block->next == NULL ? pc : block->next->pc;
2775       int new_size = next_pc - block->pc;
2776       unsigned char *new_ptr;
2777       unsigned char *old_buffer = chunk->data;
2778       unsigned char *old_ptr = old_buffer + old_size;
2779       if (new_size != old_size)
2780         {
2781           chunk->data = obstack_alloc (state->chunk_obstack, new_size);
2782           chunk->size = new_size;
2783         }
2784       new_ptr = chunk->data + new_size;
2785
2786       /* We do the relocations from back to front, because
2787          the relocations are in reverse order. */
2788       for (reloc = block->u.relocations; ; reloc = reloc->next)
2789         {
2790           /* new_ptr and old_ptr point into the old and new buffers,
2791              respectively.  (If no relocations cause the buffer to
2792              grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2793              The bytes at higher address have been copied and relocations
2794              handled; those at lower addresses remain to process. */
2795
2796           /* Lower old index of piece to be copied with no relocation.
2797              I.e. high index of the first piece that does need relocation. */
2798           int start = reloc == NULL ? 0
2799             : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2800             : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2801             ? reloc->offset + 4
2802             : reloc->offset + 2;
2803           int32 value;
2804           int new_offset;
2805           int n = (old_ptr - old_buffer) - start;
2806           new_ptr -= n;
2807           old_ptr -= n;
2808           /* Don't "copy" bytes in place, this causes valgrind
2809              warnings.  */
2810           if (n > 0 && new_ptr != old_ptr)
2811             memcpy (new_ptr, old_ptr, n);
2812           if (old_ptr == old_buffer)
2813             break;
2814
2815           new_offset = new_ptr - chunk->data;
2816           new_offset -= (reloc->kind == -1 ? 2 : 4);
2817           if (reloc->kind == 0)
2818             {
2819               old_ptr -= 4;
2820               value = GET_u4 (old_ptr);
2821             }
2822           else if (reloc->kind == BLOCK_START_RELOC)
2823             {
2824               old_ptr -= 4;
2825               value = 0;
2826               new_offset = 0;
2827             }
2828           else if (reloc->kind == SWITCH_ALIGN_RELOC)
2829             {
2830               int where = block->pc + reloc->offset;
2831               int pad = ((where + 3) & ~3) - where;
2832               while (--pad >= 0)
2833                 *--new_ptr = 0;
2834               continue;
2835             }
2836           else
2837             {
2838               old_ptr -= 2;
2839               value = GET_u2 (old_ptr);
2840             }
2841           value += reloc->label->pc - (block->pc + new_offset);
2842           *--new_ptr = (unsigned char) value;  value >>= 8;
2843           *--new_ptr = (unsigned char) value;  value >>= 8;
2844           if (reloc->kind != -1)
2845             {
2846               *--new_ptr = (unsigned char) value;  value >>= 8;
2847               *--new_ptr = (unsigned char) value;
2848             }
2849           if (reloc->kind > BLOCK_START_RELOC)
2850             {
2851               /* Convert: OP TARGET to: OP_w TARGET;  (OP is goto or jsr). */
2852               --old_ptr;
2853               *--new_ptr = reloc->kind;
2854             }
2855           else if (reloc->kind < -1)
2856             {
2857               /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2858               --old_ptr;
2859               *--new_ptr = OPCODE_goto_w;
2860               *--new_ptr = 3;
2861               *--new_ptr = 0;
2862               *--new_ptr = - reloc->kind;
2863             }
2864         }
2865       if (new_ptr != chunk->data)
2866         abort ();
2867     }
2868   state->code_length = pc;
2869 }
2870
2871 static void
2872 init_jcf_state (struct jcf_partial *state, struct obstack *work)
2873 {
2874   state->chunk_obstack = work;
2875   state->first = state->chunk = NULL;
2876   CPOOL_INIT (&state->cpool);
2877   BUFFER_INIT (&state->localvars);
2878   BUFFER_INIT (&state->bytecode);
2879 }
2880
2881 static void
2882 init_jcf_method (struct jcf_partial *state, tree method)
2883 {
2884   state->current_method = method;
2885   state->blocks = state->last_block = NULL;
2886   state->linenumber_count = 0;
2887   state->first_lvar = state->last_lvar = NULL;
2888   state->lvar_count = 0;
2889   state->labeled_blocks = NULL;
2890   state->code_length = 0;
2891   BUFFER_RESET (&state->bytecode);
2892   BUFFER_RESET (&state->localvars);
2893   state->code_SP = 0;
2894   state->code_SP_max = 0;
2895   state->handlers = NULL;
2896   state->last_handler = NULL;
2897   state->num_handlers = 0;
2898   state->num_finalizers = 0;
2899   state->return_value_decl = NULL_TREE;
2900 }
2901
2902 static void
2903 release_jcf_state (struct jcf_partial *state)
2904 {
2905   CPOOL_FINISH (&state->cpool);
2906   obstack_free (state->chunk_obstack, state->first);
2907 }
2908
2909 /* Get the access flags (modifiers) of a class (TYPE_DECL) to be used in the
2910    access_flags field of the class file header.  */
2911
2912 static int
2913 get_classfile_modifiers (tree class)
2914 {
2915   /* These are the flags which are valid class file modifiers. 
2916      See JVMS2 S4.1.  */
2917   int valid_toplevel_class_flags = (ACC_PUBLIC | ACC_FINAL | ACC_SUPER | 
2918                                     ACC_INTERFACE | ACC_ABSTRACT);
2919   int flags = get_access_flags (class);
2920
2921   /* ACC_SUPER should always be set, except for interfaces.  */
2922   if (! (flags & ACC_INTERFACE))
2923     flags |= ACC_SUPER;
2924    
2925   /* A protected member class becomes public at the top level. */
2926   if (flags & ACC_PROTECTED)
2927     flags |= ACC_PUBLIC;
2928  
2929   /* Filter out flags that are not valid for a class or interface in the 
2930      top-level access_flags field.  */
2931   flags &= valid_toplevel_class_flags;
2932
2933   return flags;
2934 }
2935
2936 /* Get the access flags (modifiers) for a method to be used in the class 
2937    file.  */
2938
2939 static int
2940 get_method_access_flags (tree decl)
2941 {
2942   int flags = get_access_flags (decl);
2943
2944   /* Promote "private" inner-class constructors to package-private.  */
2945   if (DECL_CONSTRUCTOR_P (decl)
2946       && INNER_CLASS_DECL_P (TYPE_NAME (DECL_CONTEXT (decl))))
2947     flags &= ~(ACC_PRIVATE);
2948
2949   return flags;
2950 }
2951
2952 /* Generate and return a list of chunks containing the class CLAS
2953    in the .class file representation.  The list can be written to a
2954    .class file using write_chunks.  Allocate chunks from obstack WORK. */
2955
2956 static GTY(()) tree SourceFile_node;
2957 static struct chunk *
2958 generate_classfile (tree clas, struct jcf_partial *state)
2959 {
2960   struct chunk *cpool_chunk;
2961   const char *source_file, *s;
2962   unsigned char *ptr;
2963   int i;
2964   unsigned char *fields_count_ptr;
2965   int fields_count = 0;
2966   unsigned char *methods_count_ptr;
2967   int methods_count = 0;
2968   tree part;
2969   int total_supers
2970     = clas == object_type_node ? 0 : BINFO_N_BASE_BINFOS (TYPE_BINFO (clas));
2971   
2972   ptr = append_chunk (NULL, 8, state);
2973   PUT4 (0xCafeBabe);  /* Magic number */
2974   PUT2 (3);  /* Minor version */
2975   PUT2 (45);  /* Major version */
2976   
2977   append_chunk (NULL, 0, state);
2978   cpool_chunk = state->chunk;
2979
2980   /* Next allocate the chunk containing access_flags through fields_count. */
2981   if (clas == object_type_node)
2982     i = 10;
2983   else
2984     i = 8 + 2 * total_supers;
2985   ptr = append_chunk (NULL, i, state);
2986   i = get_classfile_modifiers (TYPE_NAME (clas));  
2987   PUT2 (i); /* access_flags */
2988   i = find_class_constant (&state->cpool, clas);  PUT2 (i);  /* this_class */
2989   if (clas == object_type_node)
2990     {
2991       PUT2(0);  /* super_class */
2992       PUT2(0);  /* interfaces_count */
2993     }
2994   else
2995     {
2996       tree binfo = TYPE_BINFO (clas);
2997       tree base_binfo = BINFO_BASE_BINFO (binfo, 0);
2998       int j = find_class_constant (&state->cpool, BINFO_TYPE (base_binfo));
2999       
3000       PUT2 (j);  /* super_class */
3001       PUT2 (total_supers - 1);  /* interfaces_count */
3002       for (i = 1; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
3003         {
3004           j = find_class_constant (&state->cpool, BINFO_TYPE (base_binfo));
3005           PUT2 (j);
3006         }
3007     }
3008   fields_count_ptr = ptr;
3009
3010   for (part = TYPE_FIELDS (clas);  part;  part = TREE_CHAIN (part))
3011     {
3012       int have_value, attr_count = 0;
3013       if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
3014         continue;
3015       ptr = append_chunk (NULL, 8, state);
3016       i = get_access_flags (part);  PUT2 (i);
3017       i = find_utf8_constant (&state->cpool, DECL_NAME (part));  PUT2 (i);
3018       i = find_utf8_constant (&state->cpool, 
3019                               build_java_signature (TREE_TYPE (part)));
3020       PUT2(i);
3021       have_value = DECL_INITIAL (part) != NULL_TREE 
3022         && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
3023         && FIELD_FINAL (part)
3024         && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
3025             || TREE_TYPE (part) == string_ptr_type_node);
3026       if (have_value)
3027         attr_count++;
3028
3029       if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
3030           || FIELD_SYNTHETIC (part))
3031         attr_count++;
3032       if (FIELD_DEPRECATED (part))
3033         attr_count++;
3034
3035       PUT2 (attr_count);  /* attributes_count */
3036       if (have_value)
3037         {
3038           tree init = DECL_INITIAL (part);
3039           static tree ConstantValue_node = NULL_TREE;
3040           if (TREE_TYPE (part) != TREE_TYPE (init))
3041             fatal_error ("field initializer type mismatch");
3042           ptr = append_chunk (NULL, 8, state);
3043           if (ConstantValue_node == NULL_TREE)
3044             ConstantValue_node = get_identifier ("ConstantValue");
3045           i = find_utf8_constant (&state->cpool, ConstantValue_node);
3046           PUT2 (i);  /* attribute_name_index */
3047           PUT4 (2); /* attribute_length */
3048           i = find_constant_index (init, state);  PUT2 (i);
3049         }
3050       /* Emit the "Synthetic" attribute for val$<x> and this$<n>
3051          fields and other fields which need it.  */
3052       if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
3053           || FIELD_SYNTHETIC (part))
3054         ptr = append_synthetic_attribute (state);
3055       if (FIELD_DEPRECATED (part))
3056         append_deprecated_attribute (state);
3057       fields_count++;
3058     }
3059   ptr = fields_count_ptr;  UNSAFE_PUT2 (fields_count);
3060
3061   ptr = methods_count_ptr = append_chunk (NULL, 2, state);
3062   PUT2 (0);
3063
3064   for (part = TYPE_METHODS (clas);  part;  part = TREE_CHAIN (part))
3065     {
3066       struct jcf_block *block;
3067       tree function_body = DECL_FUNCTION_BODY (part);
3068       tree body = function_body == NULL_TREE ? NULL_TREE
3069         : BLOCK_EXPR_BODY (function_body);
3070       tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
3071         : DECL_NAME (part);
3072       tree type = TREE_TYPE (part);
3073       tree save_function = current_function_decl;
3074       int synthetic_p = 0;
3075
3076       /* Invisible Miranda methods shouldn't end up in the .class
3077          file.  */
3078       if (METHOD_INVISIBLE (part))
3079         continue;
3080
3081       current_function_decl = part;
3082       ptr = append_chunk (NULL, 8, state);
3083       i = get_method_access_flags (part);  PUT2 (i);
3084       i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
3085       i = find_utf8_constant (&state->cpool, build_java_signature (type));
3086       PUT2 (i);
3087       i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
3088
3089       /* Make room for the Synthetic attribute (of zero length.)  */
3090       if (DECL_FINIT_P (part)
3091           || DECL_INSTINIT_P (part)
3092           || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
3093           || TYPE_DOT_CLASS (clas) == part)
3094         {
3095           i++;
3096           synthetic_p = 1;
3097         }
3098       /* Make room for Deprecated attribute.  */
3099       if (METHOD_DEPRECATED (part))
3100         i++;
3101
3102       PUT2 (i);   /* attributes_count */
3103
3104       if (synthetic_p)
3105         ptr = append_synthetic_attribute (state);
3106
3107       if (body != NULL_TREE)
3108         {
3109           int code_attributes_count = 0;
3110           static tree Code_node = NULL_TREE;
3111           tree t;
3112           unsigned char *attr_len_ptr;
3113           struct jcf_handler *handler;
3114           if (Code_node == NULL_TREE)
3115             Code_node = get_identifier ("Code");
3116           ptr = append_chunk (NULL, 14, state);
3117           i = find_utf8_constant (&state->cpool, Code_node);  PUT2 (i);
3118           attr_len_ptr = ptr;
3119           init_jcf_method (state, part);
3120           get_jcf_label_here (state);  /* Force a first block. */
3121           for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
3122             localvar_alloc (t, state);
3123           state->num_jsrs = 0;
3124           generate_bytecode_insns (body, IGNORE_TARGET, state);
3125           if (CAN_COMPLETE_NORMALLY (body))
3126             {
3127               if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
3128                 abort();
3129               RESERVE (1);
3130               OP1 (OPCODE_return);
3131             }
3132           for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
3133             maybe_free_localvar (t, state, 1);
3134           if (state->return_value_decl != NULL_TREE)
3135             maybe_free_localvar (state->return_value_decl, state, 1);
3136           finish_jcf_block (state);
3137           perform_relocations (state);
3138
3139           ptr = attr_len_ptr;
3140           i = 8 + state->code_length + 4 + 8 * state->num_handlers;
3141           if (state->linenumber_count > 0)
3142             {
3143               code_attributes_count++;
3144               i += 8 + 4 * state->linenumber_count;
3145             }
3146           if (state->lvar_count > 0)
3147             {
3148               code_attributes_count++;
3149               i += 8 + 10 * state->lvar_count;
3150             }
3151           UNSAFE_PUT4 (i); /* attribute_length */
3152           UNSAFE_PUT2 (state->code_SP_max);  /* max_stack */
3153           UNSAFE_PUT2 (localvar_max);  /* max_locals */
3154           UNSAFE_PUT4 (state->code_length);
3155
3156           /* Emit the exception table. */
3157           ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3158           PUT2 (state->num_handlers);  /* exception_table_length */
3159           handler = state->handlers;
3160           for (; handler != NULL;  handler = handler->next)
3161             {
3162               int type_index;
3163               PUT2 (handler->start_label->pc);
3164               PUT2 (handler->end_label->pc);
3165               PUT2 (handler->handler_label->pc);
3166               if (handler->type == NULL_TREE)
3167                 type_index = 0;
3168               else
3169                 type_index = find_class_constant (&state->cpool,
3170                                                   handler->type);
3171               PUT2 (type_index);
3172             }
3173
3174           ptr = append_chunk (NULL, 2, state);
3175           PUT2 (code_attributes_count);
3176
3177           /* Write the LineNumberTable attribute. */
3178           if (state->linenumber_count > 0)
3179             {
3180               static tree LineNumberTable_node = NULL_TREE;
3181               ptr = append_chunk (NULL, 
3182                                   8 + 4 * state->linenumber_count, state);
3183               if (LineNumberTable_node == NULL_TREE)
3184                 LineNumberTable_node = get_identifier ("LineNumberTable");
3185               i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3186               PUT2 (i);  /* attribute_name_index */
3187               i = 2+4*state->linenumber_count;  PUT4(i); /* attribute_length */
3188               i = state->linenumber_count;  PUT2 (i);
3189               for (block = state->blocks;  block != NULL;  block = block->next)
3190                 {
3191                   int line = block->linenumber;
3192                   if (line > 0)
3193                     {
3194                       PUT2 (block->pc);
3195                       PUT2 (line);
3196                     }
3197                 }
3198             }
3199
3200           /* Write the LocalVariableTable attribute. */
3201           if (state->lvar_count > 0)
3202             {
3203               static tree LocalVariableTable_node = NULL_TREE;
3204               struct localvar_info *lvar = state->first_lvar;
3205               ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3206               if (LocalVariableTable_node == NULL_TREE)
3207                 LocalVariableTable_node = get_identifier("LocalVariableTable");
3208               i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3209               PUT2 (i);  /* attribute_name_index */
3210               i = 2 + 10 * state->lvar_count;  PUT4 (i); /* attribute_length */
3211               i = state->lvar_count;  PUT2 (i);
3212               for ( ; lvar != NULL;  lvar = lvar->next)
3213                 {
3214                   tree name = DECL_NAME (lvar->decl);
3215                   tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3216                   i = lvar->start_label->pc;  PUT2 (i);
3217                   i = lvar->end_label->pc - i;  PUT2 (i);
3218                   i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
3219                   i = find_utf8_constant (&state->cpool, sig);  PUT2 (i);
3220                   i = DECL_LOCAL_INDEX (lvar->decl);  PUT2 (i);
3221                 }
3222             }
3223         }
3224       if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3225         {
3226           tree t = DECL_FUNCTION_THROWS (part);
3227           int throws_count = list_length (t);
3228           static tree Exceptions_node = NULL_TREE;
3229           if (Exceptions_node == NULL_TREE)
3230             Exceptions_node = get_identifier ("Exceptions");
3231           ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3232           i = find_utf8_constant (&state->cpool, Exceptions_node);
3233           PUT2 (i);  /* attribute_name_index */ 
3234           i = 2 + 2 * throws_count;  PUT4(i); /* attribute_length */ 
3235           i = throws_count;  PUT2 (i); 
3236           for (;  t != NULL_TREE;  t = TREE_CHAIN (t))
3237             {
3238               i = find_class_constant (&state->cpool, TREE_VALUE (t));
3239               PUT2 (i);
3240             }
3241         }
3242
3243       if (METHOD_DEPRECATED (part))
3244         append_deprecated_attribute (state);
3245  
3246       methods_count++;
3247       current_function_decl = save_function;
3248     }
3249   ptr = methods_count_ptr;  UNSAFE_PUT2 (methods_count);
3250
3251   source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3252   for (s = source_file; ; s++)
3253     {
3254       char ch = *s;
3255       if (ch == '\0')
3256         break;
3257       if (ch == '/' || ch == '\\')
3258         source_file = s+1;
3259     }
3260   ptr = append_chunk (NULL, 10, state);
3261
3262   i = 1;                /* Source file always exists as an attribute */
3263   if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3264     i++;
3265   if (clas == object_type_node)
3266     i++;
3267   if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3268     i++;
3269
3270   PUT2 (i);                     /* attributes_count */
3271
3272   /* generate the SourceFile attribute. */
3273   if (SourceFile_node == NULL_TREE) 
3274     {
3275       SourceFile_node = get_identifier ("SourceFile");
3276     }
3277
3278   i = find_utf8_constant (&state->cpool, SourceFile_node);
3279   PUT2 (i);  /* attribute_name_index */
3280   PUT4 (2);
3281   i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3282   PUT2 (i);
3283   append_gcj_attribute (state, clas);
3284   append_innerclasses_attribute (state, clas);
3285   if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3286     append_deprecated_attribute (state);
3287
3288   /* New finally generate the contents of the constant pool chunk. */
3289   i = count_constant_pool_bytes (&state->cpool);
3290   ptr = obstack_alloc (state->chunk_obstack, i);
3291   cpool_chunk->data = ptr;
3292   cpool_chunk->size = i;
3293   write_constant_pool (&state->cpool, ptr, i);
3294   return state->first;
3295 }
3296
3297 static GTY(()) tree Synthetic_node;
3298 static unsigned char *
3299 append_synthetic_attribute (struct jcf_partial *state)
3300 {
3301   unsigned char *ptr = append_chunk (NULL, 6, state);
3302   int i;
3303
3304   if (Synthetic_node == NULL_TREE)
3305     {
3306       Synthetic_node = get_identifier ("Synthetic");
3307     }
3308   i = find_utf8_constant (&state->cpool, Synthetic_node);
3309   PUT2 (i);             /* Attribute string index */
3310   PUT4 (0);             /* Attribute length */
3311
3312   return ptr;
3313 }
3314
3315 static void
3316 append_deprecated_attribute (struct jcf_partial *state)
3317 {
3318   unsigned char *ptr = append_chunk (NULL, 6, state);
3319   int i;
3320  
3321   i = find_utf8_constant (&state->cpool, get_identifier ("Deprecated"));
3322   PUT2 (i);             /* Attribute string index */
3323   PUT4 (0);             /* Attribute length */
3324 }
3325
3326 static void
3327 append_gcj_attribute (struct jcf_partial *state, tree class)
3328 {
3329   unsigned char *ptr;
3330   int i;
3331
3332   if (class != object_type_node)
3333     return;
3334
3335   ptr = append_chunk (NULL, 6, state); /* 2+4 */
3336   i = find_utf8_constant (&state->cpool, 
3337                           get_identifier ("gnu.gcj.gcj-compiled"));
3338   PUT2 (i);                     /* Attribute string index */
3339   PUT4 (0);                     /* Attribute length */
3340 }
3341
3342 static tree InnerClasses_node;
3343 static void
3344 append_innerclasses_attribute (struct jcf_partial *state, tree class)
3345 {
3346   tree orig_decl = TYPE_NAME (class);
3347   tree current, decl;
3348   int length = 0, i;
3349   unsigned char *ptr, *length_marker, *number_marker;
3350
3351   if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3352     return;
3353
3354   ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3355   
3356   if (InnerClasses_node == NULL_TREE) 
3357     {
3358       InnerClasses_node = get_identifier ("InnerClasses");
3359     }
3360   i = find_utf8_constant (&state->cpool, InnerClasses_node);
3361   PUT2 (i);
3362   length_marker = ptr; PUT4 (0); /* length, to be later patched */
3363   number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3364
3365   /* Generate the entries: all inner classes visible from the one we
3366      process: itself, up and down. */
3367   while (class && INNER_CLASS_TYPE_P (class))
3368     {
3369       const char *n;
3370
3371       decl = TYPE_NAME (class);
3372       n = IDENTIFIER_POINTER (DECL_NAME (decl)) + 
3373         IDENTIFIER_LENGTH (DECL_NAME (decl));
3374
3375       while (n[-1] != '$')
3376         n--;
3377       append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3378       length++;
3379
3380       class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3381     }
3382
3383   decl = orig_decl;
3384   for (current = DECL_INNER_CLASS_LIST (decl); 
3385        current; current = TREE_CHAIN (current))
3386     {
3387       append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3388                                            TREE_VALUE (current));
3389       length++;
3390     }
3391   
3392   ptr = length_marker; PUT4 (8*length+2);
3393   ptr = number_marker; PUT2 (length);
3394 }
3395
3396 static void
3397 append_innerclasses_attribute_entry (struct jcf_partial *state,
3398                                      tree decl, tree name)
3399 {
3400   int icii, icaf;
3401   int ocii = 0, ini = 0;
3402   unsigned char *ptr = append_chunk (NULL, 8, state);
3403
3404   icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3405
3406   /* Sun's implementation seems to generate ocii to 0 for inner
3407      classes (which aren't considered members of the class they're
3408      in.) The specs are saying that if the class is anonymous,
3409      inner_name_index must be zero. */
3410   if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3411     {
3412       ocii = find_class_constant (&state->cpool, 
3413                                   TREE_TYPE (DECL_CONTEXT (decl)));
3414       ini = find_utf8_constant (&state->cpool, name);
3415     }
3416   icaf = get_access_flags (decl);
3417
3418   PUT2 (icii); PUT2 (ocii); PUT2 (ini);  PUT2 (icaf);
3419 }
3420
3421 static char *
3422 make_class_file_name (tree clas)
3423 {
3424   const char *dname, *cname, *slash;
3425   char *r;
3426   struct stat sb;
3427   char sep;
3428
3429   cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3430                                                 "", '.', DIR_SEPARATOR,
3431                                                 ".class"));
3432   if (jcf_write_base_directory == NULL)
3433     {
3434       /* Make sure we put the class file into the .java file's
3435          directory, and not into some subdirectory thereof.  */
3436       char *t;
3437       dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3438       slash = strrchr (dname, DIR_SEPARATOR);
3439 #ifdef DIR_SEPARATOR_2
3440       if (! slash)
3441         slash = strrchr (dname, DIR_SEPARATOR_2);
3442 #endif
3443       if (! slash)
3444         {
3445           dname = ".";
3446           slash = dname + 1;
3447           sep = DIR_SEPARATOR;
3448         }
3449       else
3450         sep = *slash;
3451
3452       t = strrchr (cname, DIR_SEPARATOR);
3453       if (t)
3454         cname = t + 1;
3455     }
3456   else
3457     {
3458       char *s;
3459
3460       dname = jcf_write_base_directory;
3461
3462       s = strrchr (dname, DIR_SEPARATOR);
3463 #ifdef DIR_SEPARATOR_2
3464       if (! s)
3465         s = strrchr (dname, DIR_SEPARATOR_2);
3466 #endif
3467       if (s)
3468         sep = *s;
3469       else
3470         sep = DIR_SEPARATOR;
3471
3472       slash = dname + strlen (dname);
3473     }
3474
3475   r = xmalloc (slash - dname + strlen (cname) + 2);
3476   strncpy (r, dname, slash - dname);
3477   r[slash - dname] = sep;
3478   strcpy (&r[slash - dname + 1], cname);
3479
3480   /* We try to make new directories when we need them.  We only do
3481      this for directories which "might not" exist.  For instance, we
3482      assume the `-d' directory exists, but we don't assume that any
3483      subdirectory below it exists.  It might be worthwhile to keep
3484      track of which directories we've created to avoid gratuitous
3485      stat()s.  */
3486   dname = r + (slash - dname) + 1;
3487   while (1)
3488     {
3489       char *s = strchr (dname, sep);
3490       if (s == NULL)
3491         break;
3492       *s = '\0';
3493       /* Try to make directory if it doesn't already exist.  */
3494       if (stat (r, &sb) == -1
3495           && mkdir (r, 0755) == -1
3496           /* The directory might have been made by another process.  */
3497           && errno != EEXIST)
3498         fatal_error ("can't create directory %s: %m", r);
3499
3500       *s = sep;
3501       /* Skip consecutive separators.  */
3502       for (dname = s + 1; *dname && *dname == sep; ++dname)
3503         ;
3504     }
3505
3506   return r;
3507 }
3508
3509 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3510    The output .class file name is make_class_file_name(CLAS). */
3511
3512 void
3513 write_classfile (tree clas)
3514 {
3515   struct obstack *work = &temporary_obstack;
3516   struct jcf_partial state[1];
3517   char *class_file_name = make_class_file_name (clas);
3518   struct chunk *chunks;
3519
3520   if (class_file_name != NULL)
3521     {
3522       FILE *stream;
3523       char *temporary_file_name;
3524
3525       /* The .class file is initially written to a ".tmp" file so that
3526          if multiple instances of the compiler are running at once
3527          they do not see partially formed class files. */
3528       temporary_file_name = concat (class_file_name, ".tmp", NULL);
3529       stream = fopen (temporary_file_name, "wb");
3530       if (stream == NULL)
3531         fatal_error ("can't open %s for writing: %m", temporary_file_name);
3532
3533       jcf_dependency_add_target (class_file_name);
3534       init_jcf_state (state, work);
3535       chunks = generate_classfile (clas, state);
3536       write_chunks (stream, chunks);
3537       if (fclose (stream))
3538         fatal_error ("error closing %s: %m", temporary_file_name);
3539
3540       /* If a file named by the string pointed to by `new' exists
3541          prior to the call to the `rename' function, the behavior
3542          is implementation-defined.  ISO 9899-1990 7.9.4.2.
3543
3544          For example, on Win32 with MSVCRT, it is an error. */
3545
3546       unlink (class_file_name);
3547
3548       if (rename (temporary_file_name, class_file_name) == -1)
3549         {
3550           remove (temporary_file_name);
3551           fatal_error ("can't create %s: %m", class_file_name);
3552         }
3553       free (temporary_file_name);
3554       free (class_file_name);
3555     }
3556   release_jcf_state (state);
3557 }
3558
3559 /* TODO:
3560    string concatenation
3561    synchronized statement
3562    */
3563
3564 #include "gt-java-jcf-write.h"