OSDN Git Service

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