OSDN Git Service

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