ifcvt.c (noce_try_addcc): Do not call emit_conditional_add with weird operands.
[official-gcc.git] / gcc / java / jcf-write.c
blob15035c05cfca752c76b758495d662aa7f3aeaa4c
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"
42 #ifndef DIR_SEPARATOR
43 #define DIR_SEPARATOR '/'
44 #endif
46 extern struct obstack temporary_obstack;
48 /* Base directory in which `.class' files should be written.
49 NULL means to put the file into the same directory as the
50 corresponding .java file. */
51 char *jcf_write_base_directory = NULL;
53 /* Make sure bytecode.data is big enough for at least N more bytes. */
55 #define RESERVE(N) \
56 do { CHECK_OP(state); \
57 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
58 buffer_grow (&state->bytecode, N); } while (0)
60 /* Add a 1-byte instruction/operand I to bytecode.data,
61 assuming space has already been RESERVE'd. */
63 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
65 /* Like OP1, but I is a 2-byte big endian integer. */
67 #define OP2(I) \
68 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
70 /* Like OP1, but I is a 4-byte big endian integer. */
72 #define OP4(I) \
73 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
74 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
76 /* Macro to call each time we push I words on the JVM stack. */
78 #define NOTE_PUSH(I) \
79 do { state->code_SP += (I); \
80 if (state->code_SP > state->code_SP_max) \
81 state->code_SP_max = state->code_SP; } while (0)
83 /* Macro to call each time we pop I words from the JVM stack. */
85 #define NOTE_POP(I) \
86 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
88 /* A chunk or segment of a .class file. */
90 struct chunk
92 /* The next segment of this .class file. */
93 struct chunk *next;
95 /* The actual data in this segment to be written to the .class file. */
96 unsigned char *data;
98 /* The size of the segment to be written to the .class file. */
99 int size;
102 #define PENDING_CLEANUP_PC (-3)
103 #define PENDING_EXIT_PC (-2)
104 #define UNDEFINED_PC (-1)
106 /* Each "block" represents a label plus the bytecode instructions following.
107 There may be branches out of the block, but no incoming jumps, except
108 to the beginning of the block.
110 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
111 associated code yet), but it is an undefined label.
114 struct jcf_block
116 /* For blocks that that are defined, the next block (in pc order).
117 For blocks that are not-yet-defined the end label of a LABELED_BLOCK_EXPR
118 or a cleanup expression (from a TRY_FINALLY_EXPR),
119 this is the next (outer) such end label, in a stack headed by
120 labeled_blocks in jcf_partial. */
121 struct jcf_block *next;
123 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
124 pc is PENDING_EXIT_PC.
125 In the not-yet-defined end label for pending cleanup subroutine,
126 pc is PENDING_CLEANUP_PC.
127 For other not-yet-defined labels, pc is UNDEFINED_PC.
129 If the label has been defined:
130 Until perform_relocations is finished, this is the maximum possible
131 value of the bytecode offset at the begnning of this block.
132 After perform_relocations, it is the actual offset (pc). */
133 int pc;
135 int linenumber;
137 /* After finish_jcf_block is called, the actual instructions
138 contained in this block. Before that NULL, and the instructions
139 are in state->bytecode. */
140 union {
141 struct chunk *chunk;
143 /* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
144 covered by the cleanup. */
145 struct jcf_block *start_label;
146 } v;
148 union {
149 /* Set of relocations (in reverse offset order) for this block. */
150 struct jcf_relocation *relocations;
152 /* If this block is that of the not-yet-defined end label of
153 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR.
154 If pc==PENDING_CLEANUP_PC, the cleanup that needs to be run. */
155 tree labeled_block;
156 } u;
159 /* A "relocation" type for the 0-3 bytes of padding at the start
160 of a tableswitch or a lookupswitch. */
161 #define SWITCH_ALIGN_RELOC 4
163 /* A relocation type for the labels in a tableswitch or a lookupswitch;
164 these are relative to the start of the instruction, but (due to
165 th 0-3 bytes of padding), we don't know the offset before relocation. */
166 #define BLOCK_START_RELOC 1
168 struct jcf_relocation
170 /* Next relocation for the current jcf_block. */
171 struct jcf_relocation *next;
173 /* The (byte) offset within the current block that needs to be relocated. */
174 HOST_WIDE_INT offset;
176 /* 0 if offset is a 4-byte relative offset.
177 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
178 for proper alignment in tableswitch/lookupswitch instructions.
179 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
180 to the start of the containing block.
181 -1 if offset is a 2-byte relative offset.
182 < -1 if offset is the address of an instruction with a 2-byte offset
183 that does not have a corresponding 4-byte offset version, in which
184 case the absolute value of kind is the inverted opcode.
185 > 4 if offset is the address of an instruction (such as jsr) with a
186 2-byte offset that does have a corresponding 4-byte offset version,
187 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
188 int kind;
190 /* The label the relocation wants to actually transfer to. */
191 struct jcf_block *label;
194 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
195 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
197 /* State for single catch clause. */
199 struct jcf_handler
201 struct jcf_handler *next;
203 struct jcf_block *start_label;
204 struct jcf_block *end_label;
205 struct jcf_block *handler_label;
207 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
208 tree type;
211 /* State for the current switch statement. */
213 struct jcf_switch_state
215 struct jcf_switch_state *prev;
216 struct jcf_block *default_label;
218 struct jcf_relocation *cases;
219 int num_cases;
220 HOST_WIDE_INT min_case, max_case;
223 /* This structure is used to contain the various pieces that will
224 become a .class file. */
226 struct jcf_partial
228 struct chunk *first;
229 struct chunk *chunk;
230 struct obstack *chunk_obstack;
231 tree current_method;
233 /* List of basic blocks for the current method. */
234 struct jcf_block *blocks;
235 struct jcf_block *last_block;
237 struct localvar_info *first_lvar;
238 struct localvar_info *last_lvar;
239 int lvar_count;
241 CPool cpool;
243 int linenumber_count;
245 /* Until perform_relocations, this is a upper bound on the number
246 of bytes (so far) in the instructions for the current method. */
247 int code_length;
249 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
250 struct jcf_block *labeled_blocks;
252 /* The current stack size (stack pointer) in the current method. */
253 int code_SP;
255 /* The largest extent of stack size (stack pointer) in the current method. */
256 int code_SP_max;
258 /* Contains a mapping from local var slot number to localvar_info. */
259 struct buffer localvars;
261 /* The buffer allocated for bytecode for the current jcf_block. */
262 struct buffer bytecode;
264 /* Chain of exception handlers for the current method. */
265 struct jcf_handler *handlers;
267 /* Last element in handlers chain. */
268 struct jcf_handler *last_handler;
270 /* Number of exception handlers for the current method. */
271 int num_handlers;
273 /* Number of finalizers we are currently nested within. */
274 int num_finalizers;
276 /* If non-NULL, use this for the return value. */
277 tree return_value_decl;
279 /* Information about the current switch statement. */
280 struct jcf_switch_state *sw_state;
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 localvar_free (tree, struct jcf_partial *);
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_innerclasses_attribute (struct jcf_partial *, tree);
344 static void append_innerclasses_attribute_entry (struct jcf_partial *, tree, tree);
345 static void append_gcj_attribute (struct jcf_partial *, tree);
347 /* Utility macros for appending (big-endian) data to a buffer.
348 We assume a local variable 'ptr' points into where we want to
349 write next, and we assume enough space has been allocated. */
351 #ifdef ENABLE_JC1_CHECKING
352 static int CHECK_PUT (void *, struct jcf_partial *, int);
354 static int
355 CHECK_PUT (ptr, state, i)
356 void *ptr;
357 struct jcf_partial *state;
358 int i;
360 if ((unsigned char *) ptr < state->chunk->data
361 || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
362 abort ();
364 return 0;
366 #else
367 #define CHECK_PUT(PTR, STATE, I) ((void)0)
368 #endif
370 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
371 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
372 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
373 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
375 /* There are some cases below where CHECK_PUT is guaranteed to fail.
376 Use the following macros in those specific cases. */
377 #define UNSAFE_PUT1(X) (*ptr++ = (X))
378 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
379 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
380 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
383 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
384 Set the data and size fields to DATA and SIZE, respectively.
385 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
387 static struct chunk *
388 alloc_chunk (last, data, size, work)
389 struct chunk *last;
390 unsigned char *data;
391 int size;
392 struct obstack *work;
394 struct chunk *chunk = (struct chunk *)
395 obstack_alloc (work, sizeof(struct chunk));
397 if (data == NULL && size > 0)
398 data = obstack_alloc (work, size);
400 chunk->next = NULL;
401 chunk->data = data;
402 chunk->size = size;
403 if (last != NULL)
404 last->next = chunk;
405 return chunk;
408 #ifdef ENABLE_JC1_CHECKING
409 static int CHECK_OP (struct jcf_partial *);
411 static int
412 CHECK_OP (state)
413 struct jcf_partial *state;
415 if (state->bytecode.ptr > state->bytecode.limit)
416 abort ();
418 return 0;
420 #else
421 #define CHECK_OP(STATE) ((void) 0)
422 #endif
424 static unsigned char *
425 append_chunk (data, size, state)
426 unsigned char *data;
427 int size;
428 struct jcf_partial *state;
430 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
431 if (state->first == NULL)
432 state->first = state->chunk;
433 return state->chunk->data;
436 static void
437 append_chunk_copy (data, size, state)
438 unsigned char *data;
439 int size;
440 struct jcf_partial *state;
442 unsigned char *ptr = append_chunk (NULL, size, state);
443 memcpy (ptr, data, size);
446 static struct jcf_block *
447 gen_jcf_label (state)
448 struct jcf_partial *state;
450 struct jcf_block *block = (struct jcf_block *)
451 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
452 block->next = NULL;
453 block->linenumber = -1;
454 block->pc = UNDEFINED_PC;
455 return block;
458 static void
459 finish_jcf_block (state)
460 struct jcf_partial *state;
462 struct jcf_block *block = state->last_block;
463 struct jcf_relocation *reloc;
464 int code_length = BUFFER_LENGTH (&state->bytecode);
465 int pc = state->code_length;
466 append_chunk_copy (state->bytecode.data, code_length, state);
467 BUFFER_RESET (&state->bytecode);
468 block->v.chunk = state->chunk;
470 /* Calculate code_length to the maximum value it can have. */
471 pc += block->v.chunk->size;
472 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
474 int kind = reloc->kind;
475 if (kind == SWITCH_ALIGN_RELOC)
476 pc += 3;
477 else if (kind > BLOCK_START_RELOC)
478 pc += 2; /* 2-byte offset may grow to 4-byte offset */
479 else if (kind < -1)
480 pc += 5; /* May need to add a goto_w. */
482 state->code_length = pc;
485 static void
486 define_jcf_label (label, state)
487 struct jcf_block *label;
488 struct jcf_partial *state;
490 if (state->last_block != NULL)
491 finish_jcf_block (state);
492 label->pc = state->code_length;
493 if (state->blocks == NULL)
494 state->blocks = label;
495 else
496 state->last_block->next = label;
497 state->last_block = label;
498 label->next = NULL;
499 label->u.relocations = NULL;
502 static struct jcf_block *
503 get_jcf_label_here (state)
504 struct jcf_partial *state;
506 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
507 return state->last_block;
508 else
510 struct jcf_block *label = gen_jcf_label (state);
511 define_jcf_label (label, state);
512 return label;
516 /* Note a line number entry for the current PC and given LINE. */
518 static void
519 put_linenumber (line, state)
520 int line;
521 struct jcf_partial *state;
523 struct jcf_block *label = get_jcf_label_here (state);
524 if (label->linenumber > 0)
526 label = gen_jcf_label (state);
527 define_jcf_label (label, state);
529 label->linenumber = line;
530 state->linenumber_count++;
533 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
534 in the range (START_LABEL, END_LABEL). */
536 static struct jcf_handler *
537 alloc_handler (start_label, end_label, state)
538 struct jcf_block *start_label;
539 struct jcf_block *end_label;
540 struct jcf_partial *state;
542 struct jcf_handler *handler = (struct jcf_handler *)
543 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
544 handler->start_label = start_label;
545 handler->end_label = end_label;
546 handler->handler_label = get_jcf_label_here (state);
547 if (state->handlers == NULL)
548 state->handlers = handler;
549 else
550 state->last_handler->next = handler;
551 state->last_handler = handler;
552 handler->next = NULL;
553 state->num_handlers++;
554 return handler;
558 /* The index of jvm local variable allocated for this DECL.
559 This is assigned when generating .class files;
560 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
561 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
563 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
565 struct localvar_info
567 struct localvar_info *next;
569 tree decl;
570 struct jcf_block *start_label;
571 struct jcf_block *end_label;
574 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
575 #define localvar_max \
576 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
578 static void
579 localvar_alloc (decl, state)
580 tree decl;
581 struct jcf_partial *state;
583 struct jcf_block *start_label = get_jcf_label_here (state);
584 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
585 int index;
586 register struct localvar_info *info;
587 register struct localvar_info **ptr = localvar_buffer;
588 register struct localvar_info **limit
589 = (struct localvar_info**) state->localvars.ptr;
590 for (index = 0; ptr < limit; index++, ptr++)
592 if (ptr[0] == NULL
593 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
594 break;
596 if (ptr == limit)
598 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
599 ptr = (struct localvar_info**) state->localvars.data + index;
600 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
602 info = (struct localvar_info *)
603 obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
604 ptr[0] = info;
605 if (wide)
606 ptr[1] = (struct localvar_info *)(~0);
607 DECL_LOCAL_INDEX (decl) = index;
608 info->decl = decl;
609 info->start_label = start_label;
611 if (debug_info_level > DINFO_LEVEL_TERSE
612 && DECL_NAME (decl) != NULL_TREE)
614 /* Generate debugging info. */
615 info->next = NULL;
616 if (state->last_lvar != NULL)
617 state->last_lvar->next = info;
618 else
619 state->first_lvar = info;
620 state->last_lvar = info;
621 state->lvar_count++;
625 static void
626 localvar_free (decl, state)
627 tree decl;
628 struct jcf_partial *state;
630 struct jcf_block *end_label = get_jcf_label_here (state);
631 int index = DECL_LOCAL_INDEX (decl);
632 register struct localvar_info **ptr = &localvar_buffer [index];
633 register struct localvar_info *info = *ptr;
634 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
636 info->end_label = end_label;
638 if (info->decl != decl)
639 abort ();
640 ptr[0] = NULL;
641 if (wide)
643 if (ptr[1] != (struct localvar_info *)(~0))
644 abort ();
645 ptr[1] = NULL;
650 #define STACK_TARGET 1
651 #define IGNORE_TARGET 2
653 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
654 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
656 static int
657 get_access_flags (decl)
658 tree decl;
660 int flags = 0;
661 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
662 if (CLASS_PUBLIC (decl)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
663 flags |= ACC_PUBLIC;
664 if (CLASS_FINAL (decl)) /* same as FIELD_FINAL and METHOD_FINAL */
665 flags |= ACC_FINAL;
666 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
668 if (TREE_PROTECTED (decl))
669 flags |= ACC_PROTECTED;
670 if (TREE_PRIVATE (decl))
671 flags |= ACC_PRIVATE;
673 else if (TREE_CODE (decl) == TYPE_DECL)
675 if (CLASS_SUPER (decl))
676 flags |= ACC_SUPER;
677 if (CLASS_ABSTRACT (decl))
678 flags |= ACC_ABSTRACT;
679 if (CLASS_INTERFACE (decl))
680 flags |= ACC_INTERFACE;
681 if (CLASS_STATIC (decl))
682 flags |= ACC_STATIC;
683 if (CLASS_PRIVATE (decl))
684 flags |= ACC_PRIVATE;
685 if (CLASS_PROTECTED (decl))
686 flags |= ACC_PROTECTED;
687 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
688 || LOCAL_CLASS_P (TREE_TYPE (decl)))
689 flags |= ACC_PRIVATE;
690 if (CLASS_STRICTFP (decl))
691 flags |= ACC_STRICT;
693 else
694 abort ();
696 if (TREE_CODE (decl) == FUNCTION_DECL)
698 if (METHOD_NATIVE (decl))
699 flags |= ACC_NATIVE;
700 if (METHOD_STATIC (decl))
701 flags |= ACC_STATIC;
702 if (METHOD_SYNCHRONIZED (decl))
703 flags |= ACC_SYNCHRONIZED;
704 if (METHOD_ABSTRACT (decl))
705 flags |= ACC_ABSTRACT;
706 if (METHOD_STRICTFP (decl))
707 flags |= ACC_STRICT;
709 if (isfield)
711 if (FIELD_STATIC (decl))
712 flags |= ACC_STATIC;
713 if (FIELD_VOLATILE (decl))
714 flags |= ACC_VOLATILE;
715 if (FIELD_TRANSIENT (decl))
716 flags |= ACC_TRANSIENT;
718 return flags;
721 /* Write the list of segments starting at CHUNKS to STREAM. */
723 static void
724 write_chunks (stream, chunks)
725 FILE* stream;
726 struct chunk *chunks;
728 for (; chunks != NULL; chunks = chunks->next)
729 fwrite (chunks->data, chunks->size, 1, stream);
732 /* Push a 1-word constant in the constant pool at the given INDEX.
733 (Caller is responsible for doing NOTE_PUSH.) */
735 static void
736 push_constant1 (index, state)
737 HOST_WIDE_INT index;
738 struct jcf_partial *state;
740 RESERVE (3);
741 if (index < 256)
743 OP1 (OPCODE_ldc);
744 OP1 (index);
746 else
748 OP1 (OPCODE_ldc_w);
749 OP2 (index);
753 /* Push a 2-word constant in the constant pool at the given INDEX.
754 (Caller is responsible for doing NOTE_PUSH.) */
756 static void
757 push_constant2 (index, state)
758 HOST_WIDE_INT index;
759 struct jcf_partial *state;
761 RESERVE (3);
762 OP1 (OPCODE_ldc2_w);
763 OP2 (index);
766 /* Push 32-bit integer constant on VM stack.
767 Caller is responsible for doing NOTE_PUSH. */
769 static void
770 push_int_const (i, state)
771 HOST_WIDE_INT i;
772 struct jcf_partial *state;
774 RESERVE(3);
775 if (i >= -1 && i <= 5)
776 OP1(OPCODE_iconst_0 + i);
777 else if (i >= -128 && i < 128)
779 OP1(OPCODE_bipush);
780 OP1(i);
782 else if (i >= -32768 && i < 32768)
784 OP1(OPCODE_sipush);
785 OP2(i);
787 else
789 i = find_constant1 (&state->cpool, CONSTANT_Integer,
790 (jword)(i & 0xFFFFFFFF));
791 push_constant1 (i, state);
795 static int
796 find_constant_wide (lo, hi, state)
797 HOST_WIDE_INT lo, hi;
798 struct jcf_partial *state;
800 HOST_WIDE_INT w1, w2;
801 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
802 return find_constant2 (&state->cpool, CONSTANT_Long,
803 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
806 /* Find or allocate a constant pool entry for the given VALUE.
807 Return the index in the constant pool. */
809 static int
810 find_constant_index (value, state)
811 tree value;
812 struct jcf_partial *state;
814 if (TREE_CODE (value) == INTEGER_CST)
816 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
817 return find_constant1 (&state->cpool, CONSTANT_Integer,
818 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
819 else
820 return find_constant_wide (TREE_INT_CST_LOW (value),
821 TREE_INT_CST_HIGH (value), state);
823 else if (TREE_CODE (value) == REAL_CST)
825 long words[2];
827 real_to_target (words, &TREE_REAL_CST (value),
828 TYPE_MODE (TREE_TYPE (value)));
829 words[0] &= 0xffffffff;
830 words[1] &= 0xffffffff;
832 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
833 return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
834 else
835 return find_constant2 (&state->cpool, CONSTANT_Double,
836 (jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
837 (jword)words[FLOAT_WORDS_BIG_ENDIAN]);
839 else if (TREE_CODE (value) == STRING_CST)
840 return find_string_constant (&state->cpool, value);
842 else
843 abort ();
846 /* Push 64-bit long constant on VM stack.
847 Caller is responsible for doing NOTE_PUSH. */
849 static void
850 push_long_const (lo, hi, state)
851 HOST_WIDE_INT lo, hi;
852 struct jcf_partial *state;
854 HOST_WIDE_INT highpart, dummy;
855 jint lowpart = WORD_TO_INT (lo);
857 rshift_double (lo, hi, 32, 64, &highpart, &dummy, 1);
859 if (highpart == 0 && (lowpart == 0 || lowpart == 1))
861 RESERVE(1);
862 OP1(OPCODE_lconst_0 + lowpart);
864 else if ((highpart == 0 && lowpart > 0 && lowpart < 32768)
865 || (highpart == -1 && lowpart < 0 && lowpart >= -32768))
867 push_int_const (lowpart, state);
868 RESERVE (1);
869 OP1 (OPCODE_i2l);
871 else
872 push_constant2 (find_constant_wide (lo, hi, state), state);
875 static void
876 field_op (field, opcode, state)
877 tree field;
878 int opcode;
879 struct jcf_partial *state;
881 int index = find_fieldref_index (&state->cpool, field);
882 RESERVE (3);
883 OP1 (opcode);
884 OP2 (index);
887 /* Returns an integer in the range 0 (for 'int') through 4 (for object
888 reference) to 7 (for 'short') which matches the pattern of how JVM
889 opcodes typically depend on the operand type. */
891 static int
892 adjust_typed_op (type, max)
893 tree type;
894 int max;
896 switch (TREE_CODE (type))
898 case POINTER_TYPE:
899 case RECORD_TYPE: return 4;
900 case BOOLEAN_TYPE:
901 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
902 case CHAR_TYPE:
903 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
904 case INTEGER_TYPE:
905 switch (TYPE_PRECISION (type))
907 case 8: return max < 5 ? 0 : 5;
908 case 16: return max < 7 ? 0 : 7;
909 case 32: return 0;
910 case 64: return 1;
912 break;
913 case REAL_TYPE:
914 switch (TYPE_PRECISION (type))
916 case 32: return 2;
917 case 64: return 3;
919 break;
920 default:
921 break;
923 abort ();
926 static void
927 maybe_wide (opcode, index, state)
928 int opcode, index;
929 struct jcf_partial *state;
931 if (index >= 256)
933 RESERVE (4);
934 OP1 (OPCODE_wide);
935 OP1 (opcode);
936 OP2 (index);
938 else
940 RESERVE (2);
941 OP1 (opcode);
942 OP1 (index);
946 /* Compile code to duplicate with offset, where
947 SIZE is the size of the stack item to duplicate (1 or 2), abd
948 OFFSET is where to insert the result (must be 0, 1, or 2).
949 (The new words get inserted at stack[SP-size-offset].) */
951 static void
952 emit_dup (size, offset, state)
953 int size, offset;
954 struct jcf_partial *state;
956 int kind;
957 if (size == 0)
958 return;
959 RESERVE(1);
960 if (offset == 0)
961 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
962 else if (offset == 1)
963 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
964 else if (offset == 2)
965 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
966 else
967 abort();
968 OP1 (kind);
969 NOTE_PUSH (size);
972 static void
973 emit_pop (size, state)
974 int size;
975 struct jcf_partial *state;
977 RESERVE (1);
978 OP1 (OPCODE_pop - 1 + size);
981 static void
982 emit_iinc (var, value, state)
983 tree var;
984 HOST_WIDE_INT value;
985 struct jcf_partial *state;
987 int slot = DECL_LOCAL_INDEX (var);
989 if (value < -128 || value > 127 || slot >= 256)
991 RESERVE (6);
992 OP1 (OPCODE_wide);
993 OP1 (OPCODE_iinc);
994 OP2 (slot);
995 OP2 (value);
997 else
999 RESERVE (3);
1000 OP1 (OPCODE_iinc);
1001 OP1 (slot);
1002 OP1 (value);
1006 static void
1007 emit_load_or_store (var, opcode, state)
1008 tree var; /* Variable to load from or store into. */
1009 int opcode; /* Either OPCODE_iload or OPCODE_istore. */
1010 struct jcf_partial *state;
1012 tree type = TREE_TYPE (var);
1013 int kind = adjust_typed_op (type, 4);
1014 int index = DECL_LOCAL_INDEX (var);
1015 if (index <= 3)
1017 RESERVE (1);
1018 OP1 (opcode + 5 + 4 * kind + index); /* [ilfda]{load,store}_[0123] */
1020 else
1021 maybe_wide (opcode + kind, index, state); /* [ilfda]{load,store} */
1024 static void
1025 emit_load (var, state)
1026 tree var;
1027 struct jcf_partial *state;
1029 emit_load_or_store (var, OPCODE_iload, state);
1030 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1033 static void
1034 emit_store (var, state)
1035 tree var;
1036 struct jcf_partial *state;
1038 emit_load_or_store (var, OPCODE_istore, state);
1039 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1042 static void
1043 emit_unop (opcode, type, state)
1044 enum java_opcode opcode;
1045 tree type ATTRIBUTE_UNUSED;
1046 struct jcf_partial *state;
1048 RESERVE(1);
1049 OP1 (opcode);
1052 static void
1053 emit_binop (opcode, type, state)
1054 enum java_opcode opcode;
1055 tree type;
1056 struct jcf_partial *state;
1058 int size = TYPE_IS_WIDE (type) ? 2 : 1;
1059 RESERVE(1);
1060 OP1 (opcode);
1061 NOTE_POP (size);
1064 static void
1065 emit_reloc (value, kind, target, state)
1066 HOST_WIDE_INT value;
1067 int kind;
1068 struct jcf_block *target;
1069 struct jcf_partial *state;
1071 struct jcf_relocation *reloc = (struct jcf_relocation *)
1072 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1073 struct jcf_block *block = state->last_block;
1074 reloc->next = block->u.relocations;
1075 block->u.relocations = reloc;
1076 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1077 reloc->label = target;
1078 reloc->kind = kind;
1079 if (kind == 0 || kind == BLOCK_START_RELOC)
1080 OP4 (value);
1081 else if (kind != SWITCH_ALIGN_RELOC)
1082 OP2 (value);
1085 static void
1086 emit_switch_reloc (label, state)
1087 struct jcf_block *label;
1088 struct jcf_partial *state;
1090 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1093 /* Similar to emit_switch_reloc,
1094 but re-uses an existing case reloc. */
1096 static void
1097 emit_case_reloc (reloc, state)
1098 struct jcf_relocation *reloc;
1099 struct jcf_partial *state;
1101 struct jcf_block *block = state->last_block;
1102 reloc->next = block->u.relocations;
1103 block->u.relocations = reloc;
1104 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1105 reloc->kind = BLOCK_START_RELOC;
1106 OP4 (0);
1109 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1110 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1112 static void
1113 emit_if (target, opcode, inv_opcode, state)
1114 struct jcf_block *target;
1115 int opcode, inv_opcode;
1116 struct jcf_partial *state;
1118 RESERVE(3);
1119 OP1 (opcode);
1120 /* value is 1 byte from reloc back to start of instruction. */
1121 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1124 static void
1125 emit_goto (target, state)
1126 struct jcf_block *target;
1127 struct jcf_partial *state;
1129 RESERVE(3);
1130 OP1 (OPCODE_goto);
1131 /* Value is 1 byte from reloc back to start of instruction. */
1132 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1135 static void
1136 emit_jsr (target, state)
1137 struct jcf_block *target;
1138 struct jcf_partial *state;
1140 RESERVE(3);
1141 OP1 (OPCODE_jsr);
1142 /* Value is 1 byte from reloc back to start of instruction. */
1143 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1146 /* Generate code to evaluate EXP. If the result is true,
1147 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1148 TRUE_BRANCH_FIRST is a code geneation hint that the
1149 TRUE_LABEL may follow right after this. (The idea is that we
1150 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1152 static void
1153 generate_bytecode_conditional (exp, true_label, false_label,
1154 true_branch_first, state)
1155 tree exp;
1156 struct jcf_block *true_label;
1157 struct jcf_block *false_label;
1158 int true_branch_first;
1159 struct jcf_partial *state;
1161 tree exp0, exp1, type;
1162 int save_SP = state->code_SP;
1163 enum java_opcode op, negop;
1164 switch (TREE_CODE (exp))
1166 case INTEGER_CST:
1167 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1168 break;
1169 case COND_EXPR:
1171 struct jcf_block *then_label = gen_jcf_label (state);
1172 struct jcf_block *else_label = gen_jcf_label (state);
1173 int save_SP_before, save_SP_after;
1174 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1175 then_label, else_label, 1, state);
1176 define_jcf_label (then_label, state);
1177 save_SP_before = state->code_SP;
1178 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1179 true_label, false_label, 1, state);
1180 save_SP_after = state->code_SP;
1181 state->code_SP = save_SP_before;
1182 define_jcf_label (else_label, state);
1183 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1184 true_label, false_label,
1185 true_branch_first, state);
1186 if (state->code_SP != save_SP_after)
1187 abort ();
1189 break;
1190 case TRUTH_NOT_EXPR:
1191 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
1192 true_label, ! true_branch_first, state);
1193 break;
1194 case TRUTH_ANDIF_EXPR:
1196 struct jcf_block *next_label = gen_jcf_label (state);
1197 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1198 next_label, false_label, 1, state);
1199 define_jcf_label (next_label, state);
1200 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1201 true_label, false_label, 1, state);
1203 break;
1204 case TRUTH_ORIF_EXPR:
1206 struct jcf_block *next_label = gen_jcf_label (state);
1207 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1208 true_label, next_label, 1, state);
1209 define_jcf_label (next_label, state);
1210 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1211 true_label, false_label, 1, state);
1213 break;
1214 compare_1:
1215 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1216 set it to the corresponding 1-operand if<COND> instructions. */
1217 op = op - 6;
1218 /* FALLTHROUGH */
1219 compare_2:
1220 /* The opcodes with their inverses are allocated in pairs.
1221 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1222 negop = (op & 1) ? op + 1 : op - 1;
1223 compare_2_ptr:
1224 if (true_branch_first)
1226 emit_if (false_label, negop, op, state);
1227 emit_goto (true_label, state);
1229 else
1231 emit_if (true_label, op, negop, state);
1232 emit_goto (false_label, state);
1234 break;
1235 case EQ_EXPR:
1236 op = OPCODE_if_icmpeq;
1237 goto compare;
1238 case NE_EXPR:
1239 op = OPCODE_if_icmpne;
1240 goto compare;
1241 case GT_EXPR:
1242 op = OPCODE_if_icmpgt;
1243 goto compare;
1244 case LT_EXPR:
1245 op = OPCODE_if_icmplt;
1246 goto compare;
1247 case GE_EXPR:
1248 op = OPCODE_if_icmpge;
1249 goto compare;
1250 case LE_EXPR:
1251 op = OPCODE_if_icmple;
1252 goto compare;
1253 compare:
1254 exp0 = TREE_OPERAND (exp, 0);
1255 exp1 = TREE_OPERAND (exp, 1);
1256 type = TREE_TYPE (exp0);
1257 switch (TREE_CODE (type))
1259 int opf;
1260 case POINTER_TYPE: case RECORD_TYPE:
1261 switch (TREE_CODE (exp))
1263 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
1264 case NE_EXPR: op = OPCODE_if_acmpne; break;
1265 default: abort();
1267 if (integer_zerop (exp1) || integer_zerop (exp0))
1269 generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
1270 STACK_TARGET, state);
1271 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1272 negop = (op & 1) ? op - 1 : op + 1;
1273 NOTE_POP (1);
1274 goto compare_2_ptr;
1276 generate_bytecode_insns (exp0, STACK_TARGET, state);
1277 generate_bytecode_insns (exp1, STACK_TARGET, state);
1278 NOTE_POP (2);
1279 goto compare_2;
1280 case REAL_TYPE:
1281 generate_bytecode_insns (exp0, STACK_TARGET, state);
1282 generate_bytecode_insns (exp1, STACK_TARGET, state);
1283 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1284 opf = OPCODE_fcmpg;
1285 else
1286 opf = OPCODE_fcmpl;
1287 if (TYPE_PRECISION (type) > 32)
1289 opf += 2;
1290 NOTE_POP (4);
1292 else
1293 NOTE_POP (2);
1294 RESERVE (1);
1295 OP1 (opf);
1296 goto compare_1;
1297 case INTEGER_TYPE:
1298 if (TYPE_PRECISION (type) > 32)
1300 generate_bytecode_insns (exp0, STACK_TARGET, state);
1301 generate_bytecode_insns (exp1, STACK_TARGET, state);
1302 NOTE_POP (4);
1303 RESERVE (1);
1304 OP1 (OPCODE_lcmp);
1305 goto compare_1;
1307 /* FALLTHOUGH */
1308 default:
1309 if (integer_zerop (exp1))
1311 generate_bytecode_insns (exp0, STACK_TARGET, state);
1312 NOTE_POP (1);
1313 goto compare_1;
1315 if (integer_zerop (exp0))
1317 switch (op)
1319 case OPCODE_if_icmplt:
1320 case OPCODE_if_icmpge:
1321 op += 2;
1322 break;
1323 case OPCODE_if_icmpgt:
1324 case OPCODE_if_icmple:
1325 op -= 2;
1326 break;
1327 default:
1328 break;
1330 generate_bytecode_insns (exp1, STACK_TARGET, state);
1331 NOTE_POP (1);
1332 goto compare_1;
1334 generate_bytecode_insns (exp0, STACK_TARGET, state);
1335 generate_bytecode_insns (exp1, STACK_TARGET, state);
1336 NOTE_POP (2);
1337 goto compare_2;
1340 default:
1341 generate_bytecode_insns (exp, STACK_TARGET, state);
1342 NOTE_POP (1);
1343 if (true_branch_first)
1345 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1346 emit_goto (true_label, state);
1348 else
1350 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1351 emit_goto (false_label, state);
1353 break;
1355 if (save_SP != state->code_SP)
1356 abort ();
1359 /* Call pending cleanups i.e. those for surrounding TRY_FINALLY_EXPRs.
1360 but only as far out as LIMIT (since we are about to jump to the
1361 emit label that is LIMIT). */
1363 static void
1364 call_cleanups (limit, state)
1365 struct jcf_block *limit;
1366 struct jcf_partial *state;
1368 struct jcf_block *block = state->labeled_blocks;
1369 for (; block != limit; block = block->next)
1371 if (block->pc == PENDING_CLEANUP_PC)
1372 emit_jsr (block, state);
1376 static void
1377 generate_bytecode_return (exp, state)
1378 tree exp;
1379 struct jcf_partial *state;
1381 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1382 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1383 int op;
1384 again:
1385 if (exp != NULL)
1387 switch (TREE_CODE (exp))
1389 case COMPOUND_EXPR:
1390 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1391 state);
1392 exp = TREE_OPERAND (exp, 1);
1393 goto again;
1394 case COND_EXPR:
1396 struct jcf_block *then_label = gen_jcf_label (state);
1397 struct jcf_block *else_label = gen_jcf_label (state);
1398 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1399 then_label, else_label, 1, state);
1400 define_jcf_label (then_label, state);
1401 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1402 define_jcf_label (else_label, state);
1403 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1405 return;
1406 default:
1407 generate_bytecode_insns (exp,
1408 returns_void ? IGNORE_TARGET
1409 : STACK_TARGET, state);
1412 if (returns_void)
1414 op = OPCODE_return;
1415 call_cleanups (NULL, state);
1417 else
1419 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1420 if (state->num_finalizers > 0)
1422 if (state->return_value_decl == NULL_TREE)
1424 state->return_value_decl
1425 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1426 localvar_alloc (state->return_value_decl, state);
1428 emit_store (state->return_value_decl, state);
1429 call_cleanups (NULL, state);
1430 emit_load (state->return_value_decl, state);
1431 /* If we call localvar_free (state->return_value_decl, state),
1432 then we risk the save decl erroneously re-used in the
1433 finalizer. Instead, we keep the state->return_value_decl
1434 allocated through the rest of the method. This is not
1435 the greatest solution, but it is at least simple and safe. */
1438 RESERVE (1);
1439 OP1 (op);
1442 /* Generate bytecode for sub-expression EXP of METHOD.
1443 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1445 static void
1446 generate_bytecode_insns (exp, target, state)
1447 tree exp;
1448 int target;
1449 struct jcf_partial *state;
1451 tree type, arg;
1452 enum java_opcode jopcode;
1453 int op;
1454 HOST_WIDE_INT value;
1455 int post_op;
1456 int size;
1457 int offset;
1459 if (exp == NULL && target == IGNORE_TARGET)
1460 return;
1462 type = TREE_TYPE (exp);
1464 switch (TREE_CODE (exp))
1466 case BLOCK:
1467 if (BLOCK_EXPR_BODY (exp))
1469 tree local;
1470 tree body = BLOCK_EXPR_BODY (exp);
1471 for (local = BLOCK_EXPR_DECLS (exp); local; )
1473 tree next = TREE_CHAIN (local);
1474 localvar_alloc (local, state);
1475 local = next;
1477 /* Avoid deep recursion for long blocks. */
1478 while (TREE_CODE (body) == COMPOUND_EXPR)
1480 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1481 body = TREE_OPERAND (body, 1);
1483 generate_bytecode_insns (body, target, state);
1484 for (local = BLOCK_EXPR_DECLS (exp); local; )
1486 tree next = TREE_CHAIN (local);
1487 localvar_free (local, state);
1488 local = next;
1491 break;
1492 case COMPOUND_EXPR:
1493 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1494 /* Normally the first operand to a COMPOUND_EXPR must complete
1495 normally. However, in the special case of a do-while
1496 statement this is not necessarily the case. */
1497 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0)))
1498 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1499 break;
1500 case EXPR_WITH_FILE_LOCATION:
1502 const char *saved_input_filename = input_filename;
1503 tree body = EXPR_WFL_NODE (exp);
1504 int saved_lineno = lineno;
1505 if (body == empty_stmt_node)
1506 break;
1507 input_filename = EXPR_WFL_FILENAME (exp);
1508 lineno = EXPR_WFL_LINENO (exp);
1509 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && lineno > 0
1510 && debug_info_level > DINFO_LEVEL_NONE)
1511 put_linenumber (lineno, state);
1512 generate_bytecode_insns (body, target, state);
1513 input_filename = saved_input_filename;
1514 lineno = saved_lineno;
1516 break;
1517 case INTEGER_CST:
1518 if (target == IGNORE_TARGET) ; /* do nothing */
1519 else if (TREE_CODE (type) == POINTER_TYPE)
1521 if (! integer_zerop (exp))
1522 abort();
1523 RESERVE(1);
1524 OP1 (OPCODE_aconst_null);
1525 NOTE_PUSH (1);
1527 else if (TYPE_PRECISION (type) <= 32)
1529 push_int_const (TREE_INT_CST_LOW (exp), state);
1530 NOTE_PUSH (1);
1532 else
1534 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1535 state);
1536 NOTE_PUSH (2);
1538 break;
1539 case REAL_CST:
1541 int prec = TYPE_PRECISION (type) >> 5;
1542 RESERVE(1);
1543 if (real_zerop (exp) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp)))
1544 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1545 else if (real_onep (exp))
1546 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1547 /* FIXME Should also use fconst_2 for 2.0f.
1548 Also, should use iconst_2/ldc followed by i2f/i2d
1549 for other float/double when the value is a small integer. */
1550 else
1552 offset = find_constant_index (exp, state);
1553 if (prec == 1)
1554 push_constant1 (offset, state);
1555 else
1556 push_constant2 (offset, state);
1558 NOTE_PUSH (prec);
1560 break;
1561 case STRING_CST:
1562 push_constant1 (find_string_constant (&state->cpool, exp), state);
1563 NOTE_PUSH (1);
1564 break;
1565 case VAR_DECL:
1566 if (TREE_STATIC (exp))
1568 field_op (exp, OPCODE_getstatic, state);
1569 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1570 break;
1572 /* ... fall through ... */
1573 case PARM_DECL:
1574 emit_load (exp, state);
1575 break;
1576 case NON_LVALUE_EXPR:
1577 case INDIRECT_REF:
1578 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1579 break;
1580 case ARRAY_REF:
1581 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1582 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1583 if (target != IGNORE_TARGET)
1585 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1586 RESERVE(1);
1587 OP1 (jopcode);
1588 if (! TYPE_IS_WIDE (type))
1589 NOTE_POP (1);
1591 break;
1592 case COMPONENT_REF:
1594 tree obj = TREE_OPERAND (exp, 0);
1595 tree field = TREE_OPERAND (exp, 1);
1596 int is_static = FIELD_STATIC (field);
1597 generate_bytecode_insns (obj,
1598 is_static ? IGNORE_TARGET : target, state);
1599 if (target != IGNORE_TARGET)
1601 if (DECL_NAME (field) == length_identifier_node && !is_static
1602 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1604 RESERVE (1);
1605 OP1 (OPCODE_arraylength);
1607 else
1609 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1610 state);
1611 if (! is_static)
1612 NOTE_POP (1);
1613 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1617 break;
1618 case TRUTH_ANDIF_EXPR:
1619 case TRUTH_ORIF_EXPR:
1620 case EQ_EXPR:
1621 case NE_EXPR:
1622 case GT_EXPR:
1623 case LT_EXPR:
1624 case GE_EXPR:
1625 case LE_EXPR:
1627 struct jcf_block *then_label = gen_jcf_label (state);
1628 struct jcf_block *else_label = gen_jcf_label (state);
1629 struct jcf_block *end_label = gen_jcf_label (state);
1630 generate_bytecode_conditional (exp,
1631 then_label, else_label, 1, state);
1632 define_jcf_label (then_label, state);
1633 push_int_const (1, state);
1634 emit_goto (end_label, state);
1635 define_jcf_label (else_label, state);
1636 push_int_const (0, state);
1637 define_jcf_label (end_label, state);
1638 NOTE_PUSH (1);
1640 break;
1641 case COND_EXPR:
1643 struct jcf_block *then_label = gen_jcf_label (state);
1644 struct jcf_block *else_label = gen_jcf_label (state);
1645 struct jcf_block *end_label = gen_jcf_label (state);
1646 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1647 then_label, else_label, 1, state);
1648 define_jcf_label (then_label, state);
1649 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1650 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1651 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1652 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1653 emit_goto (end_label, state);
1654 define_jcf_label (else_label, state);
1655 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1656 define_jcf_label (end_label, state);
1657 /* COND_EXPR can be used in a binop. The stack must be adjusted. */
1658 if (TREE_TYPE (exp) != void_type_node)
1659 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1661 break;
1662 case CASE_EXPR:
1664 struct jcf_switch_state *sw_state = state->sw_state;
1665 struct jcf_relocation *reloc = (struct jcf_relocation *)
1666 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1667 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1668 reloc->kind = 0;
1669 reloc->label = get_jcf_label_here (state);
1670 reloc->offset = case_value;
1671 reloc->next = sw_state->cases;
1672 sw_state->cases = reloc;
1673 if (sw_state->num_cases == 0)
1675 sw_state->min_case = case_value;
1676 sw_state->max_case = case_value;
1678 else
1680 if (case_value < sw_state->min_case)
1681 sw_state->min_case = case_value;
1682 if (case_value > sw_state->max_case)
1683 sw_state->max_case = case_value;
1685 sw_state->num_cases++;
1687 break;
1688 case DEFAULT_EXPR:
1689 state->sw_state->default_label = get_jcf_label_here (state);
1690 break;
1692 case SWITCH_EXPR:
1694 /* The SWITCH_EXPR has three parts, generated in the following order:
1695 1. the switch_expression (the value used to select the correct case);
1696 2. the switch_body;
1697 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1698 After code generation, we will re-order them in the order 1, 3, 2.
1699 This is to avoid any extra GOTOs. */
1700 struct jcf_switch_state sw_state;
1701 struct jcf_block *expression_last; /* Last block of the switch_expression. */
1702 struct jcf_block *body_last; /* Last block of the switch_body. */
1703 struct jcf_block *switch_instruction; /* First block of switch_instruction. */
1704 struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1705 struct jcf_block *body_block;
1706 int switch_length;
1707 sw_state.prev = state->sw_state;
1708 state->sw_state = &sw_state;
1709 sw_state.cases = NULL;
1710 sw_state.num_cases = 0;
1711 sw_state.default_label = NULL;
1712 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1713 expression_last = state->last_block;
1714 /* Force a new block here. */
1715 body_block = gen_jcf_label (state);
1716 define_jcf_label (body_block, state);
1717 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1718 body_last = state->last_block;
1720 switch_instruction = gen_jcf_label (state);
1721 define_jcf_label (switch_instruction, state);
1722 if (sw_state.default_label == NULL)
1723 sw_state.default_label = gen_jcf_label (state);
1725 if (sw_state.num_cases <= 1)
1727 if (sw_state.num_cases == 0)
1729 emit_pop (1, state);
1730 NOTE_POP (1);
1732 else
1734 push_int_const (sw_state.cases->offset, state);
1735 NOTE_PUSH (1);
1736 emit_if (sw_state.cases->label,
1737 OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
1739 emit_goto (sw_state.default_label, state);
1741 else
1743 HOST_WIDE_INT i;
1744 unsigned HOST_WIDE_INT delta;
1745 /* Copy the chain of relocs into a sorted array. */
1746 struct jcf_relocation **relocs = (struct jcf_relocation **)
1747 xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1748 /* The relocs arrays is a buffer with a gap.
1749 The assumption is that cases will normally come in "runs". */
1750 int gap_start = 0;
1751 int gap_end = sw_state.num_cases;
1752 struct jcf_relocation *reloc;
1753 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
1755 HOST_WIDE_INT case_value = reloc->offset;
1756 while (gap_end < sw_state.num_cases)
1758 struct jcf_relocation *end = relocs[gap_end];
1759 if (case_value <= end->offset)
1760 break;
1761 relocs[gap_start++] = end;
1762 gap_end++;
1764 while (gap_start > 0)
1766 struct jcf_relocation *before = relocs[gap_start-1];
1767 if (case_value >= before->offset)
1768 break;
1769 relocs[--gap_end] = before;
1770 gap_start--;
1772 relocs[gap_start++] = reloc;
1773 /* Note we don't check for duplicates. This is
1774 handled by the parser. */
1777 /* We could have DELTA < 0 if sw_state.min_case is
1778 something like Integer.MIN_VALUE. That is why delta is
1779 unsigned. */
1780 delta = sw_state.max_case - sw_state.min_case;
1781 if (2 * sw_state.num_cases >= delta)
1782 { /* Use tableswitch. */
1783 int index = 0;
1784 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1785 OP1 (OPCODE_tableswitch);
1786 emit_reloc (RELOCATION_VALUE_0,
1787 SWITCH_ALIGN_RELOC, NULL, state);
1788 emit_switch_reloc (sw_state.default_label, state);
1789 OP4 (sw_state.min_case);
1790 OP4 (sw_state.max_case);
1791 for (i = sw_state.min_case; ; )
1793 reloc = relocs[index];
1794 if (i == reloc->offset)
1796 emit_case_reloc (reloc, state);
1797 if (i == sw_state.max_case)
1798 break;
1799 index++;
1801 else
1802 emit_switch_reloc (sw_state.default_label, state);
1803 i++;
1806 else
1807 { /* Use lookupswitch. */
1808 RESERVE(9 + 8 * sw_state.num_cases);
1809 OP1 (OPCODE_lookupswitch);
1810 emit_reloc (RELOCATION_VALUE_0,
1811 SWITCH_ALIGN_RELOC, NULL, state);
1812 emit_switch_reloc (sw_state.default_label, state);
1813 OP4 (sw_state.num_cases);
1814 for (i = 0; i < sw_state.num_cases; i++)
1816 struct jcf_relocation *reloc = relocs[i];
1817 OP4 (reloc->offset);
1818 emit_case_reloc (reloc, state);
1821 free (relocs);
1824 instruction_last = state->last_block;
1825 if (sw_state.default_label->pc < 0)
1826 define_jcf_label (sw_state.default_label, state);
1827 else /* Force a new block. */
1828 sw_state.default_label = get_jcf_label_here (state);
1829 /* Now re-arrange the blocks so the switch_instruction
1830 comes before the switch_body. */
1831 switch_length = state->code_length - switch_instruction->pc;
1832 switch_instruction->pc = body_block->pc;
1833 instruction_last->next = body_block;
1834 instruction_last->v.chunk->next = body_block->v.chunk;
1835 expression_last->next = switch_instruction;
1836 expression_last->v.chunk->next = switch_instruction->v.chunk;
1837 body_last->next = sw_state.default_label;
1838 body_last->v.chunk->next = NULL;
1839 state->chunk = body_last->v.chunk;
1840 for (; body_block != sw_state.default_label; body_block = body_block->next)
1841 body_block->pc += switch_length;
1843 state->sw_state = sw_state.prev;
1844 break;
1847 case RETURN_EXPR:
1848 exp = TREE_OPERAND (exp, 0);
1849 if (exp == NULL_TREE)
1850 exp = empty_stmt_node;
1851 else if (TREE_CODE (exp) != MODIFY_EXPR)
1852 abort ();
1853 else
1854 exp = TREE_OPERAND (exp, 1);
1855 generate_bytecode_return (exp, state);
1856 break;
1857 case LABELED_BLOCK_EXPR:
1859 struct jcf_block *end_label = gen_jcf_label (state);
1860 end_label->next = state->labeled_blocks;
1861 state->labeled_blocks = end_label;
1862 end_label->pc = PENDING_EXIT_PC;
1863 end_label->u.labeled_block = exp;
1864 if (LABELED_BLOCK_BODY (exp))
1865 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1866 if (state->labeled_blocks != end_label)
1867 abort();
1868 state->labeled_blocks = end_label->next;
1869 define_jcf_label (end_label, state);
1871 break;
1872 case LOOP_EXPR:
1874 tree body = TREE_OPERAND (exp, 0);
1875 #if 0
1876 if (TREE_CODE (body) == COMPOUND_EXPR
1877 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1879 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1880 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1881 struct jcf_block *head_label;
1882 struct jcf_block *body_label;
1883 struct jcf_block *end_label = gen_jcf_label (state);
1884 struct jcf_block *exit_label = state->labeled_blocks;
1885 head_label = gen_jcf_label (state);
1886 emit_goto (head_label, state);
1887 body_label = get_jcf_label_here (state);
1888 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1889 define_jcf_label (head_label, state);
1890 generate_bytecode_conditional (TREE_OPERAND (body, 0),
1891 end_label, body_label, 1, state);
1892 define_jcf_label (end_label, state);
1894 else
1895 #endif
1897 struct jcf_block *head_label = get_jcf_label_here (state);
1898 generate_bytecode_insns (body, IGNORE_TARGET, state);
1899 if (CAN_COMPLETE_NORMALLY (body))
1900 emit_goto (head_label, state);
1903 break;
1904 case EXIT_EXPR:
1906 struct jcf_block *label = state->labeled_blocks;
1907 struct jcf_block *end_label = gen_jcf_label (state);
1908 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1909 label, end_label, 0, state);
1910 define_jcf_label (end_label, state);
1912 break;
1913 case EXIT_BLOCK_EXPR:
1915 struct jcf_block *label = state->labeled_blocks;
1916 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1917 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1918 label = label->next;
1919 call_cleanups (label, state);
1920 emit_goto (label, state);
1922 break;
1924 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
1925 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
1926 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
1927 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
1928 increment:
1930 arg = TREE_OPERAND (exp, 1);
1931 exp = TREE_OPERAND (exp, 0);
1932 type = TREE_TYPE (exp);
1933 size = TYPE_IS_WIDE (type) ? 2 : 1;
1934 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1935 && ! TREE_STATIC (exp)
1936 && TREE_CODE (type) == INTEGER_TYPE
1937 && TYPE_PRECISION (type) == 32)
1939 if (target != IGNORE_TARGET && post_op)
1940 emit_load (exp, state);
1941 emit_iinc (exp, value, state);
1942 if (target != IGNORE_TARGET && ! post_op)
1943 emit_load (exp, state);
1944 break;
1946 if (TREE_CODE (exp) == COMPONENT_REF)
1948 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1949 emit_dup (1, 0, state);
1950 /* Stack: ..., objectref, objectref. */
1951 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1952 NOTE_PUSH (size-1);
1953 /* Stack: ..., objectref, oldvalue. */
1954 offset = 1;
1956 else if (TREE_CODE (exp) == ARRAY_REF)
1958 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1959 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1960 emit_dup (2, 0, state);
1961 /* Stack: ..., array, index, array, index. */
1962 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1963 RESERVE(1);
1964 OP1 (jopcode);
1965 NOTE_POP (2-size);
1966 /* Stack: ..., array, index, oldvalue. */
1967 offset = 2;
1969 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1971 generate_bytecode_insns (exp, STACK_TARGET, state);
1972 /* Stack: ..., oldvalue. */
1973 offset = 0;
1975 else
1976 abort ();
1978 if (target != IGNORE_TARGET && post_op)
1979 emit_dup (size, offset, state);
1980 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1981 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1982 /* Stack, otherwise: ..., [result, ] oldvalue. */
1983 generate_bytecode_insns (arg, STACK_TARGET, state);
1984 emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
1985 + adjust_typed_op (type, 3),
1986 type, state);
1987 if (target != IGNORE_TARGET && ! post_op)
1988 emit_dup (size, offset, state);
1989 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1990 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1991 /* Stack, otherwise: ..., [result, ] newvalue. */
1992 goto finish_assignment;
1994 case MODIFY_EXPR:
1996 tree lhs = TREE_OPERAND (exp, 0);
1997 tree rhs = TREE_OPERAND (exp, 1);
1998 int offset = 0;
2000 /* See if we can use the iinc instruction. */
2001 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
2002 && ! TREE_STATIC (lhs)
2003 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
2004 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
2005 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
2007 tree arg0 = TREE_OPERAND (rhs, 0);
2008 tree arg1 = TREE_OPERAND (rhs, 1);
2009 HOST_WIDE_INT min_value = -32768;
2010 HOST_WIDE_INT max_value = 32767;
2011 if (TREE_CODE (rhs) == MINUS_EXPR)
2013 min_value++;
2014 max_value++;
2016 else if (arg1 == lhs)
2018 arg0 = arg1;
2019 arg1 = TREE_OPERAND (rhs, 0);
2021 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
2023 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
2024 value = TREE_INT_CST_LOW (arg1);
2025 if ((hi_value == 0 && value <= max_value)
2026 || (hi_value == -1 && value >= min_value))
2028 if (TREE_CODE (rhs) == MINUS_EXPR)
2029 value = -value;
2030 emit_iinc (lhs, value, state);
2031 if (target != IGNORE_TARGET)
2032 emit_load (lhs, state);
2033 break;
2038 if (TREE_CODE (lhs) == COMPONENT_REF)
2040 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
2041 STACK_TARGET, state);
2042 offset = 1;
2044 else if (TREE_CODE (lhs) == ARRAY_REF)
2046 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
2047 STACK_TARGET, state);
2048 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
2049 STACK_TARGET, state);
2050 offset = 2;
2052 else
2053 offset = 0;
2055 /* If the rhs is a binary expression and the left operand is
2056 `==' to the lhs then we have an OP= expression. In this
2057 case we must do some special processing. */
2058 if (TREE_CODE_CLASS (TREE_CODE (rhs)) == '2'
2059 && lhs == TREE_OPERAND (rhs, 0))
2061 if (TREE_CODE (lhs) == COMPONENT_REF)
2063 tree field = TREE_OPERAND (lhs, 1);
2064 if (! FIELD_STATIC (field))
2066 /* Duplicate the object reference so we can get
2067 the field. */
2068 emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
2069 NOTE_POP (1);
2071 field_op (field, (FIELD_STATIC (field)
2072 ? OPCODE_getstatic
2073 : OPCODE_getfield),
2074 state);
2076 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2078 else if (TREE_CODE (lhs) == VAR_DECL
2079 || TREE_CODE (lhs) == PARM_DECL)
2081 if (FIELD_STATIC (lhs))
2083 field_op (lhs, OPCODE_getstatic, state);
2084 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2086 else
2087 emit_load (lhs, state);
2089 else if (TREE_CODE (lhs) == ARRAY_REF)
2091 /* Duplicate the array and index, which are on the
2092 stack, so that we can load the old value. */
2093 emit_dup (2, 0, state);
2094 NOTE_POP (2);
2095 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
2096 RESERVE (1);
2097 OP1 (jopcode);
2098 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
2100 else
2101 abort ();
2103 /* This function correctly handles the case where the LHS
2104 of a binary expression is NULL_TREE. */
2105 rhs = build (TREE_CODE (rhs), TREE_TYPE (rhs),
2106 NULL_TREE, TREE_OPERAND (rhs, 1));
2109 generate_bytecode_insns (rhs, STACK_TARGET, state);
2110 if (target != IGNORE_TARGET)
2111 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2112 exp = lhs;
2114 /* FALLTHOUGH */
2116 finish_assignment:
2117 if (TREE_CODE (exp) == COMPONENT_REF)
2119 tree field = TREE_OPERAND (exp, 1);
2120 if (! FIELD_STATIC (field))
2121 NOTE_POP (1);
2122 field_op (field,
2123 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2124 state);
2126 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2128 else if (TREE_CODE (exp) == VAR_DECL
2129 || TREE_CODE (exp) == PARM_DECL)
2131 if (FIELD_STATIC (exp))
2133 field_op (exp, OPCODE_putstatic, state);
2134 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2136 else
2137 emit_store (exp, state);
2139 else if (TREE_CODE (exp) == ARRAY_REF)
2141 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2142 RESERVE (1);
2143 OP1 (jopcode);
2144 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2146 else
2147 abort ();
2148 break;
2149 case PLUS_EXPR:
2150 jopcode = OPCODE_iadd;
2151 goto binop;
2152 case MINUS_EXPR:
2153 jopcode = OPCODE_isub;
2154 goto binop;
2155 case MULT_EXPR:
2156 jopcode = OPCODE_imul;
2157 goto binop;
2158 case TRUNC_DIV_EXPR:
2159 case RDIV_EXPR:
2160 jopcode = OPCODE_idiv;
2161 goto binop;
2162 case TRUNC_MOD_EXPR:
2163 jopcode = OPCODE_irem;
2164 goto binop;
2165 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
2166 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
2167 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
2168 case TRUTH_AND_EXPR:
2169 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
2170 case TRUTH_OR_EXPR:
2171 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
2172 case TRUTH_XOR_EXPR:
2173 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
2174 binop:
2176 tree arg0 = TREE_OPERAND (exp, 0);
2177 tree arg1 = TREE_OPERAND (exp, 1);
2178 jopcode += adjust_typed_op (type, 3);
2179 if (arg0 == arg1 && TREE_CODE (arg0) == SAVE_EXPR)
2181 /* fold may (e.g) convert 2*x to x+x. */
2182 generate_bytecode_insns (TREE_OPERAND (arg0, 0), target, state);
2183 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2185 else
2187 /* ARG0 will be NULL_TREE if we're handling an `OP='
2188 expression. In this case the stack already holds the
2189 LHS. See the MODIFY_EXPR case. */
2190 if (arg0 != NULL_TREE)
2191 generate_bytecode_insns (arg0, target, state);
2192 if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
2193 arg1 = convert (int_type_node, arg1);
2194 generate_bytecode_insns (arg1, target, state);
2196 /* For most binary operations, both operands and the result have the
2197 same type. Shift operations are different. Using arg1's type
2198 gets us the correct SP adjustment in all cases. */
2199 if (target == STACK_TARGET)
2200 emit_binop (jopcode, TREE_TYPE (arg1), state);
2201 break;
2203 case TRUTH_NOT_EXPR:
2204 case BIT_NOT_EXPR:
2205 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2206 if (target == STACK_TARGET)
2208 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2209 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
2210 RESERVE (2);
2211 if (is_long)
2212 OP1 (OPCODE_i2l);
2213 NOTE_PUSH (1 + is_long);
2214 OP1 (OPCODE_ixor + is_long);
2215 NOTE_POP (1 + is_long);
2217 break;
2218 case NEGATE_EXPR:
2219 jopcode = OPCODE_ineg;
2220 jopcode += adjust_typed_op (type, 3);
2221 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2222 if (target == STACK_TARGET)
2223 emit_unop (jopcode, type, state);
2224 break;
2225 case INSTANCEOF_EXPR:
2227 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2228 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2229 RESERVE (3);
2230 OP1 (OPCODE_instanceof);
2231 OP2 (index);
2233 break;
2234 case SAVE_EXPR:
2235 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2236 break;
2237 case CONVERT_EXPR:
2238 case NOP_EXPR:
2239 case FLOAT_EXPR:
2240 case FIX_TRUNC_EXPR:
2242 tree src = TREE_OPERAND (exp, 0);
2243 tree src_type = TREE_TYPE (src);
2244 tree dst_type = TREE_TYPE (exp);
2245 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2246 if (target == IGNORE_TARGET || src_type == dst_type)
2247 break;
2248 if (TREE_CODE (dst_type) == POINTER_TYPE)
2250 if (TREE_CODE (exp) == CONVERT_EXPR)
2252 int index = find_class_constant (&state->cpool,
2253 TREE_TYPE (dst_type));
2254 RESERVE (3);
2255 OP1 (OPCODE_checkcast);
2256 OP2 (index);
2259 else /* Convert numeric types. */
2261 int wide_src = TYPE_PRECISION (src_type) > 32;
2262 int wide_dst = TYPE_PRECISION (dst_type) > 32;
2263 NOTE_POP (1 + wide_src);
2264 RESERVE (1);
2265 if (TREE_CODE (dst_type) == REAL_TYPE)
2267 if (TREE_CODE (src_type) == REAL_TYPE)
2268 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2269 else if (TYPE_PRECISION (src_type) == 64)
2270 OP1 (OPCODE_l2f + wide_dst);
2271 else
2272 OP1 (OPCODE_i2f + wide_dst);
2274 else /* Convert to integral type. */
2276 if (TREE_CODE (src_type) == REAL_TYPE)
2277 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2278 else if (wide_dst)
2279 OP1 (OPCODE_i2l);
2280 else if (wide_src)
2281 OP1 (OPCODE_l2i);
2282 if (TYPE_PRECISION (dst_type) < 32)
2284 RESERVE (1);
2285 /* Already converted to int, if needed. */
2286 if (TYPE_PRECISION (dst_type) <= 8)
2287 OP1 (OPCODE_i2b);
2288 else if (TREE_UNSIGNED (dst_type))
2289 OP1 (OPCODE_i2c);
2290 else
2291 OP1 (OPCODE_i2s);
2294 NOTE_PUSH (1 + wide_dst);
2297 break;
2299 case TRY_EXPR:
2301 tree try_clause = TREE_OPERAND (exp, 0);
2302 struct jcf_block *start_label = get_jcf_label_here (state);
2303 struct jcf_block *end_label; /* End of try clause. */
2304 struct jcf_block *finished_label = gen_jcf_label (state);
2305 tree clause = TREE_OPERAND (exp, 1);
2306 if (target != IGNORE_TARGET)
2307 abort ();
2308 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2309 end_label = get_jcf_label_here (state);
2310 if (end_label == start_label)
2311 break;
2312 if (CAN_COMPLETE_NORMALLY (try_clause))
2313 emit_goto (finished_label, state);
2314 while (clause != NULL_TREE)
2316 tree catch_clause = TREE_OPERAND (clause, 0);
2317 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2318 struct jcf_handler *handler = alloc_handler (start_label,
2319 end_label, state);
2320 if (exception_decl == NULL_TREE)
2321 handler->type = NULL_TREE;
2322 else
2323 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2324 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2325 clause = TREE_CHAIN (clause);
2326 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2327 emit_goto (finished_label, state);
2329 define_jcf_label (finished_label, state);
2331 break;
2333 case TRY_FINALLY_EXPR:
2335 struct jcf_block *finished_label = NULL;
2336 struct jcf_block *finally_label, *start_label, *end_label;
2337 struct jcf_handler *handler;
2338 tree try_block = TREE_OPERAND (exp, 0);
2339 tree finally = TREE_OPERAND (exp, 1);
2340 tree return_link = NULL_TREE, exception_decl = NULL_TREE;
2342 tree exception_type;
2344 finally_label = gen_jcf_label (state);
2345 start_label = get_jcf_label_here (state);
2346 /* If the `finally' clause can complete normally, we emit it
2347 as a subroutine and let the other clauses call it via
2348 `jsr'. If it can't complete normally, then we simply emit
2349 `goto's directly to it. */
2350 if (CAN_COMPLETE_NORMALLY (finally))
2352 finally_label->pc = PENDING_CLEANUP_PC;
2353 finally_label->next = state->labeled_blocks;
2354 state->labeled_blocks = finally_label;
2355 state->num_finalizers++;
2358 generate_bytecode_insns (try_block, target, state);
2360 if (CAN_COMPLETE_NORMALLY (finally))
2362 if (state->labeled_blocks != finally_label)
2363 abort();
2364 state->labeled_blocks = finally_label->next;
2366 end_label = get_jcf_label_here (state);
2368 if (end_label == start_label)
2370 state->num_finalizers--;
2371 define_jcf_label (finally_label, state);
2372 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2373 break;
2376 if (CAN_COMPLETE_NORMALLY (finally))
2378 return_link = build_decl (VAR_DECL, NULL_TREE,
2379 return_address_type_node);
2380 finished_label = gen_jcf_label (state);
2383 if (CAN_COMPLETE_NORMALLY (try_block))
2385 if (CAN_COMPLETE_NORMALLY (finally))
2387 emit_jsr (finally_label, state);
2388 emit_goto (finished_label, state);
2390 else
2391 emit_goto (finally_label, state);
2394 /* Handle exceptions. */
2396 exception_type = build_pointer_type (throwable_type_node);
2397 if (CAN_COMPLETE_NORMALLY (finally))
2399 /* We're going to generate a subroutine, so we'll need to
2400 save and restore the exception around the `jsr'. */
2401 exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2402 localvar_alloc (return_link, state);
2404 handler = alloc_handler (start_label, end_label, state);
2405 handler->type = NULL_TREE;
2406 if (CAN_COMPLETE_NORMALLY (finally))
2408 localvar_alloc (exception_decl, state);
2409 NOTE_PUSH (1);
2410 emit_store (exception_decl, state);
2411 emit_jsr (finally_label, state);
2412 emit_load (exception_decl, state);
2413 RESERVE (1);
2414 OP1 (OPCODE_athrow);
2415 NOTE_POP (1);
2417 else
2419 /* We're not generating a subroutine. In this case we can
2420 simply have the exception handler pop the exception and
2421 then fall through to the `finally' block. */
2422 NOTE_PUSH (1);
2423 emit_pop (1, state);
2424 NOTE_POP (1);
2427 /* The finally block. If we're generating a subroutine, first
2428 save return PC into return_link. Otherwise, just generate
2429 the code for the `finally' block. */
2430 define_jcf_label (finally_label, state);
2431 if (CAN_COMPLETE_NORMALLY (finally))
2433 NOTE_PUSH (1);
2434 emit_store (return_link, state);
2437 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2438 if (CAN_COMPLETE_NORMALLY (finally))
2440 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2441 localvar_free (exception_decl, state);
2442 localvar_free (return_link, state);
2443 define_jcf_label (finished_label, state);
2446 break;
2447 case THROW_EXPR:
2448 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2449 RESERVE (1);
2450 OP1 (OPCODE_athrow);
2451 break;
2452 case NEW_ARRAY_INIT:
2454 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2455 tree array_type = TREE_TYPE (TREE_TYPE (exp));
2456 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2457 HOST_WIDE_INT length = java_array_type_length (array_type);
2458 if (target == IGNORE_TARGET)
2460 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
2461 generate_bytecode_insns (TREE_VALUE (values), target, state);
2462 break;
2464 push_int_const (length, state);
2465 NOTE_PUSH (1);
2466 RESERVE (3);
2467 if (JPRIMITIVE_TYPE_P (element_type))
2469 int atype = encode_newarray_type (element_type);
2470 OP1 (OPCODE_newarray);
2471 OP1 (atype);
2473 else
2475 int index = find_class_constant (&state->cpool,
2476 TREE_TYPE (element_type));
2477 OP1 (OPCODE_anewarray);
2478 OP2 (index);
2480 offset = 0;
2481 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2482 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
2484 int save_SP = state->code_SP;
2485 emit_dup (1, 0, state);
2486 push_int_const (offset, state);
2487 NOTE_PUSH (1);
2488 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2489 RESERVE (1);
2490 OP1 (jopcode);
2491 state->code_SP = save_SP;
2494 break;
2495 case JAVA_EXC_OBJ_EXPR:
2496 NOTE_PUSH (1); /* Pushed by exception system. */
2497 break;
2498 case NEW_CLASS_EXPR:
2500 tree class = TREE_TYPE (TREE_TYPE (exp));
2501 int need_result = target != IGNORE_TARGET;
2502 int index = find_class_constant (&state->cpool, class);
2503 RESERVE (4);
2504 OP1 (OPCODE_new);
2505 OP2 (index);
2506 if (need_result)
2507 OP1 (OPCODE_dup);
2508 NOTE_PUSH (1 + need_result);
2510 /* ... fall though ... */
2511 case CALL_EXPR:
2513 tree f = TREE_OPERAND (exp, 0);
2514 tree x = TREE_OPERAND (exp, 1);
2515 int save_SP = state->code_SP;
2516 int nargs;
2517 if (TREE_CODE (f) == ADDR_EXPR)
2518 f = TREE_OPERAND (f, 0);
2519 if (f == soft_newarray_node)
2521 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2522 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2523 STACK_TARGET, state);
2524 RESERVE (2);
2525 OP1 (OPCODE_newarray);
2526 OP1 (type_code);
2527 break;
2529 else if (f == soft_multianewarray_node)
2531 int ndims;
2532 int idim;
2533 int index = find_class_constant (&state->cpool,
2534 TREE_TYPE (TREE_TYPE (exp)));
2535 x = TREE_CHAIN (x); /* Skip class argument. */
2536 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2537 for (idim = ndims; --idim >= 0; )
2539 x = TREE_CHAIN (x);
2540 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2542 RESERVE (4);
2543 OP1 (OPCODE_multianewarray);
2544 OP2 (index);
2545 OP1 (ndims);
2546 break;
2548 else if (f == soft_anewarray_node)
2550 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2551 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2552 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2553 RESERVE (3);
2554 OP1 (OPCODE_anewarray);
2555 OP2 (index);
2556 break;
2558 else if (f == soft_monitorenter_node
2559 || f == soft_monitorexit_node
2560 || f == throw_node)
2562 if (f == soft_monitorenter_node)
2563 op = OPCODE_monitorenter;
2564 else if (f == soft_monitorexit_node)
2565 op = OPCODE_monitorexit;
2566 else
2567 op = OPCODE_athrow;
2568 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2569 RESERVE (1);
2570 OP1 (op);
2571 NOTE_POP (1);
2572 break;
2574 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
2576 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2578 nargs = state->code_SP - save_SP;
2579 state->code_SP = save_SP;
2580 if (f == soft_fmod_node)
2582 RESERVE (1);
2583 OP1 (OPCODE_drem);
2584 NOTE_PUSH (2);
2585 break;
2587 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2588 NOTE_POP (1); /* Pop implicit this. */
2589 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2591 tree context = DECL_CONTEXT (f);
2592 int index, interface = 0;
2593 RESERVE (5);
2594 if (METHOD_STATIC (f))
2595 OP1 (OPCODE_invokestatic);
2596 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2597 || METHOD_PRIVATE (f))
2598 OP1 (OPCODE_invokespecial);
2599 else
2601 if (CLASS_INTERFACE (TYPE_NAME (context)))
2603 tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
2604 context = TREE_TYPE (TREE_TYPE (arg1));
2605 if (CLASS_INTERFACE (TYPE_NAME (context)))
2606 interface = 1;
2608 if (interface)
2609 OP1 (OPCODE_invokeinterface);
2610 else
2611 OP1 (OPCODE_invokevirtual);
2613 index = find_methodref_with_class_index (&state->cpool, f, context);
2614 OP2 (index);
2615 if (interface)
2617 if (nargs <= 0)
2618 abort ();
2620 OP1 (nargs);
2621 OP1 (0);
2623 f = TREE_TYPE (TREE_TYPE (f));
2624 if (TREE_CODE (f) != VOID_TYPE)
2626 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2627 if (target == IGNORE_TARGET)
2628 emit_pop (size, state);
2629 else
2630 NOTE_PUSH (size);
2632 break;
2635 /* fall through */
2636 notimpl:
2637 default:
2638 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
2639 tree_code_name [(int) TREE_CODE (exp)]);
2643 static void
2644 perform_relocations (state)
2645 struct jcf_partial *state;
2647 struct jcf_block *block;
2648 struct jcf_relocation *reloc;
2649 int pc;
2650 int shrink;
2652 /* Before we start, the pc field of each block is an upper bound on
2653 the block's start pc (it may be less, if previous blocks need less
2654 than their maximum).
2656 The minimum size of each block is in the block's chunk->size. */
2658 /* First, figure out the actual locations of each block. */
2659 pc = 0;
2660 shrink = 0;
2661 for (block = state->blocks; block != NULL; block = block->next)
2663 int block_size = block->v.chunk->size;
2665 block->pc = pc;
2667 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2668 Assumes relocations are in reverse order. */
2669 reloc = block->u.relocations;
2670 while (reloc != NULL
2671 && reloc->kind == OPCODE_goto_w
2672 && reloc->label->pc == block->next->pc
2673 && reloc->offset + 2 == block_size)
2675 reloc = reloc->next;
2676 block->u.relocations = reloc;
2677 block->v.chunk->size -= 3;
2678 block_size -= 3;
2679 shrink += 3;
2682 /* Optimize GOTO L; ... L: GOTO X by changing the first goto to
2683 jump directly to X. We're careful here to avoid an infinite
2684 loop if the `goto's themselves form one. We do this
2685 optimization because we can generate a goto-to-goto for some
2686 try/finally blocks. */
2687 while (reloc != NULL
2688 && reloc->kind == OPCODE_goto_w
2689 && reloc->label != block
2690 && reloc->label->v.chunk->data != NULL
2691 && reloc->label->v.chunk->data[0] == OPCODE_goto)
2693 /* Find the reloc for the first instruction of the
2694 destination block. */
2695 struct jcf_relocation *first_reloc;
2696 for (first_reloc = reloc->label->u.relocations;
2697 first_reloc;
2698 first_reloc = first_reloc->next)
2700 if (first_reloc->offset == 1
2701 && first_reloc->kind == OPCODE_goto_w)
2703 reloc->label = first_reloc->label;
2704 break;
2708 /* If we didn't do anything, exit the loop. */
2709 if (first_reloc == NULL)
2710 break;
2713 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
2715 if (reloc->kind == SWITCH_ALIGN_RELOC)
2717 /* We assume this is the first relocation in this block,
2718 so we know its final pc. */
2719 int where = pc + reloc->offset;
2720 int pad = ((where + 3) & ~3) - where;
2721 block_size += pad;
2723 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2725 int delta = reloc->label->pc - (pc + reloc->offset - 1);
2726 int expand = reloc->kind > 0 ? 2 : 5;
2728 if (delta > 0)
2729 delta -= shrink;
2730 if (delta >= -32768 && delta <= 32767)
2732 shrink += expand;
2733 reloc->kind = -1;
2735 else
2736 block_size += expand;
2739 pc += block_size;
2742 for (block = state->blocks; block != NULL; block = block->next)
2744 struct chunk *chunk = block->v.chunk;
2745 int old_size = chunk->size;
2746 int next_pc = block->next == NULL ? pc : block->next->pc;
2747 int new_size = next_pc - block->pc;
2748 unsigned char *new_ptr;
2749 unsigned char *old_buffer = chunk->data;
2750 unsigned char *old_ptr = old_buffer + old_size;
2751 if (new_size != old_size)
2753 chunk->data = (unsigned char *)
2754 obstack_alloc (state->chunk_obstack, new_size);
2755 chunk->size = new_size;
2757 new_ptr = chunk->data + new_size;
2759 /* We do the relocations from back to front, because
2760 the relocations are in reverse order. */
2761 for (reloc = block->u.relocations; ; reloc = reloc->next)
2763 /* new_ptr and old_ptr point into the old and new buffers,
2764 respectively. (If no relocations cause the buffer to
2765 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2766 The bytes at higher address have been copied and relocations
2767 handled; those at lower addresses remain to process. */
2769 /* Lower old index of piece to be copied with no relocation.
2770 I.e. high index of the first piece that does need relocation. */
2771 int start = reloc == NULL ? 0
2772 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2773 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2774 ? reloc->offset + 4
2775 : reloc->offset + 2;
2776 int32 value;
2777 int new_offset;
2778 int n = (old_ptr - old_buffer) - start;
2779 new_ptr -= n;
2780 old_ptr -= n;
2781 if (n > 0)
2782 memcpy (new_ptr, old_ptr, n);
2783 if (old_ptr == old_buffer)
2784 break;
2786 new_offset = new_ptr - chunk->data;
2787 new_offset -= (reloc->kind == -1 ? 2 : 4);
2788 if (reloc->kind == 0)
2790 old_ptr -= 4;
2791 value = GET_u4 (old_ptr);
2793 else if (reloc->kind == BLOCK_START_RELOC)
2795 old_ptr -= 4;
2796 value = 0;
2797 new_offset = 0;
2799 else if (reloc->kind == SWITCH_ALIGN_RELOC)
2801 int where = block->pc + reloc->offset;
2802 int pad = ((where + 3) & ~3) - where;
2803 while (--pad >= 0)
2804 *--new_ptr = 0;
2805 continue;
2807 else
2809 old_ptr -= 2;
2810 value = GET_u2 (old_ptr);
2812 value += reloc->label->pc - (block->pc + new_offset);
2813 *--new_ptr = (unsigned char) value; value >>= 8;
2814 *--new_ptr = (unsigned char) value; value >>= 8;
2815 if (reloc->kind != -1)
2817 *--new_ptr = (unsigned char) value; value >>= 8;
2818 *--new_ptr = (unsigned char) value;
2820 if (reloc->kind > BLOCK_START_RELOC)
2822 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2823 --old_ptr;
2824 *--new_ptr = reloc->kind;
2826 else if (reloc->kind < -1)
2828 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2829 --old_ptr;
2830 *--new_ptr = OPCODE_goto_w;
2831 *--new_ptr = 3;
2832 *--new_ptr = 0;
2833 *--new_ptr = - reloc->kind;
2836 if (new_ptr != chunk->data)
2837 abort ();
2839 state->code_length = pc;
2842 static void
2843 init_jcf_state (state, work)
2844 struct jcf_partial *state;
2845 struct obstack *work;
2847 state->chunk_obstack = work;
2848 state->first = state->chunk = NULL;
2849 CPOOL_INIT (&state->cpool);
2850 BUFFER_INIT (&state->localvars);
2851 BUFFER_INIT (&state->bytecode);
2854 static void
2855 init_jcf_method (state, method)
2856 struct jcf_partial *state;
2857 tree method;
2859 state->current_method = method;
2860 state->blocks = state->last_block = NULL;
2861 state->linenumber_count = 0;
2862 state->first_lvar = state->last_lvar = NULL;
2863 state->lvar_count = 0;
2864 state->labeled_blocks = NULL;
2865 state->code_length = 0;
2866 BUFFER_RESET (&state->bytecode);
2867 BUFFER_RESET (&state->localvars);
2868 state->code_SP = 0;
2869 state->code_SP_max = 0;
2870 state->handlers = NULL;
2871 state->last_handler = NULL;
2872 state->num_handlers = 0;
2873 state->num_finalizers = 0;
2874 state->return_value_decl = NULL_TREE;
2877 static void
2878 release_jcf_state (state)
2879 struct jcf_partial *state;
2881 CPOOL_FINISH (&state->cpool);
2882 obstack_free (state->chunk_obstack, state->first);
2885 /* Generate and return a list of chunks containing the class CLAS
2886 in the .class file representation. The list can be written to a
2887 .class file using write_chunks. Allocate chunks from obstack WORK. */
2889 static GTY(()) tree SourceFile_node;
2890 static struct chunk *
2891 generate_classfile (clas, state)
2892 tree clas;
2893 struct jcf_partial *state;
2895 struct chunk *cpool_chunk;
2896 const char *source_file, *s;
2897 char *ptr;
2898 int i;
2899 char *fields_count_ptr;
2900 int fields_count = 0;
2901 char *methods_count_ptr;
2902 int methods_count = 0;
2903 tree part;
2904 int total_supers
2905 = clas == object_type_node ? 0
2906 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2908 ptr = append_chunk (NULL, 8, state);
2909 PUT4 (0xCafeBabe); /* Magic number */
2910 PUT2 (3); /* Minor version */
2911 PUT2 (45); /* Major version */
2913 append_chunk (NULL, 0, state);
2914 cpool_chunk = state->chunk;
2916 /* Next allocate the chunk containing acces_flags through fields_counr. */
2917 if (clas == object_type_node)
2918 i = 10;
2919 else
2920 i = 8 + 2 * total_supers;
2921 ptr = append_chunk (NULL, i, state);
2922 i = get_access_flags (TYPE_NAME (clas));
2923 if (! (i & ACC_INTERFACE))
2924 i |= ACC_SUPER;
2925 PUT2 (i); /* acces_flags */
2926 i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
2927 if (clas == object_type_node)
2929 PUT2(0); /* super_class */
2930 PUT2(0); /* interfaces_count */
2932 else
2934 tree basetypes = TYPE_BINFO_BASETYPES (clas);
2935 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2936 int j = find_class_constant (&state->cpool, base);
2937 PUT2 (j); /* super_class */
2938 PUT2 (total_supers - 1); /* interfaces_count */
2939 for (i = 1; i < total_supers; i++)
2941 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2942 j = find_class_constant (&state->cpool, base);
2943 PUT2 (j);
2946 fields_count_ptr = ptr;
2948 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
2950 int have_value, attr_count = 0;
2951 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2952 continue;
2953 ptr = append_chunk (NULL, 8, state);
2954 i = get_access_flags (part); PUT2 (i);
2955 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
2956 i = find_utf8_constant (&state->cpool,
2957 build_java_signature (TREE_TYPE (part)));
2958 PUT2(i);
2959 have_value = DECL_INITIAL (part) != NULL_TREE
2960 && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
2961 && FIELD_FINAL (part)
2962 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
2963 || TREE_TYPE (part) == string_ptr_type_node);
2964 if (have_value)
2965 attr_count++;
2967 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part) || FIELD_SYNTHETIC (part))
2968 attr_count++;
2970 PUT2 (attr_count); /* attributes_count */
2971 if (have_value)
2973 tree init = DECL_INITIAL (part);
2974 static tree ConstantValue_node = NULL_TREE;
2975 if (TREE_TYPE (part) != TREE_TYPE (init))
2976 fatal_error ("field initializer type mismatch");
2977 ptr = append_chunk (NULL, 8, state);
2978 if (ConstantValue_node == NULL_TREE)
2979 ConstantValue_node = get_identifier ("ConstantValue");
2980 i = find_utf8_constant (&state->cpool, ConstantValue_node);
2981 PUT2 (i); /* attribute_name_index */
2982 PUT4 (2); /* attribute_length */
2983 i = find_constant_index (init, state); PUT2 (i);
2985 /* Emit the "Synthetic" attribute for val$<x> and this$<n>
2986 fields and other fields which need it. */
2987 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part)
2988 || FIELD_SYNTHETIC (part))
2989 ptr = append_synthetic_attribute (state);
2990 fields_count++;
2992 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
2994 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
2995 PUT2 (0);
2997 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
2999 struct jcf_block *block;
3000 tree function_body = DECL_FUNCTION_BODY (part);
3001 tree body = function_body == NULL_TREE ? NULL_TREE
3002 : BLOCK_EXPR_BODY (function_body);
3003 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
3004 : DECL_NAME (part);
3005 tree type = TREE_TYPE (part);
3006 tree save_function = current_function_decl;
3007 int synthetic_p = 0;
3008 current_function_decl = part;
3009 ptr = append_chunk (NULL, 8, state);
3010 i = get_access_flags (part); PUT2 (i);
3011 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3012 i = find_utf8_constant (&state->cpool, build_java_signature (type));
3013 PUT2 (i);
3014 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
3016 /* Make room for the Synthetic attribute (of zero length.) */
3017 if (DECL_FINIT_P (part)
3018 || DECL_INSTINIT_P (part)
3019 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
3020 || TYPE_DOT_CLASS (clas) == part)
3022 i++;
3023 synthetic_p = 1;
3026 PUT2 (i); /* attributes_count */
3028 if (synthetic_p)
3029 ptr = append_synthetic_attribute (state);
3031 if (body != NULL_TREE)
3033 int code_attributes_count = 0;
3034 static tree Code_node = NULL_TREE;
3035 tree t;
3036 char *attr_len_ptr;
3037 struct jcf_handler *handler;
3038 if (Code_node == NULL_TREE)
3039 Code_node = get_identifier ("Code");
3040 ptr = append_chunk (NULL, 14, state);
3041 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
3042 attr_len_ptr = ptr;
3043 init_jcf_method (state, part);
3044 get_jcf_label_here (state); /* Force a first block. */
3045 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3046 localvar_alloc (t, state);
3047 generate_bytecode_insns (body, IGNORE_TARGET, state);
3048 if (CAN_COMPLETE_NORMALLY (body))
3050 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
3051 abort();
3052 RESERVE (1);
3053 OP1 (OPCODE_return);
3055 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
3056 localvar_free (t, state);
3057 if (state->return_value_decl != NULL_TREE)
3058 localvar_free (state->return_value_decl, state);
3059 finish_jcf_block (state);
3060 perform_relocations (state);
3062 ptr = attr_len_ptr;
3063 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
3064 if (state->linenumber_count > 0)
3066 code_attributes_count++;
3067 i += 8 + 4 * state->linenumber_count;
3069 if (state->lvar_count > 0)
3071 code_attributes_count++;
3072 i += 8 + 10 * state->lvar_count;
3074 UNSAFE_PUT4 (i); /* attribute_length */
3075 UNSAFE_PUT2 (state->code_SP_max); /* max_stack */
3076 UNSAFE_PUT2 (localvar_max); /* max_locals */
3077 UNSAFE_PUT4 (state->code_length);
3079 /* Emit the exception table. */
3080 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
3081 PUT2 (state->num_handlers); /* exception_table_length */
3082 handler = state->handlers;
3083 for (; handler != NULL; handler = handler->next)
3085 int type_index;
3086 PUT2 (handler->start_label->pc);
3087 PUT2 (handler->end_label->pc);
3088 PUT2 (handler->handler_label->pc);
3089 if (handler->type == NULL_TREE)
3090 type_index = 0;
3091 else
3092 type_index = find_class_constant (&state->cpool,
3093 handler->type);
3094 PUT2 (type_index);
3097 ptr = append_chunk (NULL, 2, state);
3098 PUT2 (code_attributes_count);
3100 /* Write the LineNumberTable attribute. */
3101 if (state->linenumber_count > 0)
3103 static tree LineNumberTable_node = NULL_TREE;
3104 ptr = append_chunk (NULL,
3105 8 + 4 * state->linenumber_count, state);
3106 if (LineNumberTable_node == NULL_TREE)
3107 LineNumberTable_node = get_identifier ("LineNumberTable");
3108 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
3109 PUT2 (i); /* attribute_name_index */
3110 i = 2+4*state->linenumber_count; PUT4(i); /* attribute_length */
3111 i = state->linenumber_count; PUT2 (i);
3112 for (block = state->blocks; block != NULL; block = block->next)
3114 int line = block->linenumber;
3115 if (line > 0)
3117 PUT2 (block->pc);
3118 PUT2 (line);
3123 /* Write the LocalVariableTable attribute. */
3124 if (state->lvar_count > 0)
3126 static tree LocalVariableTable_node = NULL_TREE;
3127 struct localvar_info *lvar = state->first_lvar;
3128 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
3129 if (LocalVariableTable_node == NULL_TREE)
3130 LocalVariableTable_node = get_identifier("LocalVariableTable");
3131 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
3132 PUT2 (i); /* attribute_name_index */
3133 i = 2 + 10 * state->lvar_count; PUT4 (i); /* attribute_length */
3134 i = state->lvar_count; PUT2 (i);
3135 for ( ; lvar != NULL; lvar = lvar->next)
3137 tree name = DECL_NAME (lvar->decl);
3138 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
3139 i = lvar->start_label->pc; PUT2 (i);
3140 i = lvar->end_label->pc - i; PUT2 (i);
3141 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
3142 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
3143 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
3147 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
3149 tree t = DECL_FUNCTION_THROWS (part);
3150 int throws_count = list_length (t);
3151 static tree Exceptions_node = NULL_TREE;
3152 if (Exceptions_node == NULL_TREE)
3153 Exceptions_node = get_identifier ("Exceptions");
3154 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
3155 i = find_utf8_constant (&state->cpool, Exceptions_node);
3156 PUT2 (i); /* attribute_name_index */
3157 i = 2 + 2 * throws_count; PUT4(i); /* attribute_length */
3158 i = throws_count; PUT2 (i);
3159 for (; t != NULL_TREE; t = TREE_CHAIN (t))
3161 i = find_class_constant (&state->cpool, TREE_VALUE (t));
3162 PUT2 (i);
3165 methods_count++;
3166 current_function_decl = save_function;
3168 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
3170 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
3171 for (s = source_file; ; s++)
3173 char ch = *s;
3174 if (ch == '\0')
3175 break;
3176 if (ch == '/' || ch == '\\')
3177 source_file = s+1;
3179 ptr = append_chunk (NULL, 10, state);
3181 i = 1; /* Source file always exists as an attribute */
3182 if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
3183 i++;
3184 if (clas == object_type_node)
3185 i++;
3186 PUT2 (i); /* attributes_count */
3188 /* generate the SourceFile attribute. */
3189 if (SourceFile_node == NULL_TREE)
3191 SourceFile_node = get_identifier ("SourceFile");
3194 i = find_utf8_constant (&state->cpool, SourceFile_node);
3195 PUT2 (i); /* attribute_name_index */
3196 PUT4 (2);
3197 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3198 PUT2 (i);
3199 append_gcj_attribute (state, clas);
3200 append_innerclasses_attribute (state, clas);
3202 /* New finally generate the contents of the constant pool chunk. */
3203 i = count_constant_pool_bytes (&state->cpool);
3204 ptr = obstack_alloc (state->chunk_obstack, i);
3205 cpool_chunk->data = ptr;
3206 cpool_chunk->size = i;
3207 write_constant_pool (&state->cpool, ptr, i);
3208 return state->first;
3211 static GTY(()) tree Synthetic_node;
3212 static unsigned char *
3213 append_synthetic_attribute (state)
3214 struct jcf_partial *state;
3216 unsigned char *ptr = append_chunk (NULL, 6, state);
3217 int i;
3219 if (Synthetic_node == NULL_TREE)
3221 Synthetic_node = get_identifier ("Synthetic");
3223 i = find_utf8_constant (&state->cpool, Synthetic_node);
3224 PUT2 (i); /* Attribute string index */
3225 PUT4 (0); /* Attribute length */
3227 return ptr;
3230 static void
3231 append_gcj_attribute (state, class)
3232 struct jcf_partial *state;
3233 tree class;
3235 unsigned char *ptr;
3236 int i;
3238 if (class != object_type_node)
3239 return;
3241 ptr = append_chunk (NULL, 6, state); /* 2+4 */
3242 i = find_utf8_constant (&state->cpool,
3243 get_identifier ("gnu.gcj.gcj-compiled"));
3244 PUT2 (i); /* Attribute string index */
3245 PUT4 (0); /* Attribute length */
3248 static tree InnerClasses_node;
3249 static void
3250 append_innerclasses_attribute (state, class)
3251 struct jcf_partial *state;
3252 tree class;
3254 tree orig_decl = TYPE_NAME (class);
3255 tree current, decl;
3256 int length = 0, i;
3257 unsigned char *ptr, *length_marker, *number_marker;
3259 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
3260 return;
3262 ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
3264 if (InnerClasses_node == NULL_TREE)
3266 InnerClasses_node = get_identifier ("InnerClasses");
3268 i = find_utf8_constant (&state->cpool, InnerClasses_node);
3269 PUT2 (i);
3270 length_marker = ptr; PUT4 (0); /* length, to be later patched */
3271 number_marker = ptr; PUT2 (0); /* number of classes, tblp */
3273 /* Generate the entries: all inner classes visible from the one we
3274 process: itself, up and down. */
3275 while (class && INNER_CLASS_TYPE_P (class))
3277 const char *n;
3279 decl = TYPE_NAME (class);
3280 n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
3281 IDENTIFIER_LENGTH (DECL_NAME (decl));
3283 while (n[-1] != '$')
3284 n--;
3285 append_innerclasses_attribute_entry (state, decl, get_identifier (n));
3286 length++;
3288 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
3291 decl = orig_decl;
3292 for (current = DECL_INNER_CLASS_LIST (decl);
3293 current; current = TREE_CHAIN (current))
3295 append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
3296 TREE_VALUE (current));
3297 length++;
3300 ptr = length_marker; PUT4 (8*length+2);
3301 ptr = number_marker; PUT2 (length);
3304 static void
3305 append_innerclasses_attribute_entry (state, decl, name)
3306 struct jcf_partial *state;
3307 tree decl, name;
3309 int icii, icaf;
3310 int ocii = 0, ini = 0;
3311 unsigned char *ptr = append_chunk (NULL, 8, state);
3313 icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
3315 /* Sun's implementation seems to generate ocii to 0 for inner
3316 classes (which aren't considered members of the class they're
3317 in.) The specs are saying that if the class is anonymous,
3318 inner_name_index must be zero. */
3319 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
3321 ocii = find_class_constant (&state->cpool,
3322 TREE_TYPE (DECL_CONTEXT (decl)));
3323 ini = find_utf8_constant (&state->cpool, name);
3325 icaf = get_access_flags (decl);
3327 PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
3330 static char *
3331 make_class_file_name (clas)
3332 tree clas;
3334 const char *dname, *cname, *slash;
3335 char *r;
3336 struct stat sb;
3338 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3339 "", '.', DIR_SEPARATOR,
3340 ".class"));
3341 if (jcf_write_base_directory == NULL)
3343 /* Make sure we put the class file into the .java file's
3344 directory, and not into some subdirectory thereof. */
3345 char *t;
3346 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3347 slash = strrchr (dname, DIR_SEPARATOR);
3348 if (! slash)
3350 dname = ".";
3351 slash = dname + 1;
3353 t = strrchr (cname, DIR_SEPARATOR);
3354 if (t)
3355 cname = t + 1;
3357 else
3359 dname = jcf_write_base_directory;
3360 slash = dname + strlen (dname);
3363 r = xmalloc (slash - dname + strlen (cname) + 2);
3364 strncpy (r, dname, slash - dname);
3365 r[slash - dname] = DIR_SEPARATOR;
3366 strcpy (&r[slash - dname + 1], cname);
3368 /* We try to make new directories when we need them. We only do
3369 this for directories which "might not" exist. For instance, we
3370 assume the `-d' directory exists, but we don't assume that any
3371 subdirectory below it exists. It might be worthwhile to keep
3372 track of which directories we've created to avoid gratuitous
3373 stat()s. */
3374 dname = r + (slash - dname) + 1;
3375 while (1)
3377 char *s = strchr (dname, DIR_SEPARATOR);
3378 if (s == NULL)
3379 break;
3380 *s = '\0';
3381 if (stat (r, &sb) == -1
3382 /* Try to make it. */
3383 && mkdir (r, 0755) == -1)
3384 fatal_io_error ("can't create directory %s", r);
3386 *s = DIR_SEPARATOR;
3387 /* Skip consecutive separators. */
3388 for (dname = s + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
3392 return r;
3395 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
3396 The output .class file name is make_class_file_name(CLAS). */
3398 void
3399 write_classfile (clas)
3400 tree clas;
3402 struct obstack *work = &temporary_obstack;
3403 struct jcf_partial state[1];
3404 char *class_file_name = make_class_file_name (clas);
3405 struct chunk *chunks;
3407 if (class_file_name != NULL)
3409 FILE *stream;
3410 char *temporary_file_name;
3412 /* The .class file is initially written to a ".tmp" file so that
3413 if multiple instances of the compiler are running at once
3414 they do not see partially formed class files. */
3415 temporary_file_name = concat (class_file_name, ".tmp", NULL);
3416 stream = fopen (temporary_file_name, "wb");
3417 if (stream == NULL)
3418 fatal_io_error ("can't open %s for writing", temporary_file_name);
3420 jcf_dependency_add_target (class_file_name);
3421 init_jcf_state (state, work);
3422 chunks = generate_classfile (clas, state);
3423 write_chunks (stream, chunks);
3424 if (fclose (stream))
3425 fatal_io_error ("error closing %s", temporary_file_name);
3427 /* If a file named by the string pointed to by `new' exists
3428 prior to the call to the `rename' function, the bahaviour
3429 is implementation-defined. ISO 9899-1990 7.9.4.2.
3431 For example, on Win32 with MSVCRT, it is an error. */
3433 unlink (class_file_name);
3435 if (rename (temporary_file_name, class_file_name) == -1)
3437 remove (temporary_file_name);
3438 fatal_io_error ("can't create %s", class_file_name);
3440 free (temporary_file_name);
3441 free (class_file_name);
3443 release_jcf_state (state);
3446 /* TODO:
3447 string concatenation
3448 synchronized statement
3451 #include "gt-java-jcf-write.h"