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