2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / java / jcf-write.c
blob74ebc1aa886ade3c7d0d570b2f94fc60ec4ef2cf
1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "jcf.h"
30 #include "tree.h"
31 #include "real.h"
32 #include "java-tree.h"
33 #include "obstack.h"
34 #include "rtl.h"
35 #include "flags.h"
36 #include "java-opcodes.h"
37 #include "parse.h" /* for BLOCK_EXPR_BODY */
38 #include "buffer.h"
39 #include "toplev.h"
40 #include "ggc.h"
41 #include "tm_p.h"
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 const char *jcf_write_base_directory = NULL;
50 /* Make sure bytecode.data is big enough for at least N more bytes. */
52 #define RESERVE(N) \
53 do { CHECK_OP(state); \
54 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
55 buffer_grow (&state->bytecode, N); } while (0)
57 /* Add a 1-byte instruction/operand I to bytecode.data,
58 assuming space has already been RESERVE'd. */
60 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
62 /* Like OP1, but I is a 2-byte big endian integer. */
64 #define OP2(I) \
65 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
67 /* Like OP1, but I is a 4-byte big endian integer. */
69 #define OP4(I) \
70 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
71 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
73 /* Macro to call each time we push I words on the JVM stack. */
75 #define NOTE_PUSH(I) \
76 do { state->code_SP += (I); \
77 if (state->code_SP > state->code_SP_max) \
78 state->code_SP_max = state->code_SP; } while (0)
80 /* Macro to call each time we pop I words from the JVM stack. */
82 #define NOTE_POP(I) \
83 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
85 /* A chunk or segment of a .class file. */
87 struct chunk
89 /* The next segment of this .class file. */
90 struct chunk *next;
92 /* The actual data in this segment to be written to the .class file. */
93 unsigned char *data;
95 /* The size of the segment to be written to the .class file. */
96 int size;
99 #define PENDING_CLEANUP_PC (-3)
100 #define PENDING_EXIT_PC (-2)
101 #define UNDEFINED_PC (-1)
103 /* Each "block" represents a label plus the bytecode instructions following.
104 There may be branches out of the block, but no incoming jumps, except
105 to the beginning of the block.
107 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
108 associated code yet), but it is an undefined label.
111 struct jcf_block
113 /* For blocks that that are defined, the next block (in pc order).
114 For blocks that are not-yet-defined the end label of a LABELED_BLOCK_EXPR
115 or a cleanup expression (from a TRY_FINALLY_EXPR),
116 this is the next (outer) such end label, in a stack headed by
117 labeled_blocks in jcf_partial. */
118 struct jcf_block *next;
120 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
121 pc is PENDING_EXIT_PC.
122 In the not-yet-defined end label for pending cleanup subroutine,
123 pc is PENDING_CLEANUP_PC.
124 For other not-yet-defined labels, pc is UNDEFINED_PC.
126 If the label has been defined:
127 Until perform_relocations is finished, this is the maximum possible
128 value of the bytecode offset at the beginning 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 /* The count of jsr instructions that have been emitted. */
280 long num_jsrs;
283 static void generate_bytecode_insns (tree, int, struct jcf_partial *);
284 static struct chunk * alloc_chunk (struct chunk *, unsigned char *,
285 int, struct obstack *);
286 static unsigned char * append_chunk (unsigned char *, int,
287 struct jcf_partial *);
288 static void append_chunk_copy (unsigned char *, int, struct jcf_partial *);
289 static struct jcf_block * gen_jcf_label (struct jcf_partial *);
290 static void finish_jcf_block (struct jcf_partial *);
291 static void define_jcf_label (struct jcf_block *, struct jcf_partial *);
292 static struct jcf_block * get_jcf_label_here (struct jcf_partial *);
293 static void put_linenumber (int, struct jcf_partial *);
294 static void localvar_alloc (tree, struct jcf_partial *);
295 static void maybe_free_localvar (tree, struct jcf_partial *, int);
296 static int get_access_flags (tree);
297 static void write_chunks (FILE *, struct chunk *);
298 static int adjust_typed_op (tree, int);
299 static void generate_bytecode_conditional (tree, struct jcf_block *,
300 struct jcf_block *, int,
301 struct jcf_partial *);
302 static void generate_bytecode_return (tree, struct jcf_partial *);
303 static void perform_relocations (struct jcf_partial *);
304 static void init_jcf_state (struct jcf_partial *, struct obstack *);
305 static void init_jcf_method (struct jcf_partial *, tree);
306 static void release_jcf_state (struct jcf_partial *);
307 static struct chunk * generate_classfile (tree, struct jcf_partial *);
308 static struct jcf_handler *alloc_handler (struct jcf_block *,
309 struct jcf_block *,
310 struct jcf_partial *);
311 static void emit_iinc (tree, HOST_WIDE_INT, struct jcf_partial *);
312 static void emit_reloc (HOST_WIDE_INT, int, struct jcf_block *,
313 struct jcf_partial *);
314 static void push_constant1 (HOST_WIDE_INT, struct jcf_partial *);
315 static void push_constant2 (HOST_WIDE_INT, struct jcf_partial *);
316 static void push_int_const (HOST_WIDE_INT, struct jcf_partial *);
317 static int find_constant_wide (HOST_WIDE_INT, HOST_WIDE_INT,
318 struct jcf_partial *);
319 static void push_long_const (HOST_WIDE_INT, HOST_WIDE_INT,
320 struct jcf_partial *);
321 static int find_constant_index (tree, struct jcf_partial *);
322 static void push_long_const (HOST_WIDE_INT, HOST_WIDE_INT,
323 struct jcf_partial *);
324 static void field_op (tree, int, struct jcf_partial *);
325 static void maybe_wide (int, int, struct jcf_partial *);
326 static void emit_dup (int, int, struct jcf_partial *);
327 static void emit_pop (int, struct jcf_partial *);
328 static void emit_load_or_store (tree, int, struct jcf_partial *);
329 static void emit_load (tree, struct jcf_partial *);
330 static void emit_store (tree, struct jcf_partial *);
331 static void emit_unop (enum java_opcode, tree, struct jcf_partial *);
332 static void emit_binop (enum java_opcode, tree, struct jcf_partial *);
333 static void emit_reloc (HOST_WIDE_INT, int, struct jcf_block *,
334 struct jcf_partial *);
335 static void emit_switch_reloc (struct jcf_block *, struct jcf_partial *);
336 static void emit_case_reloc (struct jcf_relocation *, struct jcf_partial *);
337 static void emit_if (struct jcf_block *, int, int, struct jcf_partial *);
338 static void emit_goto (struct jcf_block *, struct jcf_partial *);
339 static void emit_jsr (struct jcf_block *, struct jcf_partial *);
340 static void call_cleanups (struct jcf_block *, struct jcf_partial *);
341 static char *make_class_file_name (tree);
342 static unsigned char *append_synthetic_attribute (struct jcf_partial *);
343 static void append_deprecated_attribute (struct jcf_partial *);
344 static void append_innerclasses_attribute (struct jcf_partial *, tree);
345 static void append_innerclasses_attribute_entry (struct jcf_partial *, tree, tree);
346 static void append_gcj_attribute (struct jcf_partial *, tree);
348 /* Utility macros for appending (big-endian) data to a buffer.
349 We assume a local variable 'ptr' points into where we want to
350 write next, and we assume enough space has been allocated. */
352 #ifdef ENABLE_JC1_CHECKING
353 static int CHECK_PUT (void *, struct jcf_partial *, int);
355 static int
356 CHECK_PUT (void *ptr, struct jcf_partial *state, int i)
358 if ((unsigned char *) ptr < state->chunk->data
359 || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
360 abort ();
362 return 0;
364 #else
365 #define CHECK_PUT(PTR, STATE, I) ((void)0)
366 #endif
368 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
369 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
370 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
371 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
373 /* There are some cases below where CHECK_PUT is guaranteed to fail.
374 Use the following macros in those specific cases. */
375 #define UNSAFE_PUT1(X) (*ptr++ = (X))
376 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
377 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
378 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
381 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
382 Set the data and size fields to DATA and SIZE, respectively.
383 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
385 static struct chunk *
386 alloc_chunk (struct chunk *last, unsigned char *data,
387 int size, struct obstack *work)
389 struct chunk *chunk = obstack_alloc (work, sizeof(struct chunk));
391 if (data == NULL && size > 0)
392 data = obstack_alloc (work, size);
394 chunk->next = NULL;
395 chunk->data = data;
396 chunk->size = size;
397 if (last != NULL)
398 last->next = chunk;
399 return chunk;
402 #ifdef ENABLE_JC1_CHECKING
403 static int CHECK_OP (struct jcf_partial *);
405 static int
406 CHECK_OP (struct jcf_partial *state)
408 if (state->bytecode.ptr > state->bytecode.limit)
409 abort ();
411 return 0;
413 #else
414 #define CHECK_OP(STATE) ((void) 0)
415 #endif
417 static unsigned char *
418 append_chunk (unsigned char *data, int size, struct jcf_partial *state)
420 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
421 if (state->first == NULL)
422 state->first = state->chunk;
423 return state->chunk->data;
426 static void
427 append_chunk_copy (unsigned char *data, int size, struct jcf_partial *state)
429 unsigned char *ptr = append_chunk (NULL, size, state);
430 memcpy (ptr, data, size);
433 static struct jcf_block *
434 gen_jcf_label (struct jcf_partial *state)
436 struct jcf_block *block
437 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
438 block->next = NULL;
439 block->linenumber = -1;
440 block->pc = UNDEFINED_PC;
441 return block;
444 static void
445 finish_jcf_block (struct jcf_partial *state)
447 struct jcf_block *block = state->last_block;
448 struct jcf_relocation *reloc;
449 int code_length = BUFFER_LENGTH (&state->bytecode);
450 int pc = state->code_length;
451 append_chunk_copy (state->bytecode.data, code_length, state);
452 BUFFER_RESET (&state->bytecode);
453 block->v.chunk = state->chunk;
455 /* Calculate code_length to the maximum value it can have. */
456 pc += block->v.chunk->size;
457 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
459 int kind = reloc->kind;
460 if (kind == SWITCH_ALIGN_RELOC)
461 pc += 3;
462 else if (kind > BLOCK_START_RELOC)
463 pc += 2; /* 2-byte offset may grow to 4-byte offset */
464 else if (kind < -1)
465 pc += 5; /* May need to add a goto_w. */
467 state->code_length = pc;
470 static void
471 define_jcf_label (struct jcf_block *label, struct jcf_partial *state)
473 if (state->last_block != NULL)
474 finish_jcf_block (state);
475 label->pc = state->code_length;
476 if (state->blocks == NULL)
477 state->blocks = label;
478 else
479 state->last_block->next = label;
480 state->last_block = label;
481 label->next = NULL;
482 label->u.relocations = NULL;
485 static struct jcf_block *
486 get_jcf_label_here (struct jcf_partial *state)
488 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
489 return state->last_block;
490 else
492 struct jcf_block *label = gen_jcf_label (state);
493 define_jcf_label (label, state);
494 return label;
498 /* Note a line number entry for the current PC and given LINE. */
500 static void
501 put_linenumber (int line, struct jcf_partial *state)
503 struct jcf_block *label = get_jcf_label_here (state);
504 if (label->linenumber > 0)
506 label = gen_jcf_label (state);
507 define_jcf_label (label, state);
509 label->linenumber = line;
510 state->linenumber_count++;
513 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
514 in the range (START_LABEL, END_LABEL). */
516 static struct jcf_handler *
517 alloc_handler (struct jcf_block *start_label, struct jcf_block *end_label,
518 struct jcf_partial *state)
520 struct jcf_handler *handler
521 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
522 handler->start_label = start_label;
523 handler->end_label = end_label;
524 handler->handler_label = get_jcf_label_here (state);
525 if (state->handlers == NULL)
526 state->handlers = handler;
527 else
528 state->last_handler->next = handler;
529 state->last_handler = handler;
530 handler->next = NULL;
531 state->num_handlers++;
532 return handler;
536 /* The index of jvm local variable allocated for this DECL.
537 This is assigned when generating .class files;
538 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
539 (We don't allocate DECL_LANG_SPECIFIC for locals from Java source code.) */
541 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
543 struct localvar_info
545 struct localvar_info *next;
547 tree decl;
548 struct jcf_block *start_label;
549 struct jcf_block *end_label;
552 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
553 #define localvar_max \
554 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
556 static void
557 localvar_alloc (tree decl, struct jcf_partial *state)
559 struct jcf_block *start_label = get_jcf_label_here (state);
560 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
561 int index;
562 struct localvar_info *info;
563 struct localvar_info **ptr = localvar_buffer;
564 struct localvar_info **limit
565 = (struct localvar_info**) state->localvars.ptr;
566 for (index = 0; ptr < limit; index++, ptr++)
568 if (ptr[0] == NULL
569 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
570 break;
572 if (ptr == limit)
574 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
575 ptr = (struct localvar_info**) state->localvars.data + index;
576 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
578 info = obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
579 ptr[0] = info;
580 if (wide)
581 ptr[1] = (struct localvar_info *)(~0);
582 DECL_LOCAL_INDEX (decl) = index;
583 info->decl = decl;
584 info->start_label = start_label;
586 if (debug_info_level > DINFO_LEVEL_TERSE
587 && DECL_NAME (decl) != NULL_TREE)
589 /* Generate debugging info. */
590 info->next = NULL;
591 if (state->last_lvar != NULL)
592 state->last_lvar->next = info;
593 else
594 state->first_lvar = info;
595 state->last_lvar = info;
596 state->lvar_count++;
600 static void
601 maybe_free_localvar (tree decl, struct jcf_partial *state, int really)
603 struct jcf_block *end_label = get_jcf_label_here (state);
604 int index = DECL_LOCAL_INDEX (decl);
605 struct localvar_info **ptr = &localvar_buffer [index];
606 struct localvar_info *info = *ptr;
607 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
609 info->end_label = end_label;
611 if (info->decl != decl)
612 abort ();
613 if (! really)
614 return;
615 ptr[0] = NULL;
616 if (wide)
618 if (ptr[1] != (struct localvar_info *)(~0))
619 abort ();
620 ptr[1] = NULL;
625 #define STACK_TARGET 1
626 #define IGNORE_TARGET 2
628 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
629 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
631 static int
632 get_access_flags (tree decl)
634 int flags = 0;
635 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
636 if (CLASS_PUBLIC (decl)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
637 flags |= ACC_PUBLIC;
638 if (CLASS_FINAL (decl)) /* same as FIELD_FINAL and METHOD_FINAL */
639 flags |= ACC_FINAL;
640 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
642 if (TREE_PROTECTED (decl))
643 flags |= ACC_PROTECTED;
644 if (TREE_PRIVATE (decl))
645 flags |= ACC_PRIVATE;
647 else if (TREE_CODE (decl) == TYPE_DECL)
649 if (CLASS_SUPER (decl))
650 flags |= ACC_SUPER;
651 if (CLASS_ABSTRACT (decl))
652 flags |= ACC_ABSTRACT;
653 if (CLASS_INTERFACE (decl))
654 flags |= ACC_INTERFACE;
655 if (CLASS_STATIC (decl))
656 flags |= ACC_STATIC;
657 if (CLASS_PRIVATE (decl))
658 flags |= ACC_PRIVATE;
659 if (CLASS_PROTECTED (decl))
660 flags |= ACC_PROTECTED;
661 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
662 || LOCAL_CLASS_P (TREE_TYPE (decl)))
663 flags |= ACC_PRIVATE;
664 if (CLASS_STRICTFP (decl))
665 flags |= ACC_STRICT;
667 else
668 abort ();
670 if (TREE_CODE (decl) == FUNCTION_DECL)
672 if (METHOD_NATIVE (decl))
673 flags |= ACC_NATIVE;
674 if (METHOD_STATIC (decl))
675 flags |= ACC_STATIC;
676 if (METHOD_SYNCHRONIZED (decl))
677 flags |= ACC_SYNCHRONIZED;
678 if (METHOD_ABSTRACT (decl))
679 flags |= ACC_ABSTRACT;
680 if (METHOD_STRICTFP (decl))
681 flags |= ACC_STRICT;
683 if (isfield)
685 if (FIELD_STATIC (decl))
686 flags |= ACC_STATIC;
687 if (FIELD_VOLATILE (decl))
688 flags |= ACC_VOLATILE;
689 if (FIELD_TRANSIENT (decl))
690 flags |= ACC_TRANSIENT;
692 return flags;
695 /* Write the list of segments starting at CHUNKS to STREAM. */
697 static void
698 write_chunks (FILE* stream, struct chunk *chunks)
700 for (; chunks != NULL; chunks = chunks->next)
701 fwrite (chunks->data, chunks->size, 1, stream);
704 /* Push a 1-word constant in the constant pool at the given INDEX.
705 (Caller is responsible for doing NOTE_PUSH.) */
707 static void
708 push_constant1 (HOST_WIDE_INT index, struct jcf_partial *state)
710 RESERVE (3);
711 if (index < 256)
713 OP1 (OPCODE_ldc);
714 OP1 (index);
716 else
718 OP1 (OPCODE_ldc_w);
719 OP2 (index);
723 /* Push a 2-word constant in the constant pool at the given INDEX.
724 (Caller is responsible for doing NOTE_PUSH.) */
726 static void
727 push_constant2 (HOST_WIDE_INT index, struct jcf_partial *state)
729 RESERVE (3);
730 OP1 (OPCODE_ldc2_w);
731 OP2 (index);
734 /* Push 32-bit integer constant on VM stack.
735 Caller is responsible for doing NOTE_PUSH. */
737 static void
738 push_int_const (HOST_WIDE_INT i, struct jcf_partial *state)
740 RESERVE(3);
741 if (i >= -1 && i <= 5)
742 OP1(OPCODE_iconst_0 + i);
743 else if (i >= -128 && i < 128)
745 OP1(OPCODE_bipush);
746 OP1(i);
748 else if (i >= -32768 && i < 32768)
750 OP1(OPCODE_sipush);
751 OP2(i);
753 else
755 i = find_constant1 (&state->cpool, CONSTANT_Integer,
756 (jword)(i & 0xFFFFFFFF));
757 push_constant1 (i, state);
761 static int
762 find_constant_wide (HOST_WIDE_INT lo, HOST_WIDE_INT hi,
763 struct jcf_partial *state)
765 HOST_WIDE_INT w1, w2;
766 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
767 return find_constant2 (&state->cpool, CONSTANT_Long,
768 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
771 /* Find or allocate a constant pool entry for the given VALUE.
772 Return the index in the constant pool. */
774 static int
775 find_constant_index (tree value, struct jcf_partial *state)
777 if (TREE_CODE (value) == INTEGER_CST)
779 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
780 return find_constant1 (&state->cpool, CONSTANT_Integer,
781 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
782 else
783 return find_constant_wide (TREE_INT_CST_LOW (value),
784 TREE_INT_CST_HIGH (value), state);
786 else if (TREE_CODE (value) == REAL_CST)
788 long words[2];
790 real_to_target (words, &TREE_REAL_CST (value),
791 TYPE_MODE (TREE_TYPE (value)));
792 words[0] &= 0xffffffff;
793 words[1] &= 0xffffffff;
795 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
796 return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
797 else
798 return find_constant2 (&state->cpool, CONSTANT_Double,
799 (jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
800 (jword)words[FLOAT_WORDS_BIG_ENDIAN]);
802 else if (TREE_CODE (value) == STRING_CST)
803 return find_string_constant (&state->cpool, value);
805 else
806 abort ();
809 /* Push 64-bit long constant on VM stack.
810 Caller is responsible for doing NOTE_PUSH. */
812 static void
813 push_long_const (HOST_WIDE_INT lo, HOST_WIDE_INT hi, struct jcf_partial *state)
815 HOST_WIDE_INT highpart, dummy;
816 jint lowpart = WORD_TO_INT (lo);
818 rshift_double (lo, hi, 32, 64, &highpart, &dummy, 1);
820 if (highpart == 0 && (lowpart == 0 || lowpart == 1))
822 RESERVE(1);
823 OP1(OPCODE_lconst_0 + lowpart);
825 else if ((highpart == 0 && lowpart > 0 && lowpart < 32768)
826 || (highpart == -1 && lowpart < 0 && lowpart >= -32768))
828 push_int_const (lowpart, state);
829 RESERVE (1);
830 OP1 (OPCODE_i2l);
832 else
833 push_constant2 (find_constant_wide (lo, hi, state), state);
836 static void
837 field_op (tree field, int opcode, struct jcf_partial *state)
839 int index = find_fieldref_index (&state->cpool, field);
840 RESERVE (3);
841 OP1 (opcode);
842 OP2 (index);
845 /* Returns an integer in the range 0 (for 'int') through 4 (for object
846 reference) to 7 (for 'short') which matches the pattern of how JVM
847 opcodes typically depend on the operand type. */
849 static int
850 adjust_typed_op (tree type, int max)
852 switch (TREE_CODE (type))
854 case POINTER_TYPE:
855 case RECORD_TYPE: return 4;
856 case BOOLEAN_TYPE:
857 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
858 case CHAR_TYPE:
859 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
860 case INTEGER_TYPE:
861 switch (TYPE_PRECISION (type))
863 case 8: return max < 5 ? 0 : 5;
864 case 16: return max < 7 ? 0 : 7;
865 case 32: return 0;
866 case 64: return 1;
868 break;
869 case REAL_TYPE:
870 switch (TYPE_PRECISION (type))
872 case 32: return 2;
873 case 64: return 3;
875 break;
876 default:
877 break;
879 abort ();
882 static void
883 maybe_wide (int opcode, int index, struct jcf_partial *state)
885 if (index >= 256)
887 RESERVE (4);
888 OP1 (OPCODE_wide);
889 OP1 (opcode);
890 OP2 (index);
892 else
894 RESERVE (2);
895 OP1 (opcode);
896 OP1 (index);
900 /* Compile code to duplicate with offset, where
901 SIZE is the size of the stack item to duplicate (1 or 2), abd
902 OFFSET is where to insert the result (must be 0, 1, or 2).
903 (The new words get inserted at stack[SP-size-offset].) */
905 static void
906 emit_dup (int size, int offset, struct jcf_partial *state)
908 int kind;
909 if (size == 0)
910 return;
911 RESERVE(1);
912 if (offset == 0)
913 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
914 else if (offset == 1)
915 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
916 else if (offset == 2)
917 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
918 else
919 abort();
920 OP1 (kind);
921 NOTE_PUSH (size);
924 static void
925 emit_pop (int size, struct jcf_partial *state)
927 RESERVE (1);
928 OP1 (OPCODE_pop - 1 + size);
931 static void
932 emit_iinc (tree var, HOST_WIDE_INT value, struct jcf_partial *state)
934 int slot = DECL_LOCAL_INDEX (var);
936 if (value < -128 || value > 127 || slot >= 256)
938 RESERVE (6);
939 OP1 (OPCODE_wide);
940 OP1 (OPCODE_iinc);
941 OP2 (slot);
942 OP2 (value);
944 else
946 RESERVE (3);
947 OP1 (OPCODE_iinc);
948 OP1 (slot);
949 OP1 (value);
953 static void
954 emit_load_or_store (tree var, /* Variable to load from or store into. */
955 int opcode, /* Either OPCODE_iload or OPCODE_istore. */
956 struct jcf_partial *state)
958 tree type = TREE_TYPE (var);
959 int kind = adjust_typed_op (type, 4);
960 int index = DECL_LOCAL_INDEX (var);
961 if (index <= 3)
963 RESERVE (1);
964 OP1 (opcode + 5 + 4 * kind + index); /* [ilfda]{load,store}_[0123] */
966 else
967 maybe_wide (opcode + kind, index, state); /* [ilfda]{load,store} */
970 static void
971 emit_load (tree var, struct jcf_partial *state)
973 emit_load_or_store (var, OPCODE_iload, state);
974 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
977 static void
978 emit_store (tree var, struct jcf_partial *state)
980 emit_load_or_store (var, OPCODE_istore, state);
981 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
984 static void
985 emit_unop (enum java_opcode opcode, tree type ATTRIBUTE_UNUSED,
986 struct jcf_partial *state)
988 RESERVE(1);
989 OP1 (opcode);
992 static void
993 emit_binop (enum java_opcode opcode, tree type, struct jcf_partial *state)
995 int size = TYPE_IS_WIDE (type) ? 2 : 1;
996 RESERVE(1);
997 OP1 (opcode);
998 NOTE_POP (size);
1001 static void
1002 emit_reloc (HOST_WIDE_INT value, int kind,
1003 struct jcf_block *target, struct jcf_partial *state)
1005 struct jcf_relocation *reloc
1006 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1007 struct jcf_block *block = state->last_block;
1008 reloc->next = block->u.relocations;
1009 block->u.relocations = reloc;
1010 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1011 reloc->label = target;
1012 reloc->kind = kind;
1013 if (kind == 0 || kind == BLOCK_START_RELOC)
1014 OP4 (value);
1015 else if (kind != SWITCH_ALIGN_RELOC)
1016 OP2 (value);
1019 static void
1020 emit_switch_reloc (struct jcf_block *label, struct jcf_partial *state)
1022 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1025 /* Similar to emit_switch_reloc,
1026 but re-uses an existing case reloc. */
1028 static void
1029 emit_case_reloc (struct jcf_relocation *reloc, struct jcf_partial *state)
1031 struct jcf_block *block = state->last_block;
1032 reloc->next = block->u.relocations;
1033 block->u.relocations = reloc;
1034 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1035 reloc->kind = BLOCK_START_RELOC;
1036 OP4 (0);
1039 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1040 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1042 static void
1043 emit_if (struct jcf_block *target, int opcode, int inv_opcode,
1044 struct jcf_partial *state)
1046 RESERVE(3);
1047 OP1 (opcode);
1048 /* value is 1 byte from reloc back to start of instruction. */
1049 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1052 static void
1053 emit_goto (struct jcf_block *target, struct jcf_partial *state)
1055 RESERVE(3);
1056 OP1 (OPCODE_goto);
1057 /* Value is 1 byte from reloc back to start of instruction. */
1058 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1061 static void
1062 emit_jsr (struct jcf_block *target, struct jcf_partial *state)
1064 RESERVE(3);
1065 OP1 (OPCODE_jsr);
1066 /* Value is 1 byte from reloc back to start of instruction. */
1067 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1068 state->num_jsrs++;
1071 /* Generate code to evaluate EXP. If the result is true,
1072 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1073 TRUE_BRANCH_FIRST is a code generation hint that the
1074 TRUE_LABEL may follow right after this. (The idea is that we
1075 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1077 static void
1078 generate_bytecode_conditional (tree exp,
1079 struct jcf_block *true_label,
1080 struct jcf_block *false_label,
1081 int true_branch_first,
1082 struct jcf_partial *state)
1084 tree exp0, exp1, type;
1085 int save_SP = state->code_SP;
1086 enum java_opcode op, negop;
1087 switch (TREE_CODE (exp))
1089 case INTEGER_CST:
1090 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1091 break;
1092 case COND_EXPR:
1094 struct jcf_block *then_label = gen_jcf_label (state);
1095 struct jcf_block *else_label = gen_jcf_label (state);
1096 int save_SP_before, save_SP_after;
1097 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1098 then_label, else_label, 1, state);
1099 define_jcf_label (then_label, state);
1100 save_SP_before = state->code_SP;
1101 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1102 true_label, false_label, 1, state);
1103 save_SP_after = state->code_SP;
1104 state->code_SP = save_SP_before;
1105 define_jcf_label (else_label, state);
1106 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1107 true_label, false_label,
1108 true_branch_first, state);
1109 if (state->code_SP != save_SP_after)
1110 abort ();
1112 break;
1113 case TRUTH_NOT_EXPR:
1114 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
1115 true_label, ! true_branch_first, state);
1116 break;
1117 case TRUTH_ANDIF_EXPR:
1119 struct jcf_block *next_label = gen_jcf_label (state);
1120 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1121 next_label, false_label, 1, state);
1122 define_jcf_label (next_label, state);
1123 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1124 true_label, false_label, 1, state);
1126 break;
1127 case TRUTH_ORIF_EXPR:
1129 struct jcf_block *next_label = gen_jcf_label (state);
1130 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1131 true_label, next_label, 1, state);
1132 define_jcf_label (next_label, state);
1133 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1134 true_label, false_label, 1, state);
1136 break;
1137 compare_1:
1138 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1139 set it to the corresponding 1-operand if<COND> instructions. */
1140 op = op - 6;
1141 /* FALLTHROUGH */
1142 compare_2:
1143 /* The opcodes with their inverses are allocated in pairs.
1144 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1145 negop = (op & 1) ? op + 1 : op - 1;
1146 compare_2_ptr:
1147 if (true_branch_first)
1149 emit_if (false_label, negop, op, state);
1150 emit_goto (true_label, state);
1152 else
1154 emit_if (true_label, op, negop, state);
1155 emit_goto (false_label, state);
1157 break;
1158 case EQ_EXPR:
1159 op = OPCODE_if_icmpeq;
1160 goto compare;
1161 case NE_EXPR:
1162 op = OPCODE_if_icmpne;
1163 goto compare;
1164 case GT_EXPR:
1165 op = OPCODE_if_icmpgt;
1166 goto compare;
1167 case LT_EXPR:
1168 op = OPCODE_if_icmplt;
1169 goto compare;
1170 case GE_EXPR:
1171 op = OPCODE_if_icmpge;
1172 goto compare;
1173 case LE_EXPR:
1174 op = OPCODE_if_icmple;
1175 goto compare;
1176 compare:
1177 exp0 = TREE_OPERAND (exp, 0);
1178 exp1 = TREE_OPERAND (exp, 1);
1179 type = TREE_TYPE (exp0);
1180 switch (TREE_CODE (type))
1182 int opf;
1183 case POINTER_TYPE: case RECORD_TYPE:
1184 switch (TREE_CODE (exp))
1186 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
1187 case NE_EXPR: op = OPCODE_if_acmpne; break;
1188 default: abort();
1190 if (integer_zerop (exp1) || integer_zerop (exp0))
1192 generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
1193 STACK_TARGET, state);
1194 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1195 negop = (op & 1) ? op - 1 : op + 1;
1196 NOTE_POP (1);
1197 goto compare_2_ptr;
1199 generate_bytecode_insns (exp0, STACK_TARGET, state);
1200 generate_bytecode_insns (exp1, STACK_TARGET, state);
1201 NOTE_POP (2);
1202 goto compare_2;
1203 case REAL_TYPE:
1204 generate_bytecode_insns (exp0, STACK_TARGET, state);
1205 generate_bytecode_insns (exp1, STACK_TARGET, state);
1206 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1207 opf = OPCODE_fcmpg;
1208 else
1209 opf = OPCODE_fcmpl;
1210 if (TYPE_PRECISION (type) > 32)
1212 opf += 2;
1213 NOTE_POP (4);
1215 else
1216 NOTE_POP (2);
1217 RESERVE (1);
1218 OP1 (opf);
1219 goto compare_1;
1220 case INTEGER_TYPE:
1221 if (TYPE_PRECISION (type) > 32)
1223 generate_bytecode_insns (exp0, STACK_TARGET, state);
1224 generate_bytecode_insns (exp1, STACK_TARGET, state);
1225 NOTE_POP (4);
1226 RESERVE (1);
1227 OP1 (OPCODE_lcmp);
1228 goto compare_1;
1230 /* FALLTHROUGH */
1231 default:
1232 if (integer_zerop (exp1))
1234 generate_bytecode_insns (exp0, STACK_TARGET, state);
1235 NOTE_POP (1);
1236 goto compare_1;
1238 if (integer_zerop (exp0))
1240 switch (op)
1242 case OPCODE_if_icmplt:
1243 case OPCODE_if_icmpge:
1244 op += 2;
1245 break;
1246 case OPCODE_if_icmpgt:
1247 case OPCODE_if_icmple:
1248 op -= 2;
1249 break;
1250 default:
1251 break;
1253 generate_bytecode_insns (exp1, STACK_TARGET, state);
1254 NOTE_POP (1);
1255 goto compare_1;
1257 generate_bytecode_insns (exp0, STACK_TARGET, state);
1258 generate_bytecode_insns (exp1, STACK_TARGET, state);
1259 NOTE_POP (2);
1260 goto compare_2;
1263 default:
1264 generate_bytecode_insns (exp, STACK_TARGET, state);
1265 NOTE_POP (1);
1266 if (true_branch_first)
1268 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1269 emit_goto (true_label, state);
1271 else
1273 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1274 emit_goto (false_label, state);
1276 break;
1278 if (save_SP != state->code_SP)
1279 abort ();
1282 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1283 but only as far out as LIMIT (since we are about to jump to the
1284 emit label that is LIMIT). */
1286 static void
1287 call_cleanups (struct jcf_block *limit, struct jcf_partial *state)
1289 struct jcf_block *block = state->labeled_blocks;
1290 for (; block != limit; block = block->next)
1292 if (block->pc == PENDING_CLEANUP_PC)
1293 emit_jsr (block, state);
1297 static void
1298 generate_bytecode_return (tree exp, struct jcf_partial *state)
1300 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1301 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1302 int op;
1303 again:
1304 if (exp != NULL)
1306 switch (TREE_CODE (exp))
1308 case COMPOUND_EXPR:
1309 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1310 state);
1311 exp = TREE_OPERAND (exp, 1);
1312 goto again;
1313 case COND_EXPR:
1315 struct jcf_block *then_label = gen_jcf_label (state);
1316 struct jcf_block *else_label = gen_jcf_label (state);
1317 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1318 then_label, else_label, 1, state);
1319 define_jcf_label (then_label, state);
1320 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1321 define_jcf_label (else_label, state);
1322 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1324 return;
1325 default:
1326 generate_bytecode_insns (exp,
1327 returns_void ? IGNORE_TARGET
1328 : STACK_TARGET, state);
1331 if (returns_void)
1333 op = OPCODE_return;
1334 call_cleanups (NULL, state);
1336 else
1338 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1339 if (state->num_finalizers > 0)
1341 if (state->return_value_decl == NULL_TREE)
1343 state->return_value_decl
1344 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1345 localvar_alloc (state->return_value_decl, state);
1347 emit_store (state->return_value_decl, state);
1348 call_cleanups (NULL, state);
1349 emit_load (state->return_value_decl, state);
1350 /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
1351 then we risk the save decl erroneously re-used in the
1352 finalizer. Instead, we keep the state->return_value_decl
1353 allocated through the rest of the method. This is not
1354 the greatest solution, but it is at least simple and safe. */
1357 RESERVE (1);
1358 OP1 (op);
1361 /* Generate bytecode for sub-expression EXP of METHOD.
1362 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1364 static void
1365 generate_bytecode_insns (tree exp, int target, struct jcf_partial *state)
1367 tree type, arg;
1368 enum java_opcode jopcode;
1369 int op;
1370 HOST_WIDE_INT value;
1371 int post_op;
1372 int size;
1373 int offset;
1375 if (exp == NULL && target == IGNORE_TARGET)
1376 return;
1378 type = TREE_TYPE (exp);
1380 switch (TREE_CODE (exp))
1382 case BLOCK:
1383 if (BLOCK_EXPR_BODY (exp))
1385 tree local;
1386 tree body = BLOCK_EXPR_BODY (exp);
1387 long jsrs = state->num_jsrs;
1388 for (local = BLOCK_EXPR_DECLS (exp); local; )
1390 tree next = TREE_CHAIN (local);
1391 localvar_alloc (local, state);
1392 local = next;
1394 /* Avoid deep recursion for long blocks. */
1395 while (TREE_CODE (body) == COMPOUND_EXPR)
1397 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1398 body = TREE_OPERAND (body, 1);
1400 generate_bytecode_insns (body, target, state);
1402 for (local = BLOCK_EXPR_DECLS (exp); local; )
1404 tree next = TREE_CHAIN (local);
1405 maybe_free_localvar (local, state, state->num_jsrs <= jsrs);
1406 local = next;
1409 break;
1410 case COMPOUND_EXPR:
1411 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1412 /* Normally the first operand to a COMPOUND_EXPR must complete
1413 normally. However, in the special case of a do-while
1414 statement this is not necessarily the case. */
1415 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0)))
1416 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1417 break;
1418 case EXPR_WITH_FILE_LOCATION:
1420 location_t saved_location = input_location;
1421 tree body = EXPR_WFL_NODE (exp);
1422 if (body == empty_stmt_node)
1423 break;
1424 input_filename = EXPR_WFL_FILENAME (exp);
1425 input_line = EXPR_WFL_LINENO (exp);
1426 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && input_line > 0
1427 && debug_info_level > DINFO_LEVEL_NONE)
1428 put_linenumber (input_line, state);
1429 generate_bytecode_insns (body, target, state);
1430 input_location = saved_location;
1432 break;
1433 case INTEGER_CST:
1434 if (target == IGNORE_TARGET) ; /* do nothing */
1435 else if (TREE_CODE (type) == POINTER_TYPE)
1437 if (! integer_zerop (exp))
1438 abort();
1439 RESERVE(1);
1440 OP1 (OPCODE_aconst_null);
1441 NOTE_PUSH (1);
1443 else if (TYPE_PRECISION (type) <= 32)
1445 push_int_const (TREE_INT_CST_LOW (exp), state);
1446 NOTE_PUSH (1);
1448 else
1450 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1451 state);
1452 NOTE_PUSH (2);
1454 break;
1455 case REAL_CST:
1457 int prec = TYPE_PRECISION (type) >> 5;
1458 RESERVE(1);
1459 if (real_zerop (exp) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp)))
1460 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1461 else if (real_onep (exp))
1462 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1463 else if (prec == 1 && real_twop (exp))
1464 OP1 (OPCODE_fconst_2);
1465 /* ??? We could also use iconst_3/ldc followed by i2f/i2d
1466 for other float/double when the value is a small integer. */
1467 else
1469 offset = find_constant_index (exp, state);
1470 if (prec == 1)
1471 push_constant1 (offset, state);
1472 else
1473 push_constant2 (offset, state);
1475 NOTE_PUSH (prec);
1477 break;
1478 case STRING_CST:
1479 push_constant1 (find_string_constant (&state->cpool, exp), state);
1480 NOTE_PUSH (1);
1481 break;
1482 case VAR_DECL:
1483 if (TREE_STATIC (exp))
1485 field_op (exp, OPCODE_getstatic, state);
1486 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1487 break;
1489 /* ... fall through ... */
1490 case PARM_DECL:
1491 emit_load (exp, state);
1492 break;
1493 case NON_LVALUE_EXPR:
1494 case INDIRECT_REF:
1495 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1496 break;
1497 case ARRAY_REF:
1498 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1499 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1500 if (target != IGNORE_TARGET)
1502 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1503 RESERVE(1);
1504 OP1 (jopcode);
1505 if (! TYPE_IS_WIDE (type))
1506 NOTE_POP (1);
1508 break;
1509 case COMPONENT_REF:
1511 tree obj = TREE_OPERAND (exp, 0);
1512 tree field = TREE_OPERAND (exp, 1);
1513 int is_static = FIELD_STATIC (field);
1514 generate_bytecode_insns (obj,
1515 is_static ? IGNORE_TARGET : target, state);
1516 if (target != IGNORE_TARGET)
1518 if (DECL_NAME (field) == length_identifier_node && !is_static
1519 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1521 RESERVE (1);
1522 OP1 (OPCODE_arraylength);
1524 else
1526 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1527 state);
1528 if (! is_static)
1529 NOTE_POP (1);
1530 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1534 break;
1535 case TRUTH_ANDIF_EXPR:
1536 case TRUTH_ORIF_EXPR:
1537 case EQ_EXPR:
1538 case NE_EXPR:
1539 case GT_EXPR:
1540 case LT_EXPR:
1541 case GE_EXPR:
1542 case LE_EXPR:
1544 struct jcf_block *then_label = gen_jcf_label (state);
1545 struct jcf_block *else_label = gen_jcf_label (state);
1546 struct jcf_block *end_label = gen_jcf_label (state);
1547 generate_bytecode_conditional (exp,
1548 then_label, else_label, 1, state);
1549 define_jcf_label (then_label, state);
1550 push_int_const (1, state);
1551 emit_goto (end_label, state);
1552 define_jcf_label (else_label, state);
1553 push_int_const (0, state);
1554 define_jcf_label (end_label, state);
1555 NOTE_PUSH (1);
1557 break;
1558 case COND_EXPR:
1560 struct jcf_block *then_label = gen_jcf_label (state);
1561 struct jcf_block *else_label = gen_jcf_label (state);
1562 struct jcf_block *end_label = gen_jcf_label (state);
1563 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1564 then_label, else_label, 1, state);
1565 define_jcf_label (then_label, state);
1566 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1567 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1568 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1569 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1570 emit_goto (end_label, state);
1571 define_jcf_label (else_label, state);
1572 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1573 define_jcf_label (end_label, state);
1574 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1575 if (TREE_TYPE (exp) != void_type_node)
1576 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1578 break;
1579 case CASE_EXPR:
1581 struct jcf_switch_state *sw_state = state->sw_state;
1582 struct jcf_relocation *reloc
1583 = obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1584 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1585 reloc->kind = 0;
1586 reloc->label = get_jcf_label_here (state);
1587 reloc->offset = case_value;
1588 reloc->next = sw_state->cases;
1589 sw_state->cases = reloc;
1590 if (sw_state->num_cases == 0)
1592 sw_state->min_case = case_value;
1593 sw_state->max_case = case_value;
1595 else
1597 if (case_value < sw_state->min_case)
1598 sw_state->min_case = case_value;
1599 if (case_value > sw_state->max_case)
1600 sw_state->max_case = case_value;
1602 sw_state->num_cases++;
1604 break;
1605 case DEFAULT_EXPR:
1606 state->sw_state->default_label = get_jcf_label_here (state);
1607 break;
1609 case SWITCH_EXPR:
1611 /* The SWITCH_EXPR has three parts, generated in the following order:
1612 1. the switch_expression (the value used to select the correct case);
1613 2. the switch_body;
1614 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1615 After code generation, we will re-order them in the order 1, 3, 2.
1616 This is to avoid any extra GOTOs. */
1617 struct jcf_switch_state sw_state;
1618 struct jcf_block *expression_last; /* Last block of the switch_expression. */
1619 struct jcf_block *body_last; /* Last block of the switch_body. */
1620 struct jcf_block *switch_instruction; /* First block of switch_instruction. */
1621 struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1622 struct jcf_block *body_block;
1623 int switch_length;
1624 sw_state.prev = state->sw_state;
1625 state->sw_state = &sw_state;
1626 sw_state.cases = NULL;
1627 sw_state.num_cases = 0;
1628 sw_state.default_label = NULL;
1629 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1630 expression_last = state->last_block;
1631 /* Force a new block here. */
1632 body_block = gen_jcf_label (state);
1633 define_jcf_label (body_block, state);
1634 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1635 body_last = state->last_block;
1637 switch_instruction = gen_jcf_label (state);
1638 define_jcf_label (switch_instruction, state);
1639 if (sw_state.default_label == NULL)
1640 sw_state.default_label = gen_jcf_label (state);
1642 if (sw_state.num_cases <= 1)
1644 if (sw_state.num_cases == 0)
1646 emit_pop (1, state);
1647 NOTE_POP (1);
1649 else
1651 push_int_const (sw_state.cases->offset, state);
1652 NOTE_PUSH (1);
1653 emit_if (sw_state.cases->label,
1654 OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1656 emit_goto (sw_state.default_label, state);
1658 else
1660 HOST_WIDE_INT i;
1661 unsigned HOST_WIDE_INT delta;
1662 /* Copy the chain of relocs into a sorted array. */
1663 struct jcf_relocation **relocs
1664 = xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1665 /* The relocs arrays is a buffer with a gap.
1666 The assumption is that cases will normally come in "runs". */
1667 int gap_start = 0;
1668 int gap_end = sw_state.num_cases;
1669 struct jcf_relocation *reloc;
1670 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
1672 HOST_WIDE_INT case_value = reloc->offset;
1673 while (gap_end < sw_state.num_cases)
1675 struct jcf_relocation *end = relocs[gap_end];
1676 if (case_value <= end->offset)
1677 break;
1678 relocs[gap_start++] = end;
1679 gap_end++;
1681 while (gap_start > 0)
1683 struct jcf_relocation *before = relocs[gap_start-1];
1684 if (case_value >= before->offset)
1685 break;
1686 relocs[--gap_end] = before;
1687 gap_start--;
1689 relocs[gap_start++] = reloc;
1690 /* Note we don't check for duplicates. This is
1691 handled by the parser. */
1694 /* We could have DELTA < 0 if sw_state.min_case is
1695 something like Integer.MIN_VALUE. That is why delta is
1696 unsigned. */
1697 delta = sw_state.max_case - sw_state.min_case;
1698 if (2 * (unsigned) sw_state.num_cases >= delta)
1699 { /* Use tableswitch. */
1700 int index = 0;
1701 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1702 OP1 (OPCODE_tableswitch);
1703 emit_reloc (RELOCATION_VALUE_0,
1704 SWITCH_ALIGN_RELOC, NULL, state);
1705 emit_switch_reloc (sw_state.default_label, state);
1706 OP4 (sw_state.min_case);
1707 OP4 (sw_state.max_case);
1708 for (i = sw_state.min_case; ; )
1710 reloc = relocs[index];
1711 if (i == reloc->offset)
1713 emit_case_reloc (reloc, state);
1714 if (i == sw_state.max_case)
1715 break;
1716 index++;
1718 else
1719 emit_switch_reloc (sw_state.default_label, state);
1720 i++;
1723 else
1724 { /* Use lookupswitch. */
1725 RESERVE(9 + 8 * sw_state.num_cases);
1726 OP1 (OPCODE_lookupswitch);
1727 emit_reloc (RELOCATION_VALUE_0,
1728 SWITCH_ALIGN_RELOC, NULL, state);
1729 emit_switch_reloc (sw_state.default_label, state);
1730 OP4 (sw_state.num_cases);
1731 for (i = 0; i < sw_state.num_cases; i++)
1733 struct jcf_relocation *reloc = relocs[i];
1734 OP4 (reloc->offset);
1735 emit_case_reloc (reloc, state);
1738 free (relocs);
1741 instruction_last = state->last_block;
1742 if (sw_state.default_label->pc < 0)
1743 define_jcf_label (sw_state.default_label, state);
1744 else /* Force a new block. */
1745 sw_state.default_label = get_jcf_label_here (state);
1746 /* Now re-arrange the blocks so the switch_instruction
1747 comes before the switch_body. */
1748 switch_length = state->code_length - switch_instruction->pc;
1749 switch_instruction->pc = body_block->pc;
1750 instruction_last->next = body_block;
1751 instruction_last->v.chunk->next = body_block->v.chunk;
1752 expression_last->next = switch_instruction;
1753 expression_last->v.chunk->next = switch_instruction->v.chunk;
1754 body_last->next = sw_state.default_label;
1755 body_last->v.chunk->next = NULL;
1756 state->chunk = body_last->v.chunk;
1757 for (; body_block != sw_state.default_label; body_block = body_block->next)
1758 body_block->pc += switch_length;
1760 state->sw_state = sw_state.prev;
1761 break;
1764 case RETURN_EXPR:
1765 exp = TREE_OPERAND (exp, 0);
1766 if (exp == NULL_TREE)
1767 exp = empty_stmt_node;
1768 else if (TREE_CODE (exp) != MODIFY_EXPR)
1769 abort ();
1770 else
1771 exp = TREE_OPERAND (exp, 1);
1772 generate_bytecode_return (exp, state);
1773 break;
1774 case LABELED_BLOCK_EXPR:
1776 struct jcf_block *end_label = gen_jcf_label (state);
1777 end_label->next = state->labeled_blocks;
1778 state->labeled_blocks = end_label;
1779 end_label->pc = PENDING_EXIT_PC;
1780 end_label->u.labeled_block = exp;
1781 if (LABELED_BLOCK_BODY (exp))
1782 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1783 if (state->labeled_blocks != end_label)
1784 abort();
1785 state->labeled_blocks = end_label->next;
1786 define_jcf_label (end_label, state);
1788 break;
1789 case LOOP_EXPR:
1791 tree body = TREE_OPERAND (exp, 0);
1792 #if 0
1793 if (TREE_CODE (body) == COMPOUND_EXPR
1794 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1796 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1797 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1798 struct jcf_block *head_label;
1799 struct jcf_block *body_label;
1800 struct jcf_block *end_label = gen_jcf_label (state);
1801 struct jcf_block *exit_label = state->labeled_blocks;
1802 head_label = gen_jcf_label (state);
1803 emit_goto (head_label, state);
1804 body_label = get_jcf_label_here (state);
1805 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1806 define_jcf_label (head_label, state);
1807 generate_bytecode_conditional (TREE_OPERAND (body, 0),
1808 end_label, body_label, 1, state);
1809 define_jcf_label (end_label, state);
1811 else
1812 #endif
1814 struct jcf_block *head_label = get_jcf_label_here (state);
1815 generate_bytecode_insns (body, IGNORE_TARGET, state);
1816 if (CAN_COMPLETE_NORMALLY (body))
1817 emit_goto (head_label, state);
1820 break;
1821 case EXIT_EXPR:
1823 struct jcf_block *label = state->labeled_blocks;
1824 struct jcf_block *end_label = gen_jcf_label (state);
1825 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1826 label, end_label, 0, state);
1827 define_jcf_label (end_label, state);
1829 break;
1830 case EXIT_BLOCK_EXPR:
1832 struct jcf_block *label = state->labeled_blocks;
1833 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1834 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1835 label = label->next;
1836 call_cleanups (label, state);
1837 emit_goto (label, state);
1839 break;
1841 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
1842 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
1843 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
1844 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
1845 increment:
1847 arg = TREE_OPERAND (exp, 1);
1848 exp = TREE_OPERAND (exp, 0);
1849 type = TREE_TYPE (exp);
1850 size = TYPE_IS_WIDE (type) ? 2 : 1;
1851 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1852 && ! TREE_STATIC (exp)
1853 && TREE_CODE (type) == INTEGER_TYPE
1854 && TYPE_PRECISION (type) == 32)
1856 if (target != IGNORE_TARGET && post_op)
1857 emit_load (exp, state);
1858 emit_iinc (exp, value, state);
1859 if (target != IGNORE_TARGET && ! post_op)
1860 emit_load (exp, state);
1861 break;
1863 if (TREE_CODE (exp) == COMPONENT_REF)
1865 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1866 emit_dup (1, 0, state);
1867 /* Stack: ..., objectref, objectref. */
1868 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1869 NOTE_PUSH (size-1);
1870 /* Stack: ..., objectref, oldvalue. */
1871 offset = 1;
1873 else if (TREE_CODE (exp) == ARRAY_REF)
1875 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1876 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1877 emit_dup (2, 0, state);
1878 /* Stack: ..., array, index, array, index. */
1879 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1880 RESERVE(1);
1881 OP1 (jopcode);
1882 NOTE_POP (2-size);
1883 /* Stack: ..., array, index, oldvalue. */
1884 offset = 2;
1886 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1888 generate_bytecode_insns (exp, STACK_TARGET, state);
1889 /* Stack: ..., oldvalue. */
1890 offset = 0;
1892 else
1893 abort ();
1895 if (target != IGNORE_TARGET && post_op)
1896 emit_dup (size, offset, state);
1897 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1898 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1899 /* Stack, otherwise: ..., [result, ] oldvalue. */
1900 generate_bytecode_insns (arg, STACK_TARGET, state);
1901 emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
1902 + adjust_typed_op (type, 3),
1903 type, state);
1904 if (target != IGNORE_TARGET && ! post_op)
1905 emit_dup (size, offset, state);
1906 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1907 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1908 /* Stack, otherwise: ..., [result, ] newvalue. */
1909 goto finish_assignment;
1911 case MODIFY_EXPR:
1913 tree lhs = TREE_OPERAND (exp, 0);
1914 tree rhs = TREE_OPERAND (exp, 1);
1915 int offset = 0;
1917 /* See if we can use the iinc instruction. */
1918 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
1919 && ! TREE_STATIC (lhs)
1920 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
1921 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
1922 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
1924 tree arg0 = TREE_OPERAND (rhs, 0);
1925 tree arg1 = TREE_OPERAND (rhs, 1);
1926 HOST_WIDE_INT min_value = -32768;
1927 HOST_WIDE_INT max_value = 32767;
1928 if (TREE_CODE (rhs) == MINUS_EXPR)
1930 min_value++;
1931 max_value++;
1933 else if (arg1 == lhs)
1935 arg0 = arg1;
1936 arg1 = TREE_OPERAND (rhs, 0);
1938 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
1940 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
1941 value = TREE_INT_CST_LOW (arg1);
1942 if ((hi_value == 0 && value <= max_value)
1943 || (hi_value == -1 && value >= min_value))
1945 if (TREE_CODE (rhs) == MINUS_EXPR)
1946 value = -value;
1947 emit_iinc (lhs, value, state);
1948 if (target != IGNORE_TARGET)
1949 emit_load (lhs, state);
1950 break;
1955 if (TREE_CODE (lhs) == COMPONENT_REF)
1957 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
1958 STACK_TARGET, state);
1959 offset = 1;
1961 else if (TREE_CODE (lhs) == ARRAY_REF)
1963 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
1964 STACK_TARGET, state);
1965 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
1966 STACK_TARGET, state);
1967 offset = 2;
1969 else
1970 offset = 0;
1972 /* If the rhs is a binary expression and the left operand is
1973 `==' to the lhs then we have an OP= expression. In this
1974 case we must do some special processing. */
1975 if (TREE_CODE_CLASS (TREE_CODE (rhs)) == '2'
1976 && lhs == TREE_OPERAND (rhs, 0))
1978 if (TREE_CODE (lhs) == COMPONENT_REF)
1980 tree field = TREE_OPERAND (lhs, 1);
1981 if (! FIELD_STATIC (field))
1983 /* Duplicate the object reference so we can get
1984 the field. */
1985 emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
1986 NOTE_POP (1);
1988 field_op (field, (FIELD_STATIC (field)
1989 ? OPCODE_getstatic
1990 : OPCODE_getfield),
1991 state);
1993 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1995 else if (TREE_CODE (lhs) == VAR_DECL
1996 || TREE_CODE (lhs) == PARM_DECL)
1998 if (FIELD_STATIC (lhs))
2000 field_op (lhs, OPCODE_getstatic, state);
2001 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2003 else
2004 emit_load (lhs, state);
2006 else if (TREE_CODE (lhs) == ARRAY_REF)
2008 /* Duplicate the array and index, which are on the
2009 stack, so that we can load the old value. */
2010 emit_dup (2, 0, state);
2011 NOTE_POP (2);
2012 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
2013 RESERVE (1);
2014 OP1 (jopcode);
2015 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2017 else
2018 abort ();
2020 /* This function correctly handles the case where the LHS
2021 of a binary expression is NULL_TREE. */
2022 rhs = build (TREE_CODE (rhs), TREE_TYPE (rhs),
2023 NULL_TREE, TREE_OPERAND (rhs, 1));
2026 generate_bytecode_insns (rhs, STACK_TARGET, state);
2027 if (target != IGNORE_TARGET)
2028 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2029 exp = lhs;
2031 /* FALLTHROUGH */
2033 finish_assignment:
2034 if (TREE_CODE (exp) == COMPONENT_REF)
2036 tree field = TREE_OPERAND (exp, 1);
2037 if (! FIELD_STATIC (field))
2038 NOTE_POP (1);
2039 field_op (field,
2040 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2041 state);
2043 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2045 else if (TREE_CODE (exp) == VAR_DECL
2046 || TREE_CODE (exp) == PARM_DECL)
2048 if (FIELD_STATIC (exp))
2050 field_op (exp, OPCODE_putstatic, state);
2051 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2053 else
2054 emit_store (exp, state);
2056 else if (TREE_CODE (exp) == ARRAY_REF)
2058 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2059 RESERVE (1);
2060 OP1 (jopcode);
2061 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2063 else
2064 abort ();
2065 break;
2066 case PLUS_EXPR:
2067 jopcode = OPCODE_iadd;
2068 goto binop;
2069 case MINUS_EXPR:
2070 jopcode = OPCODE_isub;
2071 goto binop;
2072 case MULT_EXPR:
2073 jopcode = OPCODE_imul;
2074 goto binop;
2075 case TRUNC_DIV_EXPR:
2076 case RDIV_EXPR:
2077 jopcode = OPCODE_idiv;
2078 goto binop;
2079 case TRUNC_MOD_EXPR:
2080 jopcode = OPCODE_irem;
2081 goto binop;
2082 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
2083 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
2084 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
2085 case TRUTH_AND_EXPR:
2086 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
2087 case TRUTH_OR_EXPR:
2088 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
2089 case TRUTH_XOR_EXPR:
2090 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
2091 binop:
2093 tree arg0 = TREE_OPERAND (exp, 0);
2094 tree arg1 = TREE_OPERAND (exp, 1);
2095 jopcode += adjust_typed_op (type, 3);
2096 if (arg0 != NULL_TREE && operand_equal_p (arg0, arg1, 0))
2098 /* fold may (e.g) convert 2*x to x+x. */
2099 generate_bytecode_insns (arg0, target, state);
2100 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2102 else
2104 /* ARG0 will be NULL_TREE if we're handling an `OP='
2105 expression. In this case the stack already holds the
2106 LHS. See the MODIFY_EXPR case. */
2107 if (arg0 != NULL_TREE)
2108 generate_bytecode_insns (arg0, target, state);
2109 if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2110 arg1 = convert (int_type_node, arg1);
2111 generate_bytecode_insns (arg1, target, state);
2113 /* For most binary operations, both operands and the result have the
2114 same type. Shift operations are different. Using arg1's type
2115 gets us the correct SP adjustment in all cases. */
2116 if (target == STACK_TARGET)
2117 emit_binop (jopcode, TREE_TYPE (arg1), state);
2118 break;
2120 case TRUTH_NOT_EXPR:
2121 case BIT_NOT_EXPR:
2122 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2123 if (target == STACK_TARGET)
2125 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2126 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
2127 RESERVE (2);
2128 if (is_long)
2129 OP1 (OPCODE_i2l);
2130 NOTE_PUSH (1 + is_long);
2131 OP1 (OPCODE_ixor + is_long);
2132 NOTE_POP (1 + is_long);
2134 break;
2135 case NEGATE_EXPR:
2136 jopcode = OPCODE_ineg;
2137 jopcode += adjust_typed_op (type, 3);
2138 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2139 if (target == STACK_TARGET)
2140 emit_unop (jopcode, type, state);
2141 break;
2142 case INSTANCEOF_EXPR:
2144 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2145 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2146 RESERVE (3);
2147 OP1 (OPCODE_instanceof);
2148 OP2 (index);
2150 break;
2151 case SAVE_EXPR:
2152 /* Because the state associated with a SAVE_EXPR tree node must
2153 be a RTL expression, we use it to store the DECL_LOCAL_INDEX
2154 of a temporary variable in a CONST_INT. */
2155 if (! SAVE_EXPR_RTL (exp))
2157 tree type = TREE_TYPE (exp);
2158 tree decl = build_decl (VAR_DECL, NULL_TREE, type);
2159 generate_bytecode_insns (TREE_OPERAND (exp, 0),
2160 STACK_TARGET, state);
2161 localvar_alloc (decl, state);
2162 SAVE_EXPR_RTL (exp) = GEN_INT (DECL_LOCAL_INDEX (decl));
2163 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1, 0, state);
2164 emit_store (decl, state);
2166 else
2168 /* The following code avoids creating a temporary DECL just
2169 to pass to emit_load. This code could be factored with
2170 the similar implementation in emit_load_or_store. */
2171 tree type = TREE_TYPE (exp);
2172 int kind = adjust_typed_op (type, 4);
2173 int index = (int) INTVAL (SAVE_EXPR_RTL (exp));
2174 if (index <= 3)
2176 RESERVE (1); /* [ilfda]load_[0123] */
2177 OP1 (OPCODE_iload + 5 + 4*kind + index);
2179 else /* [ilfda]load */
2180 maybe_wide (OPCODE_iload + kind, index, state);
2181 NOTE_PUSH (TYPE_IS_WIDE (type) ? 2 : 1);
2183 break;
2184 case CONVERT_EXPR:
2185 case NOP_EXPR:
2186 case FLOAT_EXPR:
2187 case FIX_TRUNC_EXPR:
2189 tree src = TREE_OPERAND (exp, 0);
2190 tree src_type = TREE_TYPE (src);
2191 tree dst_type = TREE_TYPE (exp);
2192 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2193 if (target == IGNORE_TARGET || src_type == dst_type)
2194 break;
2195 if (TREE_CODE (dst_type) == POINTER_TYPE)
2197 if (TREE_CODE (exp) == CONVERT_EXPR)
2199 int index = find_class_constant (&state->cpool,
2200 TREE_TYPE (dst_type));
2201 RESERVE (3);
2202 OP1 (OPCODE_checkcast);
2203 OP2 (index);
2206 else /* Convert numeric types. */
2208 int wide_src = TYPE_PRECISION (src_type) > 32;
2209 int wide_dst = TYPE_PRECISION (dst_type) > 32;
2210 NOTE_POP (1 + wide_src);
2211 RESERVE (1);
2212 if (TREE_CODE (dst_type) == REAL_TYPE)
2214 if (TREE_CODE (src_type) == REAL_TYPE)
2215 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2216 else if (TYPE_PRECISION (src_type) == 64)
2217 OP1 (OPCODE_l2f + wide_dst);
2218 else
2219 OP1 (OPCODE_i2f + wide_dst);
2221 else /* Convert to integral type. */
2223 if (TREE_CODE (src_type) == REAL_TYPE)
2224 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2225 else if (wide_dst)
2226 OP1 (OPCODE_i2l);
2227 else if (wide_src)
2228 OP1 (OPCODE_l2i);
2229 if (TYPE_PRECISION (dst_type) < 32)
2231 RESERVE (1);
2232 /* Already converted to int, if needed. */
2233 if (TYPE_PRECISION (dst_type) <= 8)
2234 OP1 (OPCODE_i2b);
2235 else if (TREE_UNSIGNED (dst_type))
2236 OP1 (OPCODE_i2c);
2237 else
2238 OP1 (OPCODE_i2s);
2241 NOTE_PUSH (1 + wide_dst);
2244 break;
2246 case TRY_EXPR:
2248 tree try_clause = TREE_OPERAND (exp, 0);
2249 struct jcf_block *start_label = get_jcf_label_here (state);
2250 struct jcf_block *end_label; /* End of try clause. */
2251 struct jcf_block *finished_label = gen_jcf_label (state);
2252 tree clause = TREE_OPERAND (exp, 1);
2253 if (target != IGNORE_TARGET)
2254 abort ();
2255 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2256 end_label = get_jcf_label_here (state);
2257 if (end_label == start_label)
2258 break;
2259 if (CAN_COMPLETE_NORMALLY (try_clause))
2260 emit_goto (finished_label, state);
2261 while (clause != NULL_TREE)
2263 tree catch_clause = TREE_OPERAND (clause, 0);
2264 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2265 struct jcf_handler *handler = alloc_handler (start_label,
2266 end_label, state);
2267 if (exception_decl == NULL_TREE)
2268 handler->type = NULL_TREE;
2269 else
2270 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2271 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2272 clause = TREE_CHAIN (clause);
2273 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2274 emit_goto (finished_label, state);
2276 define_jcf_label (finished_label, state);
2278 break;
2280 case TRY_FINALLY_EXPR:
2282 struct jcf_block *finished_label = NULL;
2283 struct jcf_block *finally_label, *start_label, *end_label;
2284 struct jcf_handler *handler;
2285 tree try_block = TREE_OPERAND (exp, 0);
2286 tree finally = TREE_OPERAND (exp, 1);
2287 tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2289 tree exception_type;
2291 finally_label = gen_jcf_label (state);
2292 start_label = get_jcf_label_here (state);
2293 /* If the `finally' clause can complete normally, we emit it
2294 as a subroutine and let the other clauses call it via
2295 `jsr'. If it can't complete normally, then we simply emit
2296 `goto's directly to it. */
2297 if (CAN_COMPLETE_NORMALLY (finally))
2299 finally_label->pc = PENDING_CLEANUP_PC;
2300 finally_label->next = state->labeled_blocks;
2301 state->labeled_blocks = finally_label;
2302 state->num_finalizers++;
2305 generate_bytecode_insns (try_block, target, state);
2307 if (CAN_COMPLETE_NORMALLY (finally))
2309 if (state->labeled_blocks != finally_label)
2310 abort();
2311 state->labeled_blocks = finally_label->next;
2313 end_label = get_jcf_label_here (state);
2315 if (end_label == start_label)
2317 state->num_finalizers--;
2318 define_jcf_label (finally_label, state);
2319 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2320 break;
2323 if (CAN_COMPLETE_NORMALLY (finally))
2325 return_link = build_decl (VAR_DECL, NULL_TREE,
2326 return_address_type_node);
2327 finished_label = gen_jcf_label (state);
2330 if (CAN_COMPLETE_NORMALLY (try_block))
2332 if (CAN_COMPLETE_NORMALLY (finally))
2334 emit_jsr (finally_label, state);
2335 emit_goto (finished_label, state);
2337 else
2338 emit_goto (finally_label, state);
2341 /* Handle exceptions. */
2343 exception_type = build_pointer_type (throwable_type_node);
2344 if (CAN_COMPLETE_NORMALLY (finally))
2346 /* We're going to generate a subroutine, so we'll need to
2347 save and restore the exception around the `jsr'. */
2348 exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2349 localvar_alloc (return_link, state);
2351 handler = alloc_handler (start_label, end_label, state);
2352 handler->type = NULL_TREE;
2353 if (CAN_COMPLETE_NORMALLY (finally))
2355 localvar_alloc (exception_decl, state);
2356 NOTE_PUSH (1);
2357 emit_store (exception_decl, state);
2358 emit_jsr (finally_label, state);
2359 emit_load (exception_decl, state);
2360 RESERVE (1);
2361 OP1 (OPCODE_athrow);
2362 NOTE_POP (1);
2364 else
2366 /* We're not generating a subroutine. In this case we can
2367 simply have the exception handler pop the exception and
2368 then fall through to the `finally' block. */
2369 NOTE_PUSH (1);
2370 emit_pop (1, state);
2371 NOTE_POP (1);
2374 /* The finally block. If we're generating a subroutine, first
2375 save return PC into return_link. Otherwise, just generate
2376 the code for the `finally' block. */
2377 define_jcf_label (finally_label, state);
2378 if (CAN_COMPLETE_NORMALLY (finally))
2380 NOTE_PUSH (1);
2381 emit_store (return_link, state);
2384 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2385 if (CAN_COMPLETE_NORMALLY (finally))
2387 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2388 maybe_free_localvar (exception_decl, state, 1);
2389 maybe_free_localvar (return_link, state, 1);
2390 define_jcf_label (finished_label, state);
2393 break;
2394 case THROW_EXPR:
2395 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2396 RESERVE (1);
2397 OP1 (OPCODE_athrow);
2398 break;
2399 case NEW_ARRAY_INIT:
2401 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2402 tree array_type = TREE_TYPE (TREE_TYPE (exp));
2403 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2404 HOST_WIDE_INT length = java_array_type_length (array_type);
2405 if (target == IGNORE_TARGET)
2407 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
2408 generate_bytecode_insns (TREE_VALUE (values), target, state);
2409 break;
2411 push_int_const (length, state);
2412 NOTE_PUSH (1);
2413 RESERVE (3);
2414 if (JPRIMITIVE_TYPE_P (element_type))
2416 int atype = encode_newarray_type (element_type);
2417 OP1 (OPCODE_newarray);
2418 OP1 (atype);
2420 else
2422 int index = find_class_constant (&state->cpool,
2423 TREE_TYPE (element_type));
2424 OP1 (OPCODE_anewarray);
2425 OP2 (index);
2427 offset = 0;
2428 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2429 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
2431 int save_SP = state->code_SP;
2432 emit_dup (1, 0, state);
2433 push_int_const (offset, state);
2434 NOTE_PUSH (1);
2435 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2436 RESERVE (1);
2437 OP1 (jopcode);
2438 state->code_SP = save_SP;
2441 break;
2442 case JAVA_EXC_OBJ_EXPR:
2443 NOTE_PUSH (1); /* Pushed by exception system. */
2444 break;
2445 case MIN_EXPR:
2446 case MAX_EXPR:
2448 /* This copes with cases where fold() has created MIN or MAX
2449 from a conditional expression. */
2450 enum tree_code code = TREE_CODE (exp) == MIN_EXPR ? LT_EXPR : GT_EXPR;
2451 tree op0 = TREE_OPERAND (exp, 0);
2452 tree op1 = TREE_OPERAND (exp, 1);
2453 tree x;
2454 if (TREE_SIDE_EFFECTS (op0) || TREE_SIDE_EFFECTS (op1))
2455 abort ();
2456 x = build (COND_EXPR, TREE_TYPE (exp),
2457 build (code, boolean_type_node, op0, op1),
2458 op0, op1);
2459 generate_bytecode_insns (x, target, state);
2460 break;
2462 case NEW_CLASS_EXPR:
2464 tree class = TREE_TYPE (TREE_TYPE (exp));
2465 int need_result = target != IGNORE_TARGET;
2466 int index = find_class_constant (&state->cpool, class);
2467 RESERVE (4);
2468 OP1 (OPCODE_new);
2469 OP2 (index);
2470 if (need_result)
2471 OP1 (OPCODE_dup);
2472 NOTE_PUSH (1 + need_result);
2474 /* ... fall though ... */
2475 case CALL_EXPR:
2477 tree f = TREE_OPERAND (exp, 0);
2478 tree x = TREE_OPERAND (exp, 1);
2479 int save_SP = state->code_SP;
2480 int nargs;
2481 if (TREE_CODE (f) == ADDR_EXPR)
2482 f = TREE_OPERAND (f, 0);
2483 if (f == soft_newarray_node)
2485 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2486 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2487 STACK_TARGET, state);
2488 RESERVE (2);
2489 OP1 (OPCODE_newarray);
2490 OP1 (type_code);
2491 break;
2493 else if (f == soft_multianewarray_node)
2495 int ndims;
2496 int idim;
2497 int index = find_class_constant (&state->cpool,
2498 TREE_TYPE (TREE_TYPE (exp)));
2499 x = TREE_CHAIN (x); /* Skip class argument. */
2500 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2501 for (idim = ndims; --idim >= 0; )
2503 x = TREE_CHAIN (x);
2504 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2506 RESERVE (4);
2507 OP1 (OPCODE_multianewarray);
2508 OP2 (index);
2509 OP1 (ndims);
2510 break;
2512 else if (f == soft_anewarray_node)
2514 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2515 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2516 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2517 RESERVE (3);
2518 OP1 (OPCODE_anewarray);
2519 OP2 (index);
2520 break;
2522 else if (f == soft_monitorenter_node
2523 || f == soft_monitorexit_node
2524 || f == throw_node)
2526 if (f == soft_monitorenter_node)
2527 op = OPCODE_monitorenter;
2528 else if (f == soft_monitorexit_node)
2529 op = OPCODE_monitorexit;
2530 else
2531 op = OPCODE_athrow;
2532 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2533 RESERVE (1);
2534 OP1 (op);
2535 NOTE_POP (1);
2536 break;
2538 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
2540 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2542 nargs = state->code_SP - save_SP;
2543 state->code_SP = save_SP;
2544 if (f == soft_fmod_node)
2546 RESERVE (1);
2547 OP1 (OPCODE_drem);
2548 NOTE_PUSH (2);
2549 break;
2551 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2552 NOTE_POP (1); /* Pop implicit this. */
2553 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2555 tree context = DECL_CONTEXT (f);
2556 int index, interface = 0;
2557 RESERVE (5);
2558 if (METHOD_STATIC (f))
2559 OP1 (OPCODE_invokestatic);
2560 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2561 || METHOD_PRIVATE (f))
2562 OP1 (OPCODE_invokespecial);
2563 else
2565 if (CLASS_INTERFACE (TYPE_NAME (context)))
2567 tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2568 context = TREE_TYPE (TREE_TYPE (arg1));
2569 if (CLASS_INTERFACE (TYPE_NAME (context)))
2570 interface = 1;
2572 if (interface)
2573 OP1 (OPCODE_invokeinterface);
2574 else
2575 OP1 (OPCODE_invokevirtual);
2577 index = find_methodref_with_class_index (&state->cpool, f, context);
2578 OP2 (index);
2579 if (interface)
2581 if (nargs <= 0)
2582 abort ();
2584 OP1 (nargs);
2585 OP1 (0);
2587 f = TREE_TYPE (TREE_TYPE (f));
2588 if (TREE_CODE (f) != VOID_TYPE)
2590 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2591 if (target == IGNORE_TARGET)
2592 emit_pop (size, state);
2593 else
2594 NOTE_PUSH (size);
2596 break;
2599 /* fall through */
2600 notimpl:
2601 default:
2602 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2603 tree_code_name [(int) TREE_CODE (exp)]);
2607 static void
2608 perform_relocations (struct jcf_partial *state)
2610 struct jcf_block *block;
2611 struct jcf_relocation *reloc;
2612 int pc;
2613 int shrink;
2615 /* Before we start, the pc field of each block is an upper bound on
2616 the block's start pc (it may be less, if previous blocks need less
2617 than their maximum).
2619 The minimum size of each block is in the block's chunk->size. */
2621 /* First, figure out the actual locations of each block. */
2622 pc = 0;
2623 shrink = 0;
2624 for (block = state->blocks; block != NULL; block = block->next)
2626 int block_size = block->v.chunk->size;
2628 block->pc = pc;
2630 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2631 Assumes relocations are in reverse order. */
2632 reloc = block->u.relocations;
2633 while (reloc != NULL
2634 && reloc->kind == OPCODE_goto_w
2635 && reloc->label->pc == block->next->pc
2636 && reloc->offset + 2 == block_size)
2638 reloc = reloc->next;
2639 block->u.relocations = reloc;
2640 block->v.chunk->size -= 3;
2641 block_size -= 3;
2642 shrink += 3;
2645 /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2646 jump directly to X. We're careful here to avoid an infinite
2647 loop if the `goto's themselves form one. We do this
2648 optimization because we can generate a goto-to-goto for some
2649 try/finally blocks. */
2650 while (reloc != NULL
2651 && reloc->kind == OPCODE_goto_w
2652 && reloc->label != block
2653 && reloc->label->v.chunk->data != NULL
2654 && reloc->label->v.chunk->data[0] == OPCODE_goto)
2656 /* Find the reloc for the first instruction of the
2657 destination block. */
2658 struct jcf_relocation *first_reloc;
2659 for (first_reloc = reloc->label->u.relocations;
2660 first_reloc;
2661 first_reloc = first_reloc->next)
2663 if (first_reloc->offset == 1
2664 && first_reloc->kind == OPCODE_goto_w)
2666 reloc->label = first_reloc->label;
2667 break;
2671 /* If we didn't do anything, exit the loop. */
2672 if (first_reloc == NULL)
2673 break;
2676 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
2678 if (reloc->kind == SWITCH_ALIGN_RELOC)
2680 /* We assume this is the first relocation in this block,
2681 so we know its final pc. */
2682 int where = pc + reloc->offset;
2683 int pad = ((where + 3) & ~3) - where;
2684 block_size += pad;
2686 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2688 int delta = reloc->label->pc - (pc + reloc->offset - 1);
2689 int expand = reloc->kind > 0 ? 2 : 5;
2691 if (delta > 0)
2692 delta -= shrink;
2693 if (delta >= -32768 && delta <= 32767)
2695 shrink += expand;
2696 reloc->kind = -1;
2698 else
2699 block_size += expand;
2702 pc += block_size;
2705 for (block = state->blocks; block != NULL; block = block->next)
2707 struct chunk *chunk = block->v.chunk;
2708 int old_size = chunk->size;
2709 int next_pc = block->next == NULL ? pc : block->next->pc;
2710 int new_size = next_pc - block->pc;
2711 unsigned char *new_ptr;
2712 unsigned char *old_buffer = chunk->data;
2713 unsigned char *old_ptr = old_buffer + old_size;
2714 if (new_size != old_size)
2716 chunk->data = obstack_alloc (state->chunk_obstack, new_size);
2717 chunk->size = new_size;
2719 new_ptr = chunk->data + new_size;
2721 /* We do the relocations from back to front, because
2722 the relocations are in reverse order. */
2723 for (reloc = block->u.relocations; ; reloc = reloc->next)
2725 /* new_ptr and old_ptr point into the old and new buffers,
2726 respectively. (If no relocations cause the buffer to
2727 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2728 The bytes at higher address have been copied and relocations
2729 handled; those at lower addresses remain to process. */
2731 /* Lower old index of piece to be copied with no relocation.
2732 I.e. high index of the first piece that does need relocation. */
2733 int start = reloc == NULL ? 0
2734 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2735 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2736 ? reloc->offset + 4
2737 : reloc->offset + 2;
2738 int32 value;
2739 int new_offset;
2740 int n = (old_ptr - old_buffer) - start;
2741 new_ptr -= n;
2742 old_ptr -= n;
2743 if (n > 0)
2744 memcpy (new_ptr, old_ptr, n);
2745 if (old_ptr == old_buffer)
2746 break;
2748 new_offset = new_ptr - chunk->data;
2749 new_offset -= (reloc->kind == -1 ? 2 : 4);
2750 if (reloc->kind == 0)
2752 old_ptr -= 4;
2753 value = GET_u4 (old_ptr);
2755 else if (reloc->kind == BLOCK_START_RELOC)
2757 old_ptr -= 4;
2758 value = 0;
2759 new_offset = 0;
2761 else if (reloc->kind == SWITCH_ALIGN_RELOC)
2763 int where = block->pc + reloc->offset;
2764 int pad = ((where + 3) & ~3) - where;
2765 while (--pad >= 0)
2766 *--new_ptr = 0;
2767 continue;
2769 else
2771 old_ptr -= 2;
2772 value = GET_u2 (old_ptr);
2774 value += reloc->label->pc - (block->pc + new_offset);
2775 *--new_ptr = (unsigned char) value; value >>= 8;
2776 *--new_ptr = (unsigned char) value; value >>= 8;
2777 if (reloc->kind != -1)
2779 *--new_ptr = (unsigned char) value; value >>= 8;
2780 *--new_ptr = (unsigned char) value;
2782 if (reloc->kind > BLOCK_START_RELOC)
2784 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2785 --old_ptr;
2786 *--new_ptr = reloc->kind;
2788 else if (reloc->kind < -1)
2790 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2791 --old_ptr;
2792 *--new_ptr = OPCODE_goto_w;
2793 *--new_ptr = 3;
2794 *--new_ptr = 0;
2795 *--new_ptr = - reloc->kind;
2798 if (new_ptr != chunk->data)
2799 abort ();
2801 state->code_length = pc;
2804 static void
2805 init_jcf_state (struct jcf_partial *state, struct obstack *work)
2807 state->chunk_obstack = work;
2808 state->first = state->chunk = NULL;
2809 CPOOL_INIT (&state->cpool);
2810 BUFFER_INIT (&state->localvars);
2811 BUFFER_INIT (&state->bytecode);
2814 static void
2815 init_jcf_method (struct jcf_partial *state, tree method)
2817 state->current_method = method;
2818 state->blocks = state->last_block = NULL;
2819 state->linenumber_count = 0;
2820 state->first_lvar = state->last_lvar = NULL;
2821 state->lvar_count = 0;
2822 state->labeled_blocks = NULL;
2823 state->code_length = 0;
2824 BUFFER_RESET (&state->bytecode);
2825 BUFFER_RESET (&state->localvars);
2826 state->code_SP = 0;
2827 state->code_SP_max = 0;
2828 state->handlers = NULL;
2829 state->last_handler = NULL;
2830 state->num_handlers = 0;
2831 state->num_finalizers = 0;
2832 state->return_value_decl = NULL_TREE;
2835 static void
2836 release_jcf_state (struct jcf_partial *state)
2838 CPOOL_FINISH (&state->cpool);
2839 obstack_free (state->chunk_obstack, state->first);
2842 /* Generate and return a list of chunks containing the class CLAS
2843 in the .class file representation. The list can be written to a
2844 .class file using write_chunks. Allocate chunks from obstack WORK. */
2846 static GTY(()) tree SourceFile_node;
2847 static struct chunk *
2848 generate_classfile (tree clas, struct jcf_partial *state)
2850 struct chunk *cpool_chunk;
2851 const char *source_file, *s;
2852 char *ptr;
2853 int i;
2854 char *fields_count_ptr;
2855 int fields_count = 0;
2856 char *methods_count_ptr;
2857 int methods_count = 0;
2858 tree part;
2859 int total_supers
2860 = clas == object_type_node ? 0
2861 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2863 ptr = append_chunk (NULL, 8, state);
2864 PUT4 (0xCafeBabe); /* Magic number */
2865 PUT2 (3); /* Minor version */
2866 PUT2 (45); /* Major version */
2868 append_chunk (NULL, 0, state);
2869 cpool_chunk = state->chunk;
2871 /* Next allocate the chunk containing access_flags through fields_count. */
2872 if (clas == object_type_node)
2873 i = 10;
2874 else
2875 i = 8 + 2 * total_supers;
2876 ptr = append_chunk (NULL, i, state);
2877 i = get_access_flags (TYPE_NAME (clas));
2878 if (! (i & ACC_INTERFACE))
2879 i |= ACC_SUPER;
2880 PUT2 (i); /* access_flags */
2881 i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
2882 if (clas == object_type_node)
2884 PUT2(0); /* super_class */
2885 PUT2(0); /* interfaces_count */
2887 else
2889 tree basetypes = TYPE_BINFO_BASETYPES (clas);
2890 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2891 int j = find_class_constant (&state->cpool, base);
2892 PUT2 (j); /* super_class */
2893 PUT2 (total_supers - 1); /* interfaces_count */
2894 for (i = 1; i < total_supers; i++)
2896 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2897 j = find_class_constant (&state->cpool, base);
2898 PUT2 (j);
2901 fields_count_ptr = ptr;
2903 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
2905 int have_value, attr_count = 0;
2906 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2907 continue;
2908 ptr = append_chunk (NULL, 8, state);
2909 i = get_access_flags (part); PUT2 (i);
2910 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
2911 i = find_utf8_constant (&state->cpool,
2912 build_java_signature (TREE_TYPE (part)));
2913 PUT2(i);
2914 have_value = DECL_INITIAL (part) != NULL_TREE
2915 && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
2916 && FIELD_FINAL (part)
2917 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
2918 || TREE_TYPE (part) == string_ptr_type_node);
2919 if (have_value)
2920 attr_count++;
2922 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2923 || FIELD_SYNTHETIC (part))
2924 attr_count++;
2925 if (FIELD_DEPRECATED (part))
2926 attr_count++;
2928 PUT2 (attr_count); /* attributes_count */
2929 if (have_value)
2931 tree init = DECL_INITIAL (part);
2932 static tree ConstantValue_node = NULL_TREE;
2933 if (TREE_TYPE (part) != TREE_TYPE (init))
2934 fatal_error ("field initializer type mismatch");
2935 ptr = append_chunk (NULL, 8, state);
2936 if (ConstantValue_node == NULL_TREE)
2937 ConstantValue_node = get_identifier ("ConstantValue");
2938 i = find_utf8_constant (&state->cpool, ConstantValue_node);
2939 PUT2 (i); /* attribute_name_index */
2940 PUT4 (2); /* attribute_length */
2941 i = find_constant_index (init, state); PUT2 (i);
2943 /* Emit the "Synthetic" attribute for val$<x> and this$<n>
2944 fields and other fields which need it. */
2945 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2946 || FIELD_SYNTHETIC (part))
2947 ptr = append_synthetic_attribute (state);
2948 if (FIELD_DEPRECATED (part))
2949 append_deprecated_attribute (state);
2950 fields_count++;
2952 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
2954 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
2955 PUT2 (0);
2957 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
2959 struct jcf_block *block;
2960 tree function_body = DECL_FUNCTION_BODY (part);
2961 tree body = function_body == NULL_TREE ? NULL_TREE
2962 : BLOCK_EXPR_BODY (function_body);
2963 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
2964 : DECL_NAME (part);
2965 tree type = TREE_TYPE (part);
2966 tree save_function = current_function_decl;
2967 int synthetic_p = 0;
2969 /* Invisible Miranda methods shouldn't end up in the .class
2970 file. */
2971 if (METHOD_INVISIBLE (part))
2972 continue;
2974 current_function_decl = part;
2975 ptr = append_chunk (NULL, 8, state);
2976 i = get_access_flags (part); PUT2 (i);
2977 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
2978 i = find_utf8_constant (&state->cpool, build_java_signature (type));
2979 PUT2 (i);
2980 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
2982 /* Make room for the Synthetic attribute (of zero length.) */
2983 if (DECL_FINIT_P (part)
2984 || DECL_INSTINIT_P (part)
2985 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
2986 || TYPE_DOT_CLASS (clas) == part)
2988 i++;
2989 synthetic_p = 1;
2991 /* Make room for Deprecated attribute. */
2992 if (METHOD_DEPRECATED (part))
2993 i++;
2995 PUT2 (i); /* attributes_count */
2997 if (synthetic_p)
2998 ptr = append_synthetic_attribute (state);
3000 if (body != NULL_TREE)
3002 int code_attributes_count = 0;
3003 static tree Code_node = NULL_TREE;
3004 tree t;
3005 char *attr_len_ptr;
3006 struct jcf_handler *handler;
3007 if (Code_node == NULL_TREE)
3008 Code_node = get_identifier ("Code");
3009 ptr = append_chunk (NULL, 14, state);
3010 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
3011 attr_len_ptr = ptr;
3012 init_jcf_method (state, part);
3013 get_jcf_label_here (state); /* Force a first block. */
3014 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3015 localvar_alloc (t, state);
3016 state->num_jsrs = 0;
3017 generate_bytecode_insns (body, IGNORE_TARGET, state);
3018 if (CAN_COMPLETE_NORMALLY (body))
3020 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
3021 abort();
3022 RESERVE (1);
3023 OP1 (OPCODE_return);
3025 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3026 maybe_free_localvar (t, state, 1);
3027 if (state->return_value_decl != NULL_TREE)
3028 maybe_free_localvar (state->return_value_decl, state, 1);
3029 finish_jcf_block (state);
3030 perform_relocations (state);
3032 ptr = attr_len_ptr;
3033 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
3034 if (state->linenumber_count > 0)
3036 code_attributes_count++;
3037 i += 8 + 4 * state->linenumber_count;
3039 if (state->lvar_count > 0)
3041 code_attributes_count++;
3042 i += 8 + 10 * state->lvar_count;
3044 UNSAFE_PUT4 (i); /* attribute_length */
3045 UNSAFE_PUT2 (state->code_SP_max); /* max_stack */
3046 UNSAFE_PUT2 (localvar_max); /* max_locals */
3047 UNSAFE_PUT4 (state->code_length);
3049 /* Emit the exception table. */
3050 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3051 PUT2 (state->num_handlers); /* exception_table_length */
3052 handler = state->handlers;
3053 for (; handler != NULL; handler = handler->next)
3055 int type_index;
3056 PUT2 (handler->start_label->pc);
3057 PUT2 (handler->end_label->pc);
3058 PUT2 (handler->handler_label->pc);
3059 if (handler->type == NULL_TREE)
3060 type_index = 0;
3061 else
3062 type_index = find_class_constant (&state->cpool,
3063 handler->type);
3064 PUT2 (type_index);
3067 ptr = append_chunk (NULL, 2, state);
3068 PUT2 (code_attributes_count);
3070 /* Write the LineNumberTable attribute. */
3071 if (state->linenumber_count > 0)
3073 static tree LineNumberTable_node = NULL_TREE;
3074 ptr = append_chunk (NULL,
3075 8 + 4 * state->linenumber_count, state);
3076 if (LineNumberTable_node == NULL_TREE)
3077 LineNumberTable_node = get_identifier ("LineNumberTable");
3078 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3079 PUT2 (i); /* attribute_name_index */
3080 i = 2+4*state->linenumber_count; PUT4(i); /* attribute_length */
3081 i = state->linenumber_count; PUT2 (i);
3082 for (block = state->blocks; block != NULL; block = block->next)
3084 int line = block->linenumber;
3085 if (line > 0)
3087 PUT2 (block->pc);
3088 PUT2 (line);
3093 /* Write the LocalVariableTable attribute. */
3094 if (state->lvar_count > 0)
3096 static tree LocalVariableTable_node = NULL_TREE;
3097 struct localvar_info *lvar = state->first_lvar;
3098 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3099 if (LocalVariableTable_node == NULL_TREE)
3100 LocalVariableTable_node = get_identifier("LocalVariableTable");
3101 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3102 PUT2 (i); /* attribute_name_index */
3103 i = 2 + 10 * state->lvar_count; PUT4 (i); /* attribute_length */
3104 i = state->lvar_count; PUT2 (i);
3105 for ( ; lvar != NULL; lvar = lvar->next)
3107 tree name = DECL_NAME (lvar->decl);
3108 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3109 i = lvar->start_label->pc; PUT2 (i);
3110 i = lvar->end_label->pc - i; PUT2 (i);
3111 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3112 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
3113 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
3117 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3119 tree t = DECL_FUNCTION_THROWS (part);
3120 int throws_count = list_length (t);
3121 static tree Exceptions_node = NULL_TREE;
3122 if (Exceptions_node == NULL_TREE)
3123 Exceptions_node = get_identifier ("Exceptions");
3124 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3125 i = find_utf8_constant (&state->cpool, Exceptions_node);
3126 PUT2 (i); /* attribute_name_index */
3127 i = 2 + 2 * throws_count; PUT4(i); /* attribute_length */
3128 i = throws_count; PUT2 (i);
3129 for (; t != NULL_TREE; t = TREE_CHAIN (t))
3131 i = find_class_constant (&state->cpool, TREE_VALUE (t));
3132 PUT2 (i);
3136 if (METHOD_DEPRECATED (part))
3137 append_deprecated_attribute (state);
3139 methods_count++;
3140 current_function_decl = save_function;
3142 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
3144 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3145 for (s = source_file; ; s++)
3147 char ch = *s;
3148 if (ch == '\0')
3149 break;
3150 if (ch == '/' || ch == '\\')
3151 source_file = s+1;
3153 ptr = append_chunk (NULL, 10, state);
3155 i = 1; /* Source file always exists as an attribute */
3156 if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3157 i++;
3158 if (clas == object_type_node)
3159 i++;
3160 if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3161 i++;
3163 PUT2 (i); /* attributes_count */
3165 /* generate the SourceFile attribute. */
3166 if (SourceFile_node == NULL_TREE)
3168 SourceFile_node = get_identifier ("SourceFile");
3171 i = find_utf8_constant (&state->cpool, SourceFile_node);
3172 PUT2 (i); /* attribute_name_index */
3173 PUT4 (2);
3174 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3175 PUT2 (i);
3176 append_gcj_attribute (state, clas);
3177 append_innerclasses_attribute (state, clas);
3178 if (CLASS_DEPRECATED (TYPE_NAME (clas)))
3179 append_deprecated_attribute (state);
3181 /* New finally generate the contents of the constant pool chunk. */
3182 i = count_constant_pool_bytes (&state->cpool);
3183 ptr = obstack_alloc (state->chunk_obstack, i);
3184 cpool_chunk->data = ptr;
3185 cpool_chunk->size = i;
3186 write_constant_pool (&state->cpool, ptr, i);
3187 return state->first;
3190 static GTY(()) tree Synthetic_node;
3191 static unsigned char *
3192 append_synthetic_attribute (struct jcf_partial *state)
3194 unsigned char *ptr = append_chunk (NULL, 6, state);
3195 int i;
3197 if (Synthetic_node == NULL_TREE)
3199 Synthetic_node = get_identifier ("Synthetic");
3201 i = find_utf8_constant (&state->cpool, Synthetic_node);
3202 PUT2 (i); /* Attribute string index */
3203 PUT4 (0); /* Attribute length */
3205 return ptr;
3208 static void
3209 append_deprecated_attribute (struct jcf_partial *state)
3211 unsigned char *ptr = append_chunk (NULL, 6, state);
3212 int i;
3214 i = find_utf8_constant (&state->cpool, get_identifier ("Deprecated"));
3215 PUT2 (i); /* Attribute string index */
3216 PUT4 (0); /* Attribute length */
3219 static void
3220 append_gcj_attribute (struct jcf_partial *state, tree class)
3222 unsigned char *ptr;
3223 int i;
3225 if (class != object_type_node)
3226 return;
3228 ptr = append_chunk (NULL, 6, state); /* 2+4 */
3229 i = find_utf8_constant (&state->cpool,
3230 get_identifier ("gnu.gcj.gcj-compiled"));
3231 PUT2 (i); /* Attribute string index */
3232 PUT4 (0); /* Attribute length */
3235 static tree InnerClasses_node;
3236 static void
3237 append_innerclasses_attribute (struct jcf_partial *state, tree class)
3239 tree orig_decl = TYPE_NAME (class);
3240 tree current, decl;
3241 int length = 0, i;
3242 unsigned char *ptr, *length_marker, *number_marker;
3244 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3245 return;
3247 ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3249 if (InnerClasses_node == NULL_TREE)
3251 InnerClasses_node = get_identifier ("InnerClasses");
3253 i = find_utf8_constant (&state->cpool, InnerClasses_node);
3254 PUT2 (i);
3255 length_marker = ptr; PUT4 (0); /* length, to be later patched */
3256 number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3258 /* Generate the entries: all inner classes visible from the one we
3259 process: itself, up and down. */
3260 while (class && INNER_CLASS_TYPE_P (class))
3262 const char *n;
3264 decl = TYPE_NAME (class);
3265 n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
3266 IDENTIFIER_LENGTH (DECL_NAME (decl));
3268 while (n[-1] != '$')
3269 n--;
3270 append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3271 length++;
3273 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3276 decl = orig_decl;
3277 for (current = DECL_INNER_CLASS_LIST (decl);
3278 current; current = TREE_CHAIN (current))
3280 append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3281 TREE_VALUE (current));
3282 length++;
3285 ptr = length_marker; PUT4 (8*length+2);
3286 ptr = number_marker; PUT2 (length);
3289 static void
3290 append_innerclasses_attribute_entry (struct jcf_partial *state,
3291 tree decl, tree name)
3293 int icii, icaf;
3294 int ocii = 0, ini = 0;
3295 unsigned char *ptr = append_chunk (NULL, 8, state);
3297 icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3299 /* Sun's implementation seems to generate ocii to 0 for inner
3300 classes (which aren't considered members of the class they're
3301 in.) The specs are saying that if the class is anonymous,
3302 inner_name_index must be zero. */
3303 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3305 ocii = find_class_constant (&state->cpool,
3306 TREE_TYPE (DECL_CONTEXT (decl)));
3307 ini = find_utf8_constant (&state->cpool, name);
3309 icaf = get_access_flags (decl);
3311 PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
3314 static char *
3315 make_class_file_name (tree clas)
3317 const char *dname, *cname, *slash;
3318 char *r;
3319 struct stat sb;
3320 char sep;
3322 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3323 "", '.', DIR_SEPARATOR,
3324 ".class"));
3325 if (jcf_write_base_directory == NULL)
3327 /* Make sure we put the class file into the .java file's
3328 directory, and not into some subdirectory thereof. */
3329 char *t;
3330 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3331 slash = strrchr (dname, DIR_SEPARATOR);
3332 #ifdef DIR_SEPARATOR_2
3333 if (! slash)
3334 slash = strrchr (dname, DIR_SEPARATOR_2);
3335 #endif
3336 if (! slash)
3338 dname = ".";
3339 slash = dname + 1;
3340 sep = DIR_SEPARATOR;
3342 else
3343 sep = *slash;
3345 t = strrchr (cname, DIR_SEPARATOR);
3346 if (t)
3347 cname = t + 1;
3349 else
3351 char *s;
3353 dname = jcf_write_base_directory;
3355 s = strrchr (dname, DIR_SEPARATOR);
3356 #ifdef DIR_SEPARATOR_2
3357 if (! s)
3358 s = strrchr (dname, DIR_SEPARATOR_2);
3359 #endif
3360 if (s)
3361 sep = *s;
3362 else
3363 sep = DIR_SEPARATOR;
3365 slash = dname + strlen (dname);
3368 r = xmalloc (slash - dname + strlen (cname) + 2);
3369 strncpy (r, dname, slash - dname);
3370 r[slash - dname] = sep;
3371 strcpy (&r[slash - dname + 1], cname);
3373 /* We try to make new directories when we need them. We only do
3374 this for directories which "might not" exist. For instance, we
3375 assume the `-d' directory exists, but we don't assume that any
3376 subdirectory below it exists. It might be worthwhile to keep
3377 track of which directories we've created to avoid gratuitous
3378 stat()s. */
3379 dname = r + (slash - dname) + 1;
3380 while (1)
3382 char *s = strchr (dname, sep);
3383 if (s == NULL)
3384 break;
3385 *s = '\0';
3386 if (stat (r, &sb) == -1
3387 /* Try to make it. */
3388 && mkdir (r, 0755) == -1)
3389 fatal_error ("can't create directory %s: %m", r);
3391 *s = sep;
3392 /* Skip consecutive separators. */
3393 for (dname = s + 1; *dname && *dname == sep; ++dname)
3397 return r;
3400 /* Write out the contents of a class (RECORD_TYPE) CLAS, as a .class file.
3401 The output .class file name is make_class_file_name(CLAS). */
3403 void
3404 write_classfile (tree clas)
3406 struct obstack *work = &temporary_obstack;
3407 struct jcf_partial state[1];
3408 char *class_file_name = make_class_file_name (clas);
3409 struct chunk *chunks;
3411 if (class_file_name != NULL)
3413 FILE *stream;
3414 char *temporary_file_name;
3416 /* The .class file is initially written to a ".tmp" file so that
3417 if multiple instances of the compiler are running at once
3418 they do not see partially formed class files. */
3419 temporary_file_name = concat (class_file_name, ".tmp", NULL);
3420 stream = fopen (temporary_file_name, "wb");
3421 if (stream == NULL)
3422 fatal_error ("can't open %s for writing: %m", temporary_file_name);
3424 jcf_dependency_add_target (class_file_name);
3425 init_jcf_state (state, work);
3426 chunks = generate_classfile (clas, state);
3427 write_chunks (stream, chunks);
3428 if (fclose (stream))
3429 fatal_error ("error closing %s: %m", temporary_file_name);
3431 /* If a file named by the string pointed to by `new' exists
3432 prior to the call to the `rename' function, the behavior
3433 is implementation-defined. ISO 9899-1990 7.9.4.2.
3435 For example, on Win32 with MSVCRT, it is an error. */
3437 unlink (class_file_name);
3439 if (rename (temporary_file_name, class_file_name) == -1)
3441 remove (temporary_file_name);
3442 fatal_error ("can't create %s: %m", class_file_name);
3444 free (temporary_file_name);
3445 free (class_file_name);
3447 release_jcf_state (state);
3450 /* TODO:
3451 string concatenation
3452 synchronized statement
3455 #include "gt-java-jcf-write.h"