OSDN Git Service

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