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