OSDN Git Service

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