1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998 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 */
40 #define DIR_SEPARATOR '/'
43 extern struct obstack temporary_obstack
;
45 /* Base directory in which `.class' files should be written.
46 NULL means to put the file into the same directory as the
47 corresponding .java file. */
48 char *jcf_write_base_directory
= NULL
;
50 /* Make sure bytecode.data is big enough for at least N more bytes. */
53 do { CHECK_OP(state); \
54 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
55 buffer_grow (&state->bytecode, N); } while (0)
57 /* Add a 1-byte instruction/operand I to bytecode.data,
58 assuming space has already been RESERVE'd. */
60 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
62 /* Like OP1, but I is a 2-byte big endian integer. */
65 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
67 /* Like OP1, but I is a 4-byte big endian integer. */
70 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
71 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
73 /* Macro to call each time we push I words on the JVM stack. */
75 #define NOTE_PUSH(I) \
76 do { state->code_SP += (I); \
77 if (state->code_SP > state->code_SP_max) \
78 state->code_SP_max = state->code_SP; } while (0)
80 /* Macro to call each time we pop I words from the JVM stack. */
83 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
85 /* A chunk or segment of a .class file. */
89 /* The next segment of this .class file. */
92 /* The actual data in this segment to be written to the .class file. */
95 /* The size of the segment to be written to the .class file. */
99 /* Each "block" represents a label plus the bytecode instructions following.
100 There may be branches out of the block, but no incoming jumps, except
101 to the beginning of the block. */
105 /* For blocks that that are defined, the next block (in pc order).
106 For blocks that are the not-yet-defined end label of a LABELED_BLOCK_EXPR,
107 this is the next (outer) such end label, in a stack heaed by
108 labeled_blocks in jcf_partial. */
109 struct jcf_block
*next
;
111 /* Until perform_relocations is finished, this is the maximum possible
112 value of the bytecode offset at the begnning of this block.
113 After perform_relocations, it is the actual offset (pc). */
118 /* After finish_jcf_block is called, The actual instructions contained in this block.
119 Before than NULL, and the instructions are in state->bytecode. */
123 /* Set of relocations (in reverse offset order) for this block. */
124 struct jcf_relocation
*relocations
;
126 /* If this block is that of the not-yet-defined end label of
127 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR. */
132 /* A "relocation" type for the 0-3 bytes of padding at the start
133 of a tableswitch or a lookupswitch. */
134 #define SWITCH_ALIGN_RELOC 4
136 /* A relocation type for the labels in a tableswitch or a lookupswitch;
137 these are relative to the start of the instruction, but (due to
138 th 0-3 bytes of padding), we don't know the offset before relocation. */
139 #define BLOCK_START_RELOC 1
141 struct jcf_relocation
143 /* Next relocation for the current jcf_block. */
144 struct jcf_relocation
*next
;
146 /* The (byte) offset within the current block that needs to be relocated. */
147 HOST_WIDE_INT offset
;
149 /* 0 if offset is a 4-byte relative offset.
150 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
151 for proper alignment in tableswitch/lookupswitch instructions.
152 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
153 to the start of the containing block.
154 -1 if offset is a 2-byte relative offset.
155 < -1 if offset is the address of an instruction with a 2-byte offset
156 that does not have a corresponding 4-byte offset version, in which
157 case the absolute value of kind is the inverted opcode.
158 > 4 if offset is the address of an instruction (such as jsr) with a
159 2-byte offset that does have a corresponding 4-byte offset version,
160 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
163 /* The label the relocation wants to actually transfer to. */
164 struct jcf_block
*label
;
167 /* State for single catch clause. */
171 struct jcf_handler
*next
;
173 struct jcf_block
*start_label
;
174 struct jcf_block
*end_label
;
175 struct jcf_block
*handler_label
;
177 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
181 /* State for the current switch statement. */
183 struct jcf_switch_state
185 struct jcf_switch_state
*prev
;
186 struct jcf_block
*default_label
;
188 struct jcf_relocation
*cases
;
190 HOST_WIDE_INT min_case
, max_case
;
193 /* This structure is used to contain the various pieces that will
194 become a .class file. */
200 struct obstack
*chunk_obstack
;
203 /* List of basic blocks for the current method. */
204 struct jcf_block
*blocks
;
205 struct jcf_block
*last_block
;
207 struct localvar_info
*first_lvar
;
208 struct localvar_info
*last_lvar
;
213 int linenumber_count
;
215 /* Until perform_relocations, this is a upper bound on the number
216 of bytes (so far) in the instructions for the current method. */
219 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
220 struct jcf_block
*labeled_blocks
;
222 /* The current stack size (stack pointer) in the current method. */
225 /* The largest extent of stack size (stack pointer) in the current method. */
228 /* Contains a mapping from local var slot number to localvar_info. */
229 struct buffer localvars
;
231 /* The buffer allocated for bytecode for the current jcf_block. */
232 struct buffer bytecode
;
234 /* Chain of exception handlers for the current method. */
235 struct jcf_handler
*handlers
;
237 /* Last element in handlers chain. */
238 struct jcf_handler
*last_handler
;
240 /* Number of exception handlers for the current method. */
243 /* Information about the current switch statemenet. */
244 struct jcf_switch_state
*sw_state
;
247 static void generate_bytecode_insns
PROTO ((tree
, int, struct jcf_partial
*));
249 /* Utility macros for appending (big-endian) data to a buffer.
250 We assume a local variable 'ptr' points into where we want to
251 write next, and we assume enoygh space has been allocated. */
253 #ifdef ENABLE_CHECKING
255 CHECK_PUT(ptr
, state
, i
)
257 struct jcf_partial
*state
;
260 if (ptr
< state
->chunk
->data
261 || (char*)ptr
+ i
> state
->chunk
->data
+ state
->chunk
->size
)
262 fatal ("internal error - CHECK_PUT failed");
266 #define CHECK_PUT(PTR, STATE, I) 0
269 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
270 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
271 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
272 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
275 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
276 Set the data and size fields to DATA and SIZE, respectively.
277 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
280 alloc_chunk (last
, data
, size
, work
)
284 struct obstack
*work
;
286 struct chunk
*chunk
= (struct chunk
*)
287 obstack_alloc (work
, sizeof(struct chunk
));
289 if (data
== NULL
&& size
> 0)
290 data
= obstack_alloc (work
, size
);
300 #ifdef ENABLE_CHECKING
302 CHECK_OP(struct jcf_partial
*state
)
304 if (state
->bytecode
.ptr
> state
->bytecode
.limit
)
306 fatal("internal error - CHECK_OP failed");
311 #define CHECK_OP(STATE) 0
315 append_chunk (data
, size
, state
)
318 struct jcf_partial
*state
;
320 state
->chunk
= alloc_chunk (state
->chunk
, data
, size
, state
->chunk_obstack
);
321 if (state
->first
== NULL
)
322 state
->first
= state
->chunk
;
323 return state
->chunk
->data
;
327 append_chunk_copy (data
, size
, state
)
330 struct jcf_partial
*state
;
332 unsigned char *ptr
= append_chunk (NULL
, size
, state
);
333 memcpy (ptr
, data
, size
);
337 gen_jcf_label (state
)
338 struct jcf_partial
*state
;
340 struct jcf_block
*block
= (struct jcf_block
*)
341 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_block
));
343 block
->linenumber
= -1;
349 finish_jcf_block (state
)
350 struct jcf_partial
*state
;
352 struct jcf_block
*block
= state
->last_block
;
353 struct jcf_relocation
*reloc
;
354 int code_length
= BUFFER_LENGTH (&state
->bytecode
);
355 int pc
= state
->code_length
;
356 append_chunk_copy (state
->bytecode
.data
, code_length
, state
);
357 BUFFER_RESET (&state
->bytecode
);
358 block
->chunk
= state
->chunk
;
360 /* Calculate code_length to the maximum value it can have. */
361 pc
+= block
->chunk
->size
;
362 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
364 int kind
= reloc
->kind
;
365 if (kind
== SWITCH_ALIGN_RELOC
)
367 else if (kind
> BLOCK_START_RELOC
)
368 pc
+= 2; /* 2-byte offset may grow to 4-byte offset */
370 pc
+= 5; /* May need to add a goto_w. */
372 state
->code_length
= pc
;
376 define_jcf_label (label
, state
)
377 struct jcf_block
*label
;
378 struct jcf_partial
*state
;
380 if (state
->last_block
!= NULL
)
381 finish_jcf_block (state
);
382 label
->pc
= state
->code_length
;
383 if (state
->blocks
== NULL
)
384 state
->blocks
= label
;
386 state
->last_block
->next
= label
;
387 state
->last_block
= label
;
389 label
->u
.relocations
= NULL
;
393 get_jcf_label_here (state
)
394 struct jcf_partial
*state
;
396 if (state
->last_block
!= NULL
&& BUFFER_LENGTH (&state
->bytecode
) == 0)
397 return state
->last_block
;
400 struct jcf_block
*label
= gen_jcf_label (state
);
401 define_jcf_label (label
, state
);
406 /* Note a line number entry for the current PC and given LINE. */
409 put_linenumber (line
, state
)
411 struct jcf_partial
*state
;
413 (get_jcf_label_here (state
))->linenumber
= line
;
414 state
->linenumber_count
++;
417 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
418 in the range (START_LABEL, END_LABEL). */
420 static struct jcf_handler
*
421 alloc_handler (start_label
, end_label
, state
)
422 struct jcf_block
*start_label
;
423 struct jcf_block
*end_label
;
424 struct jcf_partial
*state
;
426 struct jcf_handler
*handler
= (struct jcf_handler
*)
427 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_handler
));
428 handler
->start_label
= start_label
;
429 handler
->end_label
= end_label
;
430 handler
->handler_label
= get_jcf_label_here (state
);
431 if (state
->handlers
== NULL
)
432 state
->handlers
= handler
;
434 state
->last_handler
->next
= handler
;
435 state
->last_handler
= handler
;
436 handler
->next
= NULL
;
437 state
->num_handlers
++;
442 /* The index of jvm local variable allocated for this DECL.
443 This is assigned when generating .class files;
444 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
445 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
447 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
451 struct localvar_info
*next
;
454 struct jcf_block
*start_label
;
455 struct jcf_block
*end_label
;
458 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
459 #define localvar_max \
460 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
463 localvar_alloc (decl
, state
)
465 struct jcf_partial
*state
;
467 struct jcf_block
*start_label
= get_jcf_label_here (state
);
468 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
470 register struct localvar_info
*info
;
471 register struct localvar_info
**ptr
= localvar_buffer
;
472 register struct localvar_info
**limit
473 = (struct localvar_info
**) state
->localvars
.ptr
;
474 for (index
= 0; ptr
< limit
; index
++, ptr
++)
477 && (! wide
|| ((ptr
+1) < limit
&& ptr
[1] == NULL
)))
482 buffer_grow (&state
->localvars
, 2 * sizeof (struct localvar_info
*));
483 ptr
= (struct localvar_info
**) state
->localvars
.data
+ index
;
484 state
->localvars
.ptr
= (unsigned char *) (ptr
+ 1 + wide
);
486 info
= (struct localvar_info
*)
487 obstack_alloc (state
->chunk_obstack
, sizeof (struct localvar_info
));
490 ptr
[1] = (struct localvar_info
*)(~0);
491 DECL_LOCAL_INDEX (decl
) = index
;
493 info
->start_label
= start_label
;
495 if (DECL_NAME (decl
) != NULL_TREE
)
497 /* Generate debugging info. */
499 if (state
->last_lvar
!= NULL
)
500 state
->last_lvar
->next
= info
;
502 state
->first_lvar
= info
;
503 state
->last_lvar
= info
;
509 localvar_free (decl
, state
)
511 struct jcf_partial
*state
;
513 struct jcf_block
*end_label
= get_jcf_label_here (state
);
514 int index
= DECL_LOCAL_INDEX (decl
);
515 register struct localvar_info
**ptr
= &localvar_buffer
[index
];
516 register struct localvar_info
*info
= *ptr
;
517 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
520 info
->end_label
= end_label
;
522 if (info
->decl
!= decl
)
527 if (ptr
[1] != (struct localvar_info
*)(~0))
534 #define STACK_TARGET 1
535 #define IGNORE_TARGET 2
537 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
538 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
541 get_access_flags (decl
)
545 int isfield
= TREE_CODE (decl
) == FIELD_DECL
|| TREE_CODE (decl
) == VAR_DECL
;
546 if (CLASS_PUBLIC (decl
)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
548 if (CLASS_FINAL (decl
)) /* same as FIELD_FINAL and METHOD_FINAL */
550 if (isfield
|| TREE_CODE (decl
) == FUNCTION_DECL
)
552 if (TREE_PROTECTED (decl
))
553 flags
|= ACC_PROTECTED
;
554 if (TREE_PRIVATE (decl
))
555 flags
|= ACC_PRIVATE
;
557 else if (TREE_CODE (decl
) == TYPE_DECL
)
559 if (CLASS_SUPER (decl
))
561 if (CLASS_ABSTRACT (decl
))
562 flags
|= ACC_ABSTRACT
;
563 if (CLASS_INTERFACE (decl
))
564 flags
|= ACC_INTERFACE
;
567 fatal ("internal error - bad argument to get_access_flags");
568 if (TREE_CODE (decl
) == FUNCTION_DECL
)
570 if (METHOD_NATIVE (decl
))
572 if (METHOD_STATIC (decl
))
574 if (METHOD_FINAL (decl
))
576 if (METHOD_SYNCHRONIZED (decl
))
577 flags
|= ACC_SYNCHRONIZED
;
578 if (METHOD_ABSTRACT (decl
))
579 flags
|= ACC_ABSTRACT
;
583 if (FIELD_STATIC (decl
))
585 if (FIELD_VOLATILE (decl
))
586 flags
|= ACC_VOLATILE
;
587 if (FIELD_TRANSIENT (decl
))
588 flags
|= ACC_TRANSIENT
;
593 /* Write the list of segments starting at CHUNKS to STREAM. */
596 write_chunks (stream
, chunks
)
598 struct chunk
*chunks
;
600 for (; chunks
!= NULL
; chunks
= chunks
->next
)
601 fwrite (chunks
->data
, chunks
->size
, 1, stream
);
604 /* Push a 1-word constant in the constant pool at the given INDEX.
605 (Caller is responsible for doing NOTE_PUSH.) */
608 push_constant1 (index
, state
)
610 struct jcf_partial
*state
;
625 /* Push a 2-word constant in the constant pool at the given INDEX.
626 (Caller is responsible for doing NOTE_PUSH.) */
629 push_constant2 (index
, state
)
631 struct jcf_partial
*state
;
638 /* Push 32-bit integer constant on VM stack.
639 Caller is responsible for doing NOTE_PUSH. */
642 push_int_const (i
, state
)
644 struct jcf_partial
*state
;
647 if (i
>= -1 && i
<= 5)
648 OP1(OPCODE_iconst_0
+ i
);
649 else if (i
>= -128 && i
< 128)
654 else if (i
>= -32768 && i
< 32768)
661 i
= find_constant1 (&state
->cpool
, CONSTANT_Integer
, i
& 0xFFFFFFFF);
662 push_constant1 (i
, state
);
666 /* Push 64-bit long constant on VM stack.
667 Caller is responsible for doing NOTE_PUSH. */
670 push_long_const (lo
, hi
, state
)
671 HOST_WIDE_INT lo
, hi
;
672 struct jcf_partial
*state
;
674 if (hi
== 0 && lo
>= 0 && lo
<= 1)
677 OP1(OPCODE_lconst_0
+ lo
);
679 else if ((hi
== 0 && lo
< 32768) || (hi
== -1 && lo
>= -32768))
681 push_int_const (lo
, state
);
687 HOST_WIDE_INT w1
, w2
;
688 lshift_double (lo
, hi
, -32, 64, &w1
, &w2
, 1);
689 hi
= find_constant2 (&state
->cpool
, CONSTANT_Long
,
690 w1
& 0xFFFFFFFF, lo
& 0xFFFFFFFF);
691 push_constant2 (hi
, state
);
696 field_op (field
, opcode
, state
)
699 struct jcf_partial
*state
;
701 int index
= find_fieldref_index (&state
->cpool
, field
);
707 /* Returns an integer in the range 0 (for 'int') through 4 (for object
708 reference) to 7 (for 'short') which matches the pattern of how JVM
709 opcodes typically depend on the operand type. */
712 adjust_typed_op (type
, max
)
716 switch (TREE_CODE (type
))
719 case RECORD_TYPE
: return 4;
721 return TYPE_PRECISION (type
) == 32 || max
< 5 ? 0 : 5;
723 return TYPE_PRECISION (type
) == 32 || max
< 6 ? 0 : 6;
725 switch (TYPE_PRECISION (type
))
727 case 8: return max
< 5 ? 0 : 5;
728 case 16: return max
< 7 ? 0 : 7;
734 switch (TYPE_PRECISION (type
))
747 maybe_wide (opcode
, index
, state
)
749 struct jcf_partial
*state
;
766 /* Compile code to duplicate with offset, where
767 SIZE is the size of the stack item to duplicate (1 or 2), abd
768 OFFSET is where to insert the result (must be 0, 1, or 2).
769 (The new words get inserted at stack[SP-size-offset].) */
772 emit_dup (size
, offset
, state
)
774 struct jcf_partial
*state
;
781 kind
= size
== 1 ? OPCODE_dup
: OPCODE_dup2
;
782 else if (offset
== 1)
783 kind
= size
== 1 ? OPCODE_dup_x1
: OPCODE_dup2_x1
;
784 else if (offset
== 2)
785 kind
= size
== 1 ? OPCODE_dup_x2
: OPCODE_dup2_x2
;
793 emit_pop (size
, state
)
795 struct jcf_partial
*state
;
798 OP1 (OPCODE_pop
- 1 + size
);
802 emit_iinc (var
, value
, state
)
805 struct jcf_partial
*state
;
807 int slot
= DECL_LOCAL_INDEX (var
);
809 if (value
< -128 || value
> 127 || slot
>= 256)
827 emit_load_or_store (var
, opcode
, state
)
828 tree var
; /* Variable to load from or store into. */
829 int opcode
; /* Either OPCODE_iload or OPCODE_istore. */
830 struct jcf_partial
*state
;
832 tree type
= TREE_TYPE (var
);
833 int kind
= adjust_typed_op (type
, 4);
834 int index
= DECL_LOCAL_INDEX (var
);
838 OP1 (opcode
+ 5 + 4 * kind
+ index
); /* [ilfda]{load,store}_[0123] */
841 maybe_wide (opcode
+ kind
, index
, state
); /* [ilfda]{load,store} */
845 emit_load (var
, state
)
847 struct jcf_partial
*state
;
849 emit_load_or_store (var
, OPCODE_iload
, state
);
850 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
854 emit_store (var
, state
)
856 struct jcf_partial
*state
;
858 emit_load_or_store (var
, OPCODE_istore
, state
);
859 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
863 emit_unop (opcode
, type
, state
)
864 enum java_opcode opcode
;
866 struct jcf_partial
*state
;
868 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
874 emit_binop (opcode
, type
, state
)
875 enum java_opcode opcode
;
877 struct jcf_partial
*state
;
879 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
885 static struct jcf_relocation
*
886 emit_reloc (value
, kind
, target
, state
)
889 struct jcf_block
*target
;
890 struct jcf_partial
*state
;
892 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
893 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
894 struct jcf_block
*block
= state
->last_block
;
895 reloc
->next
= block
->u
.relocations
;
896 block
->u
.relocations
= reloc
;
897 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
898 reloc
->label
= target
;
900 if (kind
== 0 || kind
== BLOCK_START_RELOC
)
902 else if (kind
!= SWITCH_ALIGN_RELOC
)
907 emit_switch_reloc (label
, state
)
908 struct jcf_block
*label
;
909 struct jcf_partial
*state
;
911 emit_reloc (0, BLOCK_START_RELOC
, label
, state
);
914 /* Similar to emit_switch_reloc,
915 but re-uses an existing case reloc. */
918 emit_case_reloc (reloc
, state
)
919 struct jcf_relocation
*reloc
;
920 struct jcf_partial
*state
;
922 struct jcf_block
*block
= state
->last_block
;
923 reloc
->next
= block
->u
.relocations
;
924 block
->u
.relocations
= reloc
;
925 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
926 reloc
->kind
= BLOCK_START_RELOC
;
930 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
931 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
934 emit_if (target
, opcode
, inv_opcode
, state
)
935 struct jcf_block
*target
;
936 int opcode
, inv_opcode
;
937 struct jcf_partial
*state
;
940 // value is 1 byte from reloc back to start of instruction.
941 emit_reloc (1, - inv_opcode
, target
, state
);
945 emit_goto (target
, state
)
946 struct jcf_block
*target
;
947 struct jcf_partial
*state
;
950 // Value is 1 byte from reloc back to start of instruction.
951 emit_reloc (1, OPCODE_goto_w
, target
, state
);
955 emit_jsr (target
, state
)
956 struct jcf_block
*target
;
957 struct jcf_partial
*state
;
960 // Value is 1 byte from reloc back to start of instruction.
961 emit_reloc (1, OPCODE_jsr_w
, target
, state
);
964 /* Generate code to evaluate EXP. If the result is true,
965 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
966 TRUE_BRANCH_FIRST is a code geneation hint that the
967 TRUE_LABEL may follow right after this. (The idea is that we
968 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
971 generate_bytecode_conditional (exp
, true_label
, false_label
,
972 true_branch_first
, state
)
974 struct jcf_block
*true_label
;
975 struct jcf_block
*false_label
;
976 int true_branch_first
;
977 struct jcf_partial
*state
;
980 tree exp0
, exp1
, type
;
981 int save_SP
= state
->code_SP
;
982 enum java_opcode op
, negop
;
983 switch (TREE_CODE (exp
))
986 emit_goto (integer_zerop (exp
) ? false_label
: true_label
, state
);
990 struct jcf_block
*then_label
= gen_jcf_label (state
);
991 struct jcf_block
*else_label
= gen_jcf_label (state
);
992 int save_SP_before
, save_SP_after
;
993 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
994 then_label
, else_label
, 1, state
);
995 define_jcf_label (then_label
, state
);
996 save_SP_before
= state
->code_SP
;
997 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
998 true_label
, false_label
, 1, state
);
999 save_SP_after
= state
->code_SP
;
1000 state
->code_SP
= save_SP_before
;
1001 define_jcf_label (else_label
, state
);
1002 generate_bytecode_conditional (TREE_OPERAND (exp
, 2),
1003 true_label
, false_label
,
1004 true_branch_first
, state
);
1005 if (state
->code_SP
!= save_SP_after
)
1006 fatal ("internal error non-matching SP");
1009 case TRUTH_NOT_EXPR
:
1010 generate_bytecode_conditional (TREE_OPERAND (exp
, 0), false_label
, true_label
,
1011 ! true_branch_first
, state
);
1013 case TRUTH_ANDIF_EXPR
:
1015 struct jcf_block
*next_label
= gen_jcf_label (state
);
1016 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1017 next_label
, false_label
, 1, state
);
1018 define_jcf_label (next_label
, state
);
1019 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1020 true_label
, false_label
, 1, state
);
1023 case TRUTH_ORIF_EXPR
:
1025 struct jcf_block
*next_label
= gen_jcf_label (state
);
1026 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1027 true_label
, next_label
, 1, state
);
1028 define_jcf_label (next_label
, state
);
1029 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
1030 true_label
, false_label
, 1, state
);
1034 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1035 set it to the corresponding 1-operand if<COND> instructions. */
1039 /* The opcodes with their inverses are allocated in pairs.
1040 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1041 negop
= (op
& 1) ? op
+ 1 : op
- 1;
1043 if (true_branch_first
)
1045 emit_if (false_label
, negop
, op
, state
);
1046 emit_goto (true_label
, state
);
1050 emit_if (true_label
, op
, negop
, state
);
1051 emit_goto (false_label
, state
);
1055 op
= OPCODE_if_icmpeq
;
1058 op
= OPCODE_if_icmpne
;
1061 op
= OPCODE_if_icmpgt
;
1064 op
= OPCODE_if_icmplt
;
1067 op
= OPCODE_if_icmpge
;
1070 op
= OPCODE_if_icmple
;
1073 exp0
= TREE_OPERAND (exp
, 0);
1074 exp1
= TREE_OPERAND (exp
, 1);
1075 type
= TREE_TYPE (exp0
);
1076 switch (TREE_CODE (type
))
1079 case POINTER_TYPE
: case RECORD_TYPE
:
1080 switch (TREE_CODE (exp
))
1082 case EQ_EXPR
: op
= OPCODE_if_acmpeq
; break;
1083 case NE_EXPR
: op
= OPCODE_if_acmpne
; break;
1086 if (integer_zerop (exp1
) || integer_zerop (exp0
))
1088 generate_bytecode_insns (integer_zerop (exp1
) ? exp0
: exp0
,
1089 STACK_TARGET
, state
);
1090 op
= op
+ (OPCODE_ifnull
- OPCODE_if_acmpeq
);
1091 negop
= (op
& 1) ? op
- 1 : op
+ 1;
1095 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1096 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1100 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1101 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1102 if (op
== OPCODE_if_icmplt
|| op
== op
== OPCODE_if_icmple
)
1106 if (TYPE_PRECISION (type
) > 32)
1117 if (TYPE_PRECISION (type
) > 32)
1119 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1120 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1128 if (integer_zerop (exp1
))
1130 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1134 if (integer_zerop (exp0
))
1138 case OPCODE_if_icmplt
:
1139 case OPCODE_if_icmpge
:
1142 case OPCODE_if_icmpgt
:
1143 case OPCODE_if_icmple
:
1149 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1153 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
1154 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
1160 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1162 if (true_branch_first
)
1164 emit_if (false_label
, OPCODE_ifeq
, OPCODE_ifne
, state
);
1165 emit_goto (true_label
, state
);
1169 emit_if (true_label
, OPCODE_ifne
, OPCODE_ifeq
, state
);
1170 emit_goto (false_label
, state
);
1174 if (save_SP
!= state
->code_SP
)
1175 fatal ("internal error - SP mismatch");
1178 /* Generate bytecode for sub-expression EXP of METHOD.
1179 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1182 generate_bytecode_insns (exp
, target
, state
)
1185 struct jcf_partial
*state
;
1188 enum java_opcode jopcode
;
1190 HOST_WIDE_INT value
;
1195 if (exp
== NULL
&& target
== IGNORE_TARGET
)
1198 type
= TREE_TYPE (exp
);
1200 switch (TREE_CODE (exp
))
1203 if (BLOCK_EXPR_BODY (exp
))
1206 tree body
= BLOCK_EXPR_BODY (exp
);
1207 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1209 tree next
= TREE_CHAIN (local
);
1210 localvar_alloc (local
, state
);
1213 /* Avoid deep recursion for long blocks. */
1214 while (TREE_CODE (body
) == COMPOUND_EXPR
)
1216 generate_bytecode_insns (TREE_OPERAND (body
, 0), target
, state
);
1217 body
= TREE_OPERAND (body
, 1);
1219 generate_bytecode_insns (body
, target
, state
);
1220 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1222 tree next
= TREE_CHAIN (local
);
1223 localvar_free (local
, state
);
1229 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
1230 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1232 case EXPR_WITH_FILE_LOCATION
:
1234 char *saved_input_filename
= input_filename
;
1235 int saved_lineno
= lineno
;
1236 input_filename
= EXPR_WFL_FILENAME (exp
);
1237 lineno
= EXPR_WFL_LINENO (exp
);
1238 if (EXPR_WFL_EMIT_LINE_NOTE (exp
))
1239 put_linenumber (EXPR_WFL_LINENO (exp
), state
);
1240 generate_bytecode_insns (EXPR_WFL_NODE (exp
), target
, state
);
1241 input_filename
= saved_input_filename
;
1242 lineno
= saved_lineno
;
1246 if (target
== IGNORE_TARGET
) ; /* do nothing */
1247 else if (TREE_CODE (type
) == POINTER_TYPE
)
1249 if (! integer_zerop (exp
))
1252 OP1 (OPCODE_aconst_null
);
1255 else if (TYPE_PRECISION (type
) <= 32)
1257 push_int_const (TREE_INT_CST_LOW (exp
), state
);
1262 push_long_const (TREE_INT_CST_LOW (exp
), TREE_INT_CST_HIGH (exp
),
1268 switch (TYPE_PRECISION (type
))
1273 words
[0] = etarsingle (TREE_REAL_CST (exp
)) & 0xFFFFFFFF;
1274 index
= find_constant1 (&state
->cpool
, CONSTANT_Float
, words
[0]);
1275 push_constant1 (index
, state
);
1279 etardouble (TREE_REAL_CST (exp
), words
);
1280 index
= find_constant2 (&state
->cpool
, CONSTANT_Double
,
1281 words
[1-FLOAT_WORDS_BIG_ENDIAN
] & 0xFFFFFFFF,
1282 words
[FLOAT_WORDS_BIG_ENDIAN
] & 0xFFFFFFFF);
1283 push_constant2 (index
, state
);
1291 push_constant1 (find_string_constant (&state
->cpool
, exp
), state
);
1295 if (TREE_STATIC (exp
))
1297 field_op (exp
, OPCODE_getstatic
, state
);
1298 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1301 /* ... fall through ... */
1303 emit_load (exp
, state
);
1305 case NON_LVALUE_EXPR
:
1307 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1310 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1311 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1312 if (target
!= IGNORE_TARGET
)
1314 jopcode
= OPCODE_iaload
+ adjust_typed_op (type
, 7);
1317 if (! TYPE_IS_WIDE (type
))
1323 tree obj
= TREE_OPERAND (exp
, 0);
1324 tree field
= TREE_OPERAND (exp
, 1);
1325 int is_static
= FIELD_STATIC (field
);
1326 generate_bytecode_insns (obj
,
1327 is_static
? IGNORE_TARGET
: target
, state
);
1328 if (target
!= IGNORE_TARGET
)
1330 if (DECL_NAME (field
) == length_identifier_node
&& !is_static
1331 && TYPE_ARRAY_P (TREE_TYPE (obj
)))
1334 OP1 (OPCODE_arraylength
);
1338 field_op (field
, is_static
? OPCODE_getstatic
: OPCODE_getfield
,
1342 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1347 case TRUTH_ANDIF_EXPR
:
1348 case TRUTH_ORIF_EXPR
:
1356 struct jcf_block
*then_label
= gen_jcf_label (state
);
1357 struct jcf_block
*else_label
= gen_jcf_label (state
);
1358 struct jcf_block
*end_label
= gen_jcf_label (state
);
1359 generate_bytecode_conditional (exp
,
1360 then_label
, else_label
, 1, state
);
1361 define_jcf_label (then_label
, state
);
1362 push_int_const (1, state
);
1363 emit_goto (end_label
, state
);
1364 define_jcf_label (else_label
, state
);
1365 push_int_const (0, state
);
1366 define_jcf_label (end_label
, state
);
1372 struct jcf_block
*then_label
= gen_jcf_label (state
);
1373 struct jcf_block
*else_label
= gen_jcf_label (state
);
1374 struct jcf_block
*end_label
= gen_jcf_label (state
);
1375 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1376 then_label
, else_label
, 1, state
);
1377 define_jcf_label (then_label
, state
);
1378 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1379 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp
, 1))
1380 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1381 || TREE_CODE (TREE_TYPE (exp
)) != VOID_TYPE
)
1382 emit_goto (end_label
, state
);
1383 define_jcf_label (else_label
, state
);
1384 generate_bytecode_insns (TREE_OPERAND (exp
, 2), target
, state
);
1385 define_jcf_label (end_label
, state
);
1390 struct jcf_switch_state
*sw_state
= state
->sw_state
;
1391 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
1392 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
1393 HOST_WIDE_INT case_value
= TREE_INT_CST_LOW (TREE_OPERAND (exp
, 0));
1395 reloc
->label
= get_jcf_label_here (state
);
1396 reloc
->offset
= case_value
;
1397 reloc
->next
= sw_state
->cases
;
1398 sw_state
->cases
= reloc
;
1399 if (sw_state
->num_cases
== 0)
1401 sw_state
->min_case
= case_value
;
1402 sw_state
->max_case
= case_value
;
1406 if (case_value
< sw_state
->min_case
)
1407 sw_state
->min_case
= case_value
;
1408 if (case_value
> sw_state
->max_case
)
1409 sw_state
->max_case
= case_value
;
1411 sw_state
->num_cases
++;
1415 state
->sw_state
->default_label
= get_jcf_label_here (state
);
1420 /* The SWITCH_EXPR has three parts, generated in the following order:
1421 1. the switch_expression (the value used to select the correct case);
1423 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1424 After code generation, we will re-order then in the order 1, 3, 2.
1425 This is to avoid an extra GOTOs. */
1426 struct jcf_switch_state sw_state
;
1427 struct jcf_block
*expression_last
; /* Last block of the switch_expression. */
1428 struct jcf_block
*body_last
; /* Last block of the switch_body. */
1429 struct jcf_block
*switch_instruction
; /* First block of switch_instruction. */
1430 struct jcf_block
*instruction_last
; /* Last block of the switch_instruction. */
1431 struct jcf_block
*body_block
;
1433 sw_state
.prev
= state
->sw_state
;
1434 state
->sw_state
= &sw_state
;
1435 sw_state
.cases
= NULL
;
1436 sw_state
.num_cases
= 0;
1437 sw_state
.default_label
= NULL
;
1438 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1439 expression_last
= state
->last_block
;
1440 body_block
= get_jcf_label_here (state
); /* Force a new block here. */
1441 generate_bytecode_insns (TREE_OPERAND (exp
, 1), IGNORE_TARGET
, state
);
1442 body_last
= state
->last_block
;
1444 if (sw_state
.default_label
== NULL
)
1445 sw_state
.default_label
= gen_jcf_label (state
);
1446 switch_instruction
= get_jcf_label_here (state
);
1448 if (sw_state
.num_cases
<= 1)
1450 if (sw_state
.num_cases
== 0)
1452 emit_pop (1, state
);
1457 push_int_const (sw_state
.cases
->offset
, state
);
1458 emit_if (sw_state
.cases
->label
,
1459 OPCODE_ifeq
, OPCODE_ifne
, state
);
1461 emit_goto (sw_state
.default_label
, state
);
1466 /* Copy the chain of relocs into a sorted array. */
1467 struct jcf_relocation
**relocs
= (struct jcf_relocation
**)
1468 xmalloc (sw_state
.num_cases
* sizeof (struct jcf_relocation
*));
1469 /* The relocs arrays is a buffer with a gap.
1470 The assumption is that cases will normally come in "runs". */
1472 int gap_end
= sw_state
.num_cases
;
1473 struct jcf_relocation
*reloc
;
1474 for (reloc
= sw_state
.cases
; reloc
!= NULL
; reloc
= reloc
->next
)
1476 HOST_WIDE_INT case_value
= reloc
->offset
;
1477 while (gap_end
< sw_state
.num_cases
)
1479 struct jcf_relocation
*end
= relocs
[gap_end
];
1480 if (case_value
<= end
->offset
)
1482 relocs
[gap_start
++] = end
;
1485 while (gap_start
> 0)
1487 struct jcf_relocation
*before
= relocs
[gap_start
-1];
1488 if (case_value
>= before
->offset
)
1490 relocs
[--gap_end
] = before
;
1493 relocs
[gap_start
++] = reloc
;
1494 /* Note we don't check for duplicates. FIXME! */
1497 if (2 * sw_state
.num_cases
1498 >= sw_state
.max_case
- sw_state
.min_case
)
1499 { /* Use tableswitch. */
1501 RESERVE (13 + 4 * (sw_state
.max_case
- sw_state
.min_case
+ 1));
1502 OP1 (OPCODE_tableswitch
);
1503 emit_reloc (0, SWITCH_ALIGN_RELOC
, NULL
, state
);
1504 emit_switch_reloc (sw_state
.default_label
, state
);
1505 OP4 (sw_state
.min_case
);
1506 OP4 (sw_state
.max_case
);
1507 for (i
= sw_state
.min_case
; ; )
1509 reloc
= relocs
[index
];
1510 if (i
== reloc
->offset
)
1512 emit_case_reloc (reloc
, state
);
1513 if (i
== sw_state
.max_case
)
1518 emit_switch_reloc (sw_state
.default_label
, state
);
1523 { /* Use lookupswitch. */
1524 RESERVE(9 + 8 * sw_state
.num_cases
);
1525 OP1 (OPCODE_lookupswitch
);
1526 emit_reloc (0, SWITCH_ALIGN_RELOC
, NULL
, state
);
1527 emit_switch_reloc (sw_state
.default_label
, state
);
1528 OP4 (sw_state
.num_cases
);
1529 for (i
= 0; i
< sw_state
.num_cases
; i
++)
1531 struct jcf_relocation
*reloc
= relocs
[i
];
1532 OP4 (reloc
->offset
);
1533 emit_case_reloc (reloc
, state
);
1539 instruction_last
= state
->last_block
;
1540 if (sw_state
.default_label
->pc
< 0)
1541 define_jcf_label (sw_state
.default_label
, state
);
1542 else /* Force a new block. */
1543 sw_state
.default_label
= get_jcf_label_here (state
);
1544 /* Now re-arrange the blocks so the switch_instruction
1545 comes before the switch_body. */
1546 switch_length
= state
->code_length
- switch_instruction
->pc
;
1547 switch_instruction
->pc
= body_block
->pc
;
1548 instruction_last
->next
= body_block
;
1549 instruction_last
->chunk
->next
= body_block
->chunk
;
1550 expression_last
->next
= switch_instruction
;
1551 expression_last
->chunk
->next
= switch_instruction
->chunk
;
1552 body_last
->next
= sw_state
.default_label
;
1553 body_last
->chunk
->next
= NULL
;
1554 state
->chunk
= body_last
->chunk
;
1555 for (; body_block
!= sw_state
.default_label
; body_block
= body_block
->next
)
1556 body_block
->pc
+= switch_length
;
1558 state
->sw_state
= sw_state
.prev
;
1563 if (!TREE_OPERAND (exp
, 0))
1567 exp
= TREE_OPERAND (exp
, 0);
1568 if (TREE_CODE (exp
) != MODIFY_EXPR
)
1570 exp
= TREE_OPERAND (exp
, 1);
1571 op
= OPCODE_ireturn
+ adjust_typed_op (TREE_TYPE (exp
), 4);
1572 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1577 case LABELED_BLOCK_EXPR
:
1579 struct jcf_block
*end_label
= gen_jcf_label (state
);
1580 end_label
->next
= state
->labeled_blocks
;
1581 state
->labeled_blocks
= end_label
;
1582 end_label
->u
.labeled_block
= exp
;
1583 if (LABELED_BLOCK_BODY (exp
))
1584 generate_bytecode_insns (LABELED_BLOCK_BODY (exp
), target
, state
);
1585 if (state
->labeled_blocks
!= end_label
)
1587 state
->labeled_blocks
= end_label
->next
;
1588 define_jcf_label (end_label
, state
);
1593 tree body
= TREE_OPERAND (exp
, 0);
1595 if (TREE_CODE (body
) == COMPOUND_EXPR
1596 && TREE_CODE (TREE_OPERAND (body
, 0)) == EXIT_EXPR
)
1598 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1599 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1600 struct jcf_block
*head_label
;
1601 struct jcf_block
*body_label
;
1602 struct jcf_block
*end_label
= gen_jcf_label (state
);
1603 struct jcf_block
*exit_label
= state
->labeled_blocks
;
1604 head_label
= gen_jcf_label (state
);
1605 emit_goto (head_label
, state
);
1606 body_label
= get_jcf_label_here (state
);
1607 generate_bytecode_insns (TREE_OPERAND (body
, 1), target
, state
);
1608 define_jcf_label (head_label
, state
);
1609 generate_bytecode_conditional (TREE_OPERAND (body
, 0),
1610 end_label
, body_label
, 1, state
);
1611 define_jcf_label (end_label
, state
);
1616 struct jcf_block
*head_label
= get_jcf_label_here (state
);
1617 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1618 emit_goto (head_label
, state
);
1624 struct jcf_block
*label
= state
->labeled_blocks
;
1625 struct jcf_block
*end_label
= gen_jcf_label (state
);
1626 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1627 label
, end_label
, 0, state
);
1628 define_jcf_label (end_label
, state
);
1631 case EXIT_BLOCK_EXPR
:
1633 struct jcf_block
*label
= state
->labeled_blocks
;
1634 if (TREE_OPERAND (exp
, 1) != NULL
) goto notimpl
;
1635 while (label
->u
.labeled_block
!= TREE_OPERAND (exp
, 0))
1636 label
= label
->next
;
1637 emit_goto (label
, state
);
1641 case PREDECREMENT_EXPR
: value
= -1; post_op
= 0; goto increment
;
1642 case PREINCREMENT_EXPR
: value
= 1; post_op
= 0; goto increment
;
1643 case POSTDECREMENT_EXPR
: value
= -1; post_op
= 1; goto increment
;
1644 case POSTINCREMENT_EXPR
: value
= 1; post_op
= 1; goto increment
;
1647 exp
= TREE_OPERAND (exp
, 0);
1648 type
= TREE_TYPE (exp
);
1649 size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1650 if ((TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1651 && ! TREE_STATIC (exp
)
1652 && TREE_CODE (type
) == INTEGER_TYPE
1653 && TYPE_PRECISION (type
) == 32)
1655 if (target
!= IGNORE_TARGET
&& post_op
)
1656 emit_load (exp
, state
);
1657 emit_iinc (exp
, value
, state
);
1658 if (target
!= IGNORE_TARGET
&& ! post_op
)
1659 emit_load (exp
, state
);
1662 if (TREE_CODE (exp
) == COMPONENT_REF
)
1664 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1665 emit_dup (1, 0, state
);
1666 /* Stack: ..., objectref, objectref. */
1667 field_op (TREE_OPERAND (exp
, 1), OPCODE_getfield
, state
);
1669 /* Stack: ..., objectref, oldvalue. */
1672 else if (TREE_CODE (exp
) == ARRAY_REF
)
1674 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1675 generate_bytecode_insns (TREE_OPERAND (exp
, 1), STACK_TARGET
, state
);
1676 emit_dup (2, 0, state
);
1677 /* Stack: ..., array, index, array, index. */
1678 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (exp
), 7);
1682 /* Stack: ..., array, index, oldvalue. */
1685 else if (TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1687 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1688 /* Stack: ..., oldvalue. */
1694 if (target
!= IGNORE_TARGET
&& post_op
)
1695 emit_dup (size
, offset
, state
);
1696 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1697 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1698 /* Stack, otherwise: ..., [result, ] oldvalue. */
1699 push_int_const (value
, state
); /* FIXME - assumes int! */
1701 emit_binop (OPCODE_iadd
+ adjust_typed_op (type
, 3), type
, state
);
1702 if (target
!= IGNORE_TARGET
&& ! post_op
)
1703 emit_dup (size
, offset
, state
);
1704 /* Stack: ..., [result,] newvalue. */
1705 goto finish_assignment
;
1709 tree lhs
= TREE_OPERAND (exp
, 0);
1710 tree rhs
= TREE_OPERAND (exp
, 1);
1712 /* See if we can use the iinc instruction. */
1713 if ((TREE_CODE (lhs
) == VAR_DECL
|| TREE_CODE (lhs
) == PARM_DECL
)
1714 && ! TREE_STATIC (lhs
)
1715 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
1716 && TYPE_PRECISION (TREE_TYPE (lhs
)) == 32
1717 && (TREE_CODE (rhs
) == PLUS_EXPR
|| TREE_CODE (rhs
) == MINUS_EXPR
))
1719 tree arg0
= TREE_OPERAND (rhs
, 0);
1720 tree arg1
= TREE_OPERAND (rhs
, 1);
1721 HOST_WIDE_INT min_value
= -32768;
1722 HOST_WIDE_INT max_value
= 32767;
1723 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1728 else if (arg1
== lhs
)
1731 arg1
= TREE_OPERAND (rhs
, 0);
1733 if (lhs
== arg0
&& TREE_CODE (arg1
) == INTEGER_CST
)
1735 HOST_WIDE_INT hi_value
= TREE_INT_CST_HIGH (arg1
);
1736 value
= TREE_INT_CST_LOW (arg1
);
1737 if ((hi_value
== 0 && value
<= max_value
)
1738 || (hi_value
== -1 && value
>= min_value
))
1740 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1742 emit_iinc (lhs
, value
, state
);
1748 if (TREE_CODE (lhs
) == COMPONENT_REF
)
1749 generate_bytecode_insns (TREE_OPERAND (lhs
, 0), STACK_TARGET
, state
);
1750 else if (TREE_CODE (lhs
) == ARRAY_REF
)
1752 generate_bytecode_insns (TREE_OPERAND(lhs
, 0), STACK_TARGET
, state
);
1753 generate_bytecode_insns (TREE_OPERAND(lhs
, 1), STACK_TARGET
, state
);
1755 generate_bytecode_insns (rhs
, STACK_TARGET
, state
);
1756 if (target
!= IGNORE_TARGET
)
1757 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1 , 1, state
);
1763 if (TREE_CODE (exp
) == COMPONENT_REF
)
1765 tree field
= TREE_OPERAND (exp
, 1);
1766 if (! FIELD_STATIC (field
))
1769 FIELD_STATIC (field
) ? OPCODE_putstatic
1773 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1775 else if (TREE_CODE (exp
) == VAR_DECL
1776 || TREE_CODE (exp
) == PARM_DECL
)
1778 if (FIELD_STATIC (exp
))
1780 field_op (exp
, OPCODE_putstatic
, state
);
1781 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1784 emit_store (exp
, state
);
1786 else if (TREE_CODE (exp
) == ARRAY_REF
)
1789 jopcode
= OPCODE_iastore
+ adjust_typed_op (TREE_TYPE (exp
), 7);
1792 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1795 fatal ("internal error (bad lhs to MODIFY_EXPR)");
1798 jopcode
= OPCODE_iadd
;
1801 jopcode
= OPCODE_isub
;
1804 jopcode
= OPCODE_imul
;
1806 case TRUNC_DIV_EXPR
:
1808 jopcode
= OPCODE_idiv
;
1810 case TRUNC_MOD_EXPR
:
1811 jopcode
= OPCODE_irem
;
1813 case LSHIFT_EXPR
: jopcode
= OPCODE_ishl
; goto binop
;
1814 case RSHIFT_EXPR
: jopcode
= OPCODE_ishr
; goto binop
;
1815 case URSHIFT_EXPR
: jopcode
= OPCODE_iushr
; goto binop
;
1816 case BIT_AND_EXPR
: jopcode
= OPCODE_iand
; goto binop
;
1817 case BIT_IOR_EXPR
: jopcode
= OPCODE_ior
; goto binop
;
1818 case BIT_XOR_EXPR
: jopcode
= OPCODE_ixor
; goto binop
;
1821 tree arg0
= TREE_OPERAND (exp
, 0);
1822 tree arg1
= TREE_OPERAND (exp
, 1);
1823 jopcode
+= adjust_typed_op (type
, 3);
1824 if (arg0
== arg1
&& TREE_CODE (arg0
) == SAVE_EXPR
)
1826 /* fold may (e.g) convert 2*x to x+x. */
1827 generate_bytecode_insns (TREE_OPERAND (arg0
, 0), target
, state
);
1828 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0
)) > 32 ? 2 : 1, 0, state
);
1832 generate_bytecode_insns (arg0
, target
, state
);
1833 generate_bytecode_insns (arg1
, target
, state
);
1835 if (target
== STACK_TARGET
)
1836 emit_binop (jopcode
, type
, state
);
1839 case TRUTH_NOT_EXPR
:
1841 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1842 if (target
== STACK_TARGET
)
1844 int is_long
= TYPE_PRECISION (TREE_TYPE (exp
)) > 32;
1845 push_int_const (TREE_CODE (exp
) == BIT_NOT_EXPR
? -1 : 1, state
);
1849 OP1 (OPCODE_ixor
+ is_long
);
1853 jopcode
= OPCODE_ineg
;
1854 jopcode
+= adjust_typed_op (type
, 3);
1855 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1856 if (target
== STACK_TARGET
)
1857 emit_unop (jopcode
, type
, state
);
1859 case INSTANCEOF_EXPR
:
1861 int index
= find_class_constant (&state
->cpool
, TREE_OPERAND (exp
, 1));
1862 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1864 OP1 (OPCODE_instanceof
);
1871 case FIX_TRUNC_EXPR
:
1873 tree src
= TREE_OPERAND (exp
, 0);
1874 tree src_type
= TREE_TYPE (src
);
1875 tree dst_type
= TREE_TYPE (exp
);
1876 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1877 if (target
== IGNORE_TARGET
|| src_type
== dst_type
)
1879 if (TREE_CODE (dst_type
) == POINTER_TYPE
)
1881 if (TREE_CODE (exp
) == CONVERT_EXPR
)
1883 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (dst_type
));
1885 OP1 (OPCODE_checkcast
);
1889 else /* Convert numeric types. */
1891 int wide_src
= TYPE_PRECISION (src_type
) > 32;
1892 int wide_dst
= TYPE_PRECISION (dst_type
) > 32;
1893 NOTE_POP (1 + wide_src
);
1895 if (TREE_CODE (dst_type
) == REAL_TYPE
)
1897 if (TREE_CODE (src_type
) == REAL_TYPE
)
1898 OP1 (wide_dst
? OPCODE_f2d
: OPCODE_d2f
);
1899 else if (TYPE_PRECISION (src_type
) == 64)
1900 OP1 (OPCODE_l2f
+ wide_dst
);
1902 OP1 (OPCODE_i2f
+ wide_dst
);
1904 else /* Convert to integral type. */
1906 if (TREE_CODE (src_type
) == REAL_TYPE
)
1907 OP1 (OPCODE_f2i
+ wide_dst
+ 3 * wide_src
);
1912 if (TYPE_PRECISION (dst_type
) < 32)
1915 /* Already converted to int, if needed. */
1916 if (TYPE_PRECISION (dst_type
) <= 8)
1918 else if (TREE_UNSIGNED (dst_type
))
1924 NOTE_PUSH (1 + wide_dst
);
1930 tree try_clause
= TREE_OPERAND (exp
, 0);
1931 tree finally
= TREE_OPERAND (exp
, 2);
1932 struct jcf_block
*start_label
= get_jcf_label_here (state
);
1933 struct jcf_block
*end_label
; /* End of try clause. */
1934 struct jcf_block
*finally_label
; /* Finally subroutine. */
1935 struct jcf_block
*finished_label
= gen_jcf_label (state
);
1936 tree clause
= TREE_OPERAND (exp
, 1);
1939 finally
= FINALLY_EXPR_BLOCK (finally
);
1940 finally_label
= gen_jcf_label (state
);
1942 if (target
!= IGNORE_TARGET
)
1944 generate_bytecode_insns (try_clause
, IGNORE_TARGET
, state
);
1945 end_label
= get_jcf_label_here (state
);
1946 if (CAN_COMPLETE_NORMALLY (try_clause
))
1947 emit_goto (finished_label
, state
);
1948 for ( ; clause
!= NULL_TREE
; clause
= TREE_CHAIN (clause
))
1950 tree catch_clause
= TREE_OPERAND (clause
, 0);
1951 tree exception_decl
= BLOCK_EXPR_DECLS (catch_clause
);
1952 struct jcf_handler
*handler
= alloc_handler (start_label
, end_label
, state
);
1953 handler
->type
= TREE_TYPE (TREE_TYPE (exception_decl
));
1954 generate_bytecode_insns (catch_clause
, IGNORE_TARGET
, state
);
1955 if (CAN_COMPLETE_NORMALLY (catch_clause
))
1956 emit_goto (finished_label
, state
);
1961 tree exception_type
= build_pointer_type (throwable_type_node
);
1962 tree exception_decl
= build_decl (VAR_DECL
, NULL_TREE
,
1964 struct jcf_handler
*handler
1965 = alloc_handler (start_label
, NULL_TREE
, state
);
1966 handler
->end_label
= handler
->handler_label
;
1967 handler
->type
= NULL_TREE
;
1968 localvar_alloc (exception_decl
, state
);
1970 emit_store (exception_decl
, state
);
1971 emit_jsr (finally_label
, state
);
1972 emit_load (exception_decl
, state
);
1974 OP1 (OPCODE_athrow
);
1976 localvar_free (exception_decl
, state
);
1978 /* The finally block. */
1979 return_link
= build_decl (VAR_DECL
, NULL_TREE
,
1980 return_address_type_node
);
1981 define_jcf_label (finally_label
, state
);
1983 localvar_alloc (return_link
, state
);
1984 emit_store (return_link
, state
);
1985 generate_bytecode_insns (finally
, IGNORE_TARGET
, state
);
1986 maybe_wide (OPCODE_ret
, DECL_LOCAL_INDEX (return_link
), state
);
1987 localvar_free (return_link
, state
);
1989 define_jcf_label (finished_label
, state
);
1991 emit_jsr (finally_label
, state
);
1995 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1997 OP1 (OPCODE_athrow
);
1999 case NEW_CLASS_EXPR
:
2001 tree
class = TREE_TYPE (TREE_TYPE (exp
));
2002 int index
= find_class_constant (&state
->cpool
, class);
2009 /* ... fall though ... */
2012 tree f
= TREE_OPERAND (exp
, 0);
2013 tree x
= TREE_OPERAND (exp
, 1);
2014 int save_SP
= state
->code_SP
;
2015 if (TREE_CODE (f
) == ADDR_EXPR
)
2016 f
= TREE_OPERAND (f
, 0);
2017 if (f
== soft_newarray_node
)
2019 int type_code
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2020 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x
)),
2021 STACK_TARGET
, state
);
2023 OP1 (OPCODE_newarray
);
2027 else if (f
== soft_multianewarray_node
)
2031 int index
= find_class_constant (&state
->cpool
,
2032 TREE_TYPE (TREE_TYPE (exp
)));
2033 x
= TREE_CHAIN (x
); /* Skip class argument. */
2034 ndims
= TREE_INT_CST_LOW (TREE_VALUE (x
));
2035 for (idim
= ndims
; --idim
>= 0; )
2038 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2041 OP1 (OPCODE_multianewarray
);
2046 else if (f
== soft_anewarray_node
)
2048 tree cl
= TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp
)));
2049 int index
= find_class_constant (&state
->cpool
, TREE_TYPE (cl
));
2050 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2052 OP1 (OPCODE_anewarray
);
2056 else if (exp
== soft_exceptioninfo_call_node
)
2058 NOTE_PUSH (1); /* Pushed by exception system. */
2061 for ( ; x
!= NULL_TREE
; x
= TREE_CHAIN (x
))
2063 generate_bytecode_insns (TREE_VALUE (x
), STACK_TARGET
, state
);
2065 state
->code_SP
= save_SP
;
2066 if (TREE_CODE (f
) == FUNCTION_DECL
&& DECL_CONTEXT (f
) != NULL_TREE
)
2068 int index
= find_methodref_index (&state
->cpool
, f
);
2070 if (DECL_CONSTRUCTOR_P (f
))
2071 OP1 (OPCODE_invokespecial
);
2072 else if (METHOD_STATIC (f
))
2073 OP1 (OPCODE_invokestatic
);
2075 OP1 (OPCODE_invokevirtual
);
2077 f
= TREE_TYPE (TREE_TYPE (f
));
2078 if (TREE_CODE (f
) != VOID_TYPE
)
2080 int size
= TYPE_IS_WIDE (f
) ? 2 : 1;
2081 if (target
== IGNORE_TARGET
)
2082 emit_pop (size
, state
);
2092 error("internal error - tree code not implemented: %s",
2093 tree_code_name
[(int) TREE_CODE (exp
)]);
2098 perform_relocations (state
)
2099 struct jcf_partial
*state
;
2101 struct jcf_block
*block
;
2102 struct jcf_relocation
*reloc
;
2106 /* Before we start, the pc field of each block is an upper bound on
2107 the block's start pc (it may be less, if previous blocks need less
2108 than their maximum).
2110 The minimum size of each block is in the block's chunk->size. */
2112 /* First, figure out the actual locations of each block. */
2115 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2117 int block_size
= block
->chunk
->size
;
2121 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2122 Assumes relocations are in reverse order. */
2123 reloc
= block
->u
.relocations
;
2124 while (reloc
!= NULL
2125 && reloc
->kind
== OPCODE_goto_w
2126 && reloc
->label
->pc
== block
->next
->pc
2127 && reloc
->offset
+ 2 == block_size
)
2129 reloc
= reloc
->next
;
2130 block
->u
.relocations
= reloc
;
2131 block
->chunk
->size
-= 3;
2136 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
2138 if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2140 /* We assume this is the first relocation in this block,
2141 so we know its final pc. */
2142 int where
= pc
+ reloc
->offset
;
2143 int pad
= ((where
+ 3) & ~3) - where
;
2146 else if (reloc
->kind
< -1 || reloc
->kind
> BLOCK_START_RELOC
)
2148 int delta
= reloc
->label
->pc
- (pc
+ reloc
->offset
- 1);
2149 int expand
= reloc
->kind
> 0 ? 2 : 5;
2153 if (delta
>= -32768 && delta
<= 32767)
2159 block_size
+= expand
;
2165 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2167 struct chunk
*chunk
= block
->chunk
;
2168 int old_size
= chunk
->size
;
2169 int next_pc
= block
->next
== NULL
? pc
: block
->next
->pc
;
2170 int new_size
= next_pc
- block
->pc
;
2172 unsigned char *new_ptr
;
2173 unsigned char *old_buffer
= chunk
->data
;
2174 unsigned char *old_ptr
= old_buffer
+ old_size
;
2175 int new_end
= new_size
;
2176 if (new_size
!= old_size
)
2178 chunk
->data
= (unsigned char *)
2179 obstack_alloc (state
->chunk_obstack
, new_size
);
2180 chunk
->size
= new_size
;
2182 new_ptr
= chunk
->data
+ new_size
;
2184 /* We do the relocations from back to front, because
2185 the relocations are in reverse order. */
2186 for (reloc
= block
->u
.relocations
; ; reloc
= reloc
->next
)
2188 /* new_ptr and old_ptr point into the old and new buffers,
2189 respectively. (If no relocations cause the buffer to
2190 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2191 The bytes at higher adress have been copied and relocations
2192 handled; those at lower addresses remain to process. */
2194 /* Lower old index of piece to be copied with no relocation.
2195 I.e. high index of the first piece that does need relocation. */
2196 int start
= reloc
== NULL
? 0
2197 : reloc
->kind
== SWITCH_ALIGN_RELOC
? reloc
->offset
2198 : (reloc
->kind
== 0 || reloc
->kind
== BLOCK_START_RELOC
)
2200 : reloc
->offset
+ 2;
2203 int n
= (old_ptr
- old_buffer
) - start
;
2207 memcpy (new_ptr
, old_ptr
, n
);
2208 if (old_ptr
== old_buffer
)
2211 new_offset
= new_ptr
- chunk
->data
;
2212 new_offset
-= (reloc
->kind
== -1 ? 2 : 4);
2213 if (reloc
->kind
== 0)
2216 value
= GET_u4 (old_ptr
);
2218 else if (reloc
->kind
== BLOCK_START_RELOC
)
2224 else if (reloc
->kind
== SWITCH_ALIGN_RELOC
)
2226 int where
= block
->pc
+ reloc
->offset
;
2227 int pad
= ((where
+ 3) & ~3) - where
;
2235 value
= GET_u2 (old_ptr
);
2237 value
+= reloc
->label
->pc
- (block
->pc
+ new_offset
);
2238 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2239 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2240 if (reloc
->kind
!= -1)
2242 *--new_ptr
= (unsigned char) value
; value
>>= 8;
2243 *--new_ptr
= (unsigned char) value
;
2245 if (reloc
->kind
> BLOCK_START_RELOC
)
2247 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2249 *--new_ptr
= reloc
->kind
;
2251 else if (reloc
->kind
< -1)
2253 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2255 *--new_ptr
= OPCODE_goto_w
;
2258 *--new_ptr
= - reloc
->kind
;
2261 if (new_ptr
!= chunk
->data
)
2262 fatal ("internal error - perform_relocations");
2264 state
->code_length
= pc
;
2268 init_jcf_state (state
, work
)
2269 struct jcf_partial
*state
;
2270 struct obstack
*work
;
2272 state
->chunk_obstack
= work
;
2273 state
->first
= state
->chunk
= NULL
;
2274 CPOOL_INIT (&state
->cpool
);
2275 BUFFER_INIT (&state
->localvars
);
2276 BUFFER_INIT (&state
->bytecode
);
2280 init_jcf_method (state
, method
)
2281 struct jcf_partial
*state
;
2284 state
->current_method
= method
;
2285 state
->blocks
= state
->last_block
= NULL
;
2286 state
->linenumber_count
= 0;
2287 state
->first_lvar
= state
->last_lvar
= NULL
;
2288 state
->lvar_count
= 0;
2289 state
->labeled_blocks
= NULL
;
2290 state
->code_length
= 0;
2291 BUFFER_RESET (&state
->bytecode
);
2292 BUFFER_RESET (&state
->localvars
);
2294 state
->code_SP_max
= 0;
2295 state
->handlers
= NULL
;
2296 state
->last_handler
= NULL
;
2297 state
->num_handlers
= 0;
2301 release_jcf_state (state
)
2302 struct jcf_partial
*state
;
2304 CPOOL_FINISH (&state
->cpool
);
2305 obstack_free (state
->chunk_obstack
, state
->first
);
2308 /* Generate and return a list of chunks containing the class CLAS
2309 in the .class file representation. The list can be written to a
2310 .class file using write_chunks. Allocate chunks from obstack WORK. */
2313 generate_classfile (clas
, state
)
2315 struct jcf_partial
*state
;
2317 struct chunk
*cpool_chunk
;
2321 char *fields_count_ptr
;
2322 int fields_count
= 0;
2323 char *methods_count_ptr
;
2324 int methods_count
= 0;
2325 static tree SourceFile_node
= NULL_TREE
;
2328 = clas
== object_type_node
? 0
2329 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas
));
2331 ptr
= append_chunk (NULL
, 8, state
);
2332 PUT4 (0xCafeBabe); /* Magic number */
2333 PUT2 (3); /* Minor version */
2334 PUT2 (45); /* Major version */
2336 append_chunk (NULL
, 0, state
);
2337 cpool_chunk
= state
->chunk
;
2339 /* Next allocate the chunk containing acces_flags through fields_counr. */
2340 if (clas
== object_type_node
)
2343 i
= 8 + 2 * total_supers
;
2344 ptr
= append_chunk (NULL
, i
, state
);
2345 i
= get_access_flags (TYPE_NAME (clas
)); PUT2 (i
); /* acces_flags */
2346 i
= find_class_constant (&state
->cpool
, clas
); PUT2 (i
); /* this_class */
2347 if (clas
== object_type_node
)
2349 PUT2(0); /* super_class */
2350 PUT2(0); /* interfaces_count */
2354 tree basetypes
= TYPE_BINFO_BASETYPES (clas
);
2355 tree base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, 0));
2356 int j
= find_class_constant (&state
->cpool
, base
);
2357 PUT2 (j
); /* super_class */
2358 PUT2 (total_supers
- 1); /* interfaces_count */
2359 for (i
= 1; i
< total_supers
; i
++)
2361 base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, i
));
2362 j
= find_class_constant (&state
->cpool
, base
);
2366 fields_count_ptr
= ptr
;
2368 for (part
= TYPE_FIELDS (clas
); part
; part
= TREE_CHAIN (part
))
2370 if (DECL_NAME (part
) == NULL_TREE
)
2372 ptr
= append_chunk (NULL
, 8, state
);
2373 i
= get_access_flags (part
); PUT2 (i
);
2374 i
= find_utf8_constant (&state
->cpool
, DECL_NAME (part
)); PUT2 (i
);
2375 i
= find_utf8_constant (&state
->cpool
, build_java_signature (TREE_TYPE (part
)));
2377 PUT2 (0); /* attributes_count */
2378 /* FIXME - emit ConstantValue attribute when appropriate */
2381 ptr
= fields_count_ptr
; PUT2 (fields_count
);
2383 ptr
= methods_count_ptr
= append_chunk (NULL
, 2, state
);
2386 for (part
= TYPE_METHODS (clas
); part
; part
= TREE_CHAIN (part
))
2388 struct jcf_block
*block
;
2389 tree function_body
= DECL_FUNCTION_BODY (part
);
2390 tree body
= function_body
== NULL_TREE
? NULL_TREE
2391 : BLOCK_EXPR_BODY (function_body
);
2392 tree name
= DECL_CONSTRUCTOR_P (part
) ? init_identifier_node
2394 tree type
= TREE_TYPE (part
);
2395 ptr
= append_chunk (NULL
, 8, state
);
2396 i
= get_access_flags (part
); PUT2 (i
);
2397 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
2398 i
= find_utf8_constant (&state
->cpool
, build_java_signature (type
));
2400 PUT2 (body
!= NULL_TREE
? 1 : 0); /* attributes_count */
2401 if (body
!= NULL_TREE
)
2403 int code_attributes_count
= 0;
2404 static tree Code_node
= NULL_TREE
;
2407 struct jcf_handler
*handler
;
2408 if (Code_node
== NULL_TREE
)
2409 Code_node
= get_identifier ("Code");
2410 ptr
= append_chunk (NULL
, 14, state
);
2411 i
= find_utf8_constant (&state
->cpool
, Code_node
); PUT2 (i
);
2413 init_jcf_method (state
, part
);
2414 get_jcf_label_here (state
); /* Force a first block. */
2415 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
2416 localvar_alloc (t
, state
);
2417 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
2418 if (CAN_COMPLETE_NORMALLY (body
))
2420 if (TREE_CODE (TREE_TYPE (type
)) != VOID_TYPE
)
2423 OP1 (OPCODE_return
);
2425 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
2426 localvar_free (t
, state
);
2427 finish_jcf_block (state
);
2428 perform_relocations (state
);
2431 i
= 8 + state
->code_length
+ 4 + 8 * state
->num_handlers
;
2432 if (state
->linenumber_count
> 0)
2434 code_attributes_count
++;
2435 i
+= 8 + 4 * state
->linenumber_count
;
2437 if (state
->lvar_count
> 0)
2439 code_attributes_count
++;
2440 i
+= 8 + 10 * state
->lvar_count
;
2442 PUT4 (i
); /* attribute_length */
2443 PUT2 (state
->code_SP_max
); /* max_stack */
2444 PUT2 (localvar_max
); /* max_locals */
2445 PUT4 (state
->code_length
);
2447 /* Emit the exception table. */
2448 ptr
= append_chunk (NULL
, 2 + 8 * state
->num_handlers
, state
);
2449 PUT2 (state
->num_handlers
); /* exception_table_length */
2450 handler
= state
->handlers
;
2451 for (; handler
!= NULL
; handler
= handler
->next
)
2454 PUT2 (handler
->start_label
->pc
);
2455 PUT2 (handler
->end_label
->pc
);
2456 PUT2 (handler
->handler_label
->pc
);
2457 if (handler
->type
== NULL_TREE
)
2460 type_index
= find_class_constant (&state
->cpool
,
2465 ptr
= append_chunk (NULL
, 2, state
);
2466 PUT2 (code_attributes_count
);
2468 /* Write the LineNumberTable attribute. */
2469 if (state
->linenumber_count
> 0)
2471 static tree LineNumberTable_node
= NULL_TREE
;
2472 ptr
= append_chunk (NULL
, 8 + 4 * state
->linenumber_count
, state
);
2473 if (LineNumberTable_node
== NULL_TREE
)
2474 LineNumberTable_node
= get_identifier ("LineNumberTable");
2475 i
= find_utf8_constant (&state
->cpool
, LineNumberTable_node
);
2476 PUT2 (i
); /* attribute_name_index */
2477 i
= 2+4*state
->linenumber_count
; PUT4(i
); /* attribute_length */
2478 i
= state
->linenumber_count
; PUT2 (i
);
2479 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
2481 int line
= block
->linenumber
;
2490 /* Write the LocalVariableTable attribute. */
2491 if (state
->lvar_count
> 0)
2493 static tree LocalVariableTable_node
= NULL_TREE
;
2494 struct localvar_info
*lvar
= state
->first_lvar
;
2495 ptr
= append_chunk (NULL
, 8 + 10 * state
->lvar_count
, state
);
2496 if (LocalVariableTable_node
== NULL_TREE
)
2497 LocalVariableTable_node
= get_identifier("LocalVariableTable");
2498 i
= find_utf8_constant (&state
->cpool
, LocalVariableTable_node
);
2499 PUT2 (i
); /* attribute_name_index */
2500 i
= 2 + 10 * state
->lvar_count
; PUT4 (i
); /* attribute_length */
2501 i
= state
->lvar_count
; PUT2 (i
);
2502 for ( ; lvar
!= NULL
; lvar
= lvar
->next
)
2504 tree name
= DECL_NAME (lvar
->decl
);
2505 tree sig
= build_java_signature (TREE_TYPE (lvar
->decl
));
2506 i
= lvar
->start_label
->pc
; PUT2 (i
);
2507 i
= lvar
->end_label
->pc
- i
; PUT2 (i
);
2508 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
2509 i
= find_utf8_constant (&state
->cpool
, sig
); PUT2 (i
);
2510 i
= DECL_LOCAL_INDEX (lvar
->decl
); PUT2 (i
);
2516 ptr
= methods_count_ptr
; PUT2 (methods_count
);
2518 source_file
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
2519 for (ptr
= source_file
; ; ptr
++)
2524 if (ch
== '/' || ch
== '\\')
2525 source_file
= ptr
+1;
2527 ptr
= append_chunk (NULL
, 10, state
);
2528 PUT2 (1); /* attributes_count */
2530 /* generate the SourceFile attribute. */
2531 if (SourceFile_node
== NULL_TREE
)
2532 SourceFile_node
= get_identifier ("SourceFile");
2533 i
= find_utf8_constant (&state
->cpool
, SourceFile_node
);
2534 PUT2 (i
); /* attribute_name_index */
2536 i
= find_utf8_constant (&state
->cpool
, get_identifier (source_file
));
2539 /* New finally generate the contents of the constant pool chunk. */
2540 i
= count_constant_pool_bytes (&state
->cpool
);
2541 ptr
= obstack_alloc (state
->chunk_obstack
, i
);
2542 cpool_chunk
->data
= ptr
;
2543 cpool_chunk
->size
= i
;
2544 write_constant_pool (&state
->cpool
, ptr
, i
);
2545 return state
->first
;
2549 make_class_file_name (clas
)
2552 char *cname
, *dname
, *slash
, *r
;
2555 cname
= IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas
)),
2556 "", '.', DIR_SEPARATOR
,
2558 if (jcf_write_base_directory
== NULL
)
2560 /* Make sure we put the class file into the .java file's
2561 directory, and not into some subdirectory thereof. */
2563 dname
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
2564 slash
= strrchr (dname
, DIR_SEPARATOR
);
2570 t
= strrchr (cname
, DIR_SEPARATOR
);
2576 dname
= jcf_write_base_directory
;
2577 slash
= dname
+ strlen (dname
);
2580 r
= xmalloc (slash
- dname
+ strlen (cname
) + 2);
2581 strncpy (r
, dname
, slash
- dname
);
2582 r
[slash
- dname
] = DIR_SEPARATOR
;
2583 strcpy (&r
[slash
- dname
+ 1], cname
);
2585 /* We try to make new directories when we need them. We only do
2586 this for directories which "might not" exist. For instance, we
2587 assume the `-d' directory exists, but we don't assume that any
2588 subdirectory below it exists. It might be worthwhile to keep
2589 track of which directories we've created to avoid gratuitous
2591 dname
= r
+ (slash
- dname
) + 1;
2594 cname
= strchr (dname
, DIR_SEPARATOR
);
2598 if (stat (r
, &sb
) == -1)
2600 /* Try to make it. */
2601 if (mkdir (r
, 0755) == -1)
2603 fatal ("failed to create directory `%s'", r
);
2608 *cname
= DIR_SEPARATOR
;
2609 /* Skip consecutive separators. */
2610 for (dname
= cname
+ 1; *dname
&& *dname
== DIR_SEPARATOR
; ++dname
)
2617 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
2618 The output .class file name is make_class_file_name(CLAS). */
2621 write_classfile (clas
)
2624 struct obstack
*work
= &temporary_obstack
;
2625 struct jcf_partial state
[1];
2626 char *class_file_name
= make_class_file_name (clas
);
2627 struct chunk
*chunks
;
2629 if (class_file_name
!= NULL
)
2631 FILE* stream
= fopen (class_file_name
, "wb");
2633 fatal ("failed to open `%s' for writing", class_file_name
);
2634 jcf_dependency_add_target (class_file_name
);
2635 init_jcf_state (state
, work
);
2636 chunks
= generate_classfile (clas
, state
);
2637 write_chunks (stream
, chunks
);
2638 if (fclose (stream
))
2639 fatal ("failed to close after writing `%s'", class_file_name
);
2640 free (class_file_name
);
2642 release_jcf_state (state
);
2646 string concatenation
2647 synchronized statement