OSDN Git Service

* parse.y (java_check_regular_methods): Typo fixes. Call
[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         /* FIXME Should also use fconst_2 for 2.0f.
1466            Also, should use iconst_2/ldc followed by i2f/i2d
1467            for other float/double when the value is a small integer. */
1468         else
1469           {
1470             offset = find_constant_index (exp, state);
1471             if (prec == 1)
1472               push_constant1 (offset, state);
1473             else
1474               push_constant2 (offset, state);
1475           }
1476         NOTE_PUSH (prec);
1477       }
1478       break;
1479     case STRING_CST:
1480       push_constant1 (find_string_constant (&state->cpool, exp), state);
1481       NOTE_PUSH (1);
1482       break;
1483     case VAR_DECL:
1484       if (TREE_STATIC (exp))
1485         {
1486           field_op (exp, OPCODE_getstatic, state);
1487           NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1488           break;
1489         }
1490       /* ... fall through ... */
1491     case PARM_DECL:
1492       emit_load (exp, state);
1493       break;
1494     case NON_LVALUE_EXPR:
1495     case INDIRECT_REF:
1496       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1497       break;
1498     case ARRAY_REF:
1499       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1500       generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1501       if (target != IGNORE_TARGET)
1502         {
1503           jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1504           RESERVE(1);
1505           OP1 (jopcode);
1506           if (! TYPE_IS_WIDE (type))
1507             NOTE_POP (1);
1508         }
1509       break;
1510     case COMPONENT_REF:
1511       {
1512         tree obj = TREE_OPERAND (exp, 0);
1513         tree field = TREE_OPERAND (exp, 1);
1514         int is_static = FIELD_STATIC (field);
1515         generate_bytecode_insns (obj,
1516                                  is_static ? IGNORE_TARGET : target, state);
1517         if (target != IGNORE_TARGET)
1518           {
1519             if (DECL_NAME (field) == length_identifier_node && !is_static
1520                 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1521               {
1522                 RESERVE (1);
1523                 OP1 (OPCODE_arraylength);
1524               }
1525             else
1526               {
1527                 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1528                           state);
1529                 if (! is_static)
1530                   NOTE_POP (1);
1531                 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1532               }
1533           }
1534       }
1535       break;
1536     case TRUTH_ANDIF_EXPR:
1537     case TRUTH_ORIF_EXPR:
1538     case EQ_EXPR:
1539     case NE_EXPR:
1540     case GT_EXPR:
1541     case LT_EXPR:
1542     case GE_EXPR:
1543     case LE_EXPR:
1544       {
1545         struct jcf_block *then_label = gen_jcf_label (state);
1546         struct jcf_block *else_label = gen_jcf_label (state);
1547         struct jcf_block *end_label = gen_jcf_label (state);
1548         generate_bytecode_conditional (exp,
1549                                        then_label, else_label, 1, state);
1550         define_jcf_label (then_label, state);
1551         push_int_const (1, state);
1552         emit_goto (end_label, state);
1553         define_jcf_label (else_label, state);
1554         push_int_const (0, state);
1555         define_jcf_label (end_label, state);
1556         NOTE_PUSH (1);
1557       }
1558       break;
1559     case COND_EXPR:
1560       {
1561         struct jcf_block *then_label = gen_jcf_label (state);
1562         struct jcf_block *else_label = gen_jcf_label (state);
1563         struct jcf_block *end_label = gen_jcf_label (state);
1564         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1565                                        then_label, else_label, 1, state);
1566         define_jcf_label (then_label, state);
1567         generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1568         if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1569             /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1570             || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1571           emit_goto (end_label, state);
1572         define_jcf_label (else_label, state);
1573         generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1574         define_jcf_label (end_label, state);
1575         /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1576         if (TREE_TYPE (exp) != void_type_node)
1577           NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1578       }
1579       break;
1580     case CASE_EXPR:
1581       {
1582         struct jcf_switch_state *sw_state = state->sw_state;
1583         struct jcf_relocation *reloc
1584           = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1585         HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1586         reloc->kind = 0;
1587         reloc->label = get_jcf_label_here (state);
1588         reloc->offset = case_value;
1589         reloc->next = sw_state->cases;
1590         sw_state->cases = reloc;
1591         if (sw_state->num_cases == 0)
1592           {
1593             sw_state->min_case = case_value;
1594             sw_state->max_case = case_value;
1595           }
1596         else
1597           {
1598             if (case_value < sw_state->min_case)
1599               sw_state->min_case = case_value;
1600             if (case_value > sw_state->max_case)
1601               sw_state->max_case = case_value;
1602           }
1603         sw_state->num_cases++;
1604       }
1605       break;
1606     case DEFAULT_EXPR:
1607       state->sw_state->default_label = get_jcf_label_here (state);
1608       break;
1609
1610     case SWITCH_EXPR:
1611       {
1612         /* The SWITCH_EXPR has three parts, generated in the following order:
1613            1.  the switch_expression (the value used to select the correct case);
1614            2.  the switch_body;
1615            3.  the switch_instruction (the tableswitch/loopupswitch instruction.).
1616            After code generation, we will re-order them in the order 1, 3, 2.
1617            This is to avoid any extra GOTOs. */
1618         struct jcf_switch_state sw_state;
1619         struct jcf_block *expression_last; /* Last block of the switch_expression. */
1620         struct jcf_block *body_last; /* Last block of the switch_body. */
1621         struct jcf_block *switch_instruction;  /* First block of switch_instruction. */
1622         struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1623         struct jcf_block *body_block;
1624         int switch_length;
1625         sw_state.prev = state->sw_state;
1626         state->sw_state = &sw_state;
1627         sw_state.cases = NULL;
1628         sw_state.num_cases = 0;
1629         sw_state.default_label = NULL;
1630         generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1631         expression_last = state->last_block;
1632         /* Force a new block here.  */
1633         body_block = gen_jcf_label (state);
1634         define_jcf_label (body_block, state);
1635         generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1636         body_last = state->last_block;
1637
1638         switch_instruction = gen_jcf_label (state);
1639         define_jcf_label (switch_instruction, state);
1640         if (sw_state.default_label == NULL)
1641           sw_state.default_label = gen_jcf_label (state);
1642
1643         if (sw_state.num_cases <= 1)
1644           {
1645             if (sw_state.num_cases == 0)
1646               {
1647                 emit_pop (1, state);
1648                 NOTE_POP (1);
1649               }
1650             else
1651               {
1652                 push_int_const (sw_state.cases->offset, state);
1653                 NOTE_PUSH (1);
1654                 emit_if (sw_state.cases->label,
1655                          OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1656               }
1657             emit_goto (sw_state.default_label, state);
1658           }
1659         else
1660           {
1661             HOST_WIDE_INT i;
1662             unsigned HOST_WIDE_INT delta;
1663             /* Copy the chain of relocs into a sorted array. */
1664             struct jcf_relocation **relocs
1665               = xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1666             /* The relocs arrays is a buffer with a gap.
1667                The assumption is that cases will normally come in "runs". */
1668             int gap_start = 0;
1669             int gap_end = sw_state.num_cases;
1670             struct jcf_relocation *reloc;
1671             for (reloc = sw_state.cases;  reloc != NULL;  reloc = reloc->next)
1672               {
1673                 HOST_WIDE_INT case_value = reloc->offset;
1674                 while (gap_end < sw_state.num_cases)
1675                   {
1676                     struct jcf_relocation *end = relocs[gap_end];
1677                     if (case_value <= end->offset)
1678                       break;
1679                     relocs[gap_start++] = end;
1680                     gap_end++;
1681                   }
1682                 while (gap_start > 0)
1683                   {
1684                     struct jcf_relocation *before = relocs[gap_start-1];
1685                     if (case_value >= before->offset)
1686                       break;
1687                     relocs[--gap_end] = before;
1688                     gap_start--;
1689                   }
1690                 relocs[gap_start++] = reloc;
1691                 /* Note we don't check for duplicates.  This is
1692                    handled by the parser.  */
1693               }
1694
1695             /* We could have DELTA < 0 if sw_state.min_case is
1696                something like Integer.MIN_VALUE.  That is why delta is
1697                unsigned.  */
1698             delta = sw_state.max_case - sw_state.min_case;
1699             if (2 * (unsigned) sw_state.num_cases >= delta)
1700               { /* Use tableswitch. */
1701                 int index = 0;
1702                 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1703                 OP1 (OPCODE_tableswitch);
1704                 emit_reloc (RELOCATION_VALUE_0, 
1705                             SWITCH_ALIGN_RELOC, NULL, state);
1706                 emit_switch_reloc (sw_state.default_label, state);
1707                 OP4 (sw_state.min_case);
1708                 OP4 (sw_state.max_case);
1709                 for (i = sw_state.min_case; ; )
1710                   {
1711                     reloc = relocs[index];
1712                     if (i == reloc->offset)
1713                       {
1714                         emit_case_reloc (reloc, state);
1715                         if (i == sw_state.max_case)
1716                           break;
1717                         index++;
1718                       }
1719                     else
1720                       emit_switch_reloc (sw_state.default_label, state);
1721                     i++;
1722                   }
1723               }
1724             else
1725               { /* Use lookupswitch. */
1726                 RESERVE(9 + 8 * sw_state.num_cases);
1727                 OP1 (OPCODE_lookupswitch);
1728                 emit_reloc (RELOCATION_VALUE_0,
1729                             SWITCH_ALIGN_RELOC, NULL, state);
1730                 emit_switch_reloc (sw_state.default_label, state);
1731                 OP4 (sw_state.num_cases);
1732                 for (i = 0;  i < sw_state.num_cases;  i++)
1733                   {
1734                     struct jcf_relocation *reloc = relocs[i];
1735                     OP4 (reloc->offset);
1736                     emit_case_reloc (reloc, state);
1737                   }
1738               }
1739             free (relocs);
1740           }
1741
1742         instruction_last = state->last_block;
1743         if (sw_state.default_label->pc < 0)
1744           define_jcf_label (sw_state.default_label, state);
1745         else /* Force a new block. */
1746           sw_state.default_label = get_jcf_label_here (state);
1747         /* Now re-arrange the blocks so the switch_instruction
1748            comes before the switch_body. */
1749         switch_length = state->code_length - switch_instruction->pc;
1750         switch_instruction->pc = body_block->pc;
1751         instruction_last->next = body_block;
1752         instruction_last->v.chunk->next = body_block->v.chunk;
1753         expression_last->next = switch_instruction;
1754         expression_last->v.chunk->next = switch_instruction->v.chunk;
1755         body_last->next = sw_state.default_label;
1756         body_last->v.chunk->next = NULL;
1757         state->chunk = body_last->v.chunk;
1758         for (;  body_block != sw_state.default_label;  body_block = body_block->next)
1759           body_block->pc += switch_length;
1760
1761         state->sw_state = sw_state.prev;
1762         break;
1763       }
1764
1765     case RETURN_EXPR:
1766       exp = TREE_OPERAND (exp, 0);
1767       if (exp == NULL_TREE)
1768         exp = empty_stmt_node;
1769       else if (TREE_CODE (exp) != MODIFY_EXPR) 
1770         abort ();
1771       else
1772         exp = TREE_OPERAND (exp, 1);
1773       generate_bytecode_return (exp, state);
1774       break;
1775     case LABELED_BLOCK_EXPR:
1776       {
1777         struct jcf_block *end_label = gen_jcf_label (state);
1778         end_label->next = state->labeled_blocks;
1779         state->labeled_blocks = end_label;
1780         end_label->pc = PENDING_EXIT_PC;
1781         end_label->u.labeled_block = exp;
1782         if (LABELED_BLOCK_BODY (exp))
1783           generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1784         if (state->labeled_blocks != end_label)
1785           abort();
1786         state->labeled_blocks = end_label->next;
1787         define_jcf_label (end_label, state);
1788       }
1789       break;
1790     case LOOP_EXPR:
1791       {
1792         tree body = TREE_OPERAND (exp, 0);
1793 #if 0
1794         if (TREE_CODE (body) == COMPOUND_EXPR
1795             && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1796           {
1797             /* Optimize:  H: if (TEST) GOTO L; BODY; GOTO H; L:
1798                to:  GOTO L;  BODY;  L:  if (!TEST) GOTO L; */
1799             struct jcf_block *head_label;
1800             struct jcf_block *body_label;
1801             struct jcf_block *end_label = gen_jcf_label (state);
1802             struct jcf_block *exit_label = state->labeled_blocks;
1803             head_label = gen_jcf_label (state);
1804             emit_goto (head_label, state);
1805             body_label = get_jcf_label_here (state);
1806             generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1807             define_jcf_label (head_label, state);
1808             generate_bytecode_conditional (TREE_OPERAND (body, 0),
1809                                            end_label, body_label, 1, state);
1810             define_jcf_label (end_label, state);
1811           }
1812         else
1813 #endif
1814           {
1815             struct jcf_block *head_label = get_jcf_label_here (state);
1816             generate_bytecode_insns (body, IGNORE_TARGET, state);
1817             if (CAN_COMPLETE_NORMALLY (body))
1818               emit_goto (head_label, state);
1819           }
1820       }
1821       break;
1822     case EXIT_EXPR:
1823       {
1824         struct jcf_block *label = state->labeled_blocks;
1825         struct jcf_block *end_label = gen_jcf_label (state);
1826         generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1827                                        label, end_label, 0, state);
1828         define_jcf_label (end_label, state);
1829       }
1830       break;
1831     case EXIT_BLOCK_EXPR:
1832       {
1833         struct jcf_block *label = state->labeled_blocks;
1834         if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1835         while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1836           label = label->next;
1837         call_cleanups (label, state);
1838         emit_goto (label, state);
1839       }
1840       break;
1841
1842     case PREDECREMENT_EXPR:  value = -1; post_op = 0;  goto increment;
1843     case PREINCREMENT_EXPR:  value =  1; post_op = 0;  goto increment;
1844     case POSTDECREMENT_EXPR: value = -1; post_op = 1;  goto increment;
1845     case POSTINCREMENT_EXPR: value =  1; post_op = 1;  goto increment;
1846     increment:
1847
1848       arg = TREE_OPERAND (exp, 1);
1849       exp = TREE_OPERAND (exp, 0);
1850       type = TREE_TYPE (exp);
1851       size = TYPE_IS_WIDE (type) ? 2 : 1;
1852       if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1853           && ! TREE_STATIC (exp)
1854           && TREE_CODE (type) == INTEGER_TYPE
1855           && TYPE_PRECISION (type) == 32)
1856         {
1857           if (target != IGNORE_TARGET && post_op)
1858             emit_load (exp, state);
1859           emit_iinc (exp, value, state);
1860           if (target != IGNORE_TARGET && ! post_op)
1861             emit_load (exp, state);
1862           break;
1863         }
1864       if (TREE_CODE (exp) == COMPONENT_REF)
1865         {
1866           generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1867           emit_dup (1, 0, state);
1868           /* Stack:  ..., objectref, objectref. */
1869           field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1870           NOTE_PUSH (size-1);
1871           /* Stack:  ..., objectref, oldvalue. */
1872           offset = 1;
1873         }
1874       else if (TREE_CODE (exp) == ARRAY_REF)
1875         {
1876           generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1877           generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1878           emit_dup (2, 0, state);
1879           /* Stack:  ..., array, index, array, index. */
1880           jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1881           RESERVE(1);
1882           OP1 (jopcode);
1883           NOTE_POP (2-size);
1884           /* Stack:  ..., array, index, oldvalue. */
1885           offset = 2;
1886         }
1887       else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1888         {
1889           generate_bytecode_insns (exp, STACK_TARGET, state);
1890           /* Stack:  ..., oldvalue. */
1891           offset = 0;
1892         }
1893       else
1894         abort ();
1895
1896       if (target != IGNORE_TARGET && post_op)
1897         emit_dup (size, offset, state);
1898       /* Stack, if ARRAY_REF:  ..., [result, ] array, index, oldvalue. */
1899       /* Stack, if COMPONENT_REF:  ..., [result, ] objectref, oldvalue. */
1900       /* Stack, otherwise:  ..., [result, ] oldvalue. */
1901       generate_bytecode_insns (arg, STACK_TARGET, state);
1902       emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
1903                   + adjust_typed_op (type, 3),
1904                   type, state);
1905       if (target != IGNORE_TARGET && ! post_op)
1906         emit_dup (size, offset, state);
1907       /* Stack, if ARRAY_REF:  ..., [result, ] array, index, newvalue. */
1908       /* Stack, if COMPONENT_REF:  ..., [result, ] objectref, newvalue. */
1909       /* Stack, otherwise:  ..., [result, ] newvalue. */
1910       goto finish_assignment;
1911
1912     case MODIFY_EXPR:
1913       {
1914         tree lhs = TREE_OPERAND (exp, 0);
1915         tree rhs = TREE_OPERAND (exp, 1);
1916         int offset = 0;
1917
1918         /* See if we can use the iinc instruction. */
1919         if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
1920             && ! TREE_STATIC (lhs)
1921             && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
1922             && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
1923             && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
1924           {
1925             tree arg0 = TREE_OPERAND (rhs, 0);
1926             tree arg1 = TREE_OPERAND (rhs, 1);
1927             HOST_WIDE_INT min_value = -32768;
1928             HOST_WIDE_INT max_value = 32767;
1929             if (TREE_CODE (rhs) == MINUS_EXPR)
1930               {
1931                 min_value++;
1932                 max_value++;
1933               }
1934             else if (arg1 == lhs)
1935               {
1936                 arg0 = arg1;
1937                 arg1 = TREE_OPERAND (rhs, 0);
1938               }
1939             if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
1940               {
1941                 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
1942                 value = TREE_INT_CST_LOW (arg1);
1943                 if ((hi_value == 0 && value <= max_value)
1944                     || (hi_value == -1 && value >= min_value))
1945                   {
1946                     if (TREE_CODE (rhs) == MINUS_EXPR)
1947                       value = -value;
1948                     emit_iinc (lhs, value, state);
1949                     if (target != IGNORE_TARGET)
1950                       emit_load (lhs, state);
1951                     break;
1952                   }
1953               }
1954           }
1955
1956         if (TREE_CODE (lhs) == COMPONENT_REF)
1957           {
1958             generate_bytecode_insns (TREE_OPERAND (lhs, 0),
1959                                      STACK_TARGET, state);
1960             offset = 1;
1961           }
1962         else if (TREE_CODE (lhs) == ARRAY_REF)
1963           {
1964             generate_bytecode_insns (TREE_OPERAND(lhs, 0),
1965                                      STACK_TARGET, state);
1966             generate_bytecode_insns (TREE_OPERAND(lhs, 1),
1967                                      STACK_TARGET, state);
1968             offset = 2;
1969           }
1970         else
1971           offset = 0;
1972
1973         /* If the rhs is a binary expression and the left operand is
1974            `==' to the lhs then we have an OP= expression.  In this
1975            case we must do some special processing.  */
1976         if (TREE_CODE_CLASS (TREE_CODE (rhs)) == '2'
1977             && lhs == TREE_OPERAND (rhs, 0))
1978           {
1979             if (TREE_CODE (lhs) == COMPONENT_REF)
1980               {
1981                 tree field = TREE_OPERAND (lhs, 1);
1982                 if (! FIELD_STATIC (field))
1983                   {
1984                     /* Duplicate the object reference so we can get
1985                        the field.  */
1986                     emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
1987                     NOTE_POP (1);
1988                   }
1989                 field_op (field, (FIELD_STATIC (field)
1990                                   ? OPCODE_getstatic
1991                                   : OPCODE_getfield),
1992                           state);
1993
1994                 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1995               }
1996             else if (TREE_CODE (lhs) == VAR_DECL
1997                      || TREE_CODE (lhs) == PARM_DECL)
1998               {
1999                 if (FIELD_STATIC (lhs))
2000                   {
2001                     field_op (lhs, OPCODE_getstatic, state);
2002                     NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2003                   }
2004                 else
2005                   emit_load (lhs, state);
2006               }
2007             else if (TREE_CODE (lhs) == ARRAY_REF)
2008               {
2009                 /* Duplicate the array and index, which are on the
2010                    stack, so that we can load the old value.  */
2011                 emit_dup (2, 0, state);
2012                 NOTE_POP (2);
2013                 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
2014                 RESERVE (1);
2015                 OP1 (jopcode);
2016                 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2017               }
2018             else
2019               abort ();
2020
2021             /* This function correctly handles the case where the LHS
2022                of a binary expression is NULL_TREE.  */
2023             rhs = build (TREE_CODE (rhs), TREE_TYPE (rhs),
2024                          NULL_TREE, TREE_OPERAND (rhs, 1));
2025           }
2026
2027         generate_bytecode_insns (rhs, STACK_TARGET, state);
2028         if (target != IGNORE_TARGET)
2029           emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2030         exp = lhs;
2031       }
2032       /* FALLTHROUGH */
2033
2034     finish_assignment:
2035       if (TREE_CODE (exp) == COMPONENT_REF)
2036         {
2037           tree field = TREE_OPERAND (exp, 1);
2038           if (! FIELD_STATIC (field))
2039             NOTE_POP (1);
2040           field_op (field,
2041                     FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2042                     state);
2043
2044           NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2045         }
2046       else if (TREE_CODE (exp) == VAR_DECL
2047                || TREE_CODE (exp) == PARM_DECL)
2048         {
2049           if (FIELD_STATIC (exp))
2050             {
2051               field_op (exp, OPCODE_putstatic, state);
2052               NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2053             }
2054           else
2055             emit_store (exp, state);
2056         }
2057       else if (TREE_CODE (exp) == ARRAY_REF)
2058         {
2059           jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2060           RESERVE (1);
2061           OP1 (jopcode);
2062           NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2063         }
2064       else
2065         abort ();
2066       break;
2067     case PLUS_EXPR:
2068       jopcode = OPCODE_iadd;
2069       goto binop;
2070     case MINUS_EXPR:
2071       jopcode = OPCODE_isub;
2072       goto binop;
2073     case MULT_EXPR:
2074       jopcode = OPCODE_imul;
2075       goto binop;
2076     case TRUNC_DIV_EXPR:
2077     case RDIV_EXPR:
2078       jopcode = OPCODE_idiv;
2079       goto binop;
2080     case TRUNC_MOD_EXPR:
2081       jopcode = OPCODE_irem;
2082       goto binop;
2083     case LSHIFT_EXPR:   jopcode = OPCODE_ishl;   goto binop;
2084     case RSHIFT_EXPR:   jopcode = OPCODE_ishr;   goto binop;
2085     case URSHIFT_EXPR:  jopcode = OPCODE_iushr;  goto binop;
2086     case TRUTH_AND_EXPR:
2087     case BIT_AND_EXPR:  jopcode = OPCODE_iand;   goto binop;
2088     case TRUTH_OR_EXPR:
2089     case BIT_IOR_EXPR:  jopcode = OPCODE_ior;    goto binop;
2090     case TRUTH_XOR_EXPR:
2091     case BIT_XOR_EXPR:  jopcode = OPCODE_ixor;   goto binop;
2092     binop:
2093     {
2094       tree arg0 = TREE_OPERAND (exp, 0);
2095       tree arg1 = TREE_OPERAND (exp, 1);
2096       jopcode += adjust_typed_op (type, 3);
2097       if (arg0 == arg1 && TREE_CODE (arg0) == SAVE_EXPR)
2098         {
2099           /* fold may (e.g) convert 2*x to x+x. */
2100           generate_bytecode_insns (TREE_OPERAND (arg0, 0), target, state);
2101           emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2102         }
2103       else
2104         {
2105           /* ARG0 will be NULL_TREE if we're handling an `OP='
2106              expression.  In this case the stack already holds the
2107              LHS.  See the MODIFY_EXPR case.  */
2108           if (arg0 != NULL_TREE)
2109             generate_bytecode_insns (arg0, target, state);
2110           if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2111             arg1 = convert (int_type_node, arg1);
2112           generate_bytecode_insns (arg1, target, state);
2113         }
2114       /* For most binary operations, both operands and the result have the
2115          same type.  Shift operations are different.  Using arg1's type
2116          gets us the correct SP adjustment in all cases. */
2117       if (target == STACK_TARGET)
2118         emit_binop (jopcode, TREE_TYPE (arg1), state);
2119       break;
2120     }
2121     case TRUTH_NOT_EXPR:
2122     case BIT_NOT_EXPR:
2123       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2124       if (target == STACK_TARGET)
2125         {
2126           int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2127           push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state); 
2128           RESERVE (2);
2129           if (is_long)
2130             OP1 (OPCODE_i2l);
2131           NOTE_PUSH (1 + is_long);
2132           OP1 (OPCODE_ixor + is_long);
2133           NOTE_POP (1 + is_long);
2134         }
2135       break;
2136     case NEGATE_EXPR:
2137       jopcode = OPCODE_ineg;
2138       jopcode += adjust_typed_op (type, 3);
2139       generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2140       if (target == STACK_TARGET)
2141         emit_unop (jopcode, type, state);
2142       break;
2143     case INSTANCEOF_EXPR:
2144       {
2145         int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2146         generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2147         RESERVE (3);
2148         OP1 (OPCODE_instanceof);
2149         OP2 (index);
2150       }
2151       break;
2152     case SAVE_EXPR:
2153       generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2154       break;
2155     case CONVERT_EXPR:
2156     case NOP_EXPR:
2157     case FLOAT_EXPR:
2158     case FIX_TRUNC_EXPR:
2159       {
2160         tree src = TREE_OPERAND (exp, 0);
2161         tree src_type = TREE_TYPE (src);
2162         tree dst_type = TREE_TYPE (exp);
2163         generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2164         if (target == IGNORE_TARGET || src_type == dst_type)
2165           break;
2166         if (TREE_CODE (dst_type) == POINTER_TYPE)
2167           {
2168             if (TREE_CODE (exp) == CONVERT_EXPR)
2169               {
2170                 int index = find_class_constant (&state->cpool, 
2171                                                  TREE_TYPE (dst_type));
2172                 RESERVE (3);
2173                 OP1 (OPCODE_checkcast);
2174                 OP2 (index);
2175               }
2176           }
2177         else /* Convert numeric types. */
2178           {
2179             int wide_src = TYPE_PRECISION (src_type) > 32;
2180             int wide_dst = TYPE_PRECISION (dst_type) > 32;
2181             NOTE_POP (1 + wide_src);
2182             RESERVE (1);
2183             if (TREE_CODE (dst_type) == REAL_TYPE)
2184               {
2185                 if (TREE_CODE (src_type) == REAL_TYPE)
2186                   OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2187                 else if (TYPE_PRECISION (src_type) == 64)
2188                   OP1 (OPCODE_l2f + wide_dst);
2189                 else
2190                   OP1 (OPCODE_i2f + wide_dst);
2191               }
2192             else /* Convert to integral type. */
2193               {
2194                 if (TREE_CODE (src_type) == REAL_TYPE)
2195                   OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2196                 else if (wide_dst)
2197                   OP1 (OPCODE_i2l);
2198                 else if (wide_src)
2199                   OP1 (OPCODE_l2i);
2200                 if (TYPE_PRECISION (dst_type) < 32)
2201                   {
2202                     RESERVE (1);
2203                     /* Already converted to int, if needed. */
2204                     if (TYPE_PRECISION (dst_type) <= 8)
2205                       OP1 (OPCODE_i2b);
2206                     else if (TREE_UNSIGNED (dst_type))
2207                       OP1 (OPCODE_i2c);
2208                     else
2209                       OP1 (OPCODE_i2s);
2210                   }
2211               }
2212             NOTE_PUSH (1 + wide_dst);
2213           }
2214       }
2215       break;
2216
2217     case TRY_EXPR:
2218       {
2219         tree try_clause = TREE_OPERAND (exp, 0);
2220         struct jcf_block *start_label = get_jcf_label_here (state);
2221         struct jcf_block *end_label;  /* End of try clause. */
2222         struct jcf_block *finished_label = gen_jcf_label (state);
2223         tree clause = TREE_OPERAND (exp, 1);
2224         if (target != IGNORE_TARGET)
2225           abort ();
2226         generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2227         end_label = get_jcf_label_here (state);
2228         if (end_label == start_label)
2229           break;
2230         if (CAN_COMPLETE_NORMALLY (try_clause))
2231           emit_goto (finished_label, state);
2232         while (clause != NULL_TREE)
2233           {
2234             tree catch_clause = TREE_OPERAND (clause, 0);
2235             tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2236             struct jcf_handler *handler = alloc_handler (start_label,
2237                                                          end_label, state);
2238             if (exception_decl == NULL_TREE)
2239               handler->type = NULL_TREE;
2240             else
2241               handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2242             generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2243             clause = TREE_CHAIN (clause);
2244             if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2245               emit_goto (finished_label, state);
2246           }
2247         define_jcf_label (finished_label, state);
2248       }
2249       break;
2250
2251     case TRY_FINALLY_EXPR:
2252       {
2253         struct jcf_block *finished_label = NULL;
2254         struct jcf_block *finally_label, *start_label, *end_label;
2255         struct jcf_handler *handler;
2256         tree try_block = TREE_OPERAND (exp, 0);
2257         tree finally = TREE_OPERAND (exp, 1);
2258         tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2259
2260         tree exception_type;
2261
2262         finally_label = gen_jcf_label (state);
2263         start_label = get_jcf_label_here (state);
2264         /* If the `finally' clause can complete normally, we emit it
2265            as a subroutine and let the other clauses call it via
2266            `jsr'.  If it can't complete normally, then we simply emit
2267            `goto's directly to it.  */
2268         if (CAN_COMPLETE_NORMALLY (finally))
2269           {
2270             finally_label->pc = PENDING_CLEANUP_PC;
2271             finally_label->next = state->labeled_blocks;
2272             state->labeled_blocks = finally_label;
2273             state->num_finalizers++;
2274           }
2275
2276         generate_bytecode_insns (try_block, target, state);
2277
2278         if (CAN_COMPLETE_NORMALLY (finally))
2279           {
2280             if (state->labeled_blocks != finally_label)
2281               abort();
2282             state->labeled_blocks = finally_label->next;
2283           }
2284         end_label = get_jcf_label_here (state);
2285
2286         if (end_label == start_label)
2287           {
2288             state->num_finalizers--;
2289             define_jcf_label (finally_label, state);
2290             generate_bytecode_insns (finally, IGNORE_TARGET, state);
2291             break;
2292           }
2293
2294         if (CAN_COMPLETE_NORMALLY (finally))
2295           {
2296             return_link = build_decl (VAR_DECL, NULL_TREE,
2297                                       return_address_type_node);
2298             finished_label = gen_jcf_label (state);
2299           }
2300
2301         if (CAN_COMPLETE_NORMALLY (try_block))
2302           {
2303             if (CAN_COMPLETE_NORMALLY (finally))
2304               {
2305                 emit_jsr (finally_label, state);
2306                 emit_goto (finished_label, state);
2307               }
2308             else
2309               emit_goto (finally_label, state);
2310           }
2311
2312         /* Handle exceptions.  */
2313
2314         exception_type = build_pointer_type (throwable_type_node);
2315         if (CAN_COMPLETE_NORMALLY (finally))
2316           {
2317             /* We're going to generate a subroutine, so we'll need to
2318                save and restore the exception around the `jsr'.  */ 
2319             exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2320             localvar_alloc (return_link, state);
2321           }
2322         handler = alloc_handler (start_label, end_label, state);
2323         handler->type = NULL_TREE;
2324         if (CAN_COMPLETE_NORMALLY (finally))
2325           {
2326             localvar_alloc (exception_decl, state);
2327             NOTE_PUSH (1);
2328             emit_store (exception_decl, state);
2329             emit_jsr (finally_label, state);
2330             emit_load (exception_decl, state);
2331             RESERVE (1);
2332             OP1 (OPCODE_athrow);
2333             NOTE_POP (1);
2334           }
2335         else
2336           {
2337             /* We're not generating a subroutine.  In this case we can
2338                simply have the exception handler pop the exception and
2339                then fall through to the `finally' block.  */
2340             NOTE_PUSH (1);
2341             emit_pop (1, state);
2342             NOTE_POP (1);
2343           }
2344
2345         /* The finally block.  If we're generating a subroutine, first
2346            save return PC into return_link.  Otherwise, just generate
2347            the code for the `finally' block.  */
2348         define_jcf_label (finally_label, state);
2349         if (CAN_COMPLETE_NORMALLY (finally))
2350           {
2351             NOTE_PUSH (1);
2352             emit_store (return_link, state);
2353           }
2354
2355         generate_bytecode_insns (finally, IGNORE_TARGET, state);
2356         if (CAN_COMPLETE_NORMALLY (finally))
2357           {
2358             maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2359             maybe_free_localvar (exception_decl, state, 1);
2360             maybe_free_localvar (return_link, state, 1);
2361             define_jcf_label (finished_label, state);
2362           }
2363       }
2364       break;
2365     case THROW_EXPR:
2366       generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2367       RESERVE (1);
2368       OP1 (OPCODE_athrow);
2369       break;
2370     case NEW_ARRAY_INIT:
2371       {
2372         tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2373         tree array_type = TREE_TYPE (TREE_TYPE (exp));
2374         tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2375         HOST_WIDE_INT length = java_array_type_length (array_type);
2376         if (target == IGNORE_TARGET)
2377           {
2378             for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values))
2379               generate_bytecode_insns (TREE_VALUE (values), target, state);
2380             break;
2381           }
2382         push_int_const (length, state);
2383         NOTE_PUSH (1);
2384         RESERVE (3);
2385         if (JPRIMITIVE_TYPE_P (element_type))
2386           {
2387             int atype = encode_newarray_type (element_type);
2388             OP1 (OPCODE_newarray);
2389             OP1 (atype);
2390           }
2391         else
2392           {
2393             int index = find_class_constant (&state->cpool,
2394                                              TREE_TYPE (element_type));
2395             OP1 (OPCODE_anewarray);
2396             OP2 (index);
2397           }
2398         offset = 0;
2399         jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2400         for ( ;  values != NULL_TREE;  values = TREE_CHAIN (values), offset++)
2401           {
2402             int save_SP = state->code_SP;
2403             emit_dup (1, 0, state);
2404             push_int_const (offset, state);
2405             NOTE_PUSH (1);
2406             generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2407             RESERVE (1);
2408             OP1 (jopcode);
2409             state->code_SP = save_SP;
2410           }
2411       }
2412       break;
2413     case JAVA_EXC_OBJ_EXPR:
2414       NOTE_PUSH (1);  /* Pushed by exception system. */
2415       break;
2416     case NEW_CLASS_EXPR:
2417       {
2418         tree class = TREE_TYPE (TREE_TYPE (exp));
2419         int need_result = target != IGNORE_TARGET;
2420         int index = find_class_constant (&state->cpool, class);
2421         RESERVE (4);
2422         OP1 (OPCODE_new);
2423         OP2 (index);
2424         if (need_result)
2425           OP1 (OPCODE_dup);
2426         NOTE_PUSH (1 + need_result);
2427       }
2428       /* ... fall though ... */
2429     case CALL_EXPR:
2430       {
2431         tree f = TREE_OPERAND (exp, 0);
2432         tree x = TREE_OPERAND (exp, 1);
2433         int save_SP = state->code_SP;
2434         int nargs;
2435         if (TREE_CODE (f) == ADDR_EXPR)
2436           f = TREE_OPERAND (f, 0);
2437         if (f == soft_newarray_node)
2438           {
2439             int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2440             generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2441                                      STACK_TARGET, state);
2442             RESERVE (2);
2443             OP1 (OPCODE_newarray);
2444             OP1 (type_code);
2445             break;
2446           }
2447         else if (f == soft_multianewarray_node)
2448           {
2449             int ndims;
2450             int idim;
2451             int index = find_class_constant (&state->cpool,
2452                                              TREE_TYPE (TREE_TYPE (exp)));
2453             x = TREE_CHAIN (x);  /* Skip class argument. */
2454             ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2455             for (idim = ndims;  --idim >= 0; )
2456               {
2457                 x = TREE_CHAIN (x);
2458                 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2459               }
2460             RESERVE (4);
2461             OP1 (OPCODE_multianewarray);
2462             OP2 (index);
2463             OP1 (ndims);
2464             break;
2465           }
2466         else if (f == soft_anewarray_node)
2467           {
2468             tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2469             int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2470             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2471             RESERVE (3);
2472             OP1 (OPCODE_anewarray);
2473             OP2 (index);
2474             break;
2475           }
2476         else if (f == soft_monitorenter_node
2477                  || f == soft_monitorexit_node
2478                  || f == throw_node)
2479           {
2480             if (f == soft_monitorenter_node)
2481               op = OPCODE_monitorenter;
2482             else if (f == soft_monitorexit_node)
2483               op = OPCODE_monitorexit;
2484             else
2485               op = OPCODE_athrow;
2486             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2487             RESERVE (1);
2488             OP1 (op);
2489             NOTE_POP (1);
2490             break;
2491           }
2492         for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
2493           {
2494             generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2495           }
2496         nargs = state->code_SP - save_SP;
2497         state->code_SP = save_SP;
2498         if (f == soft_fmod_node)
2499           {
2500             RESERVE (1);
2501             OP1 (OPCODE_drem);
2502             NOTE_PUSH (2);
2503             break;
2504           }
2505         if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2506           NOTE_POP (1);  /* Pop implicit this. */
2507         if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2508           {
2509             tree context = DECL_CONTEXT (f);
2510             int index, interface = 0;
2511             RESERVE (5);
2512             if (METHOD_STATIC (f))
2513               OP1 (OPCODE_invokestatic);
2514             else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2515                 || METHOD_PRIVATE (f))
2516               OP1 (OPCODE_invokespecial);
2517             else
2518               {
2519                 if (CLASS_INTERFACE (TYPE_NAME (context)))
2520                   {
2521                     tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2522                     context = TREE_TYPE (TREE_TYPE (arg1));
2523                     if (CLASS_INTERFACE (TYPE_NAME (context)))
2524                       interface = 1;
2525                   }
2526                 if (interface)
2527                   OP1 (OPCODE_invokeinterface);
2528                 else
2529                   OP1 (OPCODE_invokevirtual);
2530               }
2531             index = find_methodref_with_class_index (&state->cpool, f, context);
2532             OP2 (index);
2533             if (interface)
2534               {
2535                 if (nargs <= 0)
2536                   abort ();
2537
2538                 OP1 (nargs);
2539                 OP1 (0);
2540               }
2541             f = TREE_TYPE (TREE_TYPE (f));
2542             if (TREE_CODE (f) != VOID_TYPE)
2543               {
2544                 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2545                 if (target == IGNORE_TARGET)
2546                   emit_pop (size, state);
2547                 else
2548                   NOTE_PUSH (size);
2549               }
2550             break;
2551           }
2552       }
2553       /* fall through */
2554     notimpl:
2555     default:
2556       error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2557             tree_code_name [(int) TREE_CODE (exp)]);
2558     }
2559 }
2560
2561 static void
2562 perform_relocations (struct jcf_partial *state)
2563 {
2564   struct jcf_block *block;
2565   struct jcf_relocation *reloc;
2566   int pc;
2567   int shrink;
2568
2569   /* Before we start, the pc field of each block is an upper bound on
2570      the block's start pc (it may be less, if previous blocks need less
2571      than their maximum).
2572
2573      The minimum size of each block is in the block's chunk->size. */
2574
2575   /* First, figure out the actual locations of each block. */
2576   pc = 0;
2577   shrink = 0;
2578   for (block = state->blocks;  block != NULL;  block = block->next)
2579     {
2580       int block_size = block->v.chunk->size;
2581
2582       block->pc = pc;
2583
2584       /* Optimize GOTO L; L: by getting rid of the redundant goto.
2585          Assumes relocations are in reverse order. */
2586       reloc = block->u.relocations;
2587       while (reloc != NULL
2588              && reloc->kind == OPCODE_goto_w
2589              && reloc->label->pc == block->next->pc
2590              && reloc->offset + 2 == block_size)
2591         {
2592           reloc = reloc->next;
2593           block->u.relocations = reloc;
2594           block->v.chunk->size -= 3;
2595           block_size -= 3;
2596           shrink += 3;
2597         }
2598
2599       /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2600          jump directly to X.  We're careful here to avoid an infinite
2601          loop if the `goto's themselves form one.  We do this
2602          optimization because we can generate a goto-to-goto for some
2603          try/finally blocks.  */
2604       while (reloc != NULL
2605              && reloc->kind == OPCODE_goto_w
2606              && reloc->label != block
2607              && reloc->label->v.chunk->data != NULL
2608              && reloc->label->v.chunk->data[0] == OPCODE_goto)
2609         {
2610           /* Find the reloc for the first instruction of the
2611              destination block.  */
2612           struct jcf_relocation *first_reloc;
2613           for (first_reloc = reloc->label->u.relocations;
2614                first_reloc;
2615                first_reloc = first_reloc->next)
2616             {
2617               if (first_reloc->offset == 1
2618                   && first_reloc->kind == OPCODE_goto_w)
2619                 {
2620                   reloc->label = first_reloc->label;
2621                   break;
2622                 }
2623             }
2624
2625           /* If we didn't do anything, exit the loop.  */
2626           if (first_reloc == NULL)
2627             break;
2628         }
2629
2630       for (reloc = block->u.relocations;  reloc != NULL;  reloc = reloc->next)
2631         {
2632           if (reloc->kind == SWITCH_ALIGN_RELOC)
2633             {
2634               /* We assume this is the first relocation in this block,
2635                  so we know its final pc. */
2636               int where = pc + reloc->offset;
2637               int pad = ((where + 3) & ~3) - where;
2638               block_size += pad;
2639             }
2640           else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2641             {
2642               int delta = reloc->label->pc - (pc + reloc->offset - 1);
2643               int expand = reloc->kind > 0 ? 2 : 5;
2644
2645               if (delta > 0)
2646                 delta -= shrink;
2647               if (delta >= -32768 && delta <= 32767)
2648                 {
2649                   shrink += expand;
2650                   reloc->kind = -1;
2651                 }
2652               else
2653                 block_size += expand;
2654             }
2655         }
2656       pc += block_size;
2657     }
2658
2659   for (block = state->blocks;  block != NULL;  block = block->next)
2660     {
2661       struct chunk *chunk = block->v.chunk;
2662       int old_size = chunk->size;
2663       int next_pc = block->next == NULL ? pc : block->next->pc;
2664       int new_size = next_pc - block->pc;
2665       unsigned char *new_ptr;
2666       unsigned char *old_buffer = chunk->data;
2667       unsigned char *old_ptr = old_buffer + old_size;
2668       if (new_size != old_size)
2669         {
2670           chunk->data = obstack_alloc (state->chunk_obstack, new_size);
2671           chunk->size = new_size;
2672         }
2673       new_ptr = chunk->data + new_size;
2674
2675       /* We do the relocations from back to front, because
2676          the relocations are in reverse order. */
2677       for (reloc = block->u.relocations; ; reloc = reloc->next)
2678         {
2679           /* new_ptr and old_ptr point into the old and new buffers,
2680              respectively.  (If no relocations cause the buffer to
2681              grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2682              The bytes at higher address have been copied and relocations
2683              handled; those at lower addresses remain to process. */
2684
2685           /* Lower old index of piece to be copied with no relocation.
2686              I.e. high index of the first piece that does need relocation. */
2687           int start = reloc == NULL ? 0
2688             : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2689             : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2690             ? reloc->offset + 4
2691             : reloc->offset + 2;
2692           int32 value;
2693           int new_offset;
2694           int n = (old_ptr - old_buffer) - start;
2695           new_ptr -= n;
2696           old_ptr -= n;
2697           if (n > 0)
2698             memcpy (new_ptr, old_ptr, n);
2699           if (old_ptr == old_buffer)
2700             break;
2701
2702           new_offset = new_ptr - chunk->data;
2703           new_offset -= (reloc->kind == -1 ? 2 : 4);
2704           if (reloc->kind == 0)
2705             {
2706               old_ptr -= 4;
2707               value = GET_u4 (old_ptr);
2708             }
2709           else if (reloc->kind == BLOCK_START_RELOC)
2710             {
2711               old_ptr -= 4;
2712               value = 0;
2713               new_offset = 0;
2714             }
2715           else if (reloc->kind == SWITCH_ALIGN_RELOC)
2716             {
2717               int where = block->pc + reloc->offset;
2718               int pad = ((where + 3) & ~3) - where;
2719               while (--pad >= 0)
2720                 *--new_ptr = 0;
2721               continue;
2722             }
2723           else
2724             {
2725               old_ptr -= 2;
2726               value = GET_u2 (old_ptr);
2727             }
2728           value += reloc->label->pc - (block->pc + new_offset);
2729           *--new_ptr = (unsigned char) value;  value >>= 8;
2730           *--new_ptr = (unsigned char) value;  value >>= 8;
2731           if (reloc->kind != -1)
2732             {
2733               *--new_ptr = (unsigned char) value;  value >>= 8;
2734               *--new_ptr = (unsigned char) value;
2735             }
2736           if (reloc->kind > BLOCK_START_RELOC)
2737             {
2738               /* Convert: OP TARGET to: OP_w TARGET;  (OP is goto or jsr). */
2739               --old_ptr;
2740               *--new_ptr = reloc->kind;
2741             }
2742           else if (reloc->kind < -1)
2743             {
2744               /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2745               --old_ptr;
2746               *--new_ptr = OPCODE_goto_w;
2747               *--new_ptr = 3;
2748               *--new_ptr = 0;
2749               *--new_ptr = - reloc->kind;
2750             }
2751         }
2752       if (new_ptr != chunk->data)
2753         abort ();
2754     }
2755   state->code_length = pc;
2756 }
2757
2758 static void
2759 init_jcf_state (struct jcf_partial *state, struct obstack *work)
2760 {
2761   state->chunk_obstack = work;
2762   state->first = state->chunk = NULL;
2763   CPOOL_INIT (&state->cpool);
2764   BUFFER_INIT (&state->localvars);
2765   BUFFER_INIT (&state->bytecode);
2766 }
2767
2768 static void
2769 init_jcf_method (struct jcf_partial *state, tree method)
2770 {
2771   state->current_method = method;
2772   state->blocks = state->last_block = NULL;
2773   state->linenumber_count = 0;
2774   state->first_lvar = state->last_lvar = NULL;
2775   state->lvar_count = 0;
2776   state->labeled_blocks = NULL;
2777   state->code_length = 0;
2778   BUFFER_RESET (&state->bytecode);
2779   BUFFER_RESET (&state->localvars);
2780   state->code_SP = 0;
2781   state->code_SP_max = 0;
2782   state->handlers = NULL;
2783   state->last_handler = NULL;
2784   state->num_handlers = 0;
2785   state->num_finalizers = 0;
2786   state->return_value_decl = NULL_TREE;
2787 }
2788
2789 static void
2790 release_jcf_state (struct jcf_partial *state)
2791 {
2792   CPOOL_FINISH (&state->cpool);
2793   obstack_free (state->chunk_obstack, state->first);
2794 }
2795
2796 /* Generate and return a list of chunks containing the class CLAS
2797    in the .class file representation.  The list can be written to a
2798    .class file using write_chunks.  Allocate chunks from obstack WORK. */
2799
2800 static GTY(()) tree SourceFile_node;
2801 static struct chunk *
2802 generate_classfile (tree clas, struct jcf_partial *state)
2803 {
2804   struct chunk *cpool_chunk;
2805   const char *source_file, *s;
2806   char *ptr;
2807   int i;
2808   char *fields_count_ptr;
2809   int fields_count = 0;
2810   char *methods_count_ptr;
2811   int methods_count = 0;
2812   tree part;
2813   int total_supers
2814     = clas == object_type_node ? 0
2815     : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2816   
2817   ptr = append_chunk (NULL, 8, state);
2818   PUT4 (0xCafeBabe);  /* Magic number */
2819   PUT2 (3);  /* Minor version */
2820   PUT2 (45);  /* Major version */
2821   
2822   append_chunk (NULL, 0, state);
2823   cpool_chunk = state->chunk;
2824
2825   /* Next allocate the chunk containing acces_flags through fields_count. */
2826   if (clas == object_type_node)
2827     i = 10;
2828   else
2829     i = 8 + 2 * total_supers;
2830   ptr = append_chunk (NULL, i, state);
2831   i = get_access_flags (TYPE_NAME (clas));
2832   if (! (i & ACC_INTERFACE))
2833     i |= ACC_SUPER;
2834   PUT2 (i); /* acces_flags */
2835   i = find_class_constant (&state->cpool, clas);  PUT2 (i);  /* this_class */
2836   if (clas == object_type_node)
2837     {
2838       PUT2(0);  /* super_class */
2839       PUT2(0);  /* interfaces_count */
2840     }
2841   else
2842     {
2843       tree basetypes = TYPE_BINFO_BASETYPES (clas);
2844       tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2845       int j = find_class_constant (&state->cpool, base);
2846       PUT2 (j);  /* super_class */
2847       PUT2 (total_supers - 1);  /* interfaces_count */
2848       for (i = 1;  i < total_supers;  i++)
2849         {
2850           base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2851           j = find_class_constant (&state->cpool, base);
2852           PUT2 (j);
2853         }
2854     }
2855   fields_count_ptr = ptr;
2856
2857   for (part = TYPE_FIELDS (clas);  part;  part = TREE_CHAIN (part))
2858     {
2859       int have_value, attr_count = 0;
2860       if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2861         continue;
2862       ptr = append_chunk (NULL, 8, state);
2863       i = get_access_flags (part);  PUT2 (i);
2864       i = find_utf8_constant (&state->cpool, DECL_NAME (part));  PUT2 (i);
2865       i = find_utf8_constant (&state->cpool, 
2866                               build_java_signature (TREE_TYPE (part)));
2867       PUT2(i);
2868       have_value = DECL_INITIAL (part) != NULL_TREE 
2869         && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
2870         && FIELD_FINAL (part)
2871         && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
2872             || TREE_TYPE (part) == string_ptr_type_node);
2873       if (have_value)
2874         attr_count++;
2875
2876       if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2877           || FIELD_SYNTHETIC (part))
2878         attr_count++;
2879       if (FIELD_DEPRECATED (part))
2880         attr_count++;
2881
2882       PUT2 (attr_count);  /* attributes_count */
2883       if (have_value)
2884         {
2885           tree init = DECL_INITIAL (part);
2886           static tree ConstantValue_node = NULL_TREE;
2887           if (TREE_TYPE (part) != TREE_TYPE (init))
2888             fatal_error ("field initializer type mismatch");
2889           ptr = append_chunk (NULL, 8, state);
2890           if (ConstantValue_node == NULL_TREE)
2891             ConstantValue_node = get_identifier ("ConstantValue");
2892           i = find_utf8_constant (&state->cpool, ConstantValue_node);
2893           PUT2 (i);  /* attribute_name_index */
2894           PUT4 (2); /* attribute_length */
2895           i = find_constant_index (init, state);  PUT2 (i);
2896         }
2897       /* Emit the "Synthetic" attribute for val$<x> and this$<n>
2898          fields and other fields which need it.  */
2899       if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2900           || FIELD_SYNTHETIC (part))
2901         ptr = append_synthetic_attribute (state);
2902       if (FIELD_DEPRECATED (part))
2903         append_deprecated_attribute (state);
2904       fields_count++;
2905     }
2906   ptr = fields_count_ptr;  UNSAFE_PUT2 (fields_count);
2907
2908   ptr = methods_count_ptr = append_chunk (NULL, 2, state);
2909   PUT2 (0);
2910
2911   for (part = TYPE_METHODS (clas);  part;  part = TREE_CHAIN (part))
2912     {
2913       struct jcf_block *block;
2914       tree function_body = DECL_FUNCTION_BODY (part);
2915       tree body = function_body == NULL_TREE ? NULL_TREE
2916         : BLOCK_EXPR_BODY (function_body);
2917       tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
2918         : DECL_NAME (part);
2919       tree type = TREE_TYPE (part);
2920       tree save_function = current_function_decl;
2921       int synthetic_p = 0;
2922
2923       /* Invisible Miranda methods shouldn't end up in the .class
2924          file.  */
2925       if (METHOD_INVISIBLE (part))
2926         continue;
2927
2928       current_function_decl = part;
2929       ptr = append_chunk (NULL, 8, state);
2930       i = get_access_flags (part);  PUT2 (i);
2931       i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
2932       i = find_utf8_constant (&state->cpool, build_java_signature (type));
2933       PUT2 (i);
2934       i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
2935
2936       /* Make room for the Synthetic attribute (of zero length.)  */
2937       if (DECL_FINIT_P (part)
2938           || DECL_INSTINIT_P (part)
2939           || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
2940           || TYPE_DOT_CLASS (clas) == part)
2941         {
2942           i++;
2943           synthetic_p = 1;
2944         }
2945       /* Make room for Deprecated attribute.  */
2946       if (METHOD_DEPRECATED (part))
2947         i++;
2948
2949       PUT2 (i);   /* attributes_count */
2950
2951       if (synthetic_p)
2952         ptr = append_synthetic_attribute (state);
2953
2954       if (body != NULL_TREE)
2955         {
2956           int code_attributes_count = 0;
2957           static tree Code_node = NULL_TREE;
2958           tree t;
2959           char *attr_len_ptr;
2960           struct jcf_handler *handler;
2961           if (Code_node == NULL_TREE)
2962             Code_node = get_identifier ("Code");
2963           ptr = append_chunk (NULL, 14, state);
2964           i = find_utf8_constant (&state->cpool, Code_node);  PUT2 (i);
2965           attr_len_ptr = ptr;
2966           init_jcf_method (state, part);
2967           get_jcf_label_here (state);  /* Force a first block. */
2968           for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
2969             localvar_alloc (t, state);
2970           state->num_jsrs = 0;
2971           generate_bytecode_insns (body, IGNORE_TARGET, state);
2972           if (CAN_COMPLETE_NORMALLY (body))
2973             {
2974               if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
2975                 abort();
2976               RESERVE (1);
2977               OP1 (OPCODE_return);
2978             }
2979           for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
2980             maybe_free_localvar (t, state, 1);
2981           if (state->return_value_decl != NULL_TREE)
2982             maybe_free_localvar (state->return_value_decl, state, 1);
2983           finish_jcf_block (state);
2984           perform_relocations (state);
2985
2986           ptr = attr_len_ptr;
2987           i = 8 + state->code_length + 4 + 8 * state->num_handlers;
2988           if (state->linenumber_count > 0)
2989             {
2990               code_attributes_count++;
2991               i += 8 + 4 * state->linenumber_count;
2992             }
2993           if (state->lvar_count > 0)
2994             {
2995               code_attributes_count++;
2996               i += 8 + 10 * state->lvar_count;
2997             }
2998           UNSAFE_PUT4 (i); /* attribute_length */
2999           UNSAFE_PUT2 (state->code_SP_max);  /* max_stack */
3000           UNSAFE_PUT2 (localvar_max);  /* max_locals */
3001           UNSAFE_PUT4 (state->code_length);
3002
3003           /* Emit the exception table. */
3004           ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3005           PUT2 (state->num_handlers);  /* exception_table_length */
3006           handler = state->handlers;
3007           for (; handler != NULL;  handler = handler->next)
3008             {
3009               int type_index;
3010               PUT2 (handler->start_label->pc);
3011               PUT2 (handler->end_label->pc);
3012               PUT2 (handler->handler_label->pc);
3013               if (handler->type == NULL_TREE)
3014                 type_index = 0;
3015               else
3016                 type_index = find_class_constant (&state->cpool,
3017                                                   handler->type);
3018               PUT2 (type_index);
3019             }
3020
3021           ptr = append_chunk (NULL, 2, state);
3022           PUT2 (code_attributes_count);
3023
3024           /* Write the LineNumberTable attribute. */
3025           if (state->linenumber_count > 0)
3026             {
3027               static tree LineNumberTable_node = NULL_TREE;
3028               ptr = append_chunk (NULL, 
3029                                   8 + 4 * state->linenumber_count, state);
3030               if (LineNumberTable_node == NULL_TREE)
3031                 LineNumberTable_node = get_identifier ("LineNumberTable");
3032               i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3033               PUT2 (i);  /* attribute_name_index */
3034               i = 2+4*state->linenumber_count;  PUT4(i); /* attribute_length */
3035               i = state->linenumber_count;  PUT2 (i);
3036               for (block = state->blocks;  block != NULL;  block = block->next)
3037                 {
3038                   int line = block->linenumber;
3039                   if (line > 0)
3040                     {
3041                       PUT2 (block->pc);
3042                       PUT2 (line);
3043                     }
3044                 }
3045             }
3046
3047           /* Write the LocalVariableTable attribute. */
3048           if (state->lvar_count > 0)
3049             {
3050               static tree LocalVariableTable_node = NULL_TREE;
3051               struct localvar_info *lvar = state->first_lvar;
3052               ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3053               if (LocalVariableTable_node == NULL_TREE)
3054                 LocalVariableTable_node = get_identifier("LocalVariableTable");
3055               i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3056               PUT2 (i);  /* attribute_name_index */
3057               i = 2 + 10 * state->lvar_count;  PUT4 (i); /* attribute_length */
3058               i = state->lvar_count;  PUT2 (i);
3059               for ( ; lvar != NULL;  lvar = lvar->next)
3060                 {
3061                   tree name = DECL_NAME (lvar->decl);
3062                   tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3063                   i = lvar->start_label->pc;  PUT2 (i);
3064                   i = lvar->end_label->pc - i;  PUT2 (i);
3065                   i = find_utf8_constant (&state->cpool, name);  PUT2 (i);
3066                   i = find_utf8_constant (&state->cpool, sig);  PUT2 (i);
3067                   i = DECL_LOCAL_INDEX (lvar->decl);  PUT2 (i);
3068                 }
3069             }
3070         }
3071       if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3072         {
3073           tree t = DECL_FUNCTION_THROWS (part);
3074           int throws_count = list_length (t);
3075           static tree Exceptions_node = NULL_TREE;
3076           if (Exceptions_node == NULL_TREE)
3077             Exceptions_node = get_identifier ("Exceptions");
3078           ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3079           i = find_utf8_constant (&state->cpool, Exceptions_node);
3080           PUT2 (i);  /* attribute_name_index */ 
3081           i = 2 + 2 * throws_count;  PUT4(i); /* attribute_length */ 
3082           i = throws_count;  PUT2 (i); 
3083           for (;  t != NULL_TREE;  t = TREE_CHAIN (t))
3084             {
3085               i = find_class_constant (&state->cpool, TREE_VALUE (t));
3086               PUT2 (i);
3087             }
3088         }
3089
3090       if (METHOD_DEPRECATED (part))
3091         append_deprecated_attribute (state);
3092  
3093       methods_count++;
3094       current_function_decl = save_function;
3095     }
3096   ptr = methods_count_ptr;  UNSAFE_PUT2 (methods_count);
3097
3098   source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3099   for (s = source_file; ; s++)
3100     {
3101       char ch = *s;
3102       if (ch == '\0')
3103         break;
3104       if (ch == '/' || ch == '\\')
3105         source_file = s+1;
3106     }
3107   ptr = append_chunk (NULL, 10, state);
3108
3109   i = 1;                /* Source file always exists as an attribute */
3110   if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3111     i++;
3112   if (clas == object_type_node)
3113     i++;
3114   if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3115     i++;
3116
3117   PUT2 (i);                     /* attributes_count */
3118
3119   /* generate the SourceFile attribute. */
3120   if (SourceFile_node == NULL_TREE) 
3121     {
3122       SourceFile_node = get_identifier ("SourceFile");
3123     }
3124
3125   i = find_utf8_constant (&state->cpool, SourceFile_node);
3126   PUT2 (i);  /* attribute_name_index */
3127   PUT4 (2);
3128   i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3129   PUT2 (i);
3130   append_gcj_attribute (state, clas);
3131   append_innerclasses_attribute (state, clas);
3132   if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3133     append_deprecated_attribute (state);
3134
3135   /* New finally generate the contents of the constant pool chunk. */
3136   i = count_constant_pool_bytes (&state->cpool);
3137   ptr = obstack_alloc (state->chunk_obstack, i);
3138   cpool_chunk->data = ptr;
3139   cpool_chunk->size = i;
3140   write_constant_pool (&state->cpool, ptr, i);
3141   return state->first;
3142 }
3143
3144 static GTY(()) tree Synthetic_node;
3145 static unsigned char *
3146 append_synthetic_attribute (struct jcf_partial *state)
3147 {
3148   unsigned char *ptr = append_chunk (NULL, 6, state);
3149   int i;
3150
3151   if (Synthetic_node == NULL_TREE)
3152     {
3153       Synthetic_node = get_identifier ("Synthetic");
3154     }
3155   i = find_utf8_constant (&state->cpool, Synthetic_node);
3156   PUT2 (i);             /* Attribute string index */
3157   PUT4 (0);             /* Attribute length */
3158
3159   return ptr;
3160 }
3161
3162 static void
3163 append_deprecated_attribute (struct jcf_partial *state)
3164 {
3165   unsigned char *ptr = append_chunk (NULL, 6, state);
3166   int i;
3167  
3168   i = find_utf8_constant (&state->cpool, get_identifier ("Deprecated"));
3169   PUT2 (i);             /* Attribute string index */
3170   PUT4 (0);             /* Attribute length */
3171 }
3172
3173 static void
3174 append_gcj_attribute (struct jcf_partial *state, tree class)
3175 {
3176   unsigned char *ptr;
3177   int i;
3178
3179   if (class != object_type_node)
3180     return;
3181
3182   ptr = append_chunk (NULL, 6, state); /* 2+4 */
3183   i = find_utf8_constant (&state->cpool, 
3184                           get_identifier ("gnu.gcj.gcj-compiled"));
3185   PUT2 (i);                     /* Attribute string index */
3186   PUT4 (0);                     /* Attribute length */
3187 }
3188
3189 static tree InnerClasses_node;
3190 static void
3191 append_innerclasses_attribute (struct jcf_partial *state, tree class)
3192 {
3193   tree orig_decl = TYPE_NAME (class);
3194   tree current, decl;
3195   int length = 0, i;
3196   unsigned char *ptr, *length_marker, *number_marker;
3197
3198   if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3199     return;
3200
3201   ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3202   
3203   if (InnerClasses_node == NULL_TREE) 
3204     {
3205       InnerClasses_node = get_identifier ("InnerClasses");
3206     }
3207   i = find_utf8_constant (&state->cpool, InnerClasses_node);
3208   PUT2 (i);
3209   length_marker = ptr; PUT4 (0); /* length, to be later patched */
3210   number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3211
3212   /* Generate the entries: all inner classes visible from the one we
3213      process: itself, up and down. */
3214   while (class && INNER_CLASS_TYPE_P (class))
3215     {
3216       const char *n;
3217
3218       decl = TYPE_NAME (class);
3219       n = IDENTIFIER_POINTER (DECL_NAME (decl)) + 
3220         IDENTIFIER_LENGTH (DECL_NAME (decl));
3221
3222       while (n[-1] != '$')
3223         n--;
3224       append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3225       length++;
3226
3227       class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3228     }
3229
3230   decl = orig_decl;
3231   for (current = DECL_INNER_CLASS_LIST (decl); 
3232        current; current = TREE_CHAIN (current))
3233     {
3234       append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3235                                            TREE_VALUE (current));
3236       length++;
3237     }
3238   
3239   ptr = length_marker; PUT4 (8*length+2);
3240   ptr = number_marker; PUT2 (length);
3241 }
3242
3243 static void
3244 append_innerclasses_attribute_entry (struct jcf_partial *state,
3245                                      tree decl, tree name)
3246 {
3247   int icii, icaf;
3248   int ocii = 0, ini = 0;
3249   unsigned char *ptr = append_chunk (NULL, 8, state);
3250
3251   icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3252
3253   /* Sun's implementation seems to generate ocii to 0 for inner
3254      classes (which aren't considered members of the class they're
3255      in.) The specs are saying that if the class is anonymous,
3256      inner_name_index must be zero. */
3257   if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3258     {
3259       ocii = find_class_constant (&state->cpool, 
3260                                   TREE_TYPE (DECL_CONTEXT (decl)));
3261       ini = find_utf8_constant (&state->cpool, name);
3262     }
3263   icaf = get_access_flags (decl);
3264
3265   PUT2 (icii); PUT2 (ocii); PUT2 (ini);  PUT2 (icaf);
3266 }
3267
3268 static char *
3269 make_class_file_name (tree clas)
3270 {
3271   const char *dname, *cname, *slash;
3272   char *r;
3273   struct stat sb;
3274   char sep;
3275
3276   cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3277                                                 "", '.', DIR_SEPARATOR,
3278                                                 ".class"));
3279   if (jcf_write_base_directory == NULL)
3280     {
3281       /* Make sure we put the class file into the .java file's
3282          directory, and not into some subdirectory thereof.  */
3283       char *t;
3284       dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3285       slash = strrchr (dname, DIR_SEPARATOR);
3286 #ifdef DIR_SEPARATOR_2
3287       if (! slash)
3288         slash = strrchr (dname, DIR_SEPARATOR_2);
3289 #endif
3290       if (! slash)
3291         {
3292           dname = ".";
3293           slash = dname + 1;
3294           sep = DIR_SEPARATOR;
3295         }
3296       else
3297         sep = *slash;
3298
3299       t = strrchr (cname, DIR_SEPARATOR);
3300       if (t)
3301         cname = t + 1;
3302     }
3303   else
3304     {
3305       char *s;
3306
3307       dname = jcf_write_base_directory;
3308
3309       s = strrchr (dname, DIR_SEPARATOR);
3310 #ifdef DIR_SEPARATOR_2
3311       if (! s)
3312         s = strrchr (dname, DIR_SEPARATOR_2);
3313 #endif
3314       if (s)
3315         sep = *s;
3316       else
3317         sep = DIR_SEPARATOR;
3318
3319       slash = dname + strlen (dname);
3320     }
3321
3322   r = xmalloc (slash - dname + strlen (cname) + 2);
3323   strncpy (r, dname, slash - dname);
3324   r[slash - dname] = sep;
3325   strcpy (&r[slash - dname + 1], cname);
3326
3327   /* We try to make new directories when we need them.  We only do
3328      this for directories which "might not" exist.  For instance, we
3329      assume the `-d' directory exists, but we don't assume that any
3330      subdirectory below it exists.  It might be worthwhile to keep
3331      track of which directories we've created to avoid gratuitous
3332      stat()s.  */
3333   dname = r + (slash - dname) + 1;
3334   while (1)
3335     {
3336       char *s = strchr (dname, sep);
3337       if (s == NULL)
3338         break;
3339       *s = '\0';
3340       if (stat (r, &sb) == -1
3341           /* Try to make it.  */
3342           && mkdir (r, 0755) == -1)
3343         fatal_error ("can't create directory %s: %m", r);
3344
3345       *s = sep;
3346       /* Skip consecutive separators.  */
3347       for (dname = s + 1; *dname && *dname == sep; ++dname)
3348         ;
3349     }
3350
3351   return r;
3352 }
3353
3354 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3355    The output .class file name is make_class_file_name(CLAS). */
3356
3357 void
3358 write_classfile (tree clas)
3359 {
3360   struct obstack *work = &temporary_obstack;
3361   struct jcf_partial state[1];
3362   char *class_file_name = make_class_file_name (clas);
3363   struct chunk *chunks;
3364
3365   if (class_file_name != NULL)
3366     {
3367       FILE *stream;
3368       char *temporary_file_name;
3369
3370       /* The .class file is initially written to a ".tmp" file so that
3371          if multiple instances of the compiler are running at once
3372          they do not see partially formed class files. */
3373       temporary_file_name = concat (class_file_name, ".tmp", NULL);
3374       stream = fopen (temporary_file_name, "wb");
3375       if (stream == NULL)
3376         fatal_error ("can't open %s for writing: %m", temporary_file_name);
3377
3378       jcf_dependency_add_target (class_file_name);
3379       init_jcf_state (state, work);
3380       chunks = generate_classfile (clas, state);
3381       write_chunks (stream, chunks);
3382       if (fclose (stream))
3383         fatal_error ("error closing %s: %m", temporary_file_name);
3384
3385       /* If a file named by the string pointed to by `new' exists
3386          prior to the call to the `rename' function, the bahaviour
3387          is implementation-defined.  ISO 9899-1990 7.9.4.2.
3388
3389          For example, on Win32 with MSVCRT, it is an error. */
3390
3391       unlink (class_file_name);
3392
3393       if (rename (temporary_file_name, class_file_name) == -1)
3394         {
3395           remove (temporary_file_name);
3396           fatal_error ("can't create %s: %m", class_file_name);
3397         }
3398       free (temporary_file_name);
3399       free (class_file_name);
3400     }
3401   release_jcf_state (state);
3402 }
3403
3404 /* TODO:
3405    string concatenation
3406    synchronized statement
3407    */
3408
3409 #include "gt-java-jcf-write.h"