OSDN Git Service

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