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