OSDN Git Service

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