1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU CC; see the file COPYING. If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc. */
28 #include "java-tree.h"
33 #include "java-opcodes.h"
34 #include "parse.h" /* for BLOCK_EXPR_BODY */
39 #define DIR_SEPARATOR '/'
42 extern struct obstack temporary_obstack
;
44 /* Base directory in which `.class' files should be written.
45 NULL means to put the file into the same directory as the
46 corresponding .java file. */
47 char *jcf_write_base_directory
= NULL
;
49 /* Make sure bytecode.data is big enough for at least N more bytes. */
52 do { CHECK_OP(state); \
53 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
54 buffer_grow (&state->bytecode, N); } while (0)
56 /* Add a 1-byte instruction/operand I to bytecode.data,
57 assuming space has already been RESERVE'd. */
59 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
61 /* Like OP1, but I is a 2-byte big endian integer. */
64 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
66 /* Like OP1, but I is a 4-byte big endian integer. */
69 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
70 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
72 /* Macro to call each time we push I words on the JVM stack. */
74 #define NOTE_PUSH(I) \
75 do { state->code_SP += (I); \
76 if (state->code_SP > state->code_SP_max) \
77 state->code_SP_max = state->code_SP; } while (0)
79 /* Macro to call each time we pop I words from the JVM stack. */
82 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
84 /* A chunk or segment of a .class file. */
88 /* The next segment of this .class file. */
91 /* The actual data in this segment to be written to the .class file. */
94 /* The size of the segment to be written to the .class file. */
98 #define PENDING_CLEANUP_PC (-3)
99 #define PENDING_EXIT_PC (-2)
100 #define UNDEFINED_PC (-1)
102 /* Each "block" represents a label plus the bytecode instructions following.
103 There may be branches out of the block, but no incoming jumps, except
104 to the beginning of the block.
106 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
107 assocated code yet), but it is an undefined label.
112 /* For blocks that that are defined, the next block (in pc order).
113 For blocks that are the not-yet-defined end label of a LABELED_BLOCK_EXPR
114 or a cleanup expression (from a WITH_CLEANUP_EXPR),
115 this is the next (outer) such end label, in a stack headed by
116 labeled_blocks in jcf_partial. */
117 struct jcf_block
*next
;
119 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
120 pc is PENDING_EXIT_PC.
121 In the not-yet-defined end label for pending cleanup subroutine,
122 pc is PENDING_CLEANUP_PC.
123 For other not-yet-defined labels, pc is UNDEFINED_PC.
125 If the label has been defined:
126 Until perform_relocations is finished, this is the maximum possible
127 value of the bytecode offset at the begnning of this block.
128 After perform_relocations, it is the actual offset (pc). */
133 /* After finish_jcf_block is called, The actual instructions contained in this block.
134 Before than NULL, and the instructions are in state->bytecode. */
138 /* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
139 coveed by the cleanup. */
140 struct jcf_block
*start_label
;
144 /* Set of relocations (in reverse offset order) for this block. */
145 struct jcf_relocation
*relocations
;
147 /* If this block is that of the not-yet-defined end label of
148 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR.
149 If pc==PENDING_CLEANUP_PC, the cleanup that needs to be run. */
154 /* A "relocation" type for the 0-3 bytes of padding at the start
155 of a tableswitch or a lookupswitch. */
156 #define SWITCH_ALIGN_RELOC 4
158 /* A relocation type for the labels in a tableswitch or a lookupswitch;
159 these are relative to the start of the instruction, but (due to
160 th 0-3 bytes of padding), we don't know the offset before relocation. */
161 #define BLOCK_START_RELOC 1
163 struct jcf_relocation
165 /* Next relocation for the current jcf_block. */
166 struct jcf_relocation
*next
;
168 /* The (byte) offset within the current block that needs to be relocated. */
169 HOST_WIDE_INT offset
;
171 /* 0 if offset is a 4-byte relative offset.
172 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
173 for proper alignment in tableswitch/lookupswitch instructions.
174 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
175 to the start of the containing block.
176 -1 if offset is a 2-byte relative offset.
177 < -1 if offset is the address of an instruction with a 2-byte offset
178 that does not have a corresponding 4-byte offset version, in which
179 case the absolute value of kind is the inverted opcode.
180 > 4 if offset is the address of an instruction (such as jsr) with a
181 2-byte offset that does have a corresponding 4-byte offset version,
182 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
185 /* The label the relocation wants to actually transfer to. */
186 struct jcf_block
*label
;
189 /* State for single catch clause. */
193 struct jcf_handler
*next
;
195 struct jcf_block
*start_label
;
196 struct jcf_block
*end_label
;
197 struct jcf_block
*handler_label
;
199 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
203 /* State for the current switch statement. */
205 struct jcf_switch_state
207 struct jcf_switch_state
*prev
;
208 struct jcf_block
*default_label
;
210 struct jcf_relocation
*cases
;
212 HOST_WIDE_INT min_case
, max_case
;
215 /* This structure is used to contain the various pieces that will
216 become a .class file. */
222 struct obstack
*chunk_obstack
;
225 /* List of basic blocks for the current method. */
226 struct jcf_block
*blocks
;
227 struct jcf_block
*last_block
;
229 struct localvar_info
*first_lvar
;
230 struct localvar_info
*last_lvar
;
235 int linenumber_count
;
237 /* Until perform_relocations, this is a upper bound on the number
238 of bytes (so far) in the instructions for the current method. */
241 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
242 struct jcf_block
*labeled_blocks
;
244 /* The current stack size (stack pointer) in the current method. */
247 /* The largest extent of stack size (stack pointer) in the current method. */
250 /* Contains a mapping from local var slot number to localvar_info. */
251 struct buffer localvars
;
253 /* The buffer allocated for bytecode for the current jcf_block. */
254 struct buffer bytecode
;
256 /* Chain of exception handlers for the current method. */
257 struct jcf_handler
*handlers
;
259 /* Last element in handlers chain. */
260 struct jcf_handler
*last_handler
;
262 /* Number of exception handlers for the current method. */
265 /* Number of finalizers we are currently nested within. */
268 /* If non-NULL, use this for the return value. */
269 tree return_value_decl
;
271 /* Information about the current switch statemenet. */
272 struct jcf_switch_state
*sw_state
;
275 static void generate_bytecode_insns
PROTO ((tree
, int, struct jcf_partial
*));
276 static struct chunk
* alloc_chunk
PROTO ((struct chunk
*, unsigned char *,
277 int, struct obstack
*));
278 static unsigned char * append_chunk
PROTO ((unsigned char *, int,
279 struct jcf_partial
*));
280 static void append_chunk_copy
PROTO ((unsigned char *, int,
281 struct jcf_partial
*));
282 static struct jcf_block
* gen_jcf_label
PROTO ((struct jcf_partial
*));
283 static void finish_jcf_block
PROTO ((struct jcf_partial
*));
284 static void define_jcf_label
PROTO ((struct jcf_block
*,
285 struct jcf_partial
*));
286 static struct jcf_block
* get_jcf_label_here
PROTO ((struct jcf_partial
*));
287 static void put_linenumber
PROTO ((int, struct jcf_partial
*));
288 static void localvar_alloc
PROTO ((tree
, struct jcf_partial
*));
289 static void localvar_free
PROTO ((tree
, struct jcf_partial
*));
290 static int get_access_flags
PROTO ((tree
));
291 static void write_chunks
PROTO ((FILE *, struct chunk
*));
292 static int adjust_typed_op
PROTO ((tree
, int));
293 static void generate_bytecode_conditional
PROTO ((tree
, struct jcf_block
*,
294 struct jcf_block
*, int,
295 struct jcf_partial
*));
296 static void generate_bytecode_return
PROTO ((tree
, struct jcf_partial
*));
297 static void perform_relocations
PROTO ((struct jcf_partial
*));
298 static void init_jcf_state
PROTO ((struct jcf_partial
*, struct obstack
*));
299 static void init_jcf_method
PROTO ((struct jcf_partial
*, tree
));
300 static void release_jcf_state
PROTO ((struct jcf_partial
*));
301 static struct chunk
* generate_classfile
PROTO ((tree
, struct jcf_partial
*));
302 static struct jcf_handler
*alloc_handler
PROTO ((struct jcf_block
*,
304 struct jcf_partial
*));
305 static void push_constant1
PROTO ((int, struct jcf_partial
*));
306 static void push_constant2
PROTO ((int, struct jcf_partial
*));
307 static void push_int_const
PROTO ((HOST_WIDE_INT
, struct jcf_partial
*));
308 static int find_constant_wide
PROTO ((HOST_WIDE_INT
, HOST_WIDE_INT
,
309 struct jcf_partial
*));
310 static int find_constant_index
PROTO ((tree
, struct jcf_partial
*));
311 static void push_long_const
PROTO ((HOST_WIDE_INT
, HOST_WIDE_INT
,
312 struct jcf_partial
*));
313 static void field_op
PROTO ((tree
, int, struct jcf_partial
*));
314 static void maybe_wide
PROTO ((int, int, struct jcf_partial
*));
315 static void emit_dup
PROTO ((int, int, struct jcf_partial
*));
316 static void emit_pop
PROTO ((int, struct jcf_partial
*));
317 static void emit_iinc
PROTO ((tree
, int, struct jcf_partial
*));
318 static void emit_load_or_store
PROTO ((tree
, int, struct jcf_partial
*));
319 static void emit_load
PROTO ((tree
, struct jcf_partial
*));
320 static void emit_store
PROTO ((tree
, struct jcf_partial
*));
321 static void emit_unop
PROTO ((enum java_opcode
, tree
, struct jcf_partial
*));
322 static void emit_binop
PROTO ((enum java_opcode
, tree
, struct jcf_partial
*));
323 static void emit_reloc
PROTO ((HOST_WIDE_INT
, int, struct jcf_block
*,
324 struct jcf_partial
*));
325 static void emit_switch_reloc
PROTO ((struct jcf_block
*,
326 struct jcf_partial
*));
327 static void emit_case_reloc
PROTO ((struct jcf_relocation
*,
328 struct jcf_partial
*));
329 static void emit_if
PROTO ((struct jcf_block
*, int, int,
330 struct jcf_partial
*));
331 static void emit_goto
PROTO ((struct jcf_block
*, struct jcf_partial
*));
332 static void emit_jsr
PROTO ((struct jcf_block
*, struct jcf_partial
*));
333 static void call_cleanups
PROTO ((struct jcf_block
*, struct jcf_partial
*));
334 static char *make_class_file_name
PROTO ((tree
));
336 /* Utility macros for appending (big-endian) data to a buffer.
337 We assume a local variable 'ptr' points into where we want to
338 write next, and we assume enoygh space has been allocated. */
340 #ifdef ENABLE_CHECKING
342 CHECK_PUT(ptr
, state
, i
)
344 struct jcf_partial
*state
;
347 if (ptr
< state
->chunk
->data
348 || (char*)ptr
+ i
> state
->chunk
->data
+ state
->chunk
->size
)
349 fatal ("internal error - CHECK_PUT failed");
353 #define CHECK_PUT(PTR, STATE, I) ((void)0)
356 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
357 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
358 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
359 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
362 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
363 Set the data and size fields to DATA and SIZE, respectively.
364 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
366 static struct chunk
*
367 alloc_chunk (last
, data
, size
, work
)
371 struct obstack
*work
;
373 struct chunk
*chunk
= (struct chunk
*)
374 obstack_alloc (work
, sizeof(struct chunk
));
376 if (data
== NULL
&& size
> 0)
377 data
= obstack_alloc (work
, size
);
387 #ifdef ENABLE_CHECKING
389 CHECK_OP(struct jcf_partial
*state
)
391 if (state
->bytecode
.ptr
> state
->bytecode
.limit
)
393 fatal("internal error - CHECK_OP failed");
398 #define CHECK_OP(STATE) ((void)0)
401 static unsigned char *
402 append_chunk (data
, size
, state
)
405 struct jcf_partial
*state
;
407 state
->chunk
= alloc_chunk (state
->chunk
, data
, size
, state
->chunk_obstack
);
408 if (state
->first
== NULL
)
409 state
->first
= state
->chunk
;
410 return state
->chunk
->data
;
414 append_chunk_copy (data
, size
, state
)
417 struct jcf_partial
*state
;
419 unsigned char *ptr
= append_chunk (NULL
, size
, state
);
420 memcpy (ptr
, data
, size
);
423 static struct jcf_block
*
424 gen_jcf_label (state
)
425 struct jcf_partial
*state
;
427 struct jcf_block
*block
= (struct jcf_block
*)
428 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_block
));
430 block
->linenumber
= -1;
431 block
->pc
= UNDEFINED_PC
;
436 finish_jcf_block (state
)
437 struct jcf_partial
*state
;
439 struct jcf_block
*block
= state
->last_block
;
440 struct jcf_relocation
*reloc
;
441 int code_length
= BUFFER_LENGTH (&state
->bytecode
);
442 int pc
= state
->code_length
;
443 append_chunk_copy (state
->bytecode
.data
, code_length
, state
);
444 BUFFER_RESET (&state
->bytecode
);
445 block
->v
.chunk
= state
->chunk
;
447 /* Calculate code_length to the maximum value it can have. */
448 pc
+= block
->v
.chunk
->size
;
449 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
451 int kind
= reloc
->kind
;
452 if (kind
== SWITCH_ALIGN_RELOC
)
454 else if (kind
> BLOCK_START_RELOC
)
455 pc
+= 2; /* 2-byte offset may grow to 4-byte offset */
457 pc
+= 5; /* May need to add a goto_w. */
459 state
->code_length
= pc
;
463 define_jcf_label (label
, state
)
464 struct jcf_block
*label
;
465 struct jcf_partial
*state
;
467 if (state
->last_block
!= NULL
)
468 finish_jcf_block (state
);
469 label
->pc
= state
->code_length
;
470 if (state
->blocks
== NULL
)
471 state
->blocks
= label
;
473 state
->last_block
->next
= label
;
474 state
->last_block
= label
;
476 label
->u
.relocations
= NULL
;
479 static struct jcf_block
*
480 get_jcf_label_here (state
)
481 struct jcf_partial
*state
;
483 if (state
->last_block
!= NULL
&& BUFFER_LENGTH (&state
->bytecode
) == 0)
484 return state
->last_block
;
487 struct jcf_block
*label
= gen_jcf_label (state
);
488 define_jcf_label (label
, state
);
493 /* Note a line number entry for the current PC and given LINE. */
496 put_linenumber (line
, state
)
498 struct jcf_partial
*state
;
500 struct jcf_block
*label
= get_jcf_label_here (state
);
501 if (label
->linenumber
> 0)
503 label
= gen_jcf_label (state
);
504 define_jcf_label (label
, state
);
506 label
->linenumber
= line
;
507 state
->linenumber_count
++;
510 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
511 in the range (START_LABEL, END_LABEL). */
513 static struct jcf_handler
*
514 alloc_handler (start_label
, end_label
, state
)
515 struct jcf_block
*start_label
;
516 struct jcf_block
*end_label
;
517 struct jcf_partial
*state
;
519 struct jcf_handler
*handler
= (struct jcf_handler
*)
520 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_handler
));
521 handler
->start_label
= start_label
;
522 handler
->end_label
= end_label
;
523 handler
->handler_label
= get_jcf_label_here (state
);
524 if (state
->handlers
== NULL
)
525 state
->handlers
= handler
;
527 state
->last_handler
->next
= handler
;
528 state
->last_handler
= handler
;
529 handler
->next
= NULL
;
530 state
->num_handlers
++;
535 /* The index of jvm local variable allocated for this DECL.
536 This is assigned when generating .class files;
537 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
538 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
540 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
544 struct localvar_info
*next
;
547 struct jcf_block
*start_label
;
548 struct jcf_block
*end_label
;
551 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
552 #define localvar_max \
553 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
556 localvar_alloc (decl
, state
)
558 struct jcf_partial
*state
;
560 struct jcf_block
*start_label
= get_jcf_label_here (state
);
561 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
563 register struct localvar_info
*info
;
564 register struct localvar_info
**ptr
= localvar_buffer
;
565 register struct localvar_info
**limit
566 = (struct localvar_info
**) state
->localvars
.ptr
;
567 for (index
= 0; ptr
< limit
; index
++, ptr
++)
570 && (! wide
|| ((ptr
+1) < limit
&& ptr
[1] == NULL
)))
575 buffer_grow (&state
->localvars
, 2 * sizeof (struct localvar_info
*));
576 ptr
= (struct localvar_info
**) state
->localvars
.data
+ index
;
577 state
->localvars
.ptr
= (unsigned char *) (ptr
+ 1 + wide
);
579 info
= (struct localvar_info
*)
580 obstack_alloc (state
->chunk_obstack
, sizeof (struct localvar_info
));
583 ptr
[1] = (struct localvar_info
*)(~0);
584 DECL_LOCAL_INDEX (decl
) = index
;
586 info
->start_label
= start_label
;
588 if (debug_info_level
> DINFO_LEVEL_TERSE
589 && DECL_NAME (decl
) != NULL_TREE
)
591 /* Generate debugging info. */
593 if (state
->last_lvar
!= NULL
)
594 state
->last_lvar
->next
= info
;
596 state
->first_lvar
= info
;
597 state
->last_lvar
= info
;
603 localvar_free (decl
, state
)
605 struct jcf_partial
*state
;
607 struct jcf_block
*end_label
= get_jcf_label_here (state
);
608 int index
= DECL_LOCAL_INDEX (decl
);
609 register struct localvar_info
**ptr
= &localvar_buffer
[index
];
610 register struct localvar_info
*info
= *ptr
;
611 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
613 info
->end_label
= end_label
;
615 if (info
->decl
!= decl
)
620 if (ptr
[1] != (struct localvar_info
*)(~0))
627 #define STACK_TARGET 1
628 #define IGNORE_TARGET 2
630 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
631 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
634 get_access_flags (decl
)
638 int isfield
= TREE_CODE (decl
) == FIELD_DECL
|| TREE_CODE (decl
) == VAR_DECL
;
639 if (CLASS_PUBLIC (decl
)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
641 if (CLASS_FINAL (decl
)) /* same as FIELD_FINAL and METHOD_FINAL */
643 if (isfield
|| TREE_CODE (decl
) == FUNCTION_DECL
)
645 if (TREE_PROTECTED (decl
))
646 flags
|= ACC_PROTECTED
;
647 if (TREE_PRIVATE (decl
))
648 flags
|= ACC_PRIVATE
;
650 else if (TREE_CODE (decl
) == TYPE_DECL
)
652 if (CLASS_SUPER (decl
))
654 if (CLASS_ABSTRACT (decl
))
655 flags
|= ACC_ABSTRACT
;
656 if (CLASS_INTERFACE (decl
))
657 flags
|= ACC_INTERFACE
;
660 fatal ("internal error - bad argument to get_access_flags");
661 if (TREE_CODE (decl
) == FUNCTION_DECL
)
663 if (METHOD_NATIVE (decl
))
665 if (METHOD_STATIC (decl
))
667 if (METHOD_SYNCHRONIZED (decl
))
668 flags
|= ACC_SYNCHRONIZED
;
669 if (METHOD_ABSTRACT (decl
))
670 flags
|= ACC_ABSTRACT
;
674 if (FIELD_STATIC (decl
))
676 if (FIELD_VOLATILE (decl
))
677 flags
|= ACC_VOLATILE
;
678 if (FIELD_TRANSIENT (decl
))
679 flags
|= ACC_TRANSIENT
;
684 /* Write the list of segments starting at CHUNKS to STREAM. */
687 write_chunks (stream
, chunks
)
689 struct chunk
*chunks
;
691 for (; chunks
!= NULL
; chunks
= chunks
->next
)
692 fwrite (chunks
->data
, chunks
->size
, 1, stream
);
695 /* Push a 1-word constant in the constant pool at the given INDEX.
696 (Caller is responsible for doing NOTE_PUSH.) */
699 push_constant1 (index
, state
)
701 struct jcf_partial
*state
;
716 /* Push a 2-word constant in the constant pool at the given INDEX.
717 (Caller is responsible for doing NOTE_PUSH.) */
720 push_constant2 (index
, state
)
722 struct jcf_partial
*state
;
729 /* Push 32-bit integer constant on VM stack.
730 Caller is responsible for doing NOTE_PUSH. */
733 push_int_const (i
, state
)
735 struct jcf_partial
*state
;
738 if (i
>= -1 && i
<= 5)
739 OP1(OPCODE_iconst_0
+ i
);
740 else if (i
>= -128 && i
< 128)
745 else if (i
>= -32768 && i
< 32768)
752 i
= find_constant1 (&state
->cpool
, CONSTANT_Integer
, i
& 0xFFFFFFFF);
753 push_constant1 (i
, state
);
758 find_constant_wide (lo
, hi
, state
)
759 HOST_WIDE_INT lo
, hi
;
760 struct jcf_partial
*state
;
762 HOST_WIDE_INT w1
, w2
;
763 lshift_double (lo
, hi
, -32, 64, &w1
, &w2
, 1);
764 return find_constant2 (&state
->cpool
, CONSTANT_Long
,
765 w1
& 0xFFFFFFFF, lo
& 0xFFFFFFFF);
768 /* Find or allocate a constant pool entry for the given VALUE.
769 Return the index in the constant pool. */
772 find_constant_index (value
, state
)
774 struct jcf_partial
*state
;
776 if (TREE_CODE (value
) == INTEGER_CST
)
778 if (TYPE_PRECISION (TREE_TYPE (value
)) <= 32)
779 return find_constant1 (&state
->cpool
, CONSTANT_Integer
,
780 TREE_INT_CST_LOW (value
) & 0xFFFFFFFF);
782 return find_constant_wide (TREE_INT_CST_LOW (value
),
783 TREE_INT_CST_HIGH (value
), state
);
785 else if (TREE_CODE (value
) == REAL_CST
)
788 if (TYPE_PRECISION (TREE_TYPE (value
)) == 32)
790 words
[0] = etarsingle (TREE_REAL_CST (value
)) & 0xFFFFFFFF;
791 return find_constant1 (&state
->cpool
, CONSTANT_Float
, words
[0]);
795 etardouble (TREE_REAL_CST (value
), words
);
796 return find_constant2 (&state
->cpool
, CONSTANT_Double
,
797 words
[1-FLOAT_WORDS_BIG_ENDIAN
] & 0xFFFFFFFF,
798 words
[FLOAT_WORDS_BIG_ENDIAN
] & 0xFFFFFFFF);
801 else if (TREE_CODE (value
) == STRING_CST
)
803 return find_string_constant (&state
->cpool
, value
);
806 fatal ("find_constant_index - bad type");
809 /* Push 64-bit long constant on VM stack.
810 Caller is responsible for doing NOTE_PUSH. */
813 push_long_const (lo
, hi
, state
)
814 HOST_WIDE_INT lo
, hi
;
815 struct jcf_partial
*state
;
817 if (hi
== 0 && lo
>= 0 && lo
<= 1)
820 OP1(OPCODE_lconst_0
+ lo
);
822 else if ((hi
== 0 && lo
< 32768) || (hi
== -1 && lo
>= -32768))
824 push_int_const (lo
, state
);
829 push_constant2 (find_constant_wide (lo
, hi
, state
), state
);
833 field_op (field
, opcode
, state
)
836 struct jcf_partial
*state
;
838 int index
= find_fieldref_index (&state
->cpool
, field
);
844 /* Returns an integer in the range 0 (for 'int') through 4 (for object
845 reference) to 7 (for 'short') which matches the pattern of how JVM
846 opcodes typically depend on the operand type. */
849 adjust_typed_op (type
, max
)
853 switch (TREE_CODE (type
))
856 case RECORD_TYPE
: return 4;
858 return TYPE_PRECISION (type
) == 32 || max
< 5 ? 0 : 5;
860 return TYPE_PRECISION (type
) == 32 || max
< 6 ? 0 : 6;
862 switch (TYPE_PRECISION (type
))
864 case 8: return max
< 5 ? 0 : 5;
865 case 16: return max
< 7 ? 0 : 7;
871 switch (TYPE_PRECISION (type
))
884 maybe_wide (opcode
, index
, state
)
886 struct jcf_partial
*state
;
903 /* Compile code to duplicate with offset, where
904 SIZE is the size of the stack item to duplicate (1 or 2), abd
905 OFFSET is where to insert the result (must be 0, 1, or 2).
906 (The new words get inserted at stack[SP-size-offset].) */
909 emit_dup (size
, offset
, state
)
911 struct jcf_partial
*state
;
918 kind
= size
== 1 ? OPCODE_dup
: OPCODE_dup2
;
919 else if (offset
== 1)
920 kind
= size
== 1 ? OPCODE_dup_x1
: OPCODE_dup2_x1
;
921 else if (offset
== 2)
922 kind
= size
== 1 ? OPCODE_dup_x2
: OPCODE_dup2_x2
;
930 emit_pop (size
, state
)
932 struct jcf_partial
*state
;
935 OP1 (OPCODE_pop
- 1 + size
);
939 emit_iinc (var
, value
, state
)
942 struct jcf_partial
*state
;
944 int slot
= DECL_LOCAL_INDEX (var
);
946 if (value
< -128 || value
> 127 || slot
>= 256)
964 emit_load_or_store (var
, opcode
, state
)
965 tree var
; /* Variable to load from or store into. */
966 int opcode
; /* Either OPCODE_iload or OPCODE_istore. */
967 struct jcf_partial
*state
;
969 tree type
= TREE_TYPE (var
);
970 int kind
= adjust_typed_op (type
, 4);
971 int index
= DECL_LOCAL_INDEX (var
);
975 OP1 (opcode
+ 5 + 4 * kind
+ index
); /* [ilfda]{load,store}_[0123] */
978 maybe_wide (opcode
+ kind
, index
, state
); /* [ilfda]{load,store} */
982 emit_load (var
, state
)
984 struct jcf_partial
*state
;
986 emit_load_or_store (var
, OPCODE_iload
, state
);
987 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
991 emit_store (var
, state
)
993 struct jcf_partial
*state
;
995 emit_load_or_store (var
, OPCODE_istore
, state
);
996 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
1000 emit_unop (opcode
, type
, state
)
1001 enum java_opcode opcode
;
1002 tree type ATTRIBUTE_UNUSED
;
1003 struct jcf_partial
*state
;
1010 emit_binop (opcode
, type
, state
)
1011 enum java_opcode opcode
;
1013 struct jcf_partial
*state
;
1015 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1022 emit_reloc (value
, kind
, target
, state
)
1023 HOST_WIDE_INT value
;
1025 struct jcf_block
*target
;
1026 struct jcf_partial
*state
;
1028 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
1029 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1030 struct jcf_block
*block
= state
->last_block
;
1031 reloc
->next
= block
->u
.relocations
;
1032 block
->u
.relocations
= reloc
;
1033 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1034 reloc
->label
= target
;
1036 if (kind
== 0 || kind
== BLOCK_START_RELOC
)
1038 else if (kind
!= SWITCH_ALIGN_RELOC
)
1043 emit_switch_reloc (label
, state
)
1044 struct jcf_block
*label
;
1045 struct jcf_partial
*state
;
1047 emit_reloc (0, BLOCK_START_RELOC
, label
, state
);
1050 /* Similar to emit_switch_reloc,
1051 but re-uses an existing case reloc. */
1054 emit_case_reloc (reloc
, state
)
1055 struct jcf_relocation
*reloc
;
1056 struct jcf_partial
*state
;
1058 struct jcf_block
*block
= state
->last_block
;
1059 reloc
->next
= block
->u
.relocations
;
1060 block
->u
.relocations
= reloc
;
1061 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
1062 reloc
->kind
= BLOCK_START_RELOC
;
1066 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1067 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1070 emit_if (target
, opcode
, inv_opcode
, state
)
1071 struct jcf_block
*target
;
1072 int opcode
, inv_opcode
;
1073 struct jcf_partial
*state
;
1076 // value is 1 byte from reloc back to start of instruction.
1077 emit_reloc (1, - inv_opcode
, target
, state
);
1081 emit_goto (target
, state
)
1082 struct jcf_block
*target
;
1083 struct jcf_partial
*state
;
1086 // Value is 1 byte from reloc back to start of instruction.
1087 emit_reloc (1, OPCODE_goto_w
, target
, state
);
1091 emit_jsr (target
, state
)
1092 struct jcf_block
*target
;
1093 struct jcf_partial
*state
;
1096 // Value is 1 byte from reloc back to start of instruction.
1097 emit_reloc (1, OPCODE_jsr_w
, target
, state
);
1100 /* Generate code to evaluate EXP. If the result is true,
1101 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1102 TRUE_BRANCH_FIRST is a code geneation hint that the
1103 TRUE_LABEL may follow right after this. (The idea is that we
1104 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1107 generate_bytecode_conditional (exp
, true_label
, false_label
,
1108 true_branch_first
, state
)
1110 struct jcf_block
*true_label
;
1111 struct jcf_block
*false_label
;
1112 int true_branch_first
;
1113 struct jcf_partial
*state
;
1115 tree exp0
, exp1
, type
;
1116 int save_SP
= state
->code_SP
;
1117 enum java_opcode op
, negop
;
1118 switch (TREE_CODE (exp
))
1121 emit_goto (integer_zerop (exp
) ? false_label
: true_label
, state
);
1125 struct jcf_block
*then_label
= gen_jcf_label (state
);
1126 struct jcf_block
*else_label
= gen_jcf_label (state
);
1127 int save_SP_before
, save_SP_after
;
1128 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1129 then_label
, else_label
, 1, state
);
1130 define_jcf_label (then_label
, state
);
1131 save_SP_before
= state
->code_SP
;
1132 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1133 true_label
, false_label
, 1, state
);
1134 save_SP_after
= state
->code_SP
;
1135 state
->code_SP
= save_SP_before
;
1136 define_jcf_label (else_label
, state
);
1137 generate_bytecode_conditional (TREE_OPERAND (exp
, 2),
1138 true_label
, false_label
,
1139 true_branch_first
, state
);
1140 if (state
->code_SP
!= save_SP_after
)
1141 fatal ("internal error non-matching SP");
1144 case TRUTH_NOT_EXPR
:
1145 generate_bytecode_conditional (TREE_OPERAND (exp
, 0), false_label
, true_label
,
1146 ! true_branch_first
, state
);
1148 case TRUTH_ANDIF_EXPR
:
1150 struct jcf_block
*next_label
= gen_jcf_label (state
);
1151 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1152 next_label
, false_label
, 1, state
);
1153 define_jcf_label (next_label
, state
);
1154 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1155 true_label
, false_label
, 1, state
);
1158 case TRUTH_ORIF_EXPR
:
1160 struct jcf_block
*next_label
= gen_jcf_label (state
);
1161 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1162 true_label
, next_label
, 1, state
);
1163 define_jcf_label (next_label
, state
);
1164 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1165 true_label
, false_label
, 1, state
);
1169 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1170 set it to the corresponding 1-operand if<COND> instructions. */
1174 /* The opcodes with their inverses are allocated in pairs.
1175 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1176 negop
= (op
& 1) ? op
+ 1 : op
- 1;
1178 if (true_branch_first
)
1180 emit_if (false_label
, negop
, op
, state
);
1181 emit_goto (true_label
, state
);
1185 emit_if (true_label
, op
, negop
, state
);
1186 emit_goto (false_label
, state
);
1190 op
= OPCODE_if_icmpeq
;
1193 op
= OPCODE_if_icmpne
;
1196 op
= OPCODE_if_icmpgt
;
1199 op
= OPCODE_if_icmplt
;
1202 op
= OPCODE_if_icmpge
;
1205 op
= OPCODE_if_icmple
;
1208 exp0
= TREE_OPERAND (exp
, 0);
1209 exp1
= TREE_OPERAND (exp
, 1);
1210 type
= TREE_TYPE (exp0
);
1211 switch (TREE_CODE (type
))
1214 case POINTER_TYPE
: case RECORD_TYPE
:
1215 switch (TREE_CODE (exp
))
1217 case EQ_EXPR
: op
= OPCODE_if_acmpeq
; break;
1218 case NE_EXPR
: op
= OPCODE_if_acmpne
; break;
1221 if (integer_zerop (exp1
) || integer_zerop (exp0
))
1223 generate_bytecode_insns (integer_zerop (exp1
) ? exp0
: exp0
,
1224 STACK_TARGET
, state
);
1225 op
= op
+ (OPCODE_ifnull
- OPCODE_if_acmpeq
);
1226 negop
= (op
& 1) ? op
- 1 : op
+ 1;
1230 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1231 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1235 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1236 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1237 if (op
== OPCODE_if_icmplt
|| op
== OPCODE_if_icmple
)
1241 if (TYPE_PRECISION (type
) > 32)
1252 if (TYPE_PRECISION (type
) > 32)
1254 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1255 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1263 if (integer_zerop (exp1
))
1265 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1269 if (integer_zerop (exp0
))
1273 case OPCODE_if_icmplt
:
1274 case OPCODE_if_icmpge
:
1277 case OPCODE_if_icmpgt
:
1278 case OPCODE_if_icmple
:
1284 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1288 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1289 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1295 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1297 if (true_branch_first
)
1299 emit_if (false_label
, OPCODE_ifeq
, OPCODE_ifne
, state
);
1300 emit_goto (true_label
, state
);
1304 emit_if (true_label
, OPCODE_ifne
, OPCODE_ifeq
, state
);
1305 emit_goto (false_label
, state
);
1309 if (save_SP
!= state
->code_SP
)
1310 fatal ("internal error - SP mismatch");
1313 /* Call pending cleanups i.e. those for surrounding CLEANUP_POINT_EXPRs
1314 but only as far out as LIMIT (since we are about to jump to the
1315 emit label that is LIMIT). */
1318 call_cleanups (limit
, state
)
1319 struct jcf_block
*limit
;
1320 struct jcf_partial
*state
;
1322 struct jcf_block
*block
= state
->labeled_blocks
;
1323 for (; block
!= limit
; block
= block
->next
)
1325 if (block
->pc
== PENDING_CLEANUP_PC
)
1326 emit_jsr (block
, state
);
1331 generate_bytecode_return (exp
, state
)
1333 struct jcf_partial
*state
;
1335 tree return_type
= TREE_TYPE (TREE_TYPE (state
->current_method
));
1336 int returns_void
= TREE_CODE (return_type
) == VOID_TYPE
;
1341 switch (TREE_CODE (exp
))
1344 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
,
1346 exp
= TREE_OPERAND (exp
, 1);
1350 struct jcf_block
*then_label
= gen_jcf_label (state
);
1351 struct jcf_block
*else_label
= gen_jcf_label (state
);
1352 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1353 then_label
, else_label
, 1, state
);
1354 define_jcf_label (then_label
, state
);
1355 generate_bytecode_return (TREE_OPERAND (exp
, 1), state
);
1356 define_jcf_label (else_label
, state
);
1357 generate_bytecode_return (TREE_OPERAND (exp
, 2), state
);
1361 generate_bytecode_insns (exp
,
1362 returns_void
? IGNORE_TARGET
1363 : STACK_TARGET
, state
);
1369 call_cleanups (NULL_PTR
, state
);
1373 op
= OPCODE_ireturn
+ adjust_typed_op (return_type
, 4);
1374 if (state
->num_finalizers
> 0)
1376 if (state
->return_value_decl
== NULL_TREE
)
1378 state
->return_value_decl
1379 = build_decl (VAR_DECL
, NULL_TREE
, TREE_TYPE (exp
));
1380 localvar_alloc (state
->return_value_decl
, state
);
1382 emit_store (state
->return_value_decl
, state
);
1383 call_cleanups (NULL_PTR
, state
);
1384 emit_load (state
->return_value_decl
, state
);
1385 /* If we call localvar_free (state->return_value_decl, state),
1386 then we risk the save decl erroneously re-used in the
1387 finalizer. Instead, we keep the state->return_value_decl
1388 allocated through the rest of the method. This is not
1389 the greatest solution, but it is at least simple and safe. */
1396 /* Generate bytecode for sub-expression EXP of METHOD.
1397 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1400 generate_bytecode_insns (exp
, target
, state
)
1403 struct jcf_partial
*state
;
1406 enum java_opcode jopcode
;
1408 HOST_WIDE_INT value
;
1413 if (exp
== NULL
&& target
== IGNORE_TARGET
)
1416 type
= TREE_TYPE (exp
);
1418 switch (TREE_CODE (exp
))
1421 if (BLOCK_EXPR_BODY (exp
))
1424 tree body
= BLOCK_EXPR_BODY (exp
);
1425 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1427 tree next
= TREE_CHAIN (local
);
1428 localvar_alloc (local
, state
);
1431 /* Avoid deep recursion for long blocks. */
1432 while (TREE_CODE (body
) == COMPOUND_EXPR
)
1434 generate_bytecode_insns (TREE_OPERAND (body
, 0), target
, state
);
1435 body
= TREE_OPERAND (body
, 1);
1437 generate_bytecode_insns (body
, target
, state
);
1438 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1440 tree next
= TREE_CHAIN (local
);
1441 localvar_free (local
, state
);
1447 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
1448 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1450 case EXPR_WITH_FILE_LOCATION
:
1452 char *saved_input_filename
= input_filename
;
1453 tree body
= EXPR_WFL_NODE (exp
);
1454 int saved_lineno
= lineno
;
1455 if (body
== empty_stmt_node
)
1457 input_filename
= EXPR_WFL_FILENAME (exp
);
1458 lineno
= EXPR_WFL_LINENO (exp
);
1459 if (EXPR_WFL_EMIT_LINE_NOTE (exp
) && lineno
> 0
1460 && debug_info_level
> DINFO_LEVEL_NONE
)
1461 put_linenumber (lineno
, state
);
1462 generate_bytecode_insns (body
, target
, state
);
1463 input_filename
= saved_input_filename
;
1464 lineno
= saved_lineno
;
1468 if (target
== IGNORE_TARGET
) ; /* do nothing */
1469 else if (TREE_CODE (type
) == POINTER_TYPE
)
1471 if (! integer_zerop (exp
))
1474 OP1 (OPCODE_aconst_null
);
1477 else if (TYPE_PRECISION (type
) <= 32)
1479 push_int_const (TREE_INT_CST_LOW (exp
), state
);
1484 push_long_const (TREE_INT_CST_LOW (exp
), TREE_INT_CST_HIGH (exp
),
1491 int prec
= TYPE_PRECISION (type
) >> 5;
1493 if (real_zerop (exp
))
1494 OP1 (prec
== 1 ? OPCODE_fconst_0
: OPCODE_dconst_0
);
1495 else if (real_onep (exp
))
1496 OP1 (prec
== 1 ? OPCODE_fconst_1
: OPCODE_dconst_1
);
1497 /* FIXME Should also use fconst_2 for 2.0f.
1498 Also, should use iconst_2/ldc followed by i2f/i2d
1499 for other float/double when the value is a small integer. */
1502 offset
= find_constant_index (exp
, state
);
1504 push_constant1 (offset
, state
);
1506 push_constant2 (offset
, state
);
1512 push_constant1 (find_string_constant (&state
->cpool
, exp
), state
);
1516 if (TREE_STATIC (exp
))
1518 field_op (exp
, OPCODE_getstatic
, state
);
1519 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1522 /* ... fall through ... */
1524 emit_load (exp
, state
);
1526 case NON_LVALUE_EXPR
:
1528 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1531 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1532 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1533 if (target
!= IGNORE_TARGET
)
1535 jopcode
= OPCODE_iaload
+ adjust_typed_op (type
, 7);
1538 if (! TYPE_IS_WIDE (type
))
1544 tree obj
= TREE_OPERAND (exp
, 0);
1545 tree field
= TREE_OPERAND (exp
, 1);
1546 int is_static
= FIELD_STATIC (field
);
1547 generate_bytecode_insns (obj
,
1548 is_static
? IGNORE_TARGET
: target
, state
);
1549 if (target
!= IGNORE_TARGET
)
1551 if (DECL_NAME (field
) == length_identifier_node
&& !is_static
1552 && TYPE_ARRAY_P (TREE_TYPE (obj
)))
1555 OP1 (OPCODE_arraylength
);
1559 field_op (field
, is_static
? OPCODE_getstatic
: OPCODE_getfield
,
1563 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1568 case TRUTH_ANDIF_EXPR
:
1569 case TRUTH_ORIF_EXPR
:
1577 struct jcf_block
*then_label
= gen_jcf_label (state
);
1578 struct jcf_block
*else_label
= gen_jcf_label (state
);
1579 struct jcf_block
*end_label
= gen_jcf_label (state
);
1580 generate_bytecode_conditional (exp
,
1581 then_label
, else_label
, 1, state
);
1582 define_jcf_label (then_label
, state
);
1583 push_int_const (1, state
);
1584 emit_goto (end_label
, state
);
1585 define_jcf_label (else_label
, state
);
1586 push_int_const (0, state
);
1587 define_jcf_label (end_label
, state
);
1593 struct jcf_block
*then_label
= gen_jcf_label (state
);
1594 struct jcf_block
*else_label
= gen_jcf_label (state
);
1595 struct jcf_block
*end_label
= gen_jcf_label (state
);
1596 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1597 then_label
, else_label
, 1, state
);
1598 define_jcf_label (then_label
, state
);
1599 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1600 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 1))
1601 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1602 || TREE_CODE (TREE_TYPE (exp
)) != VOID_TYPE
)
1603 emit_goto (end_label
, state
);
1604 define_jcf_label (else_label
, state
);
1605 generate_bytecode_insns (TREE_OPERAND (exp
, 2), target
, state
);
1606 define_jcf_label (end_label
, state
);
1611 struct jcf_switch_state
*sw_state
= state
->sw_state
;
1612 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
1613 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1614 HOST_WIDE_INT case_value
= TREE_INT_CST_LOW (TREE_OPERAND (exp
, 0));
1616 reloc
->label
= get_jcf_label_here (state
);
1617 reloc
->offset
= case_value
;
1618 reloc
->next
= sw_state
->cases
;
1619 sw_state
->cases
= reloc
;
1620 if (sw_state
->num_cases
== 0)
1622 sw_state
->min_case
= case_value
;
1623 sw_state
->max_case
= case_value
;
1627 if (case_value
< sw_state
->min_case
)
1628 sw_state
->min_case
= case_value
;
1629 if (case_value
> sw_state
->max_case
)
1630 sw_state
->max_case
= case_value
;
1632 sw_state
->num_cases
++;
1636 state
->sw_state
->default_label
= get_jcf_label_here (state
);
1641 /* The SWITCH_EXPR has three parts, generated in the following order:
1642 1. the switch_expression (the value used to select the correct case);
1644 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1645 After code generation, we will re-order then in the order 1, 3, 2.
1646 This is to avoid an extra GOTOs. */
1647 struct jcf_switch_state sw_state
;
1648 struct jcf_block
*expression_last
; /* Last block of the switch_expression. */
1649 struct jcf_block
*body_last
; /* Last block of the switch_body. */
1650 struct jcf_block
*switch_instruction
; /* First block of switch_instruction. */
1651 struct jcf_block
*instruction_last
; /* Last block of the switch_instruction. */
1652 struct jcf_block
*body_block
;
1654 sw_state
.prev
= state
->sw_state
;
1655 state
->sw_state
= &sw_state
;
1656 sw_state
.cases
= NULL
;
1657 sw_state
.num_cases
= 0;
1658 sw_state
.default_label
= NULL
;
1659 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1660 expression_last
= state
->last_block
;
1661 body_block
= get_jcf_label_here (state
); /* Force a new block here. */
1662 generate_bytecode_insns (TREE_OPERAND (exp
, 1), IGNORE_TARGET
, state
);
1663 body_last
= state
->last_block
;
1665 switch_instruction
= gen_jcf_label (state
);
1666 define_jcf_label (switch_instruction
, state
);
1667 if (sw_state
.default_label
== NULL
)
1668 sw_state
.default_label
= gen_jcf_label (state
);
1670 if (sw_state
.num_cases
<= 1)
1672 if (sw_state
.num_cases
== 0)
1674 emit_pop (1, state
);
1679 push_int_const (sw_state
.cases
->offset
, state
);
1680 emit_if (sw_state
.cases
->label
,
1681 OPCODE_ifeq
, OPCODE_ifne
, state
);
1683 emit_goto (sw_state
.default_label
, state
);
1688 /* Copy the chain of relocs into a sorted array. */
1689 struct jcf_relocation
**relocs
= (struct jcf_relocation
**)
1690 xmalloc (sw_state
.num_cases
* sizeof (struct jcf_relocation
*));
1691 /* The relocs arrays is a buffer with a gap.
1692 The assumption is that cases will normally come in "runs". */
1694 int gap_end
= sw_state
.num_cases
;
1695 struct jcf_relocation
*reloc
;
1696 for (reloc
= sw_state
.cases
; reloc
!= NULL
; reloc
= reloc
->next
)
1698 HOST_WIDE_INT case_value
= reloc
->offset
;
1699 while (gap_end
< sw_state
.num_cases
)
1701 struct jcf_relocation
*end
= relocs
[gap_end
];
1702 if (case_value
<= end
->offset
)
1704 relocs
[gap_start
++] = end
;
1707 while (gap_start
> 0)
1709 struct jcf_relocation
*before
= relocs
[gap_start
-1];
1710 if (case_value
>= before
->offset
)
1712 relocs
[--gap_end
] = before
;
1715 relocs
[gap_start
++] = reloc
;
1716 /* Note we don't check for duplicates. FIXME! */
1719 if (2 * sw_state
.num_cases
1720 >= sw_state
.max_case
- sw_state
.min_case
)
1721 { /* Use tableswitch. */
1723 RESERVE (13 + 4 * (sw_state
.max_case
- sw_state
.min_case
+ 1));
1724 OP1 (OPCODE_tableswitch
);
1725 emit_reloc (0, SWITCH_ALIGN_RELOC
, NULL
, state
);
1726 emit_switch_reloc (sw_state
.default_label
, state
);
1727 OP4 (sw_state
.min_case
);
1728 OP4 (sw_state
.max_case
);
1729 for (i
= sw_state
.min_case
; ; )
1731 reloc
= relocs
[index
];
1732 if (i
== reloc
->offset
)
1734 emit_case_reloc (reloc
, state
);
1735 if (i
== sw_state
.max_case
)
1740 emit_switch_reloc (sw_state
.default_label
, state
);
1745 { /* Use lookupswitch. */
1746 RESERVE(9 + 8 * sw_state
.num_cases
);
1747 OP1 (OPCODE_lookupswitch
);
1748 emit_reloc (0, SWITCH_ALIGN_RELOC
, NULL
, state
);
1749 emit_switch_reloc (sw_state
.default_label
, state
);
1750 OP4 (sw_state
.num_cases
);
1751 for (i
= 0; i
< sw_state
.num_cases
; i
++)
1753 struct jcf_relocation
*reloc
= relocs
[i
];
1754 OP4 (reloc
->offset
);
1755 emit_case_reloc (reloc
, state
);
1761 instruction_last
= state
->last_block
;
1762 if (sw_state
.default_label
->pc
< 0)
1763 define_jcf_label (sw_state
.default_label
, state
);
1764 else /* Force a new block. */
1765 sw_state
.default_label
= get_jcf_label_here (state
);
1766 /* Now re-arrange the blocks so the switch_instruction
1767 comes before the switch_body. */
1768 switch_length
= state
->code_length
- switch_instruction
->pc
;
1769 switch_instruction
->pc
= body_block
->pc
;
1770 instruction_last
->next
= body_block
;
1771 instruction_last
->v
.chunk
->next
= body_block
->v
.chunk
;
1772 expression_last
->next
= switch_instruction
;
1773 expression_last
->v
.chunk
->next
= switch_instruction
->v
.chunk
;
1774 body_last
->next
= sw_state
.default_label
;
1775 body_last
->v
.chunk
->next
= NULL
;
1776 state
->chunk
= body_last
->v
.chunk
;
1777 for (; body_block
!= sw_state
.default_label
; body_block
= body_block
->next
)
1778 body_block
->pc
+= switch_length
;
1780 state
->sw_state
= sw_state
.prev
;
1785 exp
= TREE_OPERAND (exp
, 0);
1786 if (exp
== NULL_TREE
)
1787 exp
= empty_stmt_node
;
1788 else if (TREE_CODE (exp
) != MODIFY_EXPR
)
1791 exp
= TREE_OPERAND (exp
, 1);
1792 generate_bytecode_return (exp
, state
);
1794 case LABELED_BLOCK_EXPR
:
1796 struct jcf_block
*end_label
= gen_jcf_label (state
);
1797 end_label
->next
= state
->labeled_blocks
;
1798 state
->labeled_blocks
= end_label
;
1799 end_label
->pc
= PENDING_EXIT_PC
;
1800 end_label
->u
.labeled_block
= exp
;
1801 if (LABELED_BLOCK_BODY (exp
))
1802 generate_bytecode_insns (LABELED_BLOCK_BODY (exp
), target
, state
);
1803 if (state
->labeled_blocks
!= end_label
)
1805 state
->labeled_blocks
= end_label
->next
;
1806 define_jcf_label (end_label
, state
);
1811 tree body
= TREE_OPERAND (exp
, 0);
1813 if (TREE_CODE (body
) == COMPOUND_EXPR
1814 && TREE_CODE (TREE_OPERAND (body
, 0)) == EXIT_EXPR
)
1816 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1817 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1818 struct jcf_block
*head_label
;
1819 struct jcf_block
*body_label
;
1820 struct jcf_block
*end_label
= gen_jcf_label (state
);
1821 struct jcf_block
*exit_label
= state
->labeled_blocks
;
1822 head_label
= gen_jcf_label (state
);
1823 emit_goto (head_label
, state
);
1824 body_label
= get_jcf_label_here (state
);
1825 generate_bytecode_insns (TREE_OPERAND (body
, 1), target
, state
);
1826 define_jcf_label (head_label
, state
);
1827 generate_bytecode_conditional (TREE_OPERAND (body
, 0),
1828 end_label
, body_label
, 1, state
);
1829 define_jcf_label (end_label
, state
);
1834 struct jcf_block
*head_label
= get_jcf_label_here (state
);
1835 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1836 emit_goto (head_label
, state
);
1842 struct jcf_block
*label
= state
->labeled_blocks
;
1843 struct jcf_block
*end_label
= gen_jcf_label (state
);
1844 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1845 label
, end_label
, 0, state
);
1846 define_jcf_label (end_label
, state
);
1849 case EXIT_BLOCK_EXPR
:
1851 struct jcf_block
*label
= state
->labeled_blocks
;
1852 if (TREE_OPERAND (exp
, 1) != NULL
) goto notimpl
;
1853 while (label
->u
.labeled_block
!= TREE_OPERAND (exp
, 0))
1854 label
= label
->next
;
1855 call_cleanups (label
, state
);
1856 emit_goto (label
, state
);
1860 case PREDECREMENT_EXPR
: value
= -1; post_op
= 0; goto increment
;
1861 case PREINCREMENT_EXPR
: value
= 1; post_op
= 0; goto increment
;
1862 case POSTDECREMENT_EXPR
: value
= -1; post_op
= 1; goto increment
;
1863 case POSTINCREMENT_EXPR
: value
= 1; post_op
= 1; goto increment
;
1866 exp
= TREE_OPERAND (exp
, 0);
1867 type
= TREE_TYPE (exp
);
1868 size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1869 if ((TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1870 && ! TREE_STATIC (exp
)
1871 && TREE_CODE (type
) == INTEGER_TYPE
1872 && TYPE_PRECISION (type
) == 32)
1874 if (target
!= IGNORE_TARGET
&& post_op
)
1875 emit_load (exp
, state
);
1876 emit_iinc (exp
, value
, state
);
1877 if (target
!= IGNORE_TARGET
&& ! post_op
)
1878 emit_load (exp
, state
);
1881 if (TREE_CODE (exp
) == COMPONENT_REF
)
1883 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1884 emit_dup (1, 0, state
);
1885 /* Stack: ..., objectref, objectref. */
1886 field_op (TREE_OPERAND (exp
, 1), OPCODE_getfield
, state
);
1888 /* Stack: ..., objectref, oldvalue. */
1891 else if (TREE_CODE (exp
) == ARRAY_REF
)
1893 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1894 generate_bytecode_insns (TREE_OPERAND (exp
, 1), STACK_TARGET
, state
);
1895 emit_dup (2, 0, state
);
1896 /* Stack: ..., array, index, array, index. */
1897 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (exp
), 7);
1901 /* Stack: ..., array, index, oldvalue. */
1904 else if (TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1906 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1907 /* Stack: ..., oldvalue. */
1913 if (target
!= IGNORE_TARGET
&& post_op
)
1914 emit_dup (size
, offset
, state
);
1915 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1916 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1917 /* Stack, otherwise: ..., [result, ] oldvalue. */
1919 push_int_const (value
, state
);
1921 push_long_const (value
, value
>= 0 ? 0 : -1, state
);
1923 emit_binop (OPCODE_iadd
+ adjust_typed_op (type
, 3), type
, state
);
1924 if (target
!= IGNORE_TARGET
&& ! post_op
)
1925 emit_dup (size
, offset
, state
);
1926 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1927 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1928 /* Stack, otherwise: ..., [result, ] newvalue. */
1929 goto finish_assignment
;
1933 tree lhs
= TREE_OPERAND (exp
, 0);
1934 tree rhs
= TREE_OPERAND (exp
, 1);
1937 /* See if we can use the iinc instruction. */
1938 if ((TREE_CODE (lhs
) == VAR_DECL
|| TREE_CODE (lhs
) == PARM_DECL
)
1939 && ! TREE_STATIC (lhs
)
1940 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
1941 && TYPE_PRECISION (TREE_TYPE (lhs
)) == 32
1942 && (TREE_CODE (rhs
) == PLUS_EXPR
|| TREE_CODE (rhs
) == MINUS_EXPR
))
1944 tree arg0
= TREE_OPERAND (rhs
, 0);
1945 tree arg1
= TREE_OPERAND (rhs
, 1);
1946 HOST_WIDE_INT min_value
= -32768;
1947 HOST_WIDE_INT max_value
= 32767;
1948 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1953 else if (arg1
== lhs
)
1956 arg1
= TREE_OPERAND (rhs
, 0);
1958 if (lhs
== arg0
&& TREE_CODE (arg1
) == INTEGER_CST
)
1960 HOST_WIDE_INT hi_value
= TREE_INT_CST_HIGH (arg1
);
1961 value
= TREE_INT_CST_LOW (arg1
);
1962 if ((hi_value
== 0 && value
<= max_value
)
1963 || (hi_value
== -1 && value
>= min_value
))
1965 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1967 emit_iinc (lhs
, value
, state
);
1973 if (TREE_CODE (lhs
) == COMPONENT_REF
)
1975 generate_bytecode_insns (TREE_OPERAND (lhs
, 0),
1976 STACK_TARGET
, state
);
1979 else if (TREE_CODE (lhs
) == ARRAY_REF
)
1981 generate_bytecode_insns (TREE_OPERAND(lhs
, 0),
1982 STACK_TARGET
, state
);
1983 generate_bytecode_insns (TREE_OPERAND(lhs
, 1),
1984 STACK_TARGET
, state
);
1989 generate_bytecode_insns (rhs
, STACK_TARGET
, state
);
1990 if (target
!= IGNORE_TARGET
)
1991 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1 , offset
, state
);
1997 if (TREE_CODE (exp
) == COMPONENT_REF
)
1999 tree field
= TREE_OPERAND (exp
, 1);
2000 if (! FIELD_STATIC (field
))
2003 FIELD_STATIC (field
) ? OPCODE_putstatic
: OPCODE_putfield
,
2006 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
2008 else if (TREE_CODE (exp
) == VAR_DECL
2009 || TREE_CODE (exp
) == PARM_DECL
)
2011 if (FIELD_STATIC (exp
))
2013 field_op (exp
, OPCODE_putstatic
, state
);
2014 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
2017 emit_store (exp
, state
);
2019 else if (TREE_CODE (exp
) == ARRAY_REF
)
2021 jopcode
= OPCODE_iastore
+ adjust_typed_op (TREE_TYPE (exp
), 7);
2024 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 4 : 3);
2027 fatal ("internal error (bad lhs to MODIFY_EXPR)");
2030 jopcode
= OPCODE_iadd
;
2033 jopcode
= OPCODE_isub
;
2036 jopcode
= OPCODE_imul
;
2038 case TRUNC_DIV_EXPR
:
2040 jopcode
= OPCODE_idiv
;
2042 case TRUNC_MOD_EXPR
:
2043 jopcode
= OPCODE_irem
;
2045 case LSHIFT_EXPR
: jopcode
= OPCODE_ishl
; goto binop
;
2046 case RSHIFT_EXPR
: jopcode
= OPCODE_ishr
; goto binop
;
2047 case URSHIFT_EXPR
: jopcode
= OPCODE_iushr
; goto binop
;
2048 case TRUTH_AND_EXPR
:
2049 case BIT_AND_EXPR
: jopcode
= OPCODE_iand
; goto binop
;
2051 case BIT_IOR_EXPR
: jopcode
= OPCODE_ior
; goto binop
;
2052 case TRUTH_XOR_EXPR
:
2053 case BIT_XOR_EXPR
: jopcode
= OPCODE_ixor
; goto binop
;
2056 tree arg0
= TREE_OPERAND (exp
, 0);
2057 tree arg1
= TREE_OPERAND (exp
, 1);
2058 jopcode
+= adjust_typed_op (type
, 3);
2059 if (arg0
== arg1
&& TREE_CODE (arg0
) == SAVE_EXPR
)
2061 /* fold may (e.g) convert 2*x to x+x. */
2062 generate_bytecode_insns (TREE_OPERAND (arg0
, 0), target
, state
);
2063 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0
)) > 32 ? 2 : 1, 0, state
);
2067 generate_bytecode_insns (arg0
, target
, state
);
2068 generate_bytecode_insns (arg1
, target
, state
);
2070 /* For most binary operations, both operands and the result have the
2071 same type. Shift operations are different. Using arg1's type
2072 gets us the correct SP adjustment in all casesd. */
2073 if (target
== STACK_TARGET
)
2074 emit_binop (jopcode
, TREE_TYPE (arg1
), state
);
2077 case TRUTH_NOT_EXPR
:
2079 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2080 if (target
== STACK_TARGET
)
2082 int is_long
= TYPE_PRECISION (TREE_TYPE (exp
)) > 32;
2083 push_int_const (TREE_CODE (exp
) == BIT_NOT_EXPR
? -1 : 1, state
);
2087 NOTE_PUSH (1 + is_long
);
2088 OP1 (OPCODE_ixor
+ is_long
);
2089 NOTE_POP (1 + is_long
);
2093 jopcode
= OPCODE_ineg
;
2094 jopcode
+= adjust_typed_op (type
, 3);
2095 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2096 if (target
== STACK_TARGET
)
2097 emit_unop (jopcode
, type
, state
);
2099 case INSTANCEOF_EXPR
:
2101 int index
= find_class_constant (&state
->cpool
, TREE_OPERAND (exp
, 1));
2102 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2104 OP1 (OPCODE_instanceof
);
2111 case FIX_TRUNC_EXPR
:
2113 tree src
= TREE_OPERAND (exp
, 0);
2114 tree src_type
= TREE_TYPE (src
);
2115 tree dst_type
= TREE_TYPE (exp
);
2116 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
2117 if (target
== IGNORE_TARGET
|| src_type
== dst_type
)
2119 if (TREE_CODE (dst_type
) == POINTER_TYPE
)
2121 if (TREE_CODE (exp
) == CONVERT_EXPR
)
2123 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (dst_type
));
2125 OP1 (OPCODE_checkcast
);
2129 else /* Convert numeric types. */
2131 int wide_src
= TYPE_PRECISION (src_type
) > 32;
2132 int wide_dst
= TYPE_PRECISION (dst_type
) > 32;
2133 NOTE_POP (1 + wide_src
);
2135 if (TREE_CODE (dst_type
) == REAL_TYPE
)
2137 if (TREE_CODE (src_type
) == REAL_TYPE
)
2138 OP1 (wide_dst
? OPCODE_f2d
: OPCODE_d2f
);
2139 else if (TYPE_PRECISION (src_type
) == 64)
2140 OP1 (OPCODE_l2f
+ wide_dst
);
2142 OP1 (OPCODE_i2f
+ wide_dst
);
2144 else /* Convert to integral type. */
2146 if (TREE_CODE (src_type
) == REAL_TYPE
)
2147 OP1 (OPCODE_f2i
+ wide_dst
+ 3 * wide_src
);
2152 if (TYPE_PRECISION (dst_type
) < 32)
2155 /* Already converted to int, if needed. */
2156 if (TYPE_PRECISION (dst_type
) <= 8)
2158 else if (TREE_UNSIGNED (dst_type
))
2164 NOTE_PUSH (1 + wide_dst
);
2169 case CLEANUP_POINT_EXPR
:
2171 struct jcf_block
*save_labeled_blocks
= state
->labeled_blocks
;
2172 int can_complete
= CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 0));
2173 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
2174 if (target
!= IGNORE_TARGET
)
2176 while (state
->labeled_blocks
!= save_labeled_blocks
)
2178 struct jcf_block
*finished_label
= NULL
;
2180 tree exception_type
= build_pointer_type (throwable_type_node
);
2181 tree exception_decl
= build_decl (VAR_DECL
, NULL_TREE
,
2183 struct jcf_block
*end_label
= get_jcf_label_here (state
);
2184 struct jcf_block
*label
= state
->labeled_blocks
;
2185 struct jcf_handler
*handler
;
2186 tree cleanup
= label
->u
.labeled_block
;
2187 state
->labeled_blocks
= label
->next
;
2188 state
->num_finalizers
--;
2191 finished_label
= gen_jcf_label (state
);
2192 emit_jsr (label
, state
);
2193 emit_goto (finished_label
, state
);
2194 if (! CAN_COMPLETE_NORMALLY (cleanup
))
2197 handler
= alloc_handler (label
->v
.start_label
, end_label
, state
);
2198 handler
->type
= NULL_TREE
;
2199 localvar_alloc (exception_decl
, state
);
2201 emit_store (exception_decl
, state
);
2202 emit_jsr (label
, state
);
2203 emit_load (exception_decl
, state
);
2205 OP1 (OPCODE_athrow
);
2208 /* The finally block. */
2209 return_link
= build_decl (VAR_DECL
, NULL_TREE
,
2210 return_address_type_node
);
2211 define_jcf_label (label
, state
);
2213 localvar_alloc (return_link
, state
);
2214 emit_store (return_link
, state
);
2215 generate_bytecode_insns (cleanup
, IGNORE_TARGET
, state
);
2216 maybe_wide (OPCODE_ret
, DECL_LOCAL_INDEX (return_link
), state
);
2217 localvar_free (return_link
, state
);
2218 localvar_free (exception_decl
, state
);
2219 if (finished_label
!= NULL
)
2220 define_jcf_label (finished_label
, state
);
2225 case WITH_CLEANUP_EXPR
:
2227 struct jcf_block
*label
;
2228 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
2229 label
= gen_jcf_label (state
);
2230 label
->pc
= PENDING_CLEANUP_PC
;
2231 label
->next
= state
->labeled_blocks
;
2232 state
->labeled_blocks
= label
;
2233 state
->num_finalizers
++;
2234 label
->u
.labeled_block
= TREE_OPERAND (exp
, 2);
2235 label
->v
.start_label
= get_jcf_label_here (state
);
2236 if (target
!= IGNORE_TARGET
)
2243 tree try_clause
= TREE_OPERAND (exp
, 0);
2244 struct jcf_block
*start_label
= get_jcf_label_here (state
);
2245 struct jcf_block
*end_label
; /* End of try clause. */
2246 struct jcf_block
*finished_label
= gen_jcf_label (state
);
2247 tree clause
= TREE_OPERAND (exp
, 1);
2248 if (target
!= IGNORE_TARGET
)
2250 generate_bytecode_insns (try_clause
, IGNORE_TARGET
, state
);
2251 end_label
= get_jcf_label_here (state
);
2252 if (CAN_COMPLETE_NORMALLY (try_clause
))
2253 emit_goto (finished_label
, state
);
2254 while (clause
!= NULL_TREE
)
2256 tree catch_clause
= TREE_OPERAND (clause
, 0);
2257 tree exception_decl
= BLOCK_EXPR_DECLS (catch_clause
);
2258 struct jcf_handler
*handler
= alloc_handler (start_label
, end_label
, state
);
2259 if (exception_decl
== NULL_TREE
)
2260 handler
->type
= NULL_TREE
;
2262 handler
->type
= TREE_TYPE (TREE_TYPE (exception_decl
));
2263 generate_bytecode_insns (catch_clause
, IGNORE_TARGET
, state
);
2264 clause
= TREE_CHAIN (clause
);
2265 if (CAN_COMPLETE_NORMALLY (catch_clause
) && clause
!= NULL_TREE
)
2266 emit_goto (finished_label
, state
);
2268 define_jcf_label (finished_label
, state
);
2271 case TRY_FINALLY_EXPR
:
2273 tree try_block
= TREE_OPERAND (exp
, 0);
2274 tree finally
= TREE_OPERAND (exp
, 1);
2275 struct jcf_block
*finished_label
= gen_jcf_label (state
);
2276 struct jcf_block
*finally_label
= gen_jcf_label (state
);
2277 struct jcf_block
*start_label
= get_jcf_label_here (state
);
2278 tree return_link
= build_decl (VAR_DECL
, NULL_TREE
,
2279 return_address_type_node
);
2280 tree exception_type
= build_pointer_type (throwable_type_node
);
2281 tree exception_decl
= build_decl (VAR_DECL
, NULL_TREE
, exception_type
);
2282 struct jcf_handler
*handler
;
2284 finally_label
->pc
= PENDING_CLEANUP_PC
;
2285 finally_label
->next
= state
->labeled_blocks
;
2286 state
->labeled_blocks
= finally_label
;
2287 state
->num_finalizers
++;
2289 generate_bytecode_insns (try_block
, target
, state
);
2290 if (state
->labeled_blocks
!= finally_label
)
2292 state
->labeled_blocks
= finally_label
->next
;
2293 emit_jsr (finally_label
, state
);
2294 if (CAN_COMPLETE_NORMALLY (try_block
))
2295 emit_goto (finished_label
, state
);
2297 /* Handle exceptions. */
2298 localvar_alloc (return_link
, state
);
2299 handler
= alloc_handler (start_label
, NULL_PTR
, state
);
2300 handler
->end_label
= handler
->handler_label
;
2301 handler
->type
= NULL_TREE
;
2302 localvar_alloc (exception_decl
, state
);
2304 emit_store (exception_decl
, state
);
2305 emit_jsr (finally_label
, state
);
2306 emit_load (exception_decl
, state
);
2308 OP1 (OPCODE_athrow
);
2310 localvar_free (exception_decl
, state
);
2312 /* The finally block. First save return PC into return_link. */
2313 define_jcf_label (finally_label
, state
);
2315 emit_store (return_link
, state
);
2317 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
2318 maybe_wide (OPCODE_ret
, DECL_LOCAL_INDEX (return_link
), state
);
2319 localvar_free (return_link
, state
);
2320 define_jcf_label (finished_label
, state
);
2324 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
2326 OP1 (OPCODE_athrow
);
2328 case NEW_ARRAY_INIT
:
2330 tree values
= CONSTRUCTOR_ELTS (TREE_OPERAND (exp
, 0));
2331 tree array_type
= TREE_TYPE (TREE_TYPE (exp
));
2332 tree element_type
= TYPE_ARRAY_ELEMENT (array_type
);
2333 HOST_WIDE_INT length
= java_array_type_length (array_type
);
2334 if (target
== IGNORE_TARGET
)
2336 for ( ; values
!= NULL_TREE
; values
= TREE_CHAIN (values
))
2337 generate_bytecode_insns (TREE_VALUE (values
), target
, state
);
2340 push_int_const (length
, state
);
2343 if (JPRIMITIVE_TYPE_P (element_type
))
2345 int atype
= encode_newarray_type (element_type
);
2346 OP1 (OPCODE_newarray
);
2351 int index
= find_class_constant (&state
->cpool
,
2352 TREE_TYPE (element_type
));
2353 OP1 (OPCODE_anewarray
);
2357 jopcode
= OPCODE_iastore
+ adjust_typed_op (element_type
, 7);
2358 for ( ; values
!= NULL_TREE
; values
= TREE_CHAIN (values
), offset
++)
2360 int save_SP
= state
->code_SP
;
2361 emit_dup (1, 0, state
);
2362 push_int_const (offset
, state
);
2364 generate_bytecode_insns (TREE_VALUE (values
), STACK_TARGET
, state
);
2367 state
->code_SP
= save_SP
;
2371 case NEW_CLASS_EXPR
:
2373 tree
class = TREE_TYPE (TREE_TYPE (exp
));
2374 int need_result
= target
!= IGNORE_TARGET
;
2375 int index
= find_class_constant (&state
->cpool
, class);
2381 NOTE_PUSH (1 + need_result
);
2383 /* ... fall though ... */
2386 tree f
= TREE_OPERAND (exp
, 0);
2387 tree x
= TREE_OPERAND (exp
, 1);
2388 int save_SP
= state
->code_SP
;
2390 if (TREE_CODE (f
) == ADDR_EXPR
)
2391 f
= TREE_OPERAND (f
, 0);
2392 if (f
== soft_newarray_node
)
2394 int type_code
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2395 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x
)),
2396 STACK_TARGET
, state
);
2398 OP1 (OPCODE_newarray
);
2402 else if (f
== soft_multianewarray_node
)
2406 int index
= find_class_constant (&state
->cpool
,
2407 TREE_TYPE (TREE_TYPE (exp
)));
2408 x
= TREE_CHAIN (x
); /* Skip class argument. */
2409 ndims
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2410 for (idim
= ndims
; --idim
>= 0; )
2413 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2416 OP1 (OPCODE_multianewarray
);
2421 else if (f
== soft_anewarray_node
)
2423 tree cl
= TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp
)));
2424 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (cl
));
2425 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2427 OP1 (OPCODE_anewarray
);
2431 else if (f
== soft_monitorenter_node
2432 || f
== soft_monitorexit_node
2435 if (f
== soft_monitorenter_node
)
2436 op
= OPCODE_monitorenter
;
2437 else if (f
== soft_monitorexit_node
)
2438 op
= OPCODE_monitorexit
;
2441 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2447 else if (exp
== soft_exceptioninfo_call_node
)
2449 NOTE_PUSH (1); /* Pushed by exception system. */
2452 for ( ; x
!= NULL_TREE
; x
= TREE_CHAIN (x
))
2454 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2456 nargs
= state
->code_SP
- save_SP
;
2457 state
->code_SP
= save_SP
;
2458 if (f
== soft_fmod_node
)
2465 if (TREE_CODE (exp
) == NEW_CLASS_EXPR
)
2466 NOTE_POP (1); /* Pop implicit this. */
2467 if (TREE_CODE (f
) == FUNCTION_DECL
&& DECL_CONTEXT (f
) != NULL_TREE
)
2469 int index
= find_methodref_index (&state
->cpool
, f
);
2472 if (METHOD_STATIC (f
))
2473 OP1 (OPCODE_invokestatic
);
2474 else if (DECL_CONSTRUCTOR_P (f
) || CALL_USING_SUPER (exp
)
2475 || METHOD_PRIVATE (f
))
2476 OP1 (OPCODE_invokespecial
);
2477 else if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (f
))))
2479 OP1 (OPCODE_invokeinterface
);
2483 OP1 (OPCODE_invokevirtual
);
2485 f
= TREE_TYPE (TREE_TYPE (f
));
2486 if (TREE_CODE (f
) != VOID_TYPE
)
2488 int size
= TYPE_IS_WIDE (f
) ? 2 : 1;
2489 if (target
== IGNORE_TARGET
)
2490 emit_pop (size
, state
);
2505 error("internal error - tree code not implemented: %s",
2506 tree_code_name
[(int) TREE_CODE (exp
)]);
2511 perform_relocations (state
)
2512 struct jcf_partial
*state
;
2514 struct jcf_block
*block
;
2515 struct jcf_relocation
*reloc
;
2519 /* Before we start, the pc field of each block is an upper bound on
2520 the block's start pc (it may be less, if previous blocks need less
2521 than their maximum).
2523 The minimum size of each block is in the block's chunk->size. */
2525 /* First, figure out the actual locations of each block. */
2528 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2530 int block_size
= block
->v
.chunk
->size
;
2534 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2535 Assumes relocations are in reverse order. */
2536 reloc
= block
->u
.relocations
;
2537 while (reloc
!= NULL
2538 && reloc
->kind
== OPCODE_goto_w
2539 && reloc
->label
->pc
== block
->next
->pc
2540 && reloc
->offset
+ 2 == block_size
)
2542 reloc
= reloc
->next
;
2543 block
->u
.relocations
= reloc
;
2544 block
->v
.chunk
->size
-= 3;
2549 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
2551 if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2553 /* We assume this is the first relocation in this block,
2554 so we know its final pc. */
2555 int where
= pc
+ reloc
->offset
;
2556 int pad
= ((where
+ 3) & ~3) - where
;
2559 else if (reloc
->kind
< -1 || reloc
->kind
> BLOCK_START_RELOC
)
2561 int delta
= reloc
->label
->pc
- (pc
+ reloc
->offset
- 1);
2562 int expand
= reloc
->kind
> 0 ? 2 : 5;
2566 if (delta
>= -32768 && delta
<= 32767)
2572 block_size
+= expand
;
2578 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2580 struct chunk
*chunk
= block
->v
.chunk
;
2581 int old_size
= chunk
->size
;
2582 int next_pc
= block
->next
== NULL
? pc
: block
->next
->pc
;
2583 int new_size
= next_pc
- block
->pc
;
2584 unsigned char *new_ptr
;
2585 unsigned char *old_buffer
= chunk
->data
;
2586 unsigned char *old_ptr
= old_buffer
+ old_size
;
2587 if (new_size
!= old_size
)
2589 chunk
->data
= (unsigned char *)
2590 obstack_alloc (state
->chunk_obstack
, new_size
);
2591 chunk
->size
= new_size
;
2593 new_ptr
= chunk
->data
+ new_size
;
2595 /* We do the relocations from back to front, because
2596 the relocations are in reverse order. */
2597 for (reloc
= block
->u
.relocations
; ; reloc
= reloc
->next
)
2599 /* new_ptr and old_ptr point into the old and new buffers,
2600 respectively. (If no relocations cause the buffer to
2601 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2602 The bytes at higher adress have been copied and relocations
2603 handled; those at lower addresses remain to process. */
2605 /* Lower old index of piece to be copied with no relocation.
2606 I.e. high index of the first piece that does need relocation. */
2607 int start
= reloc
== NULL
? 0
2608 : reloc
->kind
== SWITCH_ALIGN_RELOC
? reloc
->offset
2609 : (reloc
->kind
== 0 || reloc
->kind
== BLOCK_START_RELOC
)
2611 : reloc
->offset
+ 2;
2614 int n
= (old_ptr
- old_buffer
) - start
;
2618 memcpy (new_ptr
, old_ptr
, n
);
2619 if (old_ptr
== old_buffer
)
2622 new_offset
= new_ptr
- chunk
->data
;
2623 new_offset
-= (reloc
->kind
== -1 ? 2 : 4);
2624 if (reloc
->kind
== 0)
2627 value
= GET_u4 (old_ptr
);
2629 else if (reloc
->kind
== BLOCK_START_RELOC
)
2635 else if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2637 int where
= block
->pc
+ reloc
->offset
;
2638 int pad
= ((where
+ 3) & ~3) - where
;
2646 value
= GET_u2 (old_ptr
);
2648 value
+= reloc
->label
->pc
- (block
->pc
+ new_offset
);
2649 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2650 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2651 if (reloc
->kind
!= -1)
2653 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2654 *--new_ptr
= (unsigned char) value
;
2656 if (reloc
->kind
> BLOCK_START_RELOC
)
2658 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2660 *--new_ptr
= reloc
->kind
;
2662 else if (reloc
->kind
< -1)
2664 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2666 *--new_ptr
= OPCODE_goto_w
;
2669 *--new_ptr
= - reloc
->kind
;
2672 if (new_ptr
!= chunk
->data
)
2673 fatal ("internal error - perform_relocations");
2675 state
->code_length
= pc
;
2679 init_jcf_state (state
, work
)
2680 struct jcf_partial
*state
;
2681 struct obstack
*work
;
2683 state
->chunk_obstack
= work
;
2684 state
->first
= state
->chunk
= NULL
;
2685 CPOOL_INIT (&state
->cpool
);
2686 BUFFER_INIT (&state
->localvars
);
2687 BUFFER_INIT (&state
->bytecode
);
2691 init_jcf_method (state
, method
)
2692 struct jcf_partial
*state
;
2695 state
->current_method
= method
;
2696 state
->blocks
= state
->last_block
= NULL
;
2697 state
->linenumber_count
= 0;
2698 state
->first_lvar
= state
->last_lvar
= NULL
;
2699 state
->lvar_count
= 0;
2700 state
->labeled_blocks
= NULL
;
2701 state
->code_length
= 0;
2702 BUFFER_RESET (&state
->bytecode
);
2703 BUFFER_RESET (&state
->localvars
);
2705 state
->code_SP_max
= 0;
2706 state
->handlers
= NULL
;
2707 state
->last_handler
= NULL
;
2708 state
->num_handlers
= 0;
2709 state
->num_finalizers
= 0;
2710 state
->return_value_decl
= NULL_TREE
;
2714 release_jcf_state (state
)
2715 struct jcf_partial
*state
;
2717 CPOOL_FINISH (&state
->cpool
);
2718 obstack_free (state
->chunk_obstack
, state
->first
);
2721 /* Generate and return a list of chunks containing the class CLAS
2722 in the .class file representation. The list can be written to a
2723 .class file using write_chunks. Allocate chunks from obstack WORK. */
2725 static struct chunk
*
2726 generate_classfile (clas
, state
)
2728 struct jcf_partial
*state
;
2730 struct chunk
*cpool_chunk
;
2734 char *fields_count_ptr
;
2735 int fields_count
= 0;
2736 char *methods_count_ptr
;
2737 int methods_count
= 0;
2738 static tree SourceFile_node
= NULL_TREE
;
2741 = clas
== object_type_node
? 0
2742 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas
));
2744 ptr
= append_chunk (NULL
, 8, state
);
2745 PUT4 (0xCafeBabe); /* Magic number */
2746 PUT2 (3); /* Minor version */
2747 PUT2 (45); /* Major version */
2749 append_chunk (NULL
, 0, state
);
2750 cpool_chunk
= state
->chunk
;
2752 /* Next allocate the chunk containing acces_flags through fields_counr. */
2753 if (clas
== object_type_node
)
2756 i
= 8 + 2 * total_supers
;
2757 ptr
= append_chunk (NULL
, i
, state
);
2758 i
= get_access_flags (TYPE_NAME (clas
));
2759 if (! (i
& ACC_INTERFACE
))
2761 PUT2 (i
); /* acces_flags */
2762 i
= find_class_constant (&state
->cpool
, clas
); PUT2 (i
); /* this_class */
2763 if (clas
== object_type_node
)
2765 PUT2(0); /* super_class */
2766 PUT2(0); /* interfaces_count */
2770 tree basetypes
= TYPE_BINFO_BASETYPES (clas
);
2771 tree base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, 0));
2772 int j
= find_class_constant (&state
->cpool
, base
);
2773 PUT2 (j
); /* super_class */
2774 PUT2 (total_supers
- 1); /* interfaces_count */
2775 for (i
= 1; i
< total_supers
; i
++)
2777 base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, i
));
2778 j
= find_class_constant (&state
->cpool
, base
);
2782 fields_count_ptr
= ptr
;
2784 for (part
= TYPE_FIELDS (clas
); part
; part
= TREE_CHAIN (part
))
2787 if (DECL_NAME (part
) == NULL_TREE
|| DECL_ARTIFICIAL (part
))
2789 ptr
= append_chunk (NULL
, 8, state
);
2790 i
= get_access_flags (part
); PUT2 (i
);
2791 i
= find_utf8_constant (&state
->cpool
, DECL_NAME (part
)); PUT2 (i
);
2792 i
= find_utf8_constant (&state
->cpool
, build_java_signature (TREE_TYPE (part
)));
2794 have_value
= DECL_INITIAL (part
) != NULL_TREE
&& FIELD_STATIC (part
);
2795 PUT2 (have_value
); /* attributes_count */
2798 tree init
= DECL_INITIAL (part
);
2799 static tree ConstantValue_node
= NULL_TREE
;
2800 ptr
= append_chunk (NULL
, 8, state
);
2801 if (ConstantValue_node
== NULL_TREE
)
2802 ConstantValue_node
= get_identifier ("ConstantValue");
2803 i
= find_utf8_constant (&state
->cpool
, ConstantValue_node
);
2804 PUT2 (i
); /* attribute_name_index */
2805 PUT4 (2); /* attribute_length */
2806 i
= find_constant_index (init
, state
); PUT2 (i
);
2810 ptr
= fields_count_ptr
; PUT2 (fields_count
);
2812 ptr
= methods_count_ptr
= append_chunk (NULL
, 2, state
);
2815 for (part
= TYPE_METHODS (clas
); part
; part
= TREE_CHAIN (part
))
2817 struct jcf_block
*block
;
2818 tree function_body
= DECL_FUNCTION_BODY (part
);
2819 tree body
= function_body
== NULL_TREE
? NULL_TREE
2820 : BLOCK_EXPR_BODY (function_body
);
2821 tree name
= DECL_CONSTRUCTOR_P (part
) ? init_identifier_node
2823 tree type
= TREE_TYPE (part
);
2824 tree save_function
= current_function_decl
;
2825 current_function_decl
= part
;
2826 ptr
= append_chunk (NULL
, 8, state
);
2827 i
= get_access_flags (part
); PUT2 (i
);
2828 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
2829 i
= find_utf8_constant (&state
->cpool
, build_java_signature (type
));
2831 i
= (body
!= NULL_TREE
) + (DECL_FUNCTION_THROWS (part
) != NULL_TREE
);
2832 PUT2 (i
); /* attributes_count */
2833 if (body
!= NULL_TREE
)
2835 int code_attributes_count
= 0;
2836 static tree Code_node
= NULL_TREE
;
2839 struct jcf_handler
*handler
;
2840 if (Code_node
== NULL_TREE
)
2841 Code_node
= get_identifier ("Code");
2842 ptr
= append_chunk (NULL
, 14, state
);
2843 i
= find_utf8_constant (&state
->cpool
, Code_node
); PUT2 (i
);
2845 init_jcf_method (state
, part
);
2846 get_jcf_label_here (state
); /* Force a first block. */
2847 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
2848 localvar_alloc (t
, state
);
2849 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
2850 if (CAN_COMPLETE_NORMALLY (body
))
2852 if (TREE_CODE (TREE_TYPE (type
)) != VOID_TYPE
)
2855 OP1 (OPCODE_return
);
2857 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
2858 localvar_free (t
, state
);
2859 if (state
->return_value_decl
!= NULL_TREE
)
2860 localvar_free (state
->return_value_decl
, state
);
2861 finish_jcf_block (state
);
2862 perform_relocations (state
);
2865 i
= 8 + state
->code_length
+ 4 + 8 * state
->num_handlers
;
2866 if (state
->linenumber_count
> 0)
2868 code_attributes_count
++;
2869 i
+= 8 + 4 * state
->linenumber_count
;
2871 if (state
->lvar_count
> 0)
2873 code_attributes_count
++;
2874 i
+= 8 + 10 * state
->lvar_count
;
2876 PUT4 (i
); /* attribute_length */
2877 PUT2 (state
->code_SP_max
); /* max_stack */
2878 PUT2 (localvar_max
); /* max_locals */
2879 PUT4 (state
->code_length
);
2881 /* Emit the exception table. */
2882 ptr
= append_chunk (NULL
, 2 + 8 * state
->num_handlers
, state
);
2883 PUT2 (state
->num_handlers
); /* exception_table_length */
2884 handler
= state
->handlers
;
2885 for (; handler
!= NULL
; handler
= handler
->next
)
2888 PUT2 (handler
->start_label
->pc
);
2889 PUT2 (handler
->end_label
->pc
);
2890 PUT2 (handler
->handler_label
->pc
);
2891 if (handler
->type
== NULL_TREE
)
2894 type_index
= find_class_constant (&state
->cpool
,
2899 ptr
= append_chunk (NULL
, 2, state
);
2900 PUT2 (code_attributes_count
);
2902 /* Write the LineNumberTable attribute. */
2903 if (state
->linenumber_count
> 0)
2905 static tree LineNumberTable_node
= NULL_TREE
;
2906 ptr
= append_chunk (NULL
, 8 + 4 * state
->linenumber_count
, state
);
2907 if (LineNumberTable_node
== NULL_TREE
)
2908 LineNumberTable_node
= get_identifier ("LineNumberTable");
2909 i
= find_utf8_constant (&state
->cpool
, LineNumberTable_node
);
2910 PUT2 (i
); /* attribute_name_index */
2911 i
= 2+4*state
->linenumber_count
; PUT4(i
); /* attribute_length */
2912 i
= state
->linenumber_count
; PUT2 (i
);
2913 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2915 int line
= block
->linenumber
;
2924 /* Write the LocalVariableTable attribute. */
2925 if (state
->lvar_count
> 0)
2927 static tree LocalVariableTable_node
= NULL_TREE
;
2928 struct localvar_info
*lvar
= state
->first_lvar
;
2929 ptr
= append_chunk (NULL
, 8 + 10 * state
->lvar_count
, state
);
2930 if (LocalVariableTable_node
== NULL_TREE
)
2931 LocalVariableTable_node
= get_identifier("LocalVariableTable");
2932 i
= find_utf8_constant (&state
->cpool
, LocalVariableTable_node
);
2933 PUT2 (i
); /* attribute_name_index */
2934 i
= 2 + 10 * state
->lvar_count
; PUT4 (i
); /* attribute_length */
2935 i
= state
->lvar_count
; PUT2 (i
);
2936 for ( ; lvar
!= NULL
; lvar
= lvar
->next
)
2938 tree name
= DECL_NAME (lvar
->decl
);
2939 tree sig
= build_java_signature (TREE_TYPE (lvar
->decl
));
2940 i
= lvar
->start_label
->pc
; PUT2 (i
);
2941 i
= lvar
->end_label
->pc
- i
; PUT2 (i
);
2942 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
2943 i
= find_utf8_constant (&state
->cpool
, sig
); PUT2 (i
);
2944 i
= DECL_LOCAL_INDEX (lvar
->decl
); PUT2 (i
);
2948 if (DECL_FUNCTION_THROWS (part
) != NULL_TREE
)
2950 tree t
= DECL_FUNCTION_THROWS (part
);
2951 int throws_count
= list_length (t
);
2952 static tree Exceptions_node
= NULL_TREE
;
2953 if (Exceptions_node
== NULL_TREE
)
2954 Exceptions_node
= get_identifier ("Exceptions");
2955 ptr
= append_chunk (NULL
, 8 + 2 * throws_count
, state
);
2956 i
= find_utf8_constant (&state
->cpool
, Exceptions_node
);
2957 PUT2 (i
); /* attribute_name_index */
2958 i
= 2 + 2 * throws_count
; PUT4(i
); /* attribute_length */
2959 i
= throws_count
; PUT2 (i
);
2960 for (; t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
2962 i
= find_class_constant (&state
->cpool
, TREE_VALUE (t
));
2967 current_function_decl
= save_function
;
2969 ptr
= methods_count_ptr
; PUT2 (methods_count
);
2971 source_file
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
2972 for (ptr
= source_file
; ; ptr
++)
2977 if (ch
== '/' || ch
== '\\')
2978 source_file
= ptr
+1;
2980 ptr
= append_chunk (NULL
, 10, state
);
2981 PUT2 (1); /* attributes_count */
2983 /* generate the SourceFile attribute. */
2984 if (SourceFile_node
== NULL_TREE
)
2985 SourceFile_node
= get_identifier ("SourceFile");
2986 i
= find_utf8_constant (&state
->cpool
, SourceFile_node
);
2987 PUT2 (i
); /* attribute_name_index */
2989 i
= find_utf8_constant (&state
->cpool
, get_identifier (source_file
));
2992 /* New finally generate the contents of the constant pool chunk. */
2993 i
= count_constant_pool_bytes (&state
->cpool
);
2994 ptr
= obstack_alloc (state
->chunk_obstack
, i
);
2995 cpool_chunk
->data
= ptr
;
2996 cpool_chunk
->size
= i
;
2997 write_constant_pool (&state
->cpool
, ptr
, i
);
2998 return state
->first
;
3002 make_class_file_name (clas
)
3005 const char *dname
, *slash
;
3009 cname
= IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas
)),
3010 "", '.', DIR_SEPARATOR
,
3012 if (jcf_write_base_directory
== NULL
)
3014 /* Make sure we put the class file into the .java file's
3015 directory, and not into some subdirectory thereof. */
3017 dname
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
3018 slash
= strrchr (dname
, DIR_SEPARATOR
);
3024 t
= strrchr (cname
, DIR_SEPARATOR
);
3030 dname
= jcf_write_base_directory
;
3031 slash
= dname
+ strlen (dname
);
3034 r
= xmalloc (slash
- dname
+ strlen (cname
) + 2);
3035 strncpy (r
, dname
, slash
- dname
);
3036 r
[slash
- dname
] = DIR_SEPARATOR
;
3037 strcpy (&r
[slash
- dname
+ 1], cname
);
3039 /* We try to make new directories when we need them. We only do
3040 this for directories which "might not" exist. For instance, we
3041 assume the `-d' directory exists, but we don't assume that any
3042 subdirectory below it exists. It might be worthwhile to keep
3043 track of which directories we've created to avoid gratuitous
3045 dname
= r
+ (slash
- dname
) + 1;
3048 cname
= strchr (dname
, DIR_SEPARATOR
);
3052 if (stat (r
, &sb
) == -1)
3054 /* Try to make it. */
3055 if (mkdir (r
, 0755) == -1)
3057 fatal ("failed to create directory `%s'", r
);
3062 *cname
= DIR_SEPARATOR
;
3063 /* Skip consecutive separators. */
3064 for (dname
= cname
+ 1; *dname
&& *dname
== DIR_SEPARATOR
; ++dname
)
3071 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
3072 The output .class file name is make_class_file_name(CLAS). */
3075 write_classfile (clas
)
3078 struct obstack
*work
= &temporary_obstack
;
3079 struct jcf_partial state
[1];
3080 char *class_file_name
= make_class_file_name (clas
);
3081 struct chunk
*chunks
;
3083 if (class_file_name
!= NULL
)
3085 FILE* stream
= fopen (class_file_name
, "wb");
3087 fatal ("failed to open `%s' for writing", class_file_name
);
3088 jcf_dependency_add_target (class_file_name
);
3089 init_jcf_state (state
, work
);
3090 chunks
= generate_classfile (clas
, state
);
3091 write_chunks (stream
, chunks
);
3092 if (fclose (stream
))
3093 fatal ("failed to close after writing `%s'", class_file_name
);
3094 free (class_file_name
);
3096 release_jcf_state (state
);
3100 string concatenation
3101 synchronized statement