OSDN Git Service

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