Thu Aug 16 17:39:45 CEST 2001 Jan Hubicka <jh@suse.cz>
[official-gcc.git] / gcc / java / jcf-write.c
blobca453c8edd9b96483d947886d86728aad2679276
1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999, 2000, 2001 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->last_bc = *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 assocated 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 WITH_CLEANUP_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;
279 enum java_opcode last_bc; /* The last emitted bytecode */
282 static void generate_bytecode_insns PARAMS ((tree, int, struct jcf_partial *));
283 static struct chunk * alloc_chunk PARAMS ((struct chunk *, unsigned char *,
284 int, struct obstack *));
285 static unsigned char * append_chunk PARAMS ((unsigned char *, int,
286 struct jcf_partial *));
287 static void append_chunk_copy PARAMS ((unsigned char *, int,
288 struct jcf_partial *));
289 static struct jcf_block * gen_jcf_label PARAMS ((struct jcf_partial *));
290 static void finish_jcf_block PARAMS ((struct jcf_partial *));
291 static void define_jcf_label PARAMS ((struct jcf_block *,
292 struct jcf_partial *));
293 static struct jcf_block * get_jcf_label_here PARAMS ((struct jcf_partial *));
294 static void put_linenumber PARAMS ((int, struct jcf_partial *));
295 static void localvar_alloc PARAMS ((tree, struct jcf_partial *));
296 static void localvar_free PARAMS ((tree, struct jcf_partial *));
297 static int get_access_flags PARAMS ((tree));
298 static void write_chunks PARAMS ((FILE *, struct chunk *));
299 static int adjust_typed_op PARAMS ((tree, int));
300 static void generate_bytecode_conditional PARAMS ((tree, struct jcf_block *,
301 struct jcf_block *, int,
302 struct jcf_partial *));
303 static void generate_bytecode_return PARAMS ((tree, struct jcf_partial *));
304 static void perform_relocations PARAMS ((struct jcf_partial *));
305 static void init_jcf_state PARAMS ((struct jcf_partial *, struct obstack *));
306 static void init_jcf_method PARAMS ((struct jcf_partial *, tree));
307 static void release_jcf_state PARAMS ((struct jcf_partial *));
308 static struct chunk * generate_classfile PARAMS ((tree, struct jcf_partial *));
309 static struct jcf_handler *alloc_handler PARAMS ((struct jcf_block *,
310 struct jcf_block *,
311 struct jcf_partial *));
312 static void emit_iinc PARAMS ((tree, HOST_WIDE_INT, struct jcf_partial *));
313 static void emit_reloc PARAMS ((HOST_WIDE_INT, int, struct jcf_block *,
314 struct jcf_partial *));
315 static void push_constant1 PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
316 static void push_constant2 PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
317 static void push_int_const PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
318 static int find_constant_wide PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
319 struct jcf_partial *));
320 static void push_long_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
321 struct jcf_partial *));
322 static int find_constant_index PARAMS ((tree, struct jcf_partial *));
323 static void push_long_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
324 struct jcf_partial *));
325 static void field_op PARAMS ((tree, int, struct jcf_partial *));
326 static void maybe_wide PARAMS ((int, int, struct jcf_partial *));
327 static void emit_dup PARAMS ((int, int, struct jcf_partial *));
328 static void emit_pop PARAMS ((int, struct jcf_partial *));
329 static void emit_load_or_store PARAMS ((tree, int, struct jcf_partial *));
330 static void emit_load PARAMS ((tree, struct jcf_partial *));
331 static void emit_store PARAMS ((tree, struct jcf_partial *));
332 static void emit_unop PARAMS ((enum java_opcode, tree, struct jcf_partial *));
333 static void emit_binop PARAMS ((enum java_opcode, tree, struct jcf_partial *));
334 static void emit_reloc PARAMS ((HOST_WIDE_INT, int, struct jcf_block *,
335 struct jcf_partial *));
336 static void emit_switch_reloc PARAMS ((struct jcf_block *,
337 struct jcf_partial *));
338 static void emit_case_reloc PARAMS ((struct jcf_relocation *,
339 struct jcf_partial *));
340 static void emit_if PARAMS ((struct jcf_block *, int, int,
341 struct jcf_partial *));
342 static void emit_goto PARAMS ((struct jcf_block *, struct jcf_partial *));
343 static void emit_jsr PARAMS ((struct jcf_block *, struct jcf_partial *));
344 static void call_cleanups PARAMS ((struct jcf_block *, struct jcf_partial *));
345 static char *make_class_file_name PARAMS ((tree));
346 static unsigned char *append_synthetic_attribute PARAMS ((struct jcf_partial *));
347 static void append_innerclasses_attribute PARAMS ((struct jcf_partial *, tree));
348 static void append_innerclasses_attribute_entry PARAMS ((struct jcf_partial *, tree, tree));
349 static void append_gcj_attribute PARAMS ((struct jcf_partial *, tree));
351 /* Utility macros for appending (big-endian) data to a buffer.
352 We assume a local variable 'ptr' points into where we want to
353 write next, and we assume enough space has been allocated. */
355 #ifdef ENABLE_JC1_CHECKING
356 static int CHECK_PUT PARAMS ((void *, struct jcf_partial *, int));
358 static int
359 CHECK_PUT (ptr, state, i)
360 void *ptr;
361 struct jcf_partial *state;
362 int i;
364 if ((unsigned char *) ptr < state->chunk->data
365 || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
366 abort ();
368 return 0;
370 #else
371 #define CHECK_PUT(PTR, STATE, I) ((void)0)
372 #endif
374 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
375 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
376 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
377 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
379 /* There are some cases below where CHECK_PUT is guaranteed to fail.
380 Use the following macros in those specific cases. */
381 #define UNSAFE_PUT1(X) (*ptr++ = (X))
382 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
383 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
384 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
387 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
388 Set the data and size fields to DATA and SIZE, respectively.
389 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
391 static struct chunk *
392 alloc_chunk (last, data, size, work)
393 struct chunk *last;
394 unsigned char *data;
395 int size;
396 struct obstack *work;
398 struct chunk *chunk = (struct chunk *)
399 obstack_alloc (work, sizeof(struct chunk));
401 if (data == NULL && size > 0)
402 data = obstack_alloc (work, size);
404 chunk->next = NULL;
405 chunk->data = data;
406 chunk->size = size;
407 if (last != NULL)
408 last->next = chunk;
409 return chunk;
412 #ifdef ENABLE_JC1_CHECKING
413 static int CHECK_OP PARAMS ((struct jcf_partial *));
415 static int
416 CHECK_OP (state)
417 struct jcf_partial *state;
419 if (state->bytecode.ptr > state->bytecode.limit)
420 abort ();
422 return 0;
424 #else
425 #define CHECK_OP(STATE) ((void) 0)
426 #endif
428 static unsigned char *
429 append_chunk (data, size, state)
430 unsigned char *data;
431 int size;
432 struct jcf_partial *state;
434 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
435 if (state->first == NULL)
436 state->first = state->chunk;
437 return state->chunk->data;
440 static void
441 append_chunk_copy (data, size, state)
442 unsigned char *data;
443 int size;
444 struct jcf_partial *state;
446 unsigned char *ptr = append_chunk (NULL, size, state);
447 memcpy (ptr, data, size);
450 static struct jcf_block *
451 gen_jcf_label (state)
452 struct jcf_partial *state;
454 struct jcf_block *block = (struct jcf_block *)
455 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
456 block->next = NULL;
457 block->linenumber = -1;
458 block->pc = UNDEFINED_PC;
459 return block;
462 static void
463 finish_jcf_block (state)
464 struct jcf_partial *state;
466 struct jcf_block *block = state->last_block;
467 struct jcf_relocation *reloc;
468 int code_length = BUFFER_LENGTH (&state->bytecode);
469 int pc = state->code_length;
470 append_chunk_copy (state->bytecode.data, code_length, state);
471 BUFFER_RESET (&state->bytecode);
472 block->v.chunk = state->chunk;
474 /* Calculate code_length to the maximum value it can have. */
475 pc += block->v.chunk->size;
476 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
478 int kind = reloc->kind;
479 if (kind == SWITCH_ALIGN_RELOC)
480 pc += 3;
481 else if (kind > BLOCK_START_RELOC)
482 pc += 2; /* 2-byte offset may grow to 4-byte offset */
483 else if (kind < -1)
484 pc += 5; /* May need to add a goto_w. */
486 state->code_length = pc;
489 static void
490 define_jcf_label (label, state)
491 struct jcf_block *label;
492 struct jcf_partial *state;
494 if (state->last_block != NULL)
495 finish_jcf_block (state);
496 label->pc = state->code_length;
497 if (state->blocks == NULL)
498 state->blocks = label;
499 else
500 state->last_block->next = label;
501 state->last_block = label;
502 label->next = NULL;
503 label->u.relocations = NULL;
506 static struct jcf_block *
507 get_jcf_label_here (state)
508 struct jcf_partial *state;
510 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
511 return state->last_block;
512 else
514 struct jcf_block *label = gen_jcf_label (state);
515 define_jcf_label (label, state);
516 return label;
520 /* Note a line number entry for the current PC and given LINE. */
522 static void
523 put_linenumber (line, state)
524 int line;
525 struct jcf_partial *state;
527 struct jcf_block *label = get_jcf_label_here (state);
528 if (label->linenumber > 0)
530 label = gen_jcf_label (state);
531 define_jcf_label (label, state);
533 label->linenumber = line;
534 state->linenumber_count++;
537 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
538 in the range (START_LABEL, END_LABEL). */
540 static struct jcf_handler *
541 alloc_handler (start_label, end_label, state)
542 struct jcf_block *start_label;
543 struct jcf_block *end_label;
544 struct jcf_partial *state;
546 struct jcf_handler *handler = (struct jcf_handler *)
547 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
548 handler->start_label = start_label;
549 handler->end_label = end_label;
550 handler->handler_label = get_jcf_label_here (state);
551 if (state->handlers == NULL)
552 state->handlers = handler;
553 else
554 state->last_handler->next = handler;
555 state->last_handler = handler;
556 handler->next = NULL;
557 state->num_handlers++;
558 return handler;
562 /* The index of jvm local variable allocated for this DECL.
563 This is assigned when generating .class files;
564 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
565 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
567 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
569 struct localvar_info
571 struct localvar_info *next;
573 tree decl;
574 struct jcf_block *start_label;
575 struct jcf_block *end_label;
578 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
579 #define localvar_max \
580 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
582 static void
583 localvar_alloc (decl, state)
584 tree decl;
585 struct jcf_partial *state;
587 struct jcf_block *start_label = get_jcf_label_here (state);
588 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
589 int index;
590 register struct localvar_info *info;
591 register struct localvar_info **ptr = localvar_buffer;
592 register struct localvar_info **limit
593 = (struct localvar_info**) state->localvars.ptr;
594 for (index = 0; ptr < limit; index++, ptr++)
596 if (ptr[0] == NULL
597 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
598 break;
600 if (ptr == limit)
602 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
603 ptr = (struct localvar_info**) state->localvars.data + index;
604 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
606 info = (struct localvar_info *)
607 obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
608 ptr[0] = info;
609 if (wide)
610 ptr[1] = (struct localvar_info *)(~0);
611 DECL_LOCAL_INDEX (decl) = index;
612 info->decl = decl;
613 info->start_label = start_label;
615 if (debug_info_level > DINFO_LEVEL_TERSE
616 && DECL_NAME (decl) != NULL_TREE)
618 /* Generate debugging info. */
619 info->next = NULL;
620 if (state->last_lvar != NULL)
621 state->last_lvar->next = info;
622 else
623 state->first_lvar = info;
624 state->last_lvar = info;
625 state->lvar_count++;
629 static void
630 localvar_free (decl, state)
631 tree decl;
632 struct jcf_partial *state;
634 struct jcf_block *end_label = get_jcf_label_here (state);
635 int index = DECL_LOCAL_INDEX (decl);
636 register struct localvar_info **ptr = &localvar_buffer [index];
637 register struct localvar_info *info = *ptr;
638 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
640 info->end_label = end_label;
642 if (info->decl != decl)
643 abort ();
644 ptr[0] = NULL;
645 if (wide)
647 if (ptr[1] != (struct localvar_info *)(~0))
648 abort ();
649 ptr[1] = NULL;
654 #define STACK_TARGET 1
655 #define IGNORE_TARGET 2
657 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
658 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
660 static int
661 get_access_flags (decl)
662 tree decl;
664 int flags = 0;
665 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
666 if (CLASS_PUBLIC (decl)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
667 flags |= ACC_PUBLIC;
668 if (CLASS_FINAL (decl)) /* same as FIELD_FINAL and METHOD_FINAL */
669 flags |= ACC_FINAL;
670 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
672 if (TREE_PROTECTED (decl))
673 flags |= ACC_PROTECTED;
674 if (TREE_PRIVATE (decl))
675 flags |= ACC_PRIVATE;
677 else if (TREE_CODE (decl) == TYPE_DECL)
679 if (CLASS_SUPER (decl))
680 flags |= ACC_SUPER;
681 if (CLASS_ABSTRACT (decl))
682 flags |= ACC_ABSTRACT;
683 if (CLASS_INTERFACE (decl))
684 flags |= ACC_INTERFACE;
685 if (CLASS_STATIC (decl))
686 flags |= ACC_STATIC;
687 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
688 || LOCAL_CLASS_P (TREE_TYPE (decl)))
689 flags |= ACC_PRIVATE;
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;
705 if (isfield)
707 if (FIELD_STATIC (decl))
708 flags |= ACC_STATIC;
709 if (FIELD_VOLATILE (decl))
710 flags |= ACC_VOLATILE;
711 if (FIELD_TRANSIENT (decl))
712 flags |= ACC_TRANSIENT;
714 return flags;
717 /* Write the list of segments starting at CHUNKS to STREAM. */
719 static void
720 write_chunks (stream, chunks)
721 FILE* stream;
722 struct chunk *chunks;
724 for (; chunks != NULL; chunks = chunks->next)
725 fwrite (chunks->data, chunks->size, 1, stream);
728 /* Push a 1-word constant in the constant pool at the given INDEX.
729 (Caller is responsible for doing NOTE_PUSH.) */
731 static void
732 push_constant1 (index, state)
733 HOST_WIDE_INT index;
734 struct jcf_partial *state;
736 RESERVE (3);
737 if (index < 256)
739 OP1 (OPCODE_ldc);
740 OP1 (index);
742 else
744 OP1 (OPCODE_ldc_w);
745 OP2 (index);
749 /* Push a 2-word constant in the constant pool at the given INDEX.
750 (Caller is responsible for doing NOTE_PUSH.) */
752 static void
753 push_constant2 (index, state)
754 HOST_WIDE_INT index;
755 struct jcf_partial *state;
757 RESERVE (3);
758 OP1 (OPCODE_ldc2_w);
759 OP2 (index);
762 /* Push 32-bit integer constant on VM stack.
763 Caller is responsible for doing NOTE_PUSH. */
765 static void
766 push_int_const (i, state)
767 HOST_WIDE_INT i;
768 struct jcf_partial *state;
770 RESERVE(3);
771 if (i >= -1 && i <= 5)
772 OP1(OPCODE_iconst_0 + i);
773 else if (i >= -128 && i < 128)
775 OP1(OPCODE_bipush);
776 OP1(i);
778 else if (i >= -32768 && i < 32768)
780 OP1(OPCODE_sipush);
781 OP2(i);
783 else
785 i = find_constant1 (&state->cpool, CONSTANT_Integer,
786 (jword)(i & 0xFFFFFFFF));
787 push_constant1 (i, state);
791 static int
792 find_constant_wide (lo, hi, state)
793 HOST_WIDE_INT lo, hi;
794 struct jcf_partial *state;
796 HOST_WIDE_INT w1, w2;
797 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
798 return find_constant2 (&state->cpool, CONSTANT_Long,
799 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
802 /* Find or allocate a constant pool entry for the given VALUE.
803 Return the index in the constant pool. */
805 static int
806 find_constant_index (value, state)
807 tree value;
808 struct jcf_partial *state;
810 if (TREE_CODE (value) == INTEGER_CST)
812 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
813 return find_constant1 (&state->cpool, CONSTANT_Integer,
814 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
815 else
816 return find_constant_wide (TREE_INT_CST_LOW (value),
817 TREE_INT_CST_HIGH (value), state);
819 else if (TREE_CODE (value) == REAL_CST)
821 long words[2];
822 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
824 words[0] = etarsingle (TREE_REAL_CST (value)) & 0xFFFFFFFF;
825 return find_constant1 (&state->cpool, CONSTANT_Float,
826 (jword)words[0]);
828 else
830 etardouble (TREE_REAL_CST (value), words);
831 return find_constant2 (&state->cpool, CONSTANT_Double,
832 (jword)(words[1-FLOAT_WORDS_BIG_ENDIAN] &
833 0xFFFFFFFF),
834 (jword)(words[FLOAT_WORDS_BIG_ENDIAN] &
835 0xFFFFFFFF));
838 else if (TREE_CODE (value) == STRING_CST)
839 return find_string_constant (&state->cpool, value);
841 else
842 abort ();
845 /* Push 64-bit long constant on VM stack.
846 Caller is responsible for doing NOTE_PUSH. */
848 static void
849 push_long_const (lo, hi, state)
850 HOST_WIDE_INT lo, hi;
851 struct jcf_partial *state;
853 if (hi == 0 && lo >= 0 && lo <= 1)
855 RESERVE(1);
856 OP1(OPCODE_lconst_0 + lo);
858 else if ((hi == 0 && (jword)(lo & 0xFFFFFFFF) < 32768)
859 || (hi == -1 && (lo & 0xFFFFFFFF) >= (jword)-32768))
861 push_int_const (lo, state);
862 RESERVE (1);
863 OP1 (OPCODE_i2l);
865 else
866 push_constant2 (find_constant_wide (lo, hi, state), state);
869 static void
870 field_op (field, opcode, state)
871 tree field;
872 int opcode;
873 struct jcf_partial *state;
875 int index = find_fieldref_index (&state->cpool, field);
876 RESERVE (3);
877 OP1 (opcode);
878 OP2 (index);
881 /* Returns an integer in the range 0 (for 'int') through 4 (for object
882 reference) to 7 (for 'short') which matches the pattern of how JVM
883 opcodes typically depend on the operand type. */
885 static int
886 adjust_typed_op (type, max)
887 tree type;
888 int max;
890 switch (TREE_CODE (type))
892 case POINTER_TYPE:
893 case RECORD_TYPE: return 4;
894 case BOOLEAN_TYPE:
895 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
896 case CHAR_TYPE:
897 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
898 case INTEGER_TYPE:
899 switch (TYPE_PRECISION (type))
901 case 8: return max < 5 ? 0 : 5;
902 case 16: return max < 7 ? 0 : 7;
903 case 32: return 0;
904 case 64: return 1;
906 break;
907 case REAL_TYPE:
908 switch (TYPE_PRECISION (type))
910 case 32: return 2;
911 case 64: return 3;
913 break;
914 default:
915 break;
917 abort ();
920 static void
921 maybe_wide (opcode, index, state)
922 int opcode, index;
923 struct jcf_partial *state;
925 if (index >= 256)
927 RESERVE (4);
928 OP1 (OPCODE_wide);
929 OP1 (opcode);
930 OP2 (index);
932 else
934 RESERVE (2);
935 OP1 (opcode);
936 OP1 (index);
940 /* Compile code to duplicate with offset, where
941 SIZE is the size of the stack item to duplicate (1 or 2), abd
942 OFFSET is where to insert the result (must be 0, 1, or 2).
943 (The new words get inserted at stack[SP-size-offset].) */
945 static void
946 emit_dup (size, offset, state)
947 int size, offset;
948 struct jcf_partial *state;
950 int kind;
951 if (size == 0)
952 return;
953 RESERVE(1);
954 if (offset == 0)
955 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
956 else if (offset == 1)
957 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
958 else if (offset == 2)
959 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
960 else
961 abort();
962 OP1 (kind);
963 NOTE_PUSH (size);
966 static void
967 emit_pop (size, state)
968 int size;
969 struct jcf_partial *state;
971 RESERVE (1);
972 OP1 (OPCODE_pop - 1 + size);
975 static void
976 emit_iinc (var, value, state)
977 tree var;
978 HOST_WIDE_INT value;
979 struct jcf_partial *state;
981 int slot = DECL_LOCAL_INDEX (var);
983 if (value < -128 || value > 127 || slot >= 256)
985 RESERVE (6);
986 OP1 (OPCODE_wide);
987 OP1 (OPCODE_iinc);
988 OP2 (slot);
989 OP2 (value);
991 else
993 RESERVE (3);
994 OP1 (OPCODE_iinc);
995 OP1 (slot);
996 OP1 (value);
1000 static void
1001 emit_load_or_store (var, opcode, state)
1002 tree var; /* Variable to load from or store into. */
1003 int opcode; /* Either OPCODE_iload or OPCODE_istore. */
1004 struct jcf_partial *state;
1006 tree type = TREE_TYPE (var);
1007 int kind = adjust_typed_op (type, 4);
1008 int index = DECL_LOCAL_INDEX (var);
1009 if (index <= 3)
1011 RESERVE (1);
1012 OP1 (opcode + 5 + 4 * kind + index); /* [ilfda]{load,store}_[0123] */
1014 else
1015 maybe_wide (opcode + kind, index, state); /* [ilfda]{load,store} */
1018 static void
1019 emit_load (var, state)
1020 tree var;
1021 struct jcf_partial *state;
1023 emit_load_or_store (var, OPCODE_iload, state);
1024 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1027 static void
1028 emit_store (var, state)
1029 tree var;
1030 struct jcf_partial *state;
1032 emit_load_or_store (var, OPCODE_istore, state);
1033 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1036 static void
1037 emit_unop (opcode, type, state)
1038 enum java_opcode opcode;
1039 tree type ATTRIBUTE_UNUSED;
1040 struct jcf_partial *state;
1042 RESERVE(1);
1043 OP1 (opcode);
1046 static void
1047 emit_binop (opcode, type, state)
1048 enum java_opcode opcode;
1049 tree type;
1050 struct jcf_partial *state;
1052 int size = TYPE_IS_WIDE (type) ? 2 : 1;
1053 RESERVE(1);
1054 OP1 (opcode);
1055 NOTE_POP (size);
1058 static void
1059 emit_reloc (value, kind, target, state)
1060 HOST_WIDE_INT value;
1061 int kind;
1062 struct jcf_block *target;
1063 struct jcf_partial *state;
1065 struct jcf_relocation *reloc = (struct jcf_relocation *)
1066 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1067 struct jcf_block *block = state->last_block;
1068 reloc->next = block->u.relocations;
1069 block->u.relocations = reloc;
1070 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1071 reloc->label = target;
1072 reloc->kind = kind;
1073 if (kind == 0 || kind == BLOCK_START_RELOC)
1074 OP4 (value);
1075 else if (kind != SWITCH_ALIGN_RELOC)
1076 OP2 (value);
1079 static void
1080 emit_switch_reloc (label, state)
1081 struct jcf_block *label;
1082 struct jcf_partial *state;
1084 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1087 /* Similar to emit_switch_reloc,
1088 but re-uses an existing case reloc. */
1090 static void
1091 emit_case_reloc (reloc, state)
1092 struct jcf_relocation *reloc;
1093 struct jcf_partial *state;
1095 struct jcf_block *block = state->last_block;
1096 reloc->next = block->u.relocations;
1097 block->u.relocations = reloc;
1098 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1099 reloc->kind = BLOCK_START_RELOC;
1100 OP4 (0);
1103 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1104 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1106 static void
1107 emit_if (target, opcode, inv_opcode, state)
1108 struct jcf_block *target;
1109 int opcode, inv_opcode;
1110 struct jcf_partial *state;
1112 RESERVE(3);
1113 OP1 (opcode);
1114 /* value is 1 byte from reloc back to start of instruction. */
1115 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1118 static void
1119 emit_goto (target, state)
1120 struct jcf_block *target;
1121 struct jcf_partial *state;
1123 RESERVE(3);
1124 OP1 (OPCODE_goto);
1125 /* Value is 1 byte from reloc back to start of instruction. */
1126 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1129 static void
1130 emit_jsr (target, state)
1131 struct jcf_block *target;
1132 struct jcf_partial *state;
1134 RESERVE(3);
1135 OP1 (OPCODE_jsr);
1136 /* Value is 1 byte from reloc back to start of instruction. */
1137 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1140 /* Generate code to evaluate EXP. If the result is true,
1141 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1142 TRUE_BRANCH_FIRST is a code geneation hint that the
1143 TRUE_LABEL may follow right after this. (The idea is that we
1144 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1146 static void
1147 generate_bytecode_conditional (exp, true_label, false_label,
1148 true_branch_first, state)
1149 tree exp;
1150 struct jcf_block *true_label;
1151 struct jcf_block *false_label;
1152 int true_branch_first;
1153 struct jcf_partial *state;
1155 tree exp0, exp1, type;
1156 int save_SP = state->code_SP;
1157 enum java_opcode op, negop;
1158 switch (TREE_CODE (exp))
1160 case INTEGER_CST:
1161 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1162 break;
1163 case COND_EXPR:
1165 struct jcf_block *then_label = gen_jcf_label (state);
1166 struct jcf_block *else_label = gen_jcf_label (state);
1167 int save_SP_before, save_SP_after;
1168 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1169 then_label, else_label, 1, state);
1170 define_jcf_label (then_label, state);
1171 save_SP_before = state->code_SP;
1172 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1173 true_label, false_label, 1, state);
1174 save_SP_after = state->code_SP;
1175 state->code_SP = save_SP_before;
1176 define_jcf_label (else_label, state);
1177 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1178 true_label, false_label,
1179 true_branch_first, state);
1180 if (state->code_SP != save_SP_after)
1181 abort ();
1183 break;
1184 case TRUTH_NOT_EXPR:
1185 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
1186 true_label, ! true_branch_first, state);
1187 break;
1188 case TRUTH_ANDIF_EXPR:
1190 struct jcf_block *next_label = gen_jcf_label (state);
1191 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1192 next_label, false_label, 1, state);
1193 define_jcf_label (next_label, state);
1194 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1195 true_label, false_label, 1, state);
1197 break;
1198 case TRUTH_ORIF_EXPR:
1200 struct jcf_block *next_label = gen_jcf_label (state);
1201 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1202 true_label, next_label, 1, state);
1203 define_jcf_label (next_label, state);
1204 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1205 true_label, false_label, 1, state);
1207 break;
1208 compare_1:
1209 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1210 set it to the corresponding 1-operand if<COND> instructions. */
1211 op = op - 6;
1212 /* FALLTHROUGH */
1213 compare_2:
1214 /* The opcodes with their inverses are allocated in pairs.
1215 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1216 negop = (op & 1) ? op + 1 : op - 1;
1217 compare_2_ptr:
1218 if (true_branch_first)
1220 emit_if (false_label, negop, op, state);
1221 emit_goto (true_label, state);
1223 else
1225 emit_if (true_label, op, negop, state);
1226 emit_goto (false_label, state);
1228 break;
1229 case EQ_EXPR:
1230 op = OPCODE_if_icmpeq;
1231 goto compare;
1232 case NE_EXPR:
1233 op = OPCODE_if_icmpne;
1234 goto compare;
1235 case GT_EXPR:
1236 op = OPCODE_if_icmpgt;
1237 goto compare;
1238 case LT_EXPR:
1239 op = OPCODE_if_icmplt;
1240 goto compare;
1241 case GE_EXPR:
1242 op = OPCODE_if_icmpge;
1243 goto compare;
1244 case LE_EXPR:
1245 op = OPCODE_if_icmple;
1246 goto compare;
1247 compare:
1248 exp0 = TREE_OPERAND (exp, 0);
1249 exp1 = TREE_OPERAND (exp, 1);
1250 type = TREE_TYPE (exp0);
1251 switch (TREE_CODE (type))
1253 int opf;
1254 case POINTER_TYPE: case RECORD_TYPE:
1255 switch (TREE_CODE (exp))
1257 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
1258 case NE_EXPR: op = OPCODE_if_acmpne; break;
1259 default: abort();
1261 if (integer_zerop (exp1) || integer_zerop (exp0))
1263 generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
1264 STACK_TARGET, state);
1265 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1266 negop = (op & 1) ? op - 1 : op + 1;
1267 NOTE_POP (1);
1268 goto compare_2_ptr;
1270 generate_bytecode_insns (exp0, STACK_TARGET, state);
1271 generate_bytecode_insns (exp1, STACK_TARGET, state);
1272 NOTE_POP (2);
1273 goto compare_2;
1274 case REAL_TYPE:
1275 generate_bytecode_insns (exp0, STACK_TARGET, state);
1276 generate_bytecode_insns (exp1, STACK_TARGET, state);
1277 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1278 opf = OPCODE_fcmpg;
1279 else
1280 opf = OPCODE_fcmpl;
1281 if (TYPE_PRECISION (type) > 32)
1283 opf += 2;
1284 NOTE_POP (4);
1286 else
1287 NOTE_POP (2);
1288 RESERVE (1);
1289 OP1 (opf);
1290 goto compare_1;
1291 case INTEGER_TYPE:
1292 if (TYPE_PRECISION (type) > 32)
1294 generate_bytecode_insns (exp0, STACK_TARGET, state);
1295 generate_bytecode_insns (exp1, STACK_TARGET, state);
1296 NOTE_POP (4);
1297 RESERVE (1);
1298 OP1 (OPCODE_lcmp);
1299 goto compare_1;
1301 /* FALLTHOUGH */
1302 default:
1303 if (integer_zerop (exp1))
1305 generate_bytecode_insns (exp0, STACK_TARGET, state);
1306 NOTE_POP (1);
1307 goto compare_1;
1309 if (integer_zerop (exp0))
1311 switch (op)
1313 case OPCODE_if_icmplt:
1314 case OPCODE_if_icmpge:
1315 op += 2;
1316 break;
1317 case OPCODE_if_icmpgt:
1318 case OPCODE_if_icmple:
1319 op -= 2;
1320 break;
1321 default:
1322 break;
1324 generate_bytecode_insns (exp1, STACK_TARGET, state);
1325 NOTE_POP (1);
1326 goto compare_1;
1328 generate_bytecode_insns (exp0, STACK_TARGET, state);
1329 generate_bytecode_insns (exp1, STACK_TARGET, state);
1330 NOTE_POP (2);
1331 goto compare_2;
1334 default:
1335 generate_bytecode_insns (exp, STACK_TARGET, state);
1336 NOTE_POP (1);
1337 if (true_branch_first)
1339 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1340 emit_goto (true_label, state);
1342 else
1344 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1345 emit_goto (false_label, state);
1347 break;
1349 if (save_SP != state->code_SP)
1350 abort ();
1353 /* Call pending cleanups i.e. those for surrounding CLEANUP_POINT_EXPRs
1354 but only as far out as LIMIT (since we are about to jump to the
1355 emit label that is LIMIT). */
1357 static void
1358 call_cleanups (limit, state)
1359 struct jcf_block *limit;
1360 struct jcf_partial *state;
1362 struct jcf_block *block = state->labeled_blocks;
1363 for (; block != limit; block = block->next)
1365 if (block->pc == PENDING_CLEANUP_PC)
1366 emit_jsr (block, state);
1370 static void
1371 generate_bytecode_return (exp, state)
1372 tree exp;
1373 struct jcf_partial *state;
1375 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1376 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1377 int op;
1378 again:
1379 if (exp != NULL)
1381 switch (TREE_CODE (exp))
1383 case COMPOUND_EXPR:
1384 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1385 state);
1386 exp = TREE_OPERAND (exp, 1);
1387 goto again;
1388 case COND_EXPR:
1390 struct jcf_block *then_label = gen_jcf_label (state);
1391 struct jcf_block *else_label = gen_jcf_label (state);
1392 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1393 then_label, else_label, 1, state);
1394 define_jcf_label (then_label, state);
1395 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1396 define_jcf_label (else_label, state);
1397 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1399 return;
1400 default:
1401 generate_bytecode_insns (exp,
1402 returns_void ? IGNORE_TARGET
1403 : STACK_TARGET, state);
1406 if (returns_void)
1408 op = OPCODE_return;
1409 call_cleanups (NULL, state);
1411 else
1413 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1414 if (state->num_finalizers > 0)
1416 if (state->return_value_decl == NULL_TREE)
1418 state->return_value_decl
1419 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1420 localvar_alloc (state->return_value_decl, state);
1422 emit_store (state->return_value_decl, state);
1423 call_cleanups (NULL, state);
1424 emit_load (state->return_value_decl, state);
1425 /* If we call localvar_free (state->return_value_decl, state),
1426 then we risk the save decl erroneously re-used in the
1427 finalizer. Instead, we keep the state->return_value_decl
1428 allocated through the rest of the method. This is not
1429 the greatest solution, but it is at least simple and safe. */
1432 RESERVE (1);
1433 OP1 (op);
1436 /* Generate bytecode for sub-expression EXP of METHOD.
1437 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1439 static void
1440 generate_bytecode_insns (exp, target, state)
1441 tree exp;
1442 int target;
1443 struct jcf_partial *state;
1445 tree type;
1446 enum java_opcode jopcode;
1447 int op;
1448 HOST_WIDE_INT value;
1449 int post_op;
1450 int size;
1451 int offset;
1453 if (exp == NULL && target == IGNORE_TARGET)
1454 return;
1456 type = TREE_TYPE (exp);
1458 switch (TREE_CODE (exp))
1460 case BLOCK:
1461 if (BLOCK_EXPR_BODY (exp))
1463 tree local;
1464 tree body = BLOCK_EXPR_BODY (exp);
1465 for (local = BLOCK_EXPR_DECLS (exp); local; )
1467 tree next = TREE_CHAIN (local);
1468 localvar_alloc (local, state);
1469 local = next;
1471 /* Avoid deep recursion for long blocks. */
1472 while (TREE_CODE (body) == COMPOUND_EXPR)
1474 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1475 body = TREE_OPERAND (body, 1);
1477 generate_bytecode_insns (body, target, state);
1478 for (local = BLOCK_EXPR_DECLS (exp); local; )
1480 tree next = TREE_CHAIN (local);
1481 localvar_free (local, state);
1482 local = next;
1485 break;
1486 case COMPOUND_EXPR:
1487 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1488 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1489 break;
1490 case EXPR_WITH_FILE_LOCATION:
1492 const char *saved_input_filename = input_filename;
1493 tree body = EXPR_WFL_NODE (exp);
1494 int saved_lineno = lineno;
1495 if (body == empty_stmt_node)
1496 break;
1497 input_filename = EXPR_WFL_FILENAME (exp);
1498 lineno = EXPR_WFL_LINENO (exp);
1499 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && lineno > 0
1500 && debug_info_level > DINFO_LEVEL_NONE)
1501 put_linenumber (lineno, state);
1502 generate_bytecode_insns (body, target, state);
1503 input_filename = saved_input_filename;
1504 lineno = saved_lineno;
1506 break;
1507 case INTEGER_CST:
1508 if (target == IGNORE_TARGET) ; /* do nothing */
1509 else if (TREE_CODE (type) == POINTER_TYPE)
1511 if (! integer_zerop (exp))
1512 abort();
1513 RESERVE(1);
1514 OP1 (OPCODE_aconst_null);
1515 NOTE_PUSH (1);
1517 else if (TYPE_PRECISION (type) <= 32)
1519 push_int_const (TREE_INT_CST_LOW (exp), state);
1520 NOTE_PUSH (1);
1522 else
1524 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1525 state);
1526 NOTE_PUSH (2);
1528 break;
1529 case REAL_CST:
1531 int prec = TYPE_PRECISION (type) >> 5;
1532 RESERVE(1);
1533 if (real_zerop (exp))
1534 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1535 else if (real_onep (exp))
1536 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1537 /* FIXME Should also use fconst_2 for 2.0f.
1538 Also, should use iconst_2/ldc followed by i2f/i2d
1539 for other float/double when the value is a small integer. */
1540 else
1542 offset = find_constant_index (exp, state);
1543 if (prec == 1)
1544 push_constant1 (offset, state);
1545 else
1546 push_constant2 (offset, state);
1548 NOTE_PUSH (prec);
1550 break;
1551 case STRING_CST:
1552 push_constant1 (find_string_constant (&state->cpool, exp), state);
1553 NOTE_PUSH (1);
1554 break;
1555 case VAR_DECL:
1556 if (TREE_STATIC (exp))
1558 field_op (exp, OPCODE_getstatic, state);
1559 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1560 break;
1562 /* ... fall through ... */
1563 case PARM_DECL:
1564 emit_load (exp, state);
1565 break;
1566 case NON_LVALUE_EXPR:
1567 case INDIRECT_REF:
1568 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1569 break;
1570 case ARRAY_REF:
1571 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1572 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1573 if (target != IGNORE_TARGET)
1575 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1576 RESERVE(1);
1577 OP1 (jopcode);
1578 if (! TYPE_IS_WIDE (type))
1579 NOTE_POP (1);
1581 break;
1582 case COMPONENT_REF:
1584 tree obj = TREE_OPERAND (exp, 0);
1585 tree field = TREE_OPERAND (exp, 1);
1586 int is_static = FIELD_STATIC (field);
1587 generate_bytecode_insns (obj,
1588 is_static ? IGNORE_TARGET : target, state);
1589 if (target != IGNORE_TARGET)
1591 if (DECL_NAME (field) == length_identifier_node && !is_static
1592 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1594 RESERVE (1);
1595 OP1 (OPCODE_arraylength);
1597 else
1599 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1600 state);
1601 if (! is_static)
1602 NOTE_POP (1);
1603 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1607 break;
1608 case TRUTH_ANDIF_EXPR:
1609 case TRUTH_ORIF_EXPR:
1610 case EQ_EXPR:
1611 case NE_EXPR:
1612 case GT_EXPR:
1613 case LT_EXPR:
1614 case GE_EXPR:
1615 case LE_EXPR:
1617 struct jcf_block *then_label = gen_jcf_label (state);
1618 struct jcf_block *else_label = gen_jcf_label (state);
1619 struct jcf_block *end_label = gen_jcf_label (state);
1620 generate_bytecode_conditional (exp,
1621 then_label, else_label, 1, state);
1622 define_jcf_label (then_label, state);
1623 push_int_const (1, state);
1624 emit_goto (end_label, state);
1625 define_jcf_label (else_label, state);
1626 push_int_const (0, state);
1627 define_jcf_label (end_label, state);
1628 NOTE_PUSH (1);
1630 break;
1631 case COND_EXPR:
1633 struct jcf_block *then_label = gen_jcf_label (state);
1634 struct jcf_block *else_label = gen_jcf_label (state);
1635 struct jcf_block *end_label = gen_jcf_label (state);
1636 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1637 then_label, else_label, 1, state);
1638 define_jcf_label (then_label, state);
1639 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1640 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1641 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1642 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1643 emit_goto (end_label, state);
1644 define_jcf_label (else_label, state);
1645 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1646 define_jcf_label (end_label, state);
1647 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1648 if (TREE_TYPE (exp) != void_type_node)
1649 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1651 break;
1652 case CASE_EXPR:
1654 struct jcf_switch_state *sw_state = state->sw_state;
1655 struct jcf_relocation *reloc = (struct jcf_relocation *)
1656 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1657 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1658 reloc->kind = 0;
1659 reloc->label = get_jcf_label_here (state);
1660 reloc->offset = case_value;
1661 reloc->next = sw_state->cases;
1662 sw_state->cases = reloc;
1663 if (sw_state->num_cases == 0)
1665 sw_state->min_case = case_value;
1666 sw_state->max_case = case_value;
1668 else
1670 if (case_value < sw_state->min_case)
1671 sw_state->min_case = case_value;
1672 if (case_value > sw_state->max_case)
1673 sw_state->max_case = case_value;
1675 sw_state->num_cases++;
1677 break;
1678 case DEFAULT_EXPR:
1679 state->sw_state->default_label = get_jcf_label_here (state);
1680 break;
1682 case SWITCH_EXPR:
1684 /* The SWITCH_EXPR has three parts, generated in the following order:
1685 1. the switch_expression (the value used to select the correct case);
1686 2. the switch_body;
1687 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1688 After code generation, we will re-order then in the order 1, 3, 2.
1689 This is to avoid an extra GOTOs. */
1690 struct jcf_switch_state sw_state;
1691 struct jcf_block *expression_last; /* Last block of the switch_expression. */
1692 struct jcf_block *body_last; /* Last block of the switch_body. */
1693 struct jcf_block *switch_instruction; /* First block of switch_instruction. */
1694 struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1695 struct jcf_block *body_block;
1696 int switch_length;
1697 sw_state.prev = state->sw_state;
1698 state->sw_state = &sw_state;
1699 sw_state.cases = NULL;
1700 sw_state.num_cases = 0;
1701 sw_state.default_label = NULL;
1702 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1703 expression_last = state->last_block;
1704 body_block = get_jcf_label_here (state); /* Force a new block here. */
1705 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1706 body_last = state->last_block;
1708 switch_instruction = gen_jcf_label (state);
1709 define_jcf_label (switch_instruction, state);
1710 if (sw_state.default_label == NULL)
1711 sw_state.default_label = gen_jcf_label (state);
1713 if (sw_state.num_cases <= 1)
1715 if (sw_state.num_cases == 0)
1717 emit_pop (1, state);
1718 NOTE_POP (1);
1720 else
1722 push_int_const (sw_state.cases->offset, state);
1723 emit_if (sw_state.cases->label,
1724 OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1726 emit_goto (sw_state.default_label, state);
1728 else
1730 HOST_WIDE_INT i;
1731 /* Copy the chain of relocs into a sorted array. */
1732 struct jcf_relocation **relocs = (struct jcf_relocation **)
1733 xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1734 /* The relocs arrays is a buffer with a gap.
1735 The assumption is that cases will normally come in "runs". */
1736 int gap_start = 0;
1737 int gap_end = sw_state.num_cases;
1738 struct jcf_relocation *reloc;
1739 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
1741 HOST_WIDE_INT case_value = reloc->offset;
1742 while (gap_end < sw_state.num_cases)
1744 struct jcf_relocation *end = relocs[gap_end];
1745 if (case_value <= end->offset)
1746 break;
1747 relocs[gap_start++] = end;
1748 gap_end++;
1750 while (gap_start > 0)
1752 struct jcf_relocation *before = relocs[gap_start-1];
1753 if (case_value >= before->offset)
1754 break;
1755 relocs[--gap_end] = before;
1756 gap_start--;
1758 relocs[gap_start++] = reloc;
1759 /* Note we don't check for duplicates. FIXME! */
1762 if (2 * sw_state.num_cases
1763 >= sw_state.max_case - sw_state.min_case)
1764 { /* Use tableswitch. */
1765 int index = 0;
1766 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1767 OP1 (OPCODE_tableswitch);
1768 emit_reloc (RELOCATION_VALUE_0,
1769 SWITCH_ALIGN_RELOC, NULL, state);
1770 emit_switch_reloc (sw_state.default_label, state);
1771 OP4 (sw_state.min_case);
1772 OP4 (sw_state.max_case);
1773 for (i = sw_state.min_case; ; )
1775 reloc = relocs[index];
1776 if (i == reloc->offset)
1778 emit_case_reloc (reloc, state);
1779 if (i == sw_state.max_case)
1780 break;
1781 index++;
1783 else
1784 emit_switch_reloc (sw_state.default_label, state);
1785 i++;
1788 else
1789 { /* Use lookupswitch. */
1790 RESERVE(9 + 8 * sw_state.num_cases);
1791 OP1 (OPCODE_lookupswitch);
1792 emit_reloc (RELOCATION_VALUE_0,
1793 SWITCH_ALIGN_RELOC, NULL, state);
1794 emit_switch_reloc (sw_state.default_label, state);
1795 OP4 (sw_state.num_cases);
1796 for (i = 0; i < sw_state.num_cases; i++)
1798 struct jcf_relocation *reloc = relocs[i];
1799 OP4 (reloc->offset);
1800 emit_case_reloc (reloc, state);
1803 free (relocs);
1806 instruction_last = state->last_block;
1807 if (sw_state.default_label->pc < 0)
1808 define_jcf_label (sw_state.default_label, state);
1809 else /* Force a new block. */
1810 sw_state.default_label = get_jcf_label_here (state);
1811 /* Now re-arrange the blocks so the switch_instruction
1812 comes before the switch_body. */
1813 switch_length = state->code_length - switch_instruction->pc;
1814 switch_instruction->pc = body_block->pc;
1815 instruction_last->next = body_block;
1816 instruction_last->v.chunk->next = body_block->v.chunk;
1817 expression_last->next = switch_instruction;
1818 expression_last->v.chunk->next = switch_instruction->v.chunk;
1819 body_last->next = sw_state.default_label;
1820 body_last->v.chunk->next = NULL;
1821 state->chunk = body_last->v.chunk;
1822 for (; body_block != sw_state.default_label; body_block = body_block->next)
1823 body_block->pc += switch_length;
1825 state->sw_state = sw_state.prev;
1826 break;
1829 case RETURN_EXPR:
1830 exp = TREE_OPERAND (exp, 0);
1831 if (exp == NULL_TREE)
1832 exp = empty_stmt_node;
1833 else if (TREE_CODE (exp) != MODIFY_EXPR)
1834 abort ();
1835 else
1836 exp = TREE_OPERAND (exp, 1);
1837 generate_bytecode_return (exp, state);
1838 break;
1839 case LABELED_BLOCK_EXPR:
1841 struct jcf_block *end_label = gen_jcf_label (state);
1842 end_label->next = state->labeled_blocks;
1843 state->labeled_blocks = end_label;
1844 end_label->pc = PENDING_EXIT_PC;
1845 end_label->u.labeled_block = exp;
1846 if (LABELED_BLOCK_BODY (exp))
1847 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1848 if (state->labeled_blocks != end_label)
1849 abort();
1850 state->labeled_blocks = end_label->next;
1851 define_jcf_label (end_label, state);
1853 break;
1854 case LOOP_EXPR:
1856 tree body = TREE_OPERAND (exp, 0);
1857 #if 0
1858 if (TREE_CODE (body) == COMPOUND_EXPR
1859 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1861 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1862 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1863 struct jcf_block *head_label;
1864 struct jcf_block *body_label;
1865 struct jcf_block *end_label = gen_jcf_label (state);
1866 struct jcf_block *exit_label = state->labeled_blocks;
1867 head_label = gen_jcf_label (state);
1868 emit_goto (head_label, state);
1869 body_label = get_jcf_label_here (state);
1870 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1871 define_jcf_label (head_label, state);
1872 generate_bytecode_conditional (TREE_OPERAND (body, 0),
1873 end_label, body_label, 1, state);
1874 define_jcf_label (end_label, state);
1876 else
1877 #endif
1879 struct jcf_block *head_label = get_jcf_label_here (state);
1880 generate_bytecode_insns (body, IGNORE_TARGET, state);
1881 emit_goto (head_label, state);
1884 break;
1885 case EXIT_EXPR:
1887 struct jcf_block *label = state->labeled_blocks;
1888 struct jcf_block *end_label = gen_jcf_label (state);
1889 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1890 label, end_label, 0, state);
1891 define_jcf_label (end_label, state);
1893 break;
1894 case EXIT_BLOCK_EXPR:
1896 struct jcf_block *label = state->labeled_blocks;
1897 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1898 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1899 label = label->next;
1900 call_cleanups (label, state);
1901 emit_goto (label, state);
1903 break;
1905 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
1906 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
1907 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
1908 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
1909 increment:
1911 exp = TREE_OPERAND (exp, 0);
1912 type = TREE_TYPE (exp);
1913 size = TYPE_IS_WIDE (type) ? 2 : 1;
1914 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1915 && ! TREE_STATIC (exp)
1916 && TREE_CODE (type) == INTEGER_TYPE
1917 && TYPE_PRECISION (type) == 32)
1919 if (target != IGNORE_TARGET && post_op)
1920 emit_load (exp, state);
1921 emit_iinc (exp, value, state);
1922 if (target != IGNORE_TARGET && ! post_op)
1923 emit_load (exp, state);
1924 break;
1926 if (TREE_CODE (exp) == COMPONENT_REF)
1928 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1929 emit_dup (1, 0, state);
1930 /* Stack: ..., objectref, objectref. */
1931 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1932 NOTE_PUSH (size-1);
1933 /* Stack: ..., objectref, oldvalue. */
1934 offset = 1;
1936 else if (TREE_CODE (exp) == ARRAY_REF)
1938 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1939 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1940 emit_dup (2, 0, state);
1941 /* Stack: ..., array, index, array, index. */
1942 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1943 RESERVE(1);
1944 OP1 (jopcode);
1945 NOTE_POP (2-size);
1946 /* Stack: ..., array, index, oldvalue. */
1947 offset = 2;
1949 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1951 generate_bytecode_insns (exp, STACK_TARGET, state);
1952 /* Stack: ..., oldvalue. */
1953 offset = 0;
1955 else
1956 abort ();
1958 if (target != IGNORE_TARGET && post_op)
1959 emit_dup (size, offset, state);
1960 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1961 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1962 /* Stack, otherwise: ..., [result, ] oldvalue. */
1963 if (size == 1)
1964 push_int_const (value, state);
1965 else
1966 push_long_const (value, (HOST_WIDE_INT)(value >= 0 ? 0 : -1), state);
1967 NOTE_PUSH (size);
1968 emit_binop (OPCODE_iadd + adjust_typed_op (type, 3), type, state);
1969 if (target != IGNORE_TARGET && ! post_op)
1970 emit_dup (size, offset, state);
1971 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1972 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1973 /* Stack, otherwise: ..., [result, ] newvalue. */
1974 goto finish_assignment;
1976 case MODIFY_EXPR:
1978 tree lhs = TREE_OPERAND (exp, 0);
1979 tree rhs = TREE_OPERAND (exp, 1);
1980 int offset = 0;
1982 /* See if we can use the iinc instruction. */
1983 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
1984 && ! TREE_STATIC (lhs)
1985 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
1986 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
1987 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
1989 tree arg0 = TREE_OPERAND (rhs, 0);
1990 tree arg1 = TREE_OPERAND (rhs, 1);
1991 HOST_WIDE_INT min_value = -32768;
1992 HOST_WIDE_INT max_value = 32767;
1993 if (TREE_CODE (rhs) == MINUS_EXPR)
1995 min_value++;
1996 max_value++;
1998 else if (arg1 == lhs)
2000 arg0 = arg1;
2001 arg1 = TREE_OPERAND (rhs, 0);
2003 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
2005 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
2006 value = TREE_INT_CST_LOW (arg1);
2007 if ((hi_value == 0 && value <= max_value)
2008 || (hi_value == -1 && value >= min_value))
2010 if (TREE_CODE (rhs) == MINUS_EXPR)
2011 value = -value;
2012 emit_iinc (lhs, value, state);
2013 if (target != IGNORE_TARGET)
2014 emit_load (lhs, state);
2015 break;
2020 if (TREE_CODE (lhs) == COMPONENT_REF)
2022 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
2023 STACK_TARGET, state);
2024 offset = 1;
2026 else if (TREE_CODE (lhs) == ARRAY_REF)
2028 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
2029 STACK_TARGET, state);
2030 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
2031 STACK_TARGET, state);
2032 offset = 2;
2034 else
2035 offset = 0;
2036 generate_bytecode_insns (rhs, STACK_TARGET, state);
2037 if (target != IGNORE_TARGET)
2038 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2039 exp = lhs;
2041 /* FALLTHOUGH */
2043 finish_assignment:
2044 if (TREE_CODE (exp) == COMPONENT_REF)
2046 tree field = TREE_OPERAND (exp, 1);
2047 if (! FIELD_STATIC (field))
2048 NOTE_POP (1);
2049 field_op (field,
2050 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2051 state);
2053 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2055 else if (TREE_CODE (exp) == VAR_DECL
2056 || TREE_CODE (exp) == PARM_DECL)
2058 if (FIELD_STATIC (exp))
2060 field_op (exp, OPCODE_putstatic, state);
2061 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2063 else
2064 emit_store (exp, state);
2066 else if (TREE_CODE (exp) == ARRAY_REF)
2068 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2069 RESERVE (1);
2070 OP1 (jopcode);
2071 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2073 else
2074 abort ();
2075 break;
2076 case PLUS_EXPR:
2077 jopcode = OPCODE_iadd;
2078 goto binop;
2079 case MINUS_EXPR:
2080 jopcode = OPCODE_isub;
2081 goto binop;
2082 case MULT_EXPR:
2083 jopcode = OPCODE_imul;
2084 goto binop;
2085 case TRUNC_DIV_EXPR:
2086 case RDIV_EXPR:
2087 jopcode = OPCODE_idiv;
2088 goto binop;
2089 case TRUNC_MOD_EXPR:
2090 jopcode = OPCODE_irem;
2091 goto binop;
2092 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
2093 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
2094 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
2095 case TRUTH_AND_EXPR:
2096 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
2097 case TRUTH_OR_EXPR:
2098 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
2099 case TRUTH_XOR_EXPR:
2100 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
2101 binop:
2103 tree arg0 = TREE_OPERAND (exp, 0);
2104 tree arg1 = TREE_OPERAND (exp, 1);
2105 jopcode += adjust_typed_op (type, 3);
2106 if (arg0 == arg1 && TREE_CODE (arg0) == SAVE_EXPR)
2108 /* fold may (e.g) convert 2*x to x+x. */
2109 generate_bytecode_insns (TREE_OPERAND (arg0, 0), target, state);
2110 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2112 else
2114 generate_bytecode_insns (arg0, target, state);
2115 if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2116 arg1 = convert (int_type_node, arg1);
2117 generate_bytecode_insns (arg1, target, state);
2119 /* For most binary operations, both operands and the result have the
2120 same type. Shift operations are different. Using arg1's type
2121 gets us the correct SP adjustment in all cases. */
2122 if (target == STACK_TARGET)
2123 emit_binop (jopcode, TREE_TYPE (arg1), state);
2124 break;
2126 case TRUTH_NOT_EXPR:
2127 case BIT_NOT_EXPR:
2128 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2129 if (target == STACK_TARGET)
2131 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2132 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
2133 RESERVE (2);
2134 if (is_long)
2135 OP1 (OPCODE_i2l);
2136 NOTE_PUSH (1 + is_long);
2137 OP1 (OPCODE_ixor + is_long);
2138 NOTE_POP (1 + is_long);
2140 break;
2141 case NEGATE_EXPR:
2142 jopcode = OPCODE_ineg;
2143 jopcode += adjust_typed_op (type, 3);
2144 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2145 if (target == STACK_TARGET)
2146 emit_unop (jopcode, type, state);
2147 break;
2148 case INSTANCEOF_EXPR:
2150 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2151 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2152 RESERVE (3);
2153 OP1 (OPCODE_instanceof);
2154 OP2 (index);
2156 break;
2157 case SAVE_EXPR:
2158 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2159 break;
2160 case CONVERT_EXPR:
2161 case NOP_EXPR:
2162 case FLOAT_EXPR:
2163 case FIX_TRUNC_EXPR:
2165 tree src = TREE_OPERAND (exp, 0);
2166 tree src_type = TREE_TYPE (src);
2167 tree dst_type = TREE_TYPE (exp);
2168 /* Detect the situation of compiling an empty synchronized
2169 block. A nop should be emitted in order to produce
2170 verifiable bytecode. */
2171 if (exp == empty_stmt_node
2172 && state->last_bc == OPCODE_monitorenter
2173 && state->labeled_blocks
2174 && state->labeled_blocks->pc == PENDING_CLEANUP_PC)
2175 OP1 (OPCODE_nop);
2176 else
2177 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2178 if (target == IGNORE_TARGET || src_type == dst_type)
2179 break;
2180 if (TREE_CODE (dst_type) == POINTER_TYPE)
2182 if (TREE_CODE (exp) == CONVERT_EXPR)
2184 int index = find_class_constant (&state->cpool,
2185 TREE_TYPE (dst_type));
2186 RESERVE (3);
2187 OP1 (OPCODE_checkcast);
2188 OP2 (index);
2191 else /* Convert numeric types. */
2193 int wide_src = TYPE_PRECISION (src_type) > 32;
2194 int wide_dst = TYPE_PRECISION (dst_type) > 32;
2195 NOTE_POP (1 + wide_src);
2196 RESERVE (1);
2197 if (TREE_CODE (dst_type) == REAL_TYPE)
2199 if (TREE_CODE (src_type) == REAL_TYPE)
2200 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2201 else if (TYPE_PRECISION (src_type) == 64)
2202 OP1 (OPCODE_l2f + wide_dst);
2203 else
2204 OP1 (OPCODE_i2f + wide_dst);
2206 else /* Convert to integral type. */
2208 if (TREE_CODE (src_type) == REAL_TYPE)
2209 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2210 else if (wide_dst)
2211 OP1 (OPCODE_i2l);
2212 else if (wide_src)
2213 OP1 (OPCODE_l2i);
2214 if (TYPE_PRECISION (dst_type) < 32)
2216 RESERVE (1);
2217 /* Already converted to int, if needed. */
2218 if (TYPE_PRECISION (dst_type) <= 8)
2219 OP1 (OPCODE_i2b);
2220 else if (TREE_UNSIGNED (dst_type))
2221 OP1 (OPCODE_i2c);
2222 else
2223 OP1 (OPCODE_i2s);
2226 NOTE_PUSH (1 + wide_dst);
2229 break;
2231 case CLEANUP_POINT_EXPR:
2233 struct jcf_block *save_labeled_blocks = state->labeled_blocks;
2234 int can_complete = CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0));
2235 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
2236 if (target != IGNORE_TARGET)
2237 abort ();
2238 while (state->labeled_blocks != save_labeled_blocks)
2240 struct jcf_block *finished_label = NULL;
2241 tree return_link;
2242 tree exception_type = build_pointer_type (throwable_type_node);
2243 tree exception_decl = build_decl (VAR_DECL, NULL_TREE,
2244 exception_type);
2245 struct jcf_block *end_label = get_jcf_label_here (state);
2246 struct jcf_block *label = state->labeled_blocks;
2247 struct jcf_handler *handler;
2248 tree cleanup = label->u.labeled_block;
2249 state->labeled_blocks = label->next;
2250 state->num_finalizers--;
2251 if (can_complete)
2253 finished_label = gen_jcf_label (state);
2254 emit_jsr (label, state);
2255 emit_goto (finished_label, state);
2256 if (! CAN_COMPLETE_NORMALLY (cleanup))
2257 can_complete = 0;
2259 handler = alloc_handler (label->v.start_label, end_label, state);
2260 handler->type = NULL_TREE;
2261 localvar_alloc (exception_decl, state);
2262 NOTE_PUSH (1);
2263 emit_store (exception_decl, state);
2264 emit_jsr (label, state);
2265 emit_load (exception_decl, state);
2266 RESERVE (1);
2267 OP1 (OPCODE_athrow);
2268 NOTE_POP (1);
2270 /* The finally block. */
2271 return_link = build_decl (VAR_DECL, NULL_TREE,
2272 return_address_type_node);
2273 define_jcf_label (label, state);
2274 NOTE_PUSH (1);
2275 localvar_alloc (return_link, state);
2276 emit_store (return_link, state);
2277 generate_bytecode_insns (cleanup, IGNORE_TARGET, state);
2278 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2279 localvar_free (return_link, state);
2280 localvar_free (exception_decl, state);
2281 if (finished_label != NULL)
2282 define_jcf_label (finished_label, state);
2285 break;
2287 case WITH_CLEANUP_EXPR:
2289 struct jcf_block *label;
2290 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
2291 label = gen_jcf_label (state);
2292 label->pc = PENDING_CLEANUP_PC;
2293 label->next = state->labeled_blocks;
2294 state->labeled_blocks = label;
2295 state->num_finalizers++;
2296 label->u.labeled_block = TREE_OPERAND (exp, 1);
2297 label->v.start_label = get_jcf_label_here (state);
2298 if (target != IGNORE_TARGET)
2299 abort ();
2301 break;
2303 case TRY_EXPR:
2305 tree try_clause = TREE_OPERAND (exp, 0);
2306 struct jcf_block *start_label = get_jcf_label_here (state);
2307 struct jcf_block *end_label; /* End of try clause. */
2308 struct jcf_block *finished_label = gen_jcf_label (state);
2309 tree clause = TREE_OPERAND (exp, 1);
2310 if (target != IGNORE_TARGET)
2311 abort ();
2312 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2313 end_label = get_jcf_label_here (state);
2314 if (end_label == start_label)
2315 break;
2316 if (CAN_COMPLETE_NORMALLY (try_clause))
2317 emit_goto (finished_label, state);
2318 while (clause != NULL_TREE)
2320 tree catch_clause = TREE_OPERAND (clause, 0);
2321 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2322 struct jcf_handler *handler = alloc_handler (start_label, end_label, state);
2323 if (exception_decl == NULL_TREE)
2324 handler->type = NULL_TREE;
2325 else
2326 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2327 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2328 clause = TREE_CHAIN (clause);
2329 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2330 emit_goto (finished_label, state);
2332 define_jcf_label (finished_label, state);
2334 break;
2335 case TRY_FINALLY_EXPR:
2337 struct jcf_block *finished_label,
2338 *finally_label, *start_label, *end_label;
2339 struct jcf_handler *handler;
2340 tree try_block = TREE_OPERAND (exp, 0);
2341 tree finally = TREE_OPERAND (exp, 1);
2342 tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2344 tree exception_type;
2346 finally_label = gen_jcf_label (state);
2347 start_label = get_jcf_label_here (state);
2348 finally_label->pc = PENDING_CLEANUP_PC;
2349 finally_label->next = state->labeled_blocks;
2350 state->labeled_blocks = finally_label;
2351 state->num_finalizers++;
2353 generate_bytecode_insns (try_block, target, state);
2354 if (state->labeled_blocks != finally_label)
2355 abort();
2356 state->labeled_blocks = finally_label->next;
2357 end_label = get_jcf_label_here (state);
2359 if (end_label == start_label)
2361 state->num_finalizers--;
2362 define_jcf_label (finally_label, state);
2363 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2364 break;
2367 return_link = build_decl (VAR_DECL, NULL_TREE,
2368 return_address_type_node);
2369 finished_label = gen_jcf_label (state);
2372 if (CAN_COMPLETE_NORMALLY (try_block))
2374 emit_jsr (finally_label, state);
2375 emit_goto (finished_label, state);
2378 /* Handle exceptions. */
2380 exception_type = build_pointer_type (throwable_type_node);
2381 exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2382 localvar_alloc (return_link, state);
2383 handler = alloc_handler (start_label, end_label, state);
2384 handler->type = NULL_TREE;
2385 localvar_alloc (exception_decl, state);
2386 NOTE_PUSH (1);
2387 emit_store (exception_decl, state);
2388 emit_jsr (finally_label, state);
2389 emit_load (exception_decl, state);
2390 RESERVE (1);
2391 OP1 (OPCODE_athrow);
2392 NOTE_POP (1);
2394 /* The finally block. First save return PC into return_link. */
2395 define_jcf_label (finally_label, state);
2396 NOTE_PUSH (1);
2397 emit_store (return_link, state);
2399 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2400 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2401 localvar_free (exception_decl, state);
2402 localvar_free (return_link, state);
2403 define_jcf_label (finished_label, state);
2405 break;
2406 case THROW_EXPR:
2407 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2408 RESERVE (1);
2409 OP1 (OPCODE_athrow);
2410 break;
2411 case NEW_ARRAY_INIT:
2413 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2414 tree array_type = TREE_TYPE (TREE_TYPE (exp));
2415 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2416 HOST_WIDE_INT length = java_array_type_length (array_type);
2417 if (target == IGNORE_TARGET)
2419 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
2420 generate_bytecode_insns (TREE_VALUE (values), target, state);
2421 break;
2423 push_int_const (length, state);
2424 NOTE_PUSH (1);
2425 RESERVE (3);
2426 if (JPRIMITIVE_TYPE_P (element_type))
2428 int atype = encode_newarray_type (element_type);
2429 OP1 (OPCODE_newarray);
2430 OP1 (atype);
2432 else
2434 int index = find_class_constant (&state->cpool,
2435 TREE_TYPE (element_type));
2436 OP1 (OPCODE_anewarray);
2437 OP2 (index);
2439 offset = 0;
2440 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2441 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
2443 int save_SP = state->code_SP;
2444 emit_dup (1, 0, state);
2445 push_int_const (offset, state);
2446 NOTE_PUSH (1);
2447 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2448 RESERVE (1);
2449 OP1 (jopcode);
2450 state->code_SP = save_SP;
2453 break;
2454 case JAVA_EXC_OBJ_EXPR:
2455 NOTE_PUSH (1); /* Pushed by exception system. */
2456 break;
2457 case NEW_CLASS_EXPR:
2459 tree class = TREE_TYPE (TREE_TYPE (exp));
2460 int need_result = target != IGNORE_TARGET;
2461 int index = find_class_constant (&state->cpool, class);
2462 RESERVE (4);
2463 OP1 (OPCODE_new);
2464 OP2 (index);
2465 if (need_result)
2466 OP1 (OPCODE_dup);
2467 NOTE_PUSH (1 + need_result);
2469 /* ... fall though ... */
2470 case CALL_EXPR:
2472 tree f = TREE_OPERAND (exp, 0);
2473 tree x = TREE_OPERAND (exp, 1);
2474 int save_SP = state->code_SP;
2475 int nargs;
2476 if (TREE_CODE (f) == ADDR_EXPR)
2477 f = TREE_OPERAND (f, 0);
2478 if (f == soft_newarray_node)
2480 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2481 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2482 STACK_TARGET, state);
2483 RESERVE (2);
2484 OP1 (OPCODE_newarray);
2485 OP1 (type_code);
2486 break;
2488 else if (f == soft_multianewarray_node)
2490 int ndims;
2491 int idim;
2492 int index = find_class_constant (&state->cpool,
2493 TREE_TYPE (TREE_TYPE (exp)));
2494 x = TREE_CHAIN (x); /* Skip class argument. */
2495 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2496 for (idim = ndims; --idim >= 0; )
2498 x = TREE_CHAIN (x);
2499 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2501 RESERVE (4);
2502 OP1 (OPCODE_multianewarray);
2503 OP2 (index);
2504 OP1 (ndims);
2505 break;
2507 else if (f == soft_anewarray_node)
2509 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2510 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2511 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2512 RESERVE (3);
2513 OP1 (OPCODE_anewarray);
2514 OP2 (index);
2515 break;
2517 else if (f == soft_monitorenter_node
2518 || f == soft_monitorexit_node
2519 || f == throw_node)
2521 if (f == soft_monitorenter_node)
2522 op = OPCODE_monitorenter;
2523 else if (f == soft_monitorexit_node)
2524 op = OPCODE_monitorexit;
2525 else
2526 op = OPCODE_athrow;
2527 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2528 RESERVE (1);
2529 OP1 (op);
2530 NOTE_POP (1);
2531 break;
2533 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
2535 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2537 nargs = state->code_SP - save_SP;
2538 state->code_SP = save_SP;
2539 if (f == soft_fmod_node)
2541 RESERVE (1);
2542 OP1 (OPCODE_drem);
2543 NOTE_PUSH (2);
2544 break;
2546 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2547 NOTE_POP (1); /* Pop implicit this. */
2548 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2550 tree context = DECL_CONTEXT (f);
2551 int index, interface = 0;
2552 RESERVE (5);
2553 if (METHOD_STATIC (f))
2554 OP1 (OPCODE_invokestatic);
2555 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2556 || METHOD_PRIVATE (f))
2557 OP1 (OPCODE_invokespecial);
2558 else
2560 if (CLASS_INTERFACE (TYPE_NAME (context)))
2562 tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2563 context = TREE_TYPE (TREE_TYPE (arg1));
2564 if (CLASS_INTERFACE (TYPE_NAME (context)))
2565 interface = 1;
2567 if (interface)
2568 OP1 (OPCODE_invokeinterface);
2569 else
2570 OP1 (OPCODE_invokevirtual);
2572 index = find_methodref_with_class_index (&state->cpool, f, context);
2573 OP2 (index);
2574 if (interface)
2576 if (nargs <= 0)
2577 abort ();
2579 OP1 (nargs);
2580 OP1 (0);
2582 f = TREE_TYPE (TREE_TYPE (f));
2583 if (TREE_CODE (f) != VOID_TYPE)
2585 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2586 if (target == IGNORE_TARGET)
2587 emit_pop (size, state);
2588 else
2589 NOTE_PUSH (size);
2591 break;
2594 /* fall through */
2595 notimpl:
2596 default:
2597 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2598 tree_code_name [(int) TREE_CODE (exp)]);
2602 static void
2603 perform_relocations (state)
2604 struct jcf_partial *state;
2606 struct jcf_block *block;
2607 struct jcf_relocation *reloc;
2608 int pc;
2609 int shrink;
2611 /* Before we start, the pc field of each block is an upper bound on
2612 the block's start pc (it may be less, if previous blocks need less
2613 than their maximum).
2615 The minimum size of each block is in the block's chunk->size. */
2617 /* First, figure out the actual locations of each block. */
2618 pc = 0;
2619 shrink = 0;
2620 for (block = state->blocks; block != NULL; block = block->next)
2622 int block_size = block->v.chunk->size;
2624 block->pc = pc;
2626 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2627 Assumes relocations are in reverse order. */
2628 reloc = block->u.relocations;
2629 while (reloc != NULL
2630 && reloc->kind == OPCODE_goto_w
2631 && reloc->label->pc == block->next->pc
2632 && reloc->offset + 2 == block_size)
2634 reloc = reloc->next;
2635 block->u.relocations = reloc;
2636 block->v.chunk->size -= 3;
2637 block_size -= 3;
2638 shrink += 3;
2641 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
2643 if (reloc->kind == SWITCH_ALIGN_RELOC)
2645 /* We assume this is the first relocation in this block,
2646 so we know its final pc. */
2647 int where = pc + reloc->offset;
2648 int pad = ((where + 3) & ~3) - where;
2649 block_size += pad;
2651 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2653 int delta = reloc->label->pc - (pc + reloc->offset - 1);
2654 int expand = reloc->kind > 0 ? 2 : 5;
2656 if (delta > 0)
2657 delta -= shrink;
2658 if (delta >= -32768 && delta <= 32767)
2660 shrink += expand;
2661 reloc->kind = -1;
2663 else
2664 block_size += expand;
2667 pc += block_size;
2670 for (block = state->blocks; block != NULL; block = block->next)
2672 struct chunk *chunk = block->v.chunk;
2673 int old_size = chunk->size;
2674 int next_pc = block->next == NULL ? pc : block->next->pc;
2675 int new_size = next_pc - block->pc;
2676 unsigned char *new_ptr;
2677 unsigned char *old_buffer = chunk->data;
2678 unsigned char *old_ptr = old_buffer + old_size;
2679 if (new_size != old_size)
2681 chunk->data = (unsigned char *)
2682 obstack_alloc (state->chunk_obstack, new_size);
2683 chunk->size = new_size;
2685 new_ptr = chunk->data + new_size;
2687 /* We do the relocations from back to front, because
2688 the relocations are in reverse order. */
2689 for (reloc = block->u.relocations; ; reloc = reloc->next)
2691 /* new_ptr and old_ptr point into the old and new buffers,
2692 respectively. (If no relocations cause the buffer to
2693 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2694 The bytes at higher adress have been copied and relocations
2695 handled; those at lower addresses remain to process. */
2697 /* Lower old index of piece to be copied with no relocation.
2698 I.e. high index of the first piece that does need relocation. */
2699 int start = reloc == NULL ? 0
2700 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2701 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2702 ? reloc->offset + 4
2703 : reloc->offset + 2;
2704 int32 value;
2705 int new_offset;
2706 int n = (old_ptr - old_buffer) - start;
2707 new_ptr -= n;
2708 old_ptr -= n;
2709 if (n > 0)
2710 memcpy (new_ptr, old_ptr, n);
2711 if (old_ptr == old_buffer)
2712 break;
2714 new_offset = new_ptr - chunk->data;
2715 new_offset -= (reloc->kind == -1 ? 2 : 4);
2716 if (reloc->kind == 0)
2718 old_ptr -= 4;
2719 value = GET_u4 (old_ptr);
2721 else if (reloc->kind == BLOCK_START_RELOC)
2723 old_ptr -= 4;
2724 value = 0;
2725 new_offset = 0;
2727 else if (reloc->kind == SWITCH_ALIGN_RELOC)
2729 int where = block->pc + reloc->offset;
2730 int pad = ((where + 3) & ~3) - where;
2731 while (--pad >= 0)
2732 *--new_ptr = 0;
2733 continue;
2735 else
2737 old_ptr -= 2;
2738 value = GET_u2 (old_ptr);
2740 value += reloc->label->pc - (block->pc + new_offset);
2741 *--new_ptr = (unsigned char) value; value >>= 8;
2742 *--new_ptr = (unsigned char) value; value >>= 8;
2743 if (reloc->kind != -1)
2745 *--new_ptr = (unsigned char) value; value >>= 8;
2746 *--new_ptr = (unsigned char) value;
2748 if (reloc->kind > BLOCK_START_RELOC)
2750 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2751 --old_ptr;
2752 *--new_ptr = reloc->kind;
2754 else if (reloc->kind < -1)
2756 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2757 --old_ptr;
2758 *--new_ptr = OPCODE_goto_w;
2759 *--new_ptr = 3;
2760 *--new_ptr = 0;
2761 *--new_ptr = - reloc->kind;
2764 if (new_ptr != chunk->data)
2765 abort ();
2767 state->code_length = pc;
2770 static void
2771 init_jcf_state (state, work)
2772 struct jcf_partial *state;
2773 struct obstack *work;
2775 state->chunk_obstack = work;
2776 state->first = state->chunk = NULL;
2777 CPOOL_INIT (&state->cpool);
2778 BUFFER_INIT (&state->localvars);
2779 BUFFER_INIT (&state->bytecode);
2782 static void
2783 init_jcf_method (state, method)
2784 struct jcf_partial *state;
2785 tree method;
2787 state->current_method = method;
2788 state->blocks = state->last_block = NULL;
2789 state->linenumber_count = 0;
2790 state->first_lvar = state->last_lvar = NULL;
2791 state->lvar_count = 0;
2792 state->labeled_blocks = NULL;
2793 state->code_length = 0;
2794 BUFFER_RESET (&state->bytecode);
2795 BUFFER_RESET (&state->localvars);
2796 state->code_SP = 0;
2797 state->code_SP_max = 0;
2798 state->handlers = NULL;
2799 state->last_handler = NULL;
2800 state->num_handlers = 0;
2801 state->num_finalizers = 0;
2802 state->return_value_decl = NULL_TREE;
2805 static void
2806 release_jcf_state (state)
2807 struct jcf_partial *state;
2809 CPOOL_FINISH (&state->cpool);
2810 obstack_free (state->chunk_obstack, state->first);
2813 /* Generate and return a list of chunks containing the class CLAS
2814 in the .class file representation. The list can be written to a
2815 .class file using write_chunks. Allocate chunks from obstack WORK. */
2817 static struct chunk *
2818 generate_classfile (clas, state)
2819 tree clas;
2820 struct jcf_partial *state;
2822 struct chunk *cpool_chunk;
2823 const char *source_file, *s;
2824 char *ptr;
2825 int i;
2826 char *fields_count_ptr;
2827 int fields_count = 0;
2828 char *methods_count_ptr;
2829 int methods_count = 0;
2830 static tree SourceFile_node = NULL_TREE;
2831 tree part;
2832 int total_supers
2833 = clas == object_type_node ? 0
2834 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2836 ptr = append_chunk (NULL, 8, state);
2837 PUT4 (0xCafeBabe); /* Magic number */
2838 PUT2 (3); /* Minor version */
2839 PUT2 (45); /* Major version */
2841 append_chunk (NULL, 0, state);
2842 cpool_chunk = state->chunk;
2844 /* Next allocate the chunk containing acces_flags through fields_counr. */
2845 if (clas == object_type_node)
2846 i = 10;
2847 else
2848 i = 8 + 2 * total_supers;
2849 ptr = append_chunk (NULL, i, state);
2850 i = get_access_flags (TYPE_NAME (clas));
2851 if (! (i & ACC_INTERFACE))
2852 i |= ACC_SUPER;
2853 PUT2 (i); /* acces_flags */
2854 i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
2855 if (clas == object_type_node)
2857 PUT2(0); /* super_class */
2858 PUT2(0); /* interfaces_count */
2860 else
2862 tree basetypes = TYPE_BINFO_BASETYPES (clas);
2863 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2864 int j = find_class_constant (&state->cpool, base);
2865 PUT2 (j); /* super_class */
2866 PUT2 (total_supers - 1); /* interfaces_count */
2867 for (i = 1; i < total_supers; i++)
2869 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2870 j = find_class_constant (&state->cpool, base);
2871 PUT2 (j);
2874 fields_count_ptr = ptr;
2876 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
2878 int have_value, attr_count = 0;
2879 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2880 continue;
2881 ptr = append_chunk (NULL, 8, state);
2882 i = get_access_flags (part); PUT2 (i);
2883 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
2884 i = find_utf8_constant (&state->cpool,
2885 build_java_signature (TREE_TYPE (part)));
2886 PUT2(i);
2887 have_value = DECL_INITIAL (part) != NULL_TREE
2888 && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part));
2889 if (have_value)
2890 attr_count++;
2892 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
2893 attr_count++;
2895 PUT2 (attr_count); /* attributes_count */
2896 if (have_value)
2898 tree init = DECL_INITIAL (part);
2899 static tree ConstantValue_node = NULL_TREE;
2900 ptr = append_chunk (NULL, 8, state);
2901 if (ConstantValue_node == NULL_TREE)
2902 ConstantValue_node = get_identifier ("ConstantValue");
2903 i = find_utf8_constant (&state->cpool, ConstantValue_node);
2904 PUT2 (i); /* attribute_name_index */
2905 PUT4 (2); /* attribute_length */
2906 i = find_constant_index (init, state); PUT2 (i);
2908 /* Emit the "Synthetic" attribute for val$<x> and this$<n> fields. */
2909 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
2910 ptr = append_synthetic_attribute (state);
2911 fields_count++;
2913 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
2915 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
2916 PUT2 (0);
2918 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
2920 struct jcf_block *block;
2921 tree function_body = DECL_FUNCTION_BODY (part);
2922 tree body = function_body == NULL_TREE ? NULL_TREE
2923 : BLOCK_EXPR_BODY (function_body);
2924 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
2925 : DECL_NAME (part);
2926 tree type = TREE_TYPE (part);
2927 tree save_function = current_function_decl;
2928 int synthetic_p = 0;
2929 current_function_decl = part;
2930 ptr = append_chunk (NULL, 8, state);
2931 i = get_access_flags (part); PUT2 (i);
2932 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
2933 i = find_utf8_constant (&state->cpool, build_java_signature (type));
2934 PUT2 (i);
2935 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
2937 /* Make room for the Synthetic attribute (of zero length.) */
2938 if (DECL_FINIT_P (part)
2939 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
2940 || TYPE_DOT_CLASS (clas) == part)
2942 i++;
2943 synthetic_p = 1;
2946 PUT2 (i); /* attributes_count */
2948 if (synthetic_p)
2949 ptr = append_synthetic_attribute (state);
2951 if (body != NULL_TREE)
2953 int code_attributes_count = 0;
2954 static tree Code_node = NULL_TREE;
2955 tree t;
2956 char *attr_len_ptr;
2957 struct jcf_handler *handler;
2958 if (Code_node == NULL_TREE)
2959 Code_node = get_identifier ("Code");
2960 ptr = append_chunk (NULL, 14, state);
2961 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
2962 attr_len_ptr = ptr;
2963 init_jcf_method (state, part);
2964 get_jcf_label_here (state); /* Force a first block. */
2965 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
2966 localvar_alloc (t, state);
2967 generate_bytecode_insns (body, IGNORE_TARGET, state);
2968 if (CAN_COMPLETE_NORMALLY (body))
2970 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
2971 abort();
2972 RESERVE (1);
2973 OP1 (OPCODE_return);
2975 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
2976 localvar_free (t, state);
2977 if (state->return_value_decl != NULL_TREE)
2978 localvar_free (state->return_value_decl, state);
2979 finish_jcf_block (state);
2980 perform_relocations (state);
2982 ptr = attr_len_ptr;
2983 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
2984 if (state->linenumber_count > 0)
2986 code_attributes_count++;
2987 i += 8 + 4 * state->linenumber_count;
2989 if (state->lvar_count > 0)
2991 code_attributes_count++;
2992 i += 8 + 10 * state->lvar_count;
2994 UNSAFE_PUT4 (i); /* attribute_length */
2995 UNSAFE_PUT2 (state->code_SP_max); /* max_stack */
2996 UNSAFE_PUT2 (localvar_max); /* max_locals */
2997 UNSAFE_PUT4 (state->code_length);
2999 /* Emit the exception table. */
3000 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3001 PUT2 (state->num_handlers); /* exception_table_length */
3002 handler = state->handlers;
3003 for (; handler != NULL; handler = handler->next)
3005 int type_index;
3006 PUT2 (handler->start_label->pc);
3007 PUT2 (handler->end_label->pc);
3008 PUT2 (handler->handler_label->pc);
3009 if (handler->type == NULL_TREE)
3010 type_index = 0;
3011 else
3012 type_index = find_class_constant (&state->cpool,
3013 handler->type);
3014 PUT2 (type_index);
3017 ptr = append_chunk (NULL, 2, state);
3018 PUT2 (code_attributes_count);
3020 /* Write the LineNumberTable attribute. */
3021 if (state->linenumber_count > 0)
3023 static tree LineNumberTable_node = NULL_TREE;
3024 ptr = append_chunk (NULL,
3025 8 + 4 * state->linenumber_count, state);
3026 if (LineNumberTable_node == NULL_TREE)
3027 LineNumberTable_node = get_identifier ("LineNumberTable");
3028 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3029 PUT2 (i); /* attribute_name_index */
3030 i = 2+4*state->linenumber_count; PUT4(i); /* attribute_length */
3031 i = state->linenumber_count; PUT2 (i);
3032 for (block = state->blocks; block != NULL; block = block->next)
3034 int line = block->linenumber;
3035 if (line > 0)
3037 PUT2 (block->pc);
3038 PUT2 (line);
3043 /* Write the LocalVariableTable attribute. */
3044 if (state->lvar_count > 0)
3046 static tree LocalVariableTable_node = NULL_TREE;
3047 struct localvar_info *lvar = state->first_lvar;
3048 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3049 if (LocalVariableTable_node == NULL_TREE)
3050 LocalVariableTable_node = get_identifier("LocalVariableTable");
3051 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3052 PUT2 (i); /* attribute_name_index */
3053 i = 2 + 10 * state->lvar_count; PUT4 (i); /* attribute_length */
3054 i = state->lvar_count; PUT2 (i);
3055 for ( ; lvar != NULL; lvar = lvar->next)
3057 tree name = DECL_NAME (lvar->decl);
3058 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3059 i = lvar->start_label->pc; PUT2 (i);
3060 i = lvar->end_label->pc - i; PUT2 (i);
3061 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3062 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
3063 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
3067 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3069 tree t = DECL_FUNCTION_THROWS (part);
3070 int throws_count = list_length (t);
3071 static tree Exceptions_node = NULL_TREE;
3072 if (Exceptions_node == NULL_TREE)
3073 Exceptions_node = get_identifier ("Exceptions");
3074 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3075 i = find_utf8_constant (&state->cpool, Exceptions_node);
3076 PUT2 (i); /* attribute_name_index */
3077 i = 2 + 2 * throws_count; PUT4(i); /* attribute_length */
3078 i = throws_count; PUT2 (i);
3079 for (; t != NULL_TREE; t = TREE_CHAIN (t))
3081 i = find_class_constant (&state->cpool, TREE_VALUE (t));
3082 PUT2 (i);
3085 methods_count++;
3086 current_function_decl = save_function;
3088 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
3090 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3091 for (s = source_file; ; s++)
3093 char ch = *s;
3094 if (ch == '\0')
3095 break;
3096 if (ch == '/' || ch == '\\')
3097 source_file = s+1;
3099 ptr = append_chunk (NULL, 10, state);
3101 i = 1; /* Source file always exists as an attribute */
3102 if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3103 i++;
3104 if (clas == object_type_node)
3105 i++;
3106 PUT2 (i); /* attributes_count */
3108 /* generate the SourceFile attribute. */
3109 if (SourceFile_node == NULL_TREE)
3111 SourceFile_node = get_identifier ("SourceFile");
3112 ggc_add_tree_root (&SourceFile_node, 1);
3115 i = find_utf8_constant (&state->cpool, SourceFile_node);
3116 PUT2 (i); /* attribute_name_index */
3117 PUT4 (2);
3118 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3119 PUT2 (i);
3120 append_gcj_attribute (state, clas);
3121 append_innerclasses_attribute (state, clas);
3123 /* New finally generate the contents of the constant pool chunk. */
3124 i = count_constant_pool_bytes (&state->cpool);
3125 ptr = obstack_alloc (state->chunk_obstack, i);
3126 cpool_chunk->data = ptr;
3127 cpool_chunk->size = i;
3128 write_constant_pool (&state->cpool, ptr, i);
3129 return state->first;
3132 static unsigned char *
3133 append_synthetic_attribute (state)
3134 struct jcf_partial *state;
3136 static tree Synthetic_node = NULL_TREE;
3137 unsigned char *ptr = append_chunk (NULL, 6, state);
3138 int i;
3140 if (Synthetic_node == NULL_TREE)
3142 Synthetic_node = get_identifier ("Synthetic");
3143 ggc_add_tree_root (&Synthetic_node, 1);
3145 i = find_utf8_constant (&state->cpool, Synthetic_node);
3146 PUT2 (i); /* Attribute string index */
3147 PUT4 (0); /* Attribute length */
3149 return ptr;
3152 static void
3153 append_gcj_attribute (state, class)
3154 struct jcf_partial *state;
3155 tree class;
3157 unsigned char *ptr;
3158 int i;
3160 if (class != object_type_node)
3161 return;
3163 ptr = append_chunk (NULL, 6, state); /* 2+4 */
3164 i = find_utf8_constant (&state->cpool,
3165 get_identifier ("gnu.gcj.gcj-compiled"));
3166 PUT2 (i); /* Attribute string index */
3167 PUT4 (0); /* Attribute length */
3170 static void
3171 append_innerclasses_attribute (state, class)
3172 struct jcf_partial *state;
3173 tree class;
3175 static tree InnerClasses_node = NULL_TREE;
3176 tree orig_decl = TYPE_NAME (class);
3177 tree current, decl;
3178 int length = 0, i;
3179 unsigned char *ptr, *length_marker, *number_marker;
3181 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3182 return;
3184 ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3186 if (InnerClasses_node == NULL_TREE)
3188 InnerClasses_node = get_identifier ("InnerClasses");
3189 ggc_add_tree_root (&InnerClasses_node, 1);
3191 i = find_utf8_constant (&state->cpool, InnerClasses_node);
3192 PUT2 (i);
3193 length_marker = ptr; PUT4 (0); /* length, to be later patched */
3194 number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3196 /* Generate the entries: all inner classes visible from the one we
3197 process: itself, up and down. */
3198 while (class && INNER_CLASS_TYPE_P (class))
3200 const char *n;
3202 decl = TYPE_NAME (class);
3203 n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
3204 IDENTIFIER_LENGTH (DECL_NAME (decl));
3206 while (n[-1] != '$')
3207 n--;
3208 append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3209 length++;
3211 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3214 decl = orig_decl;
3215 for (current = DECL_INNER_CLASS_LIST (decl);
3216 current; current = TREE_CHAIN (current))
3218 append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3219 TREE_VALUE (current));
3220 length++;
3223 ptr = length_marker; PUT4 (8*length+2);
3224 ptr = number_marker; PUT2 (length);
3227 static void
3228 append_innerclasses_attribute_entry (state, decl, name)
3229 struct jcf_partial *state;
3230 tree decl, name;
3232 int icii, icaf;
3233 int ocii = 0, ini = 0;
3234 unsigned char *ptr = append_chunk (NULL, 8, state);
3236 icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3238 /* Sun's implementation seems to generate ocii to 0 for inner
3239 classes (which aren't considered members of the class they're
3240 in.) The specs are saying that if the class is anonymous,
3241 inner_name_index must be zero. */
3242 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3244 ocii = find_class_constant (&state->cpool,
3245 TREE_TYPE (DECL_CONTEXT (decl)));
3246 ini = find_utf8_constant (&state->cpool, name);
3248 icaf = get_access_flags (decl);
3250 PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
3253 static char *
3254 make_class_file_name (clas)
3255 tree clas;
3257 const char *dname, *cname, *slash;
3258 char *r;
3259 struct stat sb;
3261 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3262 "", '.', DIR_SEPARATOR,
3263 ".class"));
3264 if (jcf_write_base_directory == NULL)
3266 /* Make sure we put the class file into the .java file's
3267 directory, and not into some subdirectory thereof. */
3268 char *t;
3269 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3270 slash = strrchr (dname, DIR_SEPARATOR);
3271 if (! slash)
3273 dname = ".";
3274 slash = dname + 1;
3276 t = strrchr (cname, DIR_SEPARATOR);
3277 if (t)
3278 cname = t + 1;
3280 else
3282 dname = jcf_write_base_directory;
3283 slash = dname + strlen (dname);
3286 r = xmalloc (slash - dname + strlen (cname) + 2);
3287 strncpy (r, dname, slash - dname);
3288 r[slash - dname] = DIR_SEPARATOR;
3289 strcpy (&r[slash - dname + 1], cname);
3291 /* We try to make new directories when we need them. We only do
3292 this for directories which "might not" exist. For instance, we
3293 assume the `-d' directory exists, but we don't assume that any
3294 subdirectory below it exists. It might be worthwhile to keep
3295 track of which directories we've created to avoid gratuitous
3296 stat()s. */
3297 dname = r + (slash - dname) + 1;
3298 while (1)
3300 char *s = strchr (dname, DIR_SEPARATOR);
3301 if (s == NULL)
3302 break;
3303 *s = '\0';
3304 if (stat (r, &sb) == -1
3305 /* Try to make it. */
3306 && mkdir (r, 0755) == -1)
3307 fatal_io_error ("can't create directory %s", r);
3309 *s = DIR_SEPARATOR;
3310 /* Skip consecutive separators. */
3311 for (dname = s + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
3315 return r;
3318 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
3319 The output .class file name is make_class_file_name(CLAS). */
3321 void
3322 write_classfile (clas)
3323 tree clas;
3325 struct obstack *work = &temporary_obstack;
3326 struct jcf_partial state[1];
3327 char *class_file_name = make_class_file_name (clas);
3328 struct chunk *chunks;
3330 if (class_file_name != NULL)
3332 FILE *stream = fopen (class_file_name, "wb");
3333 if (stream == NULL)
3334 fatal_io_error ("can't to open %s", class_file_name);
3336 jcf_dependency_add_target (class_file_name);
3337 init_jcf_state (state, work);
3338 chunks = generate_classfile (clas, state);
3339 write_chunks (stream, chunks);
3340 if (fclose (stream))
3341 fatal_io_error ("can't close %s", class_file_name);
3342 free (class_file_name);
3344 release_jcf_state (state);
3347 /* TODO:
3348 string concatenation
3349 synchronized statement