OSDN Git Service

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