OSDN Git Service

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