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. */
27 #include "java-tree.h"
32 #include "java-opcodes.h"
33 #include "parse.h" /* for BLOCK_EXPR_BODY */
36 extern struct obstack temporary_obstack
;
38 /* Make sure bytecode.data is big enough for at least N more bytes. */
41 do { if (state->bytecode.ptr + (N) > state->bytecode.limit) \
42 buffer_grow (&state->bytecode, N); } while (0)
44 /* Add a 1-byte instruction/operand I to bytecode.data,
45 assuming space has already been RESERVE'd. */
47 #define OP1(I) (*state->bytecode.ptr++ = (I))
49 /* Like OP1, but I is a 2-byte big endian integer. */
52 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); } while (0)
54 /* Like OP1, but I is a 4-byte big endian integer. */
57 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
58 OP1 (_i >> 8); OP1 (_i); } while (0)
60 /* The current stack size (stack pointer) in the current method. */
64 /* The largest extent of stack size (stack pointer) in the current method. */
70 /* Macro to call each time we push I words on the JVM stack. */
72 #define NOTE_PUSH(I) \
73 do { state->code_SP += (I); \
74 if (state->code_SP > state->code_SP_max) \
75 state->code_SP_max = state->code_SP; } while (0)
77 /* Macro to call each time we pop I words from the JVM stack. */
80 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
82 /* A chunk or segment of a .class file. */
86 /* The next segment of this .class file. */
89 /* The actual data in this segment to be written to the .class file. */
92 /* The size of the segment to be written to the .class file. */
96 /* Each "block" represents a label plus the bytecode instructions following.
97 There may be branches out of the block, but no incoming jumps, except
98 to the beginning of the block. */
102 /* For blocks that that are defined, the next block (in pc order).
103 For blocks that are the not-yet-defined end label of a LABELED_BLOCK_EXPR,
104 this is the next (outer) such end label, in a stack heaed by
105 labeled_blocks in jcf_partial. */
106 struct jcf_block
*next
;
108 /* Until perform_relocations is finished, this is the maximum possible
109 value of the bytecode offset at the begnning of this block.
110 After perform_relocations, it is the actual offset (pc). */
118 /* Set of relocations (in reverse offset order) for this block. */
119 struct jcf_relocation
*relocations
;
121 /* If this block is that of the not-yet-defined end label of
122 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR. */
127 struct jcf_relocation
129 /* Next relocation for the current jcf_block. */
130 struct jcf_relocation
*next
;
132 /* The (byte) offset within the current block that needs to be relocated. */
135 /* 0 if offset is a 4-byte relative offset.
136 -1 if offset is a 2-byte relative offset.
137 < 0 if offset is the address of an instruction with a 2-byte offset
138 that does not have a corresponding 4-byte offset version, in which
139 case the absolute value of kind is the inverted opcode.
140 > 0 if offset is the address of an instruction (such as jsr) with a
141 2-byte offset that does have a corresponding 4-byte offset version,
142 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
145 /* The label the relocation wants to actually transfer to. */
146 struct jcf_block
*label
;
149 /* This structure is used to contain the various pieces that will
150 become a .class file. */
156 struct obstack
*chunk_obstack
;
159 /* List of basic blocks for the current method. */
160 struct jcf_block
*blocks
;
161 struct jcf_block
*last_block
;
163 struct localvar_info
*first_lvar
;
164 struct localvar_info
*last_lvar
;
169 int linenumber_count
;
171 /* Until perform_relocations, this is a upper bound on the number
172 of bytes (so far) in the instructions for the current method. */
175 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
176 struct jcf_block
*labeled_blocks
;
178 /* The current stack size (stack pointer) in the current method. */
181 /* The largest extent of stack size (stack pointer) in the current method. */
184 /* Contains a mapping from local var slot number to localvar_info. */
185 struct buffer localvars
;
187 /* The buffer allocated for bytecode for the current jcf_block. */
188 struct buffer bytecode
;
191 static void generate_bytecode_insns
PROTO ((tree
, int, struct jcf_partial
*));
193 /* Utility macros for appending (big-endian) data to a buffer.
194 We assume a local variable 'ptr' points into where we want to
195 write next, and we assume enoygh space has been allocated. */
197 #define PUT1(X) (*ptr++ = (X))
198 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
199 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
200 #define PUTN(P, N) (bcopy(P, ptr, N), ptr += (N))
203 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
204 Set the data and size fields to DATA and SIZE, respectively.
205 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
208 alloc_chunk (last
, data
, size
, work
)
212 struct obstack
*work
;
214 struct chunk
*chunk
= (struct chunk
*)
215 obstack_alloc (work
, sizeof(struct chunk
));
217 if (data
== NULL
&& size
> 0)
218 data
= obstack_alloc (work
, size
);
229 append_chunk (data
, size
, state
)
232 struct jcf_partial
*state
;
234 state
->chunk
= alloc_chunk (state
->chunk
, data
, size
, state
->chunk_obstack
);
235 if (state
->first
== NULL
)
236 state
->first
= state
->chunk
;
237 return state
->chunk
->data
;
241 append_chunk_copy (data
, size
, state
)
244 struct jcf_partial
*state
;
246 unsigned char *ptr
= append_chunk (NULL
, size
, state
);
247 bcopy (data
, ptr
, size
);
251 gen_jcf_label (state
)
252 struct jcf_partial
*state
;
254 struct jcf_block
*block
= (struct jcf_block
*)
255 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_block
));
257 block
->linenumber
= -1;
263 finish_jcf_block (state
)
264 struct jcf_partial
*state
;
266 struct jcf_block
*block
= state
->last_block
;
267 struct jcf_relocation
*reloc
;
268 int pc
= state
->code_length
;
269 append_chunk_copy (state
->bytecode
.data
, BUFFER_LENGTH (&state
->bytecode
),
271 BUFFER_RESET (&state
->bytecode
);
272 block
->chunk
= state
->chunk
;
274 /* Calculate code_length to the maximum value it can have. */
275 pc
+= block
->chunk
->size
;
276 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
278 int kind
= reloc
->kind
;
280 pc
+= 2; /* 2-byte offset may grow to 4-byte offset */
282 pc
+= 5; /* May need to add a goto_w. */
284 state
->code_length
= pc
;
288 define_jcf_label (label
, state
)
289 struct jcf_block
*label
;
290 struct jcf_partial
*state
;
292 if (state
->last_block
!= NULL
)
293 finish_jcf_block (state
);
294 label
->pc
= state
->code_length
;
295 if (state
->blocks
== NULL
)
296 state
->blocks
= label
;
298 state
->last_block
->next
= label
;
299 state
->last_block
= label
;
301 label
->u
.relocations
= NULL
;
305 get_jcf_label_here (state
)
306 struct jcf_partial
*state
;
308 if (state
->last_block
!= NULL
&& BUFFER_LENGTH (&state
->bytecode
) == 0)
309 return state
->last_block
;
312 struct jcf_block
*label
= gen_jcf_label (state
);
313 define_jcf_label (label
, state
);
318 /* Note a line number entry for the current PC and given LINE. */
321 put_linenumber (line
, state
)
323 struct jcf_partial
*state
;
325 (get_jcf_label_here (state
))->linenumber
= line
;
326 state
->linenumber_count
++;
330 /* The index of jvm local variable allocated for this DECL.
331 This is assigned when generating .class files;
332 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
333 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
335 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
339 struct localvar_info
*next
;
342 struct jcf_block
*start_label
;
343 struct jcf_block
*end_label
;
346 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
347 #define localvar_max \
348 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
351 localvar_alloc (decl
, state
)
353 struct jcf_partial
*state
;
355 struct jcf_block
*start_label
= get_jcf_label_here (state
);
356 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
358 register struct localvar_info
*info
;
359 register struct localvar_info
**ptr
= localvar_buffer
;
360 register struct localvar_info
**limit
361 = (struct localvar_info
**) state
->localvars
.ptr
;
362 for (index
= 0; ptr
< limit
; index
++, ptr
++)
365 && (! wide
|| ((ptr
+1) < limit
&& ptr
[1] == NULL
)))
370 buffer_grow (&state
->localvars
, 2 * sizeof (struct localvar_info
*));
371 ptr
= (struct localvar_info
**) state
->localvars
.data
+ index
;
372 state
->localvars
.ptr
= (unsigned char *) (ptr
+ 1 + wide
);
374 info
= (struct localvar_info
*)
375 obstack_alloc (state
->chunk_obstack
, sizeof (struct localvar_info
));
378 ptr
[1] = (struct localvar_info
*)(~0);
379 DECL_LOCAL_INDEX (decl
) = index
;
381 info
->start_label
= start_label
;
383 if (DECL_NAME (decl
) != NULL_TREE
)
385 /* Generate debugging info. */
387 if (state
->last_lvar
!= NULL
)
388 state
->last_lvar
->next
= info
;
390 state
->first_lvar
= info
;
391 state
->last_lvar
= info
;
397 localvar_free (decl
, state
)
399 struct jcf_partial
*state
;
401 struct jcf_block
*end_label
= get_jcf_label_here (state
);
402 int index
= DECL_LOCAL_INDEX (decl
);
403 register struct localvar_info
**ptr
= &localvar_buffer
[index
];
404 register struct localvar_info
*info
= *ptr
;
405 int wide
= TYPE_IS_WIDE (TREE_TYPE (decl
));
407 info
->end_label
= end_label
;
409 if (info
->decl
!= decl
)
414 if (ptr
[1] != (struct localvar_info
*)(~0))
421 #define STACK_TARGET 1
422 #define IGNORE_TARGET 2
424 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
425 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
428 get_access_flags (decl
)
432 int isfield
= TREE_CODE (decl
) == FIELD_DECL
|| TREE_CODE (decl
) == VAR_DECL
;
433 if (CLASS_PUBLIC (decl
)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
435 if (CLASS_FINAL (decl
)) /* same as FIELD_FINAL and METHOD_FINAL */
437 if (isfield
|| TREE_CODE (decl
) == FUNCTION_DECL
)
439 if (TREE_PROTECTED (decl
))
440 flags
|= ACC_PROTECTED
;
441 if (TREE_PRIVATE (decl
))
442 flags
|= ACC_PRIVATE
;
444 else if (TREE_CODE (decl
) == TYPE_DECL
)
446 if (CLASS_SUPER (decl
))
448 if (CLASS_ABSTRACT (decl
))
449 flags
|= ACC_ABSTRACT
;
450 if (CLASS_INTERFACE (decl
))
451 flags
|= ACC_INTERFACE
;
454 fatal ("internal error - bad argument to get_access_flags");
455 if (TREE_CODE (decl
) == FUNCTION_DECL
)
457 if (METHOD_NATIVE (decl
))
459 if (METHOD_STATIC (decl
))
461 if (METHOD_FINAL (decl
))
463 if (METHOD_SYNCHRONIZED (decl
))
464 flags
|= ACC_SYNCHRONIZED
;
465 if (METHOD_ABSTRACT (decl
))
466 flags
|= ACC_ABSTRACT
;
470 if (FIELD_STATIC (decl
))
472 if (FIELD_VOLATILE (decl
))
473 flags
|= ACC_VOLATILE
;
474 if (FIELD_TRANSIENT (decl
))
475 flags
|= ACC_TRANSIENT
;
480 /* Write the list of segments starting at CHUNKS to STREAM. */
483 write_chunks (stream
, chunks
)
485 struct chunk
*chunks
;
487 for (; chunks
!= NULL
; chunks
= chunks
->next
)
488 fwrite (chunks
->data
, chunks
->size
, 1, stream
);
492 push_constant1 (index
, state
)
494 struct jcf_partial
*state
;
509 push_constant2 (index
, state
)
511 struct jcf_partial
*state
;
518 /* Push 32-bit integer constant on VM stack.
519 Caller is responsible for doing NOTE_PUSH. */
522 push_int_const (i
, state
)
524 struct jcf_partial
*state
;
527 if (i
>= -1 && i
<= 5)
528 OP1(OPCODE_iconst_0
+ i
);
529 else if (i
>= -128 && i
< 128)
534 else if (i
>= -32768 && i
< 32768)
542 i
= find_constant1 (&state
->cpool
, CONSTANT_Integer
, i
& 0xFFFFFFFF);
547 /* Push 64-bit long constant on VM stack.
548 Caller is responsible for doing NOTE_PUSH. */
551 push_long_const (lo
, hi
, state
)
552 HOST_WIDE_INT lo
, hi
;
553 struct jcf_partial
*state
;
555 if (hi
== 0 && lo
>= 0 && lo
<= 1)
558 OP1(OPCODE_lconst_0
+ lo
);
561 else if ((jlong
) (jint
) i
== i
)
563 push_int_const ((jint
) i
, state
);
570 HOST_WIDE_INT w1
, w2
;
571 lshift_double (lo
, hi
, -32, 64, &w1
, &w2
, 1);
572 hi
= find_constant1 (&state
->cpool
, CONSTANT_Long
,
573 w1
& 0xFFFFFFFF, lo
& 0xFFFFFFFF);
579 field_op (field
, opcode
, state
)
582 struct jcf_partial
*state
;
584 int index
= find_fieldref_index (&state
->cpool
, field
);
590 /* Returns an integer in the range 0 (for 'int') through 4 (for object
591 reference) to 7 (for 'short') which matches the pattern of how JVM
592 opcodes typically depend on the operand type. */
595 adjust_typed_op (type
)
598 switch (TREE_CODE (type
))
601 case RECORD_TYPE
: return 4;
603 return TYPE_PRECISION (type
) == 32 ? 0 : 5;
605 return TYPE_PRECISION (type
) == 32 ? 0 : 6;
607 switch (TYPE_PRECISION (type
))
616 switch (TYPE_PRECISION (type
))
627 maybe_wide (opcode
, index
, state
)
629 struct jcf_partial
*state
;
646 /* Compile code to duplicate with offset, where
647 SIZE is the size of the stack item to duplicate (1 or 2), abd
648 OFFSET is where to insert the result (must be 0, 1, or 2).
649 (The new words get inserted at stack[SP-size-offset].) */
652 emit_dup (size
, offset
, state
)
654 struct jcf_partial
*state
;
661 kind
= size
== 1 ? OPCODE_dup
: OPCODE_dup2
;
662 else if (offset
== 1)
663 kind
= size
== 1 ? OPCODE_dup_x1
: OPCODE_dup2_x1
;
664 else if (offset
== 2)
665 kind
= size
== 1 ? OPCODE_dup_x2
: OPCODE_dup2_x2
;
673 emit_pop (size
, state
)
675 struct jcf_partial
*state
;
678 OP1 (OPCODE_pop
- 1 + size
);
682 emit_iinc (var
, value
, state
)
685 struct jcf_partial
*state
;
687 int slot
= DECL_LOCAL_INDEX (var
);
689 if (value
< -128 || value
> 127 || slot
>= 256)
707 emit_load_or_store (var
, opcode
, state
)
709 struct jcf_partial
*state
;
711 tree type
= TREE_TYPE (var
);
712 int kind
= adjust_typed_op (type
);
713 int index
= DECL_LOCAL_INDEX (var
);
717 OP1 (opcode
+ 5 + 4 * kind
+ index
); /* [ilfda]{load,store}_[0123] */
720 maybe_wide (opcode
+ kind
, index
); /* [ilfda]{load,store} */
724 emit_load (var
, state
)
726 struct jcf_partial
*state
;
728 emit_load_or_store (var
, OPCODE_iload
, state
);
729 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
733 emit_store (var
, state
)
735 struct jcf_partial
*state
;
737 emit_load_or_store (var
, OPCODE_istore
, state
);
738 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var
)) ? 2 : 1);
742 emit_binop (opcode
, type
, state
)
743 enum java_opcode opcode
;
745 struct jcf_partial
*state
;
747 int size
= TYPE_IS_WIDE (type
) ? 2 : 1;
753 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
754 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
757 emit_if (target
, opcode
, inv_opcode
, state
)
758 struct jcf_block
*target
;
759 int opcode
, inv_opcode
;
760 struct jcf_partial
*state
;
762 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
763 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
764 struct jcf_block
*block
= state
->last_block
;
765 reloc
->next
= block
->u
.relocations
;
766 block
->u
.relocations
= reloc
;
768 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
769 OP2 (1); // 1 byte from reloc back to start of instruction.
770 reloc
->kind
= - inv_opcode
;
771 reloc
->label
= target
;
775 emit_goto_or_jsr (target
, opcode
, opcode_w
, state
)
776 struct jcf_block
*target
;
777 int opcode
, opcode_w
;
778 struct jcf_partial
*state
;
780 struct jcf_relocation
*reloc
= (struct jcf_relocation
*)
781 obstack_alloc (state
->chunk_obstack
, sizeof (struct jcf_relocation
));
782 struct jcf_block
*block
= state
->last_block
;
783 reloc
->next
= block
->u
.relocations
;
784 block
->u
.relocations
= reloc
;
786 reloc
->offset
= BUFFER_LENGTH (&state
->bytecode
);
787 OP2 (1); // 1 byte from reloc back to start of instruction.
788 reloc
->kind
= opcode_w
;
789 reloc
->label
= target
;
793 emit_goto (target
, state
)
794 struct jcf_block
*target
;
795 struct jcf_partial
*state
;
797 emit_goto_or_jsr (target
, OPCODE_goto
, OPCODE_goto_w
, state
);
801 emit_jsr (target
, state
)
802 struct jcf_block
*target
;
803 struct jcf_partial
*state
;
805 emit_goto_or_jsr (target
, OPCODE_jsr
, OPCODE_jsr_w
, state
);
808 /* Generate code to evaluate EXP. If the result is true,
809 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
810 TRUE_BRANCH_FIRST is a code geneation hint that the
811 TRUE_LABEL may follow right after this. (The idea is that we
812 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
815 generate_bytecode_conditional (exp
, true_label
, false_label
,
816 true_branch_first
, state
)
818 struct jcf_block
*true_label
;
819 struct jcf_block
*false_label
;
820 int true_branch_first
;
821 struct jcf_partial
*state
;
824 tree exp0
, exp1
, type
;
825 int save_SP
= state
->code_SP
;
826 enum java_opcode op
, negop
;
827 switch (TREE_CODE (exp
))
830 emit_goto (integer_zerop (exp
) ? false_label
: true_label
, state
);
834 struct jcf_block
*then_label
= gen_jcf_label (state
);
835 struct jcf_block
*else_label
= gen_jcf_label (state
);
836 int save_SP_before
, save_SP_after
;
837 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
838 then_label
, else_label
, 1, state
);
839 define_jcf_label (then_label
, state
);
840 save_SP_before
= state
->code_SP
;
841 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
842 true_label
, false_label
, 1, state
);
843 save_SP_after
= state
->code_SP
;
844 state
->code_SP
= save_SP_before
;
845 define_jcf_label (else_label
, state
);
846 generate_bytecode_conditional (TREE_OPERAND (exp
, 2),
847 true_label
, false_label
,
848 true_branch_first
, state
);
849 if (state
->code_SP
!= save_SP_after
)
850 fatal ("internal error non-matching SP");
853 case TRUTH_ANDIF_EXPR
:
855 struct jcf_block
*next_label
= gen_jcf_label (state
);
856 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
857 next_label
, false_label
, 1, state
);
858 define_jcf_label (next_label
, state
);
859 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
860 true_label
, false_label
, 1, state
);
863 case TRUTH_ORIF_EXPR
:
865 struct jcf_block
*next_label
= gen_jcf_label (state
);
866 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
867 true_label
, next_label
, 1, state
);
868 define_jcf_label (next_label
, state
);
869 generate_bytecode_conditional (TREE_OPERAND (exp
, 1),
870 true_label
, false_label
, 1, state
);
874 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
875 set it to the corresponding 1-operand if<COND> instructions. */
879 /* The opcodes with their inverses are allocated in pairs.
880 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
881 negop
= (op
& 1) ? op
+ 1 : op
- 1;
883 if (true_branch_first
)
885 emit_if (false_label
, negop
, op
, state
);
886 emit_goto (true_label
, state
);
890 emit_if (true_label
, op
, negop
, state
);
891 emit_goto (false_label
, state
);
895 op
= OPCODE_if_icmpeq
;
898 op
= OPCODE_if_icmpne
;
901 op
= OPCODE_if_icmpgt
;
904 op
= OPCODE_if_icmplt
;
907 op
= OPCODE_if_icmpge
;
910 op
= OPCODE_if_icmple
;
913 exp0
= TREE_OPERAND (exp
, 0);
914 exp1
= TREE_OPERAND (exp
, 1);
915 type
= TREE_TYPE (exp0
);
916 switch (TREE_CODE (type
))
918 case POINTER_TYPE
: case RECORD_TYPE
:
919 switch (TREE_CODE (exp
))
921 case EQ_EXPR
: op
= OPCODE_if_acmpeq
; break;
922 case NE_EXPR
: op
= OPCODE_if_acmpne
; break;
925 if (integer_zerop (exp1
) || integer_zerop (exp0
))
927 generate_bytecode_insns (integer_zerop (exp1
) ? exp0
: exp0
,
928 STACK_TARGET
, state
);
929 op
= op
+ (OPCODE_ifnull
- OPCODE_if_acmpeq
);
930 negop
= (op
& 1) ? op
- 1 : op
+ 1;
934 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
935 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
939 fatal ("float comparison not implemented");
941 if (TYPE_PRECISION (type
) > 32)
943 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
944 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
952 if (integer_zerop (exp1
))
954 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
958 if (integer_zerop (exp0
))
962 case OPCODE_if_icmplt
:
963 case OPCODE_if_icmpge
:
966 case OPCODE_if_icmpgt
:
967 case OPCODE_if_icmple
:
971 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
975 generate_bytecode_insns (exp0
, STACK_TARGET
, state
);
976 generate_bytecode_insns (exp1
, STACK_TARGET
, state
);
982 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
984 if (true_branch_first
)
986 emit_if (false_label
, OPCODE_ifeq
, OPCODE_ifne
, state
);
987 emit_goto (true_label
, state
);
991 emit_if (true_label
, OPCODE_ifne
, OPCODE_ifeq
, state
);
992 emit_goto (false_label
, state
);
996 if (save_SP
!= state
->code_SP
)
997 fatal ("inetrnal error - SP mismatch");
1000 /* Generate bytecode for sub-expression EXP of METHOD.
1001 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1004 generate_bytecode_insns (exp
, target
, state
)
1007 struct jcf_partial
*state
;
1010 enum java_opcode jopcode
;
1012 HOST_WIDE_INT value
;
1017 if (exp
== NULL
&& target
== IGNORE_TARGET
)
1020 type
= TREE_TYPE (exp
);
1022 switch (TREE_CODE (exp
))
1025 if (BLOCK_EXPR_BODY (exp
))
1028 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1030 tree next
= TREE_CHAIN (local
);
1031 localvar_alloc (local
, state
);
1034 generate_bytecode_insns (BLOCK_EXPR_BODY (exp
), target
, state
);
1035 for (local
= BLOCK_EXPR_DECLS (exp
); local
; )
1037 tree next
= TREE_CHAIN (local
);
1038 localvar_free (local
, state
);
1044 generate_bytecode_insns (TREE_OPERAND (exp
, 0), IGNORE_TARGET
, state
);
1045 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1047 case EXPR_WITH_FILE_LOCATION
:
1049 char *saved_input_filename
= input_filename
;
1050 int saved_lineno
= lineno
;
1051 input_filename
= EXPR_WFL_FILENAME (exp
);
1052 lineno
= EXPR_WFL_LINENO (exp
);
1053 if (EXPR_WFL_EMIT_LINE_NOTE (exp
))
1054 put_linenumber (EXPR_WFL_LINENO (exp
), state
);
1055 generate_bytecode_insns (EXPR_WFL_NODE (exp
), target
, state
);
1056 input_filename
= saved_input_filename
;
1057 lineno
= saved_lineno
;
1061 if (target
== IGNORE_TARGET
) ; /* do nothing */
1062 else if (TREE_CODE (type
) == POINTER_TYPE
)
1064 if (! integer_zerop (exp
))
1067 OP1 (OPCODE_aconst_null
);
1070 else if (TYPE_PRECISION (type
) <= 32)
1072 push_int_const (TREE_INT_CST_LOW (exp
), state
);
1077 push_long_const (TREE_INT_CST_LOW (exp
), TREE_INT_CST_HIGH (exp
),
1083 if (TREE_STATIC (exp
))
1085 field_op (exp
, OPCODE_getstatic
, state
);
1086 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1089 /* ... fall through ... */
1091 emit_load (exp
, state
);
1094 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1097 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1098 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1099 if (target
!= IGNORE_TARGET
)
1101 jopcode
= OPCODE_iaload
+ adjust_typed_op (type
);
1109 tree obj
= TREE_OPERAND (exp
, 0);
1110 tree field
= TREE_OPERAND (exp
, 1);
1111 int is_static
= FIELD_STATIC (field
);
1112 generate_bytecode_insns (obj
,
1113 is_static
? IGNORE_TARGET
: target
, state
);
1114 if (target
!= IGNORE_TARGET
)
1116 if (DECL_NAME (field
) == length_identifier_node
&& !is_static
1117 && TYPE_ARRAY_P (TREE_TYPE (obj
)))
1120 OP1 (OPCODE_arraylength
);
1124 field_op (field
, is_static
? OPCODE_getstatic
: OPCODE_getfield
,
1128 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1133 case TRUTH_ANDIF_EXPR
:
1134 case TRUTH_ORIF_EXPR
:
1142 struct jcf_block
*then_label
= gen_jcf_label (state
);
1143 struct jcf_block
*else_label
= gen_jcf_label (state
);
1144 struct jcf_block
*end_label
= gen_jcf_label (state
);
1145 generate_bytecode_conditional (exp
,
1146 then_label
, else_label
, 1, state
);
1147 define_jcf_label (then_label
, state
);
1148 push_int_const (1, state
);
1149 emit_goto (end_label
, state
);
1150 define_jcf_label (else_label
, state
);
1151 push_int_const (0, state
);
1152 define_jcf_label (end_label
, state
);
1158 struct jcf_block
*then_label
= gen_jcf_label (state
);
1159 struct jcf_block
*else_label
= gen_jcf_label (state
);
1160 struct jcf_block
*end_label
= gen_jcf_label (state
);
1161 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1162 then_label
, else_label
, 1, state
);
1163 define_jcf_label (then_label
, state
);
1164 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1165 emit_goto (end_label
, state
);
1166 define_jcf_label (else_label
, state
);
1167 generate_bytecode_insns (TREE_OPERAND (exp
, 2), target
, state
);
1168 define_jcf_label (end_label
, state
);
1172 if (!TREE_OPERAND (exp
, 0))
1176 exp
= TREE_OPERAND (exp
, 0);
1177 if (TREE_CODE (exp
) != MODIFY_EXPR
)
1179 exp
= TREE_OPERAND (exp
, 1);
1180 op
= OPCODE_ireturn
+ adjust_typed_op (TREE_TYPE (exp
));
1181 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1186 case LABELED_BLOCK_EXPR
:
1188 struct jcf_block
*end_label
= gen_jcf_label (state
);
1189 end_label
->next
= state
->labeled_blocks
;
1190 state
->labeled_blocks
= end_label
;
1191 end_label
->u
.labeled_block
= exp
;
1192 if (LABELED_BLOCK_BODY (exp
))
1193 generate_bytecode_insns (LABELED_BLOCK_BODY (exp
), target
, state
);
1194 if (state
->labeled_blocks
!= end_label
)
1196 state
->labeled_blocks
= end_label
->next
;
1197 define_jcf_label (end_label
, state
);
1202 tree body
= TREE_OPERAND (exp
, 0);
1204 if (TREE_CODE (body
) == COMPOUND_EXPR
1205 && TREE_CODE (TREE_OPERAND (body
, 0)) == EXIT_EXPR
)
1207 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1208 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1209 struct jcf_block
*head_label
;
1210 struct jcf_block
*body_label
;
1211 struct jcf_block
*end_label
= gen_jcf_label (state
);
1212 struct jcf_block
*exit_label
= state
->labeled_blocks
;
1213 head_label
= gen_jcf_label (state
);
1214 emit_goto (head_label
, state
);
1215 body_label
= get_jcf_label_here (state
);
1216 generate_bytecode_insns (TREE_OPERAND (body
, 1), target
, state
);
1217 define_jcf_label (head_label
, state
);
1218 generate_bytecode_conditional (TREE_OPERAND (body
, 0),
1219 end_label
, body_label
, 1, state
);
1220 define_jcf_label (end_label
, state
);
1225 struct jcf_block
*head_label
= get_jcf_label_here (state
);
1226 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1227 emit_goto (head_label
, state
);
1233 struct jcf_block
*label
= state
->labeled_blocks
;
1234 struct jcf_block
*end_label
= gen_jcf_label (state
);
1235 generate_bytecode_conditional (TREE_OPERAND (exp
, 0),
1236 label
, end_label
, 0, state
);
1237 define_jcf_label (end_label
, state
);
1240 case EXIT_BLOCK_EXPR
:
1242 struct jcf_block
*label
= state
->labeled_blocks
;
1243 if (TREE_OPERAND (exp
, 1) != NULL
) goto notimpl
;
1244 while (label
->u
.labeled_block
!= TREE_OPERAND (exp
, 0))
1245 label
= label
->next
;
1246 emit_goto (label
, state
);
1250 case PREDECREMENT_EXPR
: value
= -1; post_op
= 0; goto increment
;
1251 case PREINCREMENT_EXPR
: value
= 1; post_op
= 0; goto increment
;
1252 case POSTDECREMENT_EXPR
: value
= -1; post_op
= 1; goto increment
;
1253 case POSTINCREMENT_EXPR
: value
= 1; post_op
= 1; goto increment
;
1256 exp
= TREE_OPERAND (exp
, 0);
1257 type
= TREE_TYPE (exp
);
1258 size
= TYPE_IS_WIDE (type
) ? 2 : 1;
1259 if ((TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1260 && ! TREE_STATIC (exp
)
1261 && TREE_CODE (type
) == INTEGER_TYPE
1262 && TYPE_PRECISION (type
) == 32)
1264 if (target
!= IGNORE_TARGET
&& post_op
)
1265 emit_load (exp
, state
);
1266 emit_iinc (exp
, value
, state
);
1267 if (target
!= IGNORE_TARGET
)
1270 emit_load (exp
, state
);
1275 if (TREE_CODE (exp
) == COMPONENT_REF
)
1277 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1278 emit_dup (1, 0, state
);
1279 /* Stack: ..., objectref, objectref. */
1280 field_op (TREE_OPERAND (exp
, 1), OPCODE_getstatic
, state
);
1282 /* Stack: ..., objectref, oldvalue. */
1285 else if (TREE_CODE (exp
) == ARRAY_REF
)
1287 generate_bytecode_insns (TREE_OPERAND (exp
, 0), STACK_TARGET
, state
);
1288 generate_bytecode_insns (TREE_OPERAND (exp
, 1), STACK_TARGET
, state
);
1289 emit_dup (2, 0, state
);
1290 /* Stack: ..., array, index, array, index. */
1291 jopcode
= OPCODE_iaload
+ adjust_typed_op (TREE_TYPE (exp
));
1295 /* Stack: ..., array, index, oldvalue. */
1298 else if (TREE_CODE (exp
) == VAR_DECL
|| TREE_CODE (exp
) == PARM_DECL
)
1300 generate_bytecode_insns (exp
, STACK_TARGET
, state
);
1301 /* Stack: ..., oldvalue. */
1307 if (target
!= IGNORE_TARGET
&& post_op
)
1308 emit_dup (size
, offset
, state
);
1309 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1310 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1311 /* Stack, otherwise: ..., [result, ] oldvalue. */
1312 push_int_const (value
, state
); /* FIXME - assumes int! */
1314 emit_binop (OPCODE_iadd
+ adjust_typed_op (type
), type
, state
);
1315 if (target
!= IGNORE_TARGET
&& ! post_op
)
1316 emit_dup (size
, offset
, state
);
1317 /* Stack: ..., [result,] newvalue. */
1318 goto finish_assignment
;
1322 tree lhs
= TREE_OPERAND (exp
, 0);
1323 tree rhs
= TREE_OPERAND (exp
, 1);
1325 /* See if we can use the iinc instruction. */
1326 if ((TREE_CODE (lhs
) == VAR_DECL
|| TREE_CODE (lhs
) == PARM_DECL
)
1327 && ! TREE_STATIC (lhs
)
1328 && TREE_CODE (TREE_TYPE (lhs
)) == INTEGER_TYPE
1329 && TYPE_PRECISION (TREE_TYPE (lhs
)) == 32
1330 && (TREE_CODE (rhs
) == PLUS_EXPR
|| TREE_CODE (rhs
) == MINUS_EXPR
))
1332 tree arg0
= TREE_OPERAND (rhs
, 0);
1333 tree arg1
= TREE_OPERAND (rhs
, 1);
1334 HOST_WIDE_INT min_value
= -32768;
1335 HOST_WIDE_INT max_value
= 32767;
1336 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1341 else if (arg1
== lhs
)
1344 arg1
= TREE_OPERAND (rhs
, 0);
1346 if (lhs
== arg0
&& TREE_CODE (arg1
) == INTEGER_CST
)
1348 HOST_WIDE_INT hi_value
= TREE_INT_CST_HIGH (arg1
);
1349 value
= TREE_INT_CST_LOW (arg1
);
1350 if ((hi_value
== 0 && value
<= max_value
)
1351 || (hi_value
== -1 && value
>= min_value
))
1353 if (TREE_CODE (rhs
) == MINUS_EXPR
)
1355 emit_iinc (lhs
, value
, state
);
1361 if (TREE_CODE (lhs
) == COMPONENT_REF
)
1362 generate_bytecode_insns (TREE_OPERAND (lhs
, 0), STACK_TARGET
, state
);
1363 else if (TREE_CODE (lhs
) == ARRAY_REF
)
1365 generate_bytecode_insns (TREE_OPERAND(lhs
, 0), STACK_TARGET
, state
);
1366 generate_bytecode_insns (TREE_OPERAND(lhs
, 1), STACK_TARGET
, state
);
1368 generate_bytecode_insns (rhs
, STACK_TARGET
, state
);
1369 if (target
!= IGNORE_TARGET
)
1370 emit_dup (TYPE_IS_WIDE (type
) ? 2 : 1 , 1, state
);
1376 if (TREE_CODE (exp
) == COMPONENT_REF
)
1378 tree field
= TREE_OPERAND (exp
, 1);
1379 if (! FIELD_STATIC (field
))
1382 FIELD_STATIC (field
) ? OPCODE_putstatic
1386 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field
)) ? 2 : 1);
1388 else if (TREE_CODE (exp
) == VAR_DECL
1389 || TREE_CODE (exp
) == PARM_DECL
)
1391 if (FIELD_STATIC (exp
))
1393 field_op (exp
, OPCODE_putstatic
, state
);
1394 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1397 emit_store (exp
, state
);
1399 else if (TREE_CODE (exp
) == ARRAY_REF
)
1402 jopcode
= OPCODE_iastore
+ adjust_typed_op (TREE_TYPE (exp
));
1405 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp
)) ? 2 : 1);
1408 fatal ("internal error (bad lhs to MODIFY_EXPR)");
1411 jopcode
= OPCODE_iadd
+ adjust_typed_op (type
);
1414 jopcode
= OPCODE_isub
+ adjust_typed_op (type
);
1417 jopcode
= OPCODE_imul
+ adjust_typed_op (type
);
1419 case TRUNC_DIV_EXPR
:
1421 jopcode
= OPCODE_idiv
+ adjust_typed_op (type
);
1424 generate_bytecode_insns (TREE_OPERAND (exp
, 0), target
, state
);
1425 generate_bytecode_insns (TREE_OPERAND (exp
, 1), target
, state
);
1426 if (target
== STACK_TARGET
)
1427 emit_binop (jopcode
, type
, state
);
1432 int save_SP
= state
->code_SP
;
1433 for (t
= TREE_OPERAND (exp
, 1); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
1435 generate_bytecode_insns (TREE_VALUE (t
), STACK_TARGET
, state
);
1437 t
= TREE_OPERAND (exp
, 0);
1438 state
->code_SP
= save_SP
;
1439 if (TREE_CODE (t
) == FUNCTION_DECL
)
1441 int index
= find_methodref_index (&state
->cpool
, t
);
1443 if (DECL_CONSTRUCTOR_P (t
))
1444 OP1 (OPCODE_invokespecial
);
1445 else if (METHOD_STATIC (t
))
1446 OP1 (OPCODE_invokestatic
);
1448 OP1 (OPCODE_invokevirtual
);
1450 t
= TREE_TYPE (TREE_TYPE (t
));
1451 if (TREE_CODE (t
) != VOID_TYPE
)
1453 int size
= TYPE_IS_WIDE (t
) ? 2 : 1;
1454 if (target
== IGNORE_TARGET
)
1455 emit_pop (size
, state
);
1465 error("internal error - tree code not implemented: %s",
1466 tree_code_name
[(int) TREE_CODE (exp
)]);
1471 perform_relocations (state
)
1472 struct jcf_partial
*state
;
1474 struct jcf_block
*block
;
1475 struct jcf_relocation
*reloc
;
1479 /* Figure out the actual locations of each block. */
1482 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
1484 int block_size
= block
->chunk
->size
;
1488 /* Optimize GOTO L; L: by getting rid of the redundant goto.
1489 Assumes relocations are in reverse order. */
1490 reloc
= block
->u
.relocations
;
1491 while (reloc
!= NULL
1492 && reloc
->label
->pc
== block
->next
->pc
1493 && reloc
->offset
+ 2 == block_size
1494 && reloc
->kind
== OPCODE_goto_w
)
1496 reloc
= reloc
->next
;
1497 block
->u
.relocations
= reloc
;
1498 block
->chunk
->size
-= 3;
1503 for (reloc
= block
->u
.relocations
; reloc
!= NULL
; reloc
= reloc
->next
)
1505 if (reloc
->kind
< -1 || reloc
->kind
> 0)
1507 int delta
= reloc
->label
->pc
- (pc
+ reloc
->offset
- 1);
1508 int expand
= reloc
->kind
> 0 ? 2 : 5;
1512 if (delta
>= -32768 && delta
<= 32767)
1518 block_size
+= expand
;
1524 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
1526 struct chunk
*chunk
= block
->chunk
;
1527 int old_size
= chunk
->size
;
1528 int next_pc
= block
->next
== NULL
? pc
: block
->next
->pc
;
1529 int new_size
= next_pc
- block
->pc
;
1531 unsigned char *new_ptr
;
1532 unsigned char *old_buffer
= chunk
->data
;
1533 unsigned char *old_ptr
= old_buffer
+ old_size
;
1534 int new_end
= new_size
;
1535 if (new_size
!= old_size
)
1537 chunk
->data
= (unsigned char *)
1538 obstack_alloc (state
->chunk_obstack
, new_size
);
1540 new_ptr
= chunk
->data
+ new_size
;
1542 /* We do the relocations from back to front, because
1543 thre relocations are in reverse order. */
1544 for (reloc
= block
->u
.relocations
; ; reloc
= reloc
->next
)
1546 /* Lower old index of piece to be copied with no relocation. */
1547 int start
= reloc
== NULL
? 0
1548 : reloc
->kind
== 0 ? reloc
->offset
+ 4
1549 : reloc
->offset
+ 2;
1552 int n
= (old_ptr
- old_buffer
) - start
;
1556 bcopy (old_ptr
, new_ptr
, n
);
1557 if (old_ptr
== old_buffer
)
1560 if (reloc
->kind
== 0)
1563 value
= GET_u4 (old_ptr
);
1568 value
= GET_u2 (old_ptr
);
1570 new_offset
= new_ptr
- chunk
->data
- (reloc
->kind
== -1 ? 2 : 4);
1571 value
+= reloc
->label
->pc
- (block
->pc
+ new_offset
);
1572 *--new_ptr
= (unsigned char) value
; value
>>= 8;
1573 *--new_ptr
= (unsigned char) value
; value
>>= 8;
1574 if (reloc
->kind
!= -1)
1576 *--new_ptr
= (unsigned char) value
; value
>>= 8;
1577 *--new_ptr
= (unsigned char) value
;
1579 if (reloc
->kind
> 0)
1581 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
1583 *--new_ptr
= reloc
->kind
;
1585 else if (reloc
->kind
< -1)
1587 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
1589 *--new_ptr
= OPCODE_goto_w
;
1592 *--new_ptr
= - reloc
->kind
;
1596 state
->code_length
= pc
;
1600 init_jcf_state (state
, work
)
1601 struct jcf_partial
*state
;
1602 struct obstack
*work
;
1604 state
->chunk_obstack
= work
;
1605 state
->first
= state
->chunk
= NULL
;
1606 CPOOL_INIT (&state
->cpool
);
1607 BUFFER_INIT (&state
->localvars
);
1608 BUFFER_INIT (&state
->bytecode
);
1612 init_jcf_method (state
, method
)
1613 struct jcf_partial
*state
;
1616 state
->current_method
= method
;
1617 state
->blocks
= state
->last_block
= NULL
;
1618 state
->linenumber_count
= 0;
1619 state
->first_lvar
= state
->last_lvar
= NULL
;
1620 state
->lvar_count
= 0;
1621 state
->labeled_blocks
= NULL
;
1622 state
->code_length
= 0;
1623 BUFFER_RESET (&state
->bytecode
);
1624 BUFFER_RESET (&state
->localvars
);
1626 state
->code_SP_max
= 0;
1630 release_jcf_state (state
)
1631 struct jcf_partial
*state
;
1633 CPOOL_FINISH (&state
->cpool
);
1634 obstack_free (state
->chunk_obstack
, state
->first
);
1637 /* Generate and return a list of chunks containing the class CLAS
1638 in the .class file representation. The list can be written to a
1639 .class file using write_chunks. Allocate chunks from obstack WORK. */
1642 generate_classfile (clas
, state
)
1644 struct jcf_partial
*state
;
1646 struct chunk
*cpool_chunk
;
1650 char *fields_count_ptr
;
1651 int fields_count
= 0;
1652 char *methods_count_ptr
;
1653 int methods_count
= 0;
1654 static tree SourceFile_node
= NULL_TREE
;
1657 = clas
== object_type_node
? 0
1658 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas
));
1660 ptr
= append_chunk (NULL
, 8, state
);
1661 PUT4 (0xCafeBabe); /* Magic number */
1662 PUT2 (3); /* Minor version */
1663 PUT2 (45); /* Major version */
1665 append_chunk (NULL
, 0, state
);
1666 cpool_chunk
= state
->chunk
;
1668 /* Next allocate the chunk containing acces_flags through fields_counr. */
1669 if (clas
== object_type_node
)
1672 i
= 8 + 2 * total_supers
;
1673 ptr
= append_chunk (NULL
, i
, state
);
1674 i
= get_access_flags (TYPE_NAME (clas
)); PUT2 (i
); /* acces_flags */
1675 i
= find_class_constant (&state
->cpool
, clas
); PUT2 (i
); /* this_class */
1676 if (clas
== object_type_node
)
1678 PUT2(0); /* super_class */
1679 PUT2(0); /* interfaces_count */
1683 tree basetypes
= TYPE_BINFO_BASETYPES (clas
);
1684 tree base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, 0));
1685 int j
= find_class_constant (&state
->cpool
, base
);
1686 PUT2 (j
); /* super_class */
1687 PUT2 (total_supers
- 1); /* interfaces_count */
1688 for (i
= 1; i
< total_supers
; i
++)
1690 base
= BINFO_TYPE (TREE_VEC_ELT (basetypes
, i
));
1691 j
= find_class_constant (&state
->cpool
, base
);
1695 fields_count_ptr
= ptr
;
1697 for (part
= TYPE_FIELDS (clas
); part
; part
= TREE_CHAIN (part
))
1699 if (DECL_NAME (part
) == NULL_TREE
)
1701 ptr
= append_chunk (NULL
, 8, state
);
1702 i
= get_access_flags (part
); PUT2 (i
);
1703 i
= find_utf8_constant (&state
->cpool
, DECL_NAME (part
)); PUT2 (i
);
1704 i
= find_utf8_constant (&state
->cpool
, build_java_signature (TREE_TYPE (part
)));
1706 PUT2 (0); /* attributes_count */
1707 /* FIXME - emit ConstantValue attribute when appropriate */
1710 ptr
= fields_count_ptr
; PUT2 (fields_count
);
1712 ptr
= methods_count_ptr
= append_chunk (NULL
, 2, state
);
1715 for (part
= TYPE_METHODS (clas
); part
; part
= TREE_CHAIN (part
))
1717 struct jcf_block
*block
;
1718 tree body
= BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (part
));
1719 tree name
= DECL_CONSTRUCTOR_P (part
) ? init_identifier_node
1721 tree type
= TREE_TYPE (part
);
1722 ptr
= append_chunk (NULL
, 8, state
);
1723 i
= get_access_flags (part
); PUT2 (i
);
1724 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
1725 i
= find_utf8_constant (&state
->cpool
, build_java_signature (type
));
1727 PUT2 (body
!= NULL_TREE
? 1 : 0); /* attributes_count */
1728 if (body
!= NULL_TREE
)
1730 int code_attributes_count
= 0;
1731 static tree Code_node
= NULL_TREE
;
1734 if (Code_node
== NULL_TREE
)
1735 Code_node
= get_identifier ("Code");
1736 ptr
= append_chunk (NULL
, 14, state
);
1737 i
= find_utf8_constant (&state
->cpool
, Code_node
); PUT2 (i
);
1739 init_jcf_method (state
, part
);
1740 get_jcf_label_here (state
); /* Force a first block. */
1741 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
1742 localvar_alloc (t
, state
);
1743 generate_bytecode_insns (body
, IGNORE_TARGET
, state
);
1744 for (t
= DECL_ARGUMENTS (part
); t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
1745 localvar_free (t
, state
);
1746 finish_jcf_block (state
);
1747 perform_relocations (state
);
1750 i
= 8 + state
->code_length
+ 4;
1751 if (state
->linenumber_count
> 0)
1753 code_attributes_count
++;
1754 i
+= 8 + 4 * state
->linenumber_count
;
1756 if (state
->lvar_count
> 0)
1758 code_attributes_count
++;
1759 i
+= 8 + 10 * state
->lvar_count
;
1761 PUT4 (i
); /* attribute_length */
1762 PUT2 (state
->code_SP_max
); /* max_stack */
1763 PUT2 (localvar_max
); /* max_locals */
1764 PUT4 (state
->code_length
);
1765 ptr
= append_chunk (NULL
, 4, state
);
1766 PUT2 (0); /* exception_table_length */
1767 PUT2 (code_attributes_count
);
1769 /* Write the LineNumberTable attribute. */
1770 if (state
->linenumber_count
> 0)
1772 static tree LineNumberTable_node
= NULL_TREE
;
1773 ptr
= append_chunk (NULL
, 8 + 4 * state
->linenumber_count
, state
);
1774 if (LineNumberTable_node
== NULL_TREE
)
1775 LineNumberTable_node
= get_identifier ("LineNumberTable");
1776 i
= find_utf8_constant (&state
->cpool
, LineNumberTable_node
);
1777 PUT2 (i
); /* attribute_name_index */
1778 i
= 2+4*state
->linenumber_count
; PUT4(i
); /* attribute_length */
1779 i
= state
->linenumber_count
; PUT2 (i
);
1780 for (block
= state
->blocks
; block
!= NULL
; block
= block
->next
)
1782 int line
= block
->linenumber
;
1791 /* Write the LocalVariableTable attribute. */
1792 if (state
->lvar_count
> 0)
1794 static tree LocalVariableTable_node
= NULL_TREE
;
1795 struct localvar_info
*lvar
= state
->first_lvar
;
1796 ptr
= append_chunk (NULL
, 8 + 10 * state
->lvar_count
, state
);
1797 if (LocalVariableTable_node
== NULL_TREE
)
1798 LocalVariableTable_node
= get_identifier("LocalVariableTable");
1799 i
= find_utf8_constant (&state
->cpool
, LocalVariableTable_node
);
1800 PUT2 (i
); /* attribute_name_index */
1801 i
= 2 + 10 * state
->lvar_count
; PUT4 (i
); /* attribute_length */
1802 i
= state
->lvar_count
; PUT2 (i
);
1803 for ( ; lvar
!= NULL
; lvar
= lvar
->next
)
1805 tree name
= DECL_NAME (lvar
->decl
);
1806 tree sig
= build_java_signature (TREE_TYPE (lvar
->decl
));
1807 i
= lvar
->start_label
->pc
; PUT2 (i
);
1808 i
= lvar
->end_label
->pc
- i
; PUT2 (i
);
1809 i
= find_utf8_constant (&state
->cpool
, name
); PUT2 (i
);
1810 i
= find_utf8_constant (&state
->cpool
, sig
); PUT2 (i
);
1811 i
= DECL_LOCAL_INDEX (lvar
->decl
); PUT2 (i
);
1817 ptr
= methods_count_ptr
; PUT2 (methods_count
);
1819 source_file
= DECL_SOURCE_FILE (TYPE_NAME (clas
));
1820 for (ptr
= source_file
; ; ptr
++)
1825 if (ch
== '/' || ch
== '\\')
1826 source_file
= ptr
+1;
1828 ptr
= append_chunk (NULL
, 10, state
);
1829 PUT2 (1); /* attributes_count */
1831 /* generate the SourceFile attribute. */
1832 if (SourceFile_node
== NULL_TREE
)
1833 SourceFile_node
= get_identifier ("SourceFile");
1834 i
= find_utf8_constant (&state
->cpool
, SourceFile_node
);
1835 PUT2 (i
); /* attribute_name_index */
1837 i
= find_utf8_constant (&state
->cpool
, get_identifier (source_file
));
1840 /* New finally generate the contents of the constant pool chunk. */
1841 i
= count_constant_pool_bytes (&state
->cpool
);
1842 ptr
= obstack_alloc (state
->chunk_obstack
, i
);
1843 cpool_chunk
->data
= ptr
;
1844 cpool_chunk
->size
= i
;
1845 write_constant_pool (&state
->cpool
, ptr
, i
);
1846 return state
->first
;
1850 make_class_file_name (clas
)
1853 /* Should prepend an output directly, but need an option to specify it. */
1854 return IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas
)),
1855 "", '.', '/', ".class"));
1858 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
1859 The output .class file name is make_class_file_name(CLAS). */
1862 write_classfile (clas
)
1865 struct obstack
*work
= &temporary_obstack
;
1866 struct jcf_partial state
[1];
1867 char *class_file_name
= make_class_file_name (clas
);
1868 struct chunk
*chunks
;
1869 FILE* stream
= fopen (class_file_name
, "wb");
1871 fatal ("failed to open `%s' for writing", class_file_name
);
1872 jcf_dependency_add_target (class_file_name
);
1873 init_jcf_state (state
, work
);
1874 chunks
= generate_classfile (clas
, state
);
1875 write_chunks (stream
, chunks
);
1876 if (fclose (stream
))
1877 fatal ("failed to close after writing `%s'", class_file_name
);
1878 release_jcf_state (state
);