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