]> gcc.gnu.org Git - gcc.git/blob - gcc/java/jcf-write.c
jcf-write.c (generate_byecode_insns): Fixed indentation for COMPOUND_EXPR and FIX_TRU...
[gcc.git] / gcc / java / jcf-write.c
1 /* Write out a Java(TM) class file.
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
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)
9 any later version.
10
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.
19
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. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "jcf.h"
27 #include "tree.h"
28 #include "java-tree.h"
29 #include "obstack.h"
30 #undef AND
31 #include "rtl.h"
32 #include "flags.h"
33 #include "java-opcodes.h"
34 #include "parse.h" /* for BLOCK_EXPR_BODY */
35 #include "buffer.h"
36 #include "toplev.h"
37
38 #ifndef DIR_SEPARATOR
39 #define DIR_SEPARATOR '/'
40 #endif
41
42 extern struct obstack temporary_obstack;
43
44 /* Base directory in which `.class' files should be written.
45 NULL means to put the file into the same directory as the
46 corresponding .java file. */
47 char *jcf_write_base_directory = NULL;
48
49 /* Make sure bytecode.data is big enough for at least N more bytes. */
50
51 #define RESERVE(N) \
52 do { CHECK_OP(state); \
53 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
54 buffer_grow (&state->bytecode, N); } while (0)
55
56 /* Add a 1-byte instruction/operand I to bytecode.data,
57 assuming space has already been RESERVE'd. */
58
59 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
60
61 /* Like OP1, but I is a 2-byte big endian integer. */
62
63 #define OP2(I) \
64 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
65
66 /* Like OP1, but I is a 4-byte big endian integer. */
67
68 #define OP4(I) \
69 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
70 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
71
72 /* Macro to call each time we push I words on the JVM stack. */
73
74 #define NOTE_PUSH(I) \
75 do { state->code_SP += (I); \
76 if (state->code_SP > state->code_SP_max) \
77 state->code_SP_max = state->code_SP; } while (0)
78
79 /* Macro to call each time we pop I words from the JVM stack. */
80
81 #define NOTE_POP(I) \
82 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
83
84 /* A chunk or segment of a .class file. */
85
86 struct chunk
87 {
88 /* The next segment of this .class file. */
89 struct chunk *next;
90
91 /* The actual data in this segment to be written to the .class file. */
92 unsigned char *data;
93
94 /* The size of the segment to be written to the .class file. */
95 int size;
96 };
97
98 #define PENDING_CLEANUP_PC (-3)
99 #define PENDING_EXIT_PC (-2)
100 #define UNDEFINED_PC (-1)
101
102 /* Each "block" represents a label plus the bytecode instructions following.
103 There may be branches out of the block, but no incoming jumps, except
104 to the beginning of the block.
105
106 If (pc < 0), the jcf_block is not an actual block (i.e. it has no
107 assocated code yet), but it is an undefined label.
108 */
109
110 struct jcf_block
111 {
112 /* For blocks that that are defined, the next block (in pc order).
113 For blocks that are the not-yet-defined end label of a LABELED_BLOCK_EXPR
114 or a cleanup expression (from a WITH_CLEANUP_EXPR),
115 this is the next (outer) such end label, in a stack headed by
116 labeled_blocks in jcf_partial. */
117 struct jcf_block *next;
118
119 /* In the not-yet-defined end label for an unfinished EXIT_BLOCK_EXPR.
120 pc is PENDING_EXIT_PC.
121 In the not-yet-defined end label for pending cleanup subroutine,
122 pc is PENDING_CLEANUP_PC.
123 For other not-yet-defined labels, pc is UNDEFINED_PC.
124
125 If the label has been defined:
126 Until perform_relocations is finished, this is the maximum possible
127 value of the bytecode offset at the begnning of this block.
128 After perform_relocations, it is the actual offset (pc). */
129 int pc;
130
131 int linenumber;
132
133 /* After finish_jcf_block is called, The actual instructions contained in this block.
134 Before than NULL, and the instructions are in state->bytecode. */
135 union {
136 struct chunk *chunk;
137
138 /* If pc==PENDING_CLEANUP_PC, start_label is the start of the region
139 coveed by the cleanup. */
140 struct jcf_block *start_label;
141 } v;
142
143 union {
144 /* Set of relocations (in reverse offset order) for this block. */
145 struct jcf_relocation *relocations;
146
147 /* If this block is that of the not-yet-defined end label of
148 a LABELED_BLOCK_EXPR, where LABELED_BLOCK is that LABELED_BLOCK_EXPR.
149 If pc==PENDING_CLEANUP_PC, the cleanup that needs to be run. */
150 tree labeled_block;
151 } u;
152 };
153
154 /* A "relocation" type for the 0-3 bytes of padding at the start
155 of a tableswitch or a lookupswitch. */
156 #define SWITCH_ALIGN_RELOC 4
157
158 /* A relocation type for the labels in a tableswitch or a lookupswitch;
159 these are relative to the start of the instruction, but (due to
160 th 0-3 bytes of padding), we don't know the offset before relocation. */
161 #define BLOCK_START_RELOC 1
162
163 struct jcf_relocation
164 {
165 /* Next relocation for the current jcf_block. */
166 struct jcf_relocation *next;
167
168 /* The (byte) offset within the current block that needs to be relocated. */
169 HOST_WIDE_INT offset;
170
171 /* 0 if offset is a 4-byte relative offset.
172 4 (SWITCH_ALIGN_RELOC) if offset points to 0-3 padding bytes inserted
173 for proper alignment in tableswitch/lookupswitch instructions.
174 1 (BLOCK_START_RELOC) if offset points to a 4-byte offset relative
175 to the start of the containing block.
176 -1 if offset is a 2-byte relative offset.
177 < -1 if offset is the address of an instruction with a 2-byte offset
178 that does not have a corresponding 4-byte offset version, in which
179 case the absolute value of kind is the inverted opcode.
180 > 4 if offset is the address of an instruction (such as jsr) with a
181 2-byte offset that does have a corresponding 4-byte offset version,
182 in which case kind is the opcode of the 4-byte version (such as jsr_w). */
183 int kind;
184
185 /* The label the relocation wants to actually transfer to. */
186 struct jcf_block *label;
187 };
188
189 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
190 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
191
192 /* State for single catch clause. */
193
194 struct jcf_handler
195 {
196 struct jcf_handler *next;
197
198 struct jcf_block *start_label;
199 struct jcf_block *end_label;
200 struct jcf_block *handler_label;
201
202 /* The sub-class of Throwable handled, or NULL_TREE (for finally). */
203 tree type;
204 };
205
206 /* State for the current switch statement. */
207
208 struct jcf_switch_state
209 {
210 struct jcf_switch_state *prev;
211 struct jcf_block *default_label;
212
213 struct jcf_relocation *cases;
214 int num_cases;
215 HOST_WIDE_INT min_case, max_case;
216 };
217
218 /* This structure is used to contain the various pieces that will
219 become a .class file. */
220
221 struct jcf_partial
222 {
223 struct chunk *first;
224 struct chunk *chunk;
225 struct obstack *chunk_obstack;
226 tree current_method;
227
228 /* List of basic blocks for the current method. */
229 struct jcf_block *blocks;
230 struct jcf_block *last_block;
231
232 struct localvar_info *first_lvar;
233 struct localvar_info *last_lvar;
234 int lvar_count;
235
236 CPool cpool;
237
238 int linenumber_count;
239
240 /* Until perform_relocations, this is a upper bound on the number
241 of bytes (so far) in the instructions for the current method. */
242 int code_length;
243
244 /* Stack of undefined ending labels for LABELED_BLOCK_EXPR. */
245 struct jcf_block *labeled_blocks;
246
247 /* The current stack size (stack pointer) in the current method. */
248 int code_SP;
249
250 /* The largest extent of stack size (stack pointer) in the current method. */
251 int code_SP_max;
252
253 /* Contains a mapping from local var slot number to localvar_info. */
254 struct buffer localvars;
255
256 /* The buffer allocated for bytecode for the current jcf_block. */
257 struct buffer bytecode;
258
259 /* Chain of exception handlers for the current method. */
260 struct jcf_handler *handlers;
261
262 /* Last element in handlers chain. */
263 struct jcf_handler *last_handler;
264
265 /* Number of exception handlers for the current method. */
266 int num_handlers;
267
268 /* Number of finalizers we are currently nested within. */
269 int num_finalizers;
270
271 /* If non-NULL, use this for the return value. */
272 tree return_value_decl;
273
274 /* Information about the current switch statemenet. */
275 struct jcf_switch_state *sw_state;
276 };
277
278 static void generate_bytecode_insns PROTO ((tree, int, struct jcf_partial *));
279 static struct chunk * alloc_chunk PROTO ((struct chunk *, unsigned char *,
280 int, struct obstack *));
281 static unsigned char * append_chunk PROTO ((unsigned char *, int,
282 struct jcf_partial *));
283 static void append_chunk_copy PROTO ((unsigned char *, int,
284 struct jcf_partial *));
285 static struct jcf_block * gen_jcf_label PROTO ((struct jcf_partial *));
286 static void finish_jcf_block PROTO ((struct jcf_partial *));
287 static void define_jcf_label PROTO ((struct jcf_block *,
288 struct jcf_partial *));
289 static struct jcf_block * get_jcf_label_here PROTO ((struct jcf_partial *));
290 static void put_linenumber PROTO ((int, struct jcf_partial *));
291 static void localvar_alloc PROTO ((tree, struct jcf_partial *));
292 static void localvar_free PROTO ((tree, struct jcf_partial *));
293 static int get_access_flags PROTO ((tree));
294 static void write_chunks PROTO ((FILE *, struct chunk *));
295 static int adjust_typed_op PROTO ((tree, int));
296 static void generate_bytecode_conditional PROTO ((tree, struct jcf_block *,
297 struct jcf_block *, int,
298 struct jcf_partial *));
299 static void generate_bytecode_return PROTO ((tree, struct jcf_partial *));
300 static void perform_relocations PROTO ((struct jcf_partial *));
301 static void init_jcf_state PROTO ((struct jcf_partial *, struct obstack *));
302 static void init_jcf_method PROTO ((struct jcf_partial *, tree));
303 static void release_jcf_state PROTO ((struct jcf_partial *));
304 static struct chunk * generate_classfile PROTO ((tree, struct jcf_partial *));
305 static struct jcf_handler *alloc_handler PROTO ((struct jcf_block *,
306 struct jcf_block *,
307 struct jcf_partial *));
308 static void emit_iinc PROTO ((tree, HOST_WIDE_INT, struct jcf_partial *));
309 static void emit_reloc PROTO ((HOST_WIDE_INT, int, struct jcf_block *,
310 struct jcf_partial *));
311 static void push_constant1 PROTO ((HOST_WIDE_INT, struct jcf_partial *));
312 static void push_constant2 PROTO ((HOST_WIDE_INT, struct jcf_partial *));
313 static void push_int_const PROTO ((HOST_WIDE_INT, struct jcf_partial *));
314 static int find_constant_wide PROTO ((HOST_WIDE_INT, HOST_WIDE_INT,
315 struct jcf_partial *));
316 static void push_long_const PROTO ((HOST_WIDE_INT, HOST_WIDE_INT,
317 struct jcf_partial *));
318 static int find_constant_index PROTO ((tree, struct jcf_partial *));
319 static void push_long_const PROTO ((HOST_WIDE_INT, HOST_WIDE_INT,
320 struct jcf_partial *));
321 static void field_op PROTO ((tree, int, struct jcf_partial *));
322 static void maybe_wide PROTO ((int, int, struct jcf_partial *));
323 static void emit_dup PROTO ((int, int, struct jcf_partial *));
324 static void emit_pop PROTO ((int, struct jcf_partial *));
325 static void emit_load_or_store PROTO ((tree, int, struct jcf_partial *));
326 static void emit_load PROTO ((tree, struct jcf_partial *));
327 static void emit_store PROTO ((tree, struct jcf_partial *));
328 static void emit_unop PROTO ((enum java_opcode, tree, struct jcf_partial *));
329 static void emit_binop PROTO ((enum java_opcode, tree, struct jcf_partial *));
330 static void emit_reloc PROTO ((HOST_WIDE_INT, int, struct jcf_block *,
331 struct jcf_partial *));
332 static void emit_switch_reloc PROTO ((struct jcf_block *,
333 struct jcf_partial *));
334 static void emit_case_reloc PROTO ((struct jcf_relocation *,
335 struct jcf_partial *));
336 static void emit_if PROTO ((struct jcf_block *, int, int,
337 struct jcf_partial *));
338 static void emit_goto PROTO ((struct jcf_block *, struct jcf_partial *));
339 static void emit_jsr PROTO ((struct jcf_block *, struct jcf_partial *));
340 static void call_cleanups PROTO ((struct jcf_block *, struct jcf_partial *));
341 static char *make_class_file_name PROTO ((tree));
342
343 /* Utility macros for appending (big-endian) data to a buffer.
344 We assume a local variable 'ptr' points into where we want to
345 write next, and we assume enoygh space has been allocated. */
346
347 #ifdef ENABLE_CHECKING
348 int
349 CHECK_PUT(ptr, state, i)
350 void *ptr;
351 struct jcf_partial *state;
352 int i;
353 {
354 if (ptr < state->chunk->data
355 || (char*)ptr + i > state->chunk->data + state->chunk->size)
356 fatal ("internal error - CHECK_PUT failed");
357 return 0;
358 }
359 #else
360 #define CHECK_PUT(PTR, STATE, I) ((void)0)
361 #endif
362
363 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
364 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
365 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
366 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
367
368 /* There are some cases below where CHECK_PUT is guaranteed to fail.
369 Use the following macros in those specific cases. */
370 #define UNSAFE_PUT1(X) (*ptr++ = (X))
371 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
372 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
373 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
374
375 \f
376 /* Allocate a new chunk on obstack WORK, and link it in after LAST.
377 Set the data and size fields to DATA and SIZE, respectively.
378 However, if DATA is NULL and SIZE>0, allocate a buffer as well. */
379
380 static struct chunk *
381 alloc_chunk (last, data, size, work)
382 struct chunk *last;
383 unsigned char *data;
384 int size;
385 struct obstack *work;
386 {
387 struct chunk *chunk = (struct chunk *)
388 obstack_alloc (work, sizeof(struct chunk));
389
390 if (data == NULL && size > 0)
391 data = obstack_alloc (work, size);
392
393 chunk->next = NULL;
394 chunk->data = data;
395 chunk->size = size;
396 if (last != NULL)
397 last->next = chunk;
398 return chunk;
399 }
400
401 #ifdef ENABLE_CHECKING
402 int
403 CHECK_OP(struct jcf_partial *state)
404 {
405 if (state->bytecode.ptr > state->bytecode.limit)
406 {
407 fatal("internal error - CHECK_OP failed");
408 }
409 return 0;
410 }
411 #else
412 #define CHECK_OP(STATE) ((void)0)
413 #endif
414
415 static unsigned char *
416 append_chunk (data, size, state)
417 unsigned char *data;
418 int size;
419 struct jcf_partial *state;
420 {
421 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
422 if (state->first == NULL)
423 state->first = state->chunk;
424 return state->chunk->data;
425 }
426
427 static void
428 append_chunk_copy (data, size, state)
429 unsigned char *data;
430 int size;
431 struct jcf_partial *state;
432 {
433 unsigned char *ptr = append_chunk (NULL, size, state);
434 memcpy (ptr, data, size);
435 }
436 \f
437 static struct jcf_block *
438 gen_jcf_label (state)
439 struct jcf_partial *state;
440 {
441 struct jcf_block *block = (struct jcf_block *)
442 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
443 block->next = NULL;
444 block->linenumber = -1;
445 block->pc = UNDEFINED_PC;
446 return block;
447 }
448
449 static void
450 finish_jcf_block (state)
451 struct jcf_partial *state;
452 {
453 struct jcf_block *block = state->last_block;
454 struct jcf_relocation *reloc;
455 int code_length = BUFFER_LENGTH (&state->bytecode);
456 int pc = state->code_length;
457 append_chunk_copy (state->bytecode.data, code_length, state);
458 BUFFER_RESET (&state->bytecode);
459 block->v.chunk = state->chunk;
460
461 /* Calculate code_length to the maximum value it can have. */
462 pc += block->v.chunk->size;
463 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
464 {
465 int kind = reloc->kind;
466 if (kind == SWITCH_ALIGN_RELOC)
467 pc += 3;
468 else if (kind > BLOCK_START_RELOC)
469 pc += 2; /* 2-byte offset may grow to 4-byte offset */
470 else if (kind < -1)
471 pc += 5; /* May need to add a goto_w. */
472 }
473 state->code_length = pc;
474 }
475
476 static void
477 define_jcf_label (label, state)
478 struct jcf_block *label;
479 struct jcf_partial *state;
480 {
481 if (state->last_block != NULL)
482 finish_jcf_block (state);
483 label->pc = state->code_length;
484 if (state->blocks == NULL)
485 state->blocks = label;
486 else
487 state->last_block->next = label;
488 state->last_block = label;
489 label->next = NULL;
490 label->u.relocations = NULL;
491 }
492
493 static struct jcf_block *
494 get_jcf_label_here (state)
495 struct jcf_partial *state;
496 {
497 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
498 return state->last_block;
499 else
500 {
501 struct jcf_block *label = gen_jcf_label (state);
502 define_jcf_label (label, state);
503 return label;
504 }
505 }
506
507 /* Note a line number entry for the current PC and given LINE. */
508
509 static void
510 put_linenumber (line, state)
511 int line;
512 struct jcf_partial *state;
513 {
514 struct jcf_block *label = get_jcf_label_here (state);
515 if (label->linenumber > 0)
516 {
517 label = gen_jcf_label (state);
518 define_jcf_label (label, state);
519 }
520 label->linenumber = line;
521 state->linenumber_count++;
522 }
523
524 /* Allocate a new jcf_handler, for a catch clause that catches exceptions
525 in the range (START_LABEL, END_LABEL). */
526
527 static struct jcf_handler *
528 alloc_handler (start_label, end_label, state)
529 struct jcf_block *start_label;
530 struct jcf_block *end_label;
531 struct jcf_partial *state;
532 {
533 struct jcf_handler *handler = (struct jcf_handler *)
534 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
535 handler->start_label = start_label;
536 handler->end_label = end_label;
537 handler->handler_label = get_jcf_label_here (state);
538 if (state->handlers == NULL)
539 state->handlers = handler;
540 else
541 state->last_handler->next = handler;
542 state->last_handler = handler;
543 handler->next = NULL;
544 state->num_handlers++;
545 return handler;
546 }
547
548 \f
549 /* The index of jvm local variable allocated for this DECL.
550 This is assigned when generating .class files;
551 contrast DECL_LOCAL_SLOT_NUMBER which is set when *reading* a .class file.
552 (We don't allocate DECL_LANG_SPECIFIC for locals from Java sourc code.) */
553
554 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
555
556 struct localvar_info
557 {
558 struct localvar_info *next;
559
560 tree decl;
561 struct jcf_block *start_label;
562 struct jcf_block *end_label;
563 };
564
565 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
566 #define localvar_max \
567 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
568
569 static void
570 localvar_alloc (decl, state)
571 tree decl;
572 struct jcf_partial *state;
573 {
574 struct jcf_block *start_label = get_jcf_label_here (state);
575 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
576 int index;
577 register struct localvar_info *info;
578 register struct localvar_info **ptr = localvar_buffer;
579 register struct localvar_info **limit
580 = (struct localvar_info**) state->localvars.ptr;
581 for (index = 0; ptr < limit; index++, ptr++)
582 {
583 if (ptr[0] == NULL
584 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
585 break;
586 }
587 if (ptr == limit)
588 {
589 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
590 ptr = (struct localvar_info**) state->localvars.data + index;
591 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
592 }
593 info = (struct localvar_info *)
594 obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
595 ptr[0] = info;
596 if (wide)
597 ptr[1] = (struct localvar_info *)(~0);
598 DECL_LOCAL_INDEX (decl) = index;
599 info->decl = decl;
600 info->start_label = start_label;
601
602 if (debug_info_level > DINFO_LEVEL_TERSE
603 && DECL_NAME (decl) != NULL_TREE)
604 {
605 /* Generate debugging info. */
606 info->next = NULL;
607 if (state->last_lvar != NULL)
608 state->last_lvar->next = info;
609 else
610 state->first_lvar = info;
611 state->last_lvar = info;
612 state->lvar_count++;
613 }
614 }
615
616 static void
617 localvar_free (decl, state)
618 tree decl;
619 struct jcf_partial *state;
620 {
621 struct jcf_block *end_label = get_jcf_label_here (state);
622 int index = DECL_LOCAL_INDEX (decl);
623 register struct localvar_info **ptr = &localvar_buffer [index];
624 register struct localvar_info *info = *ptr;
625 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
626
627 info->end_label = end_label;
628
629 if (info->decl != decl)
630 abort ();
631 ptr[0] = NULL;
632 if (wide)
633 {
634 if (ptr[1] != (struct localvar_info *)(~0))
635 abort ();
636 ptr[1] = NULL;
637 }
638 }
639
640 \f
641 #define STACK_TARGET 1
642 #define IGNORE_TARGET 2
643
644 /* Get the access flags of a class (TYPE_DECL), a method (FUNCTION_DECL), or
645 a field (FIELD_DECL or VAR_DECL, if static), as encoded in a .class file. */
646
647 static int
648 get_access_flags (decl)
649 tree decl;
650 {
651 int flags = 0;
652 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
653 if (CLASS_PUBLIC (decl)) /* same as FIELD_PUBLIC and METHOD_PUBLIC */
654 flags |= ACC_PUBLIC;
655 if (CLASS_FINAL (decl)) /* same as FIELD_FINAL and METHOD_FINAL */
656 flags |= ACC_FINAL;
657 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
658 {
659 if (TREE_PROTECTED (decl))
660 flags |= ACC_PROTECTED;
661 if (TREE_PRIVATE (decl))
662 flags |= ACC_PRIVATE;
663 }
664 else if (TREE_CODE (decl) == TYPE_DECL)
665 {
666 if (CLASS_SUPER (decl))
667 flags |= ACC_SUPER;
668 if (CLASS_ABSTRACT (decl))
669 flags |= ACC_ABSTRACT;
670 if (CLASS_INTERFACE (decl))
671 flags |= ACC_INTERFACE;
672 }
673 else
674 fatal ("internal error - bad argument to get_access_flags");
675 if (TREE_CODE (decl) == FUNCTION_DECL)
676 {
677 if (METHOD_NATIVE (decl))
678 flags |= ACC_NATIVE;
679 if (METHOD_STATIC (decl))
680 flags |= ACC_STATIC;
681 if (METHOD_SYNCHRONIZED (decl))
682 flags |= ACC_SYNCHRONIZED;
683 if (METHOD_ABSTRACT (decl))
684 flags |= ACC_ABSTRACT;
685 }
686 if (isfield)
687 {
688 if (FIELD_STATIC (decl))
689 flags |= ACC_STATIC;
690 if (FIELD_VOLATILE (decl))
691 flags |= ACC_VOLATILE;
692 if (FIELD_TRANSIENT (decl))
693 flags |= ACC_TRANSIENT;
694 }
695 return flags;
696 }
697
698 /* Write the list of segments starting at CHUNKS to STREAM. */
699
700 static void
701 write_chunks (stream, chunks)
702 FILE* stream;
703 struct chunk *chunks;
704 {
705 for (; chunks != NULL; chunks = chunks->next)
706 fwrite (chunks->data, chunks->size, 1, stream);
707 }
708
709 /* Push a 1-word constant in the constant pool at the given INDEX.
710 (Caller is responsible for doing NOTE_PUSH.) */
711
712 static void
713 push_constant1 (index, state)
714 HOST_WIDE_INT index;
715 struct jcf_partial *state;
716 {
717 RESERVE (3);
718 if (index < 256)
719 {
720 OP1 (OPCODE_ldc);
721 OP1 (index);
722 }
723 else
724 {
725 OP1 (OPCODE_ldc_w);
726 OP2 (index);
727 }
728 }
729
730 /* Push a 2-word constant in the constant pool at the given INDEX.
731 (Caller is responsible for doing NOTE_PUSH.) */
732
733 static void
734 push_constant2 (index, state)
735 HOST_WIDE_INT index;
736 struct jcf_partial *state;
737 {
738 RESERVE (3);
739 OP1 (OPCODE_ldc2_w);
740 OP2 (index);
741 }
742
743 /* Push 32-bit integer constant on VM stack.
744 Caller is responsible for doing NOTE_PUSH. */
745
746 static void
747 push_int_const (i, state)
748 HOST_WIDE_INT i;
749 struct jcf_partial *state;
750 {
751 RESERVE(3);
752 if (i >= -1 && i <= 5)
753 OP1(OPCODE_iconst_0 + i);
754 else if (i >= -128 && i < 128)
755 {
756 OP1(OPCODE_bipush);
757 OP1(i);
758 }
759 else if (i >= -32768 && i < 32768)
760 {
761 OP1(OPCODE_sipush);
762 OP2(i);
763 }
764 else
765 {
766 i = find_constant1 (&state->cpool, CONSTANT_Integer,
767 (jword)(i & 0xFFFFFFFF));
768 push_constant1 (i, state);
769 }
770 }
771
772 static int
773 find_constant_wide (lo, hi, state)
774 HOST_WIDE_INT lo, hi;
775 struct jcf_partial *state;
776 {
777 HOST_WIDE_INT w1, w2;
778 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
779 return find_constant2 (&state->cpool, CONSTANT_Long,
780 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
781 }
782
783 /* Find or allocate a constant pool entry for the given VALUE.
784 Return the index in the constant pool. */
785
786 static int
787 find_constant_index (value, state)
788 tree value;
789 struct jcf_partial *state;
790 {
791 if (TREE_CODE (value) == INTEGER_CST)
792 {
793 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
794 return find_constant1 (&state->cpool, CONSTANT_Integer,
795 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
796 else
797 return find_constant_wide (TREE_INT_CST_LOW (value),
798 TREE_INT_CST_HIGH (value), state);
799 }
800 else if (TREE_CODE (value) == REAL_CST)
801 {
802 long words[2];
803 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
804 {
805 words[0] = etarsingle (TREE_REAL_CST (value)) & 0xFFFFFFFF;
806 return find_constant1 (&state->cpool, CONSTANT_Float,
807 (jword)words[0]);
808 }
809 else
810 {
811 etardouble (TREE_REAL_CST (value), words);
812 return find_constant2 (&state->cpool, CONSTANT_Double,
813 (jword)(words[1-FLOAT_WORDS_BIG_ENDIAN] &
814 0xFFFFFFFF),
815 (jword)(words[FLOAT_WORDS_BIG_ENDIAN] &
816 0xFFFFFFFF));
817 }
818 }
819 else if (TREE_CODE (value) == STRING_CST)
820 {
821 return find_string_constant (&state->cpool, value);
822 }
823 else
824 fatal ("find_constant_index - bad type");
825 }
826
827 /* Push 64-bit long constant on VM stack.
828 Caller is responsible for doing NOTE_PUSH. */
829
830 static void
831 push_long_const (lo, hi, state)
832 HOST_WIDE_INT lo, hi;
833 struct jcf_partial *state;
834 {
835 if (hi == 0 && lo >= 0 && lo <= 1)
836 {
837 RESERVE(1);
838 OP1(OPCODE_lconst_0 + lo);
839 }
840 else if ((hi == 0 && lo < 32768) || (hi == -1 && lo >= -32768))
841 {
842 push_int_const (lo, state);
843 RESERVE (1);
844 OP1 (OPCODE_i2l);
845 }
846 else
847 push_constant2 (find_constant_wide (lo, hi, state), state);
848 }
849
850 static void
851 field_op (field, opcode, state)
852 tree field;
853 int opcode;
854 struct jcf_partial *state;
855 {
856 int index = find_fieldref_index (&state->cpool, field);
857 RESERVE (3);
858 OP1 (opcode);
859 OP2 (index);
860 }
861
862 /* Returns an integer in the range 0 (for 'int') through 4 (for object
863 reference) to 7 (for 'short') which matches the pattern of how JVM
864 opcodes typically depend on the operand type. */
865
866 static int
867 adjust_typed_op (type, max)
868 tree type;
869 int max;
870 {
871 switch (TREE_CODE (type))
872 {
873 case POINTER_TYPE:
874 case RECORD_TYPE: return 4;
875 case BOOLEAN_TYPE:
876 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
877 case CHAR_TYPE:
878 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
879 case INTEGER_TYPE:
880 switch (TYPE_PRECISION (type))
881 {
882 case 8: return max < 5 ? 0 : 5;
883 case 16: return max < 7 ? 0 : 7;
884 case 32: return 0;
885 case 64: return 1;
886 }
887 break;
888 case REAL_TYPE:
889 switch (TYPE_PRECISION (type))
890 {
891 case 32: return 2;
892 case 64: return 3;
893 }
894 break;
895 default:
896 break;
897 }
898 abort ();
899 }
900
901 static void
902 maybe_wide (opcode, index, state)
903 int opcode, index;
904 struct jcf_partial *state;
905 {
906 if (index >= 256)
907 {
908 RESERVE (4);
909 OP1 (OPCODE_wide);
910 OP1 (opcode);
911 OP2 (index);
912 }
913 else
914 {
915 RESERVE (2);
916 OP1 (opcode);
917 OP1 (index);
918 }
919 }
920
921 /* Compile code to duplicate with offset, where
922 SIZE is the size of the stack item to duplicate (1 or 2), abd
923 OFFSET is where to insert the result (must be 0, 1, or 2).
924 (The new words get inserted at stack[SP-size-offset].) */
925
926 static void
927 emit_dup (size, offset, state)
928 int size, offset;
929 struct jcf_partial *state;
930 {
931 int kind;
932 if (size == 0)
933 return;
934 RESERVE(1);
935 if (offset == 0)
936 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
937 else if (offset == 1)
938 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
939 else if (offset == 2)
940 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
941 else
942 abort();
943 OP1 (kind);
944 NOTE_PUSH (size);
945 }
946
947 static void
948 emit_pop (size, state)
949 int size;
950 struct jcf_partial *state;
951 {
952 RESERVE (1);
953 OP1 (OPCODE_pop - 1 + size);
954 }
955
956 static void
957 emit_iinc (var, value, state)
958 tree var;
959 HOST_WIDE_INT value;
960 struct jcf_partial *state;
961 {
962 int slot = DECL_LOCAL_INDEX (var);
963
964 if (value < -128 || value > 127 || slot >= 256)
965 {
966 RESERVE (6);
967 OP1 (OPCODE_wide);
968 OP1 (OPCODE_iinc);
969 OP2 (slot);
970 OP2 (value);
971 }
972 else
973 {
974 RESERVE (3);
975 OP1 (OPCODE_iinc);
976 OP1 (slot);
977 OP1 (value);
978 }
979 }
980
981 static void
982 emit_load_or_store (var, opcode, state)
983 tree var; /* Variable to load from or store into. */
984 int opcode; /* Either OPCODE_iload or OPCODE_istore. */
985 struct jcf_partial *state;
986 {
987 tree type = TREE_TYPE (var);
988 int kind = adjust_typed_op (type, 4);
989 int index = DECL_LOCAL_INDEX (var);
990 if (index <= 3)
991 {
992 RESERVE (1);
993 OP1 (opcode + 5 + 4 * kind + index); /* [ilfda]{load,store}_[0123] */
994 }
995 else
996 maybe_wide (opcode + kind, index, state); /* [ilfda]{load,store} */
997 }
998
999 static void
1000 emit_load (var, state)
1001 tree var;
1002 struct jcf_partial *state;
1003 {
1004 emit_load_or_store (var, OPCODE_iload, state);
1005 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1006 }
1007
1008 static void
1009 emit_store (var, state)
1010 tree var;
1011 struct jcf_partial *state;
1012 {
1013 emit_load_or_store (var, OPCODE_istore, state);
1014 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
1015 }
1016
1017 static void
1018 emit_unop (opcode, type, state)
1019 enum java_opcode opcode;
1020 tree type ATTRIBUTE_UNUSED;
1021 struct jcf_partial *state;
1022 {
1023 RESERVE(1);
1024 OP1 (opcode);
1025 }
1026
1027 static void
1028 emit_binop (opcode, type, state)
1029 enum java_opcode opcode;
1030 tree type;
1031 struct jcf_partial *state;
1032 {
1033 int size = TYPE_IS_WIDE (type) ? 2 : 1;
1034 RESERVE(1);
1035 OP1 (opcode);
1036 NOTE_POP (size);
1037 }
1038
1039 static void
1040 emit_reloc (value, kind, target, state)
1041 HOST_WIDE_INT value;
1042 int kind;
1043 struct jcf_block *target;
1044 struct jcf_partial *state;
1045 {
1046 struct jcf_relocation *reloc = (struct jcf_relocation *)
1047 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1048 struct jcf_block *block = state->last_block;
1049 reloc->next = block->u.relocations;
1050 block->u.relocations = reloc;
1051 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1052 reloc->label = target;
1053 reloc->kind = kind;
1054 if (kind == 0 || kind == BLOCK_START_RELOC)
1055 OP4 (value);
1056 else if (kind != SWITCH_ALIGN_RELOC)
1057 OP2 (value);
1058 }
1059
1060 static void
1061 emit_switch_reloc (label, state)
1062 struct jcf_block *label;
1063 struct jcf_partial *state;
1064 {
1065 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
1066 }
1067
1068 /* Similar to emit_switch_reloc,
1069 but re-uses an existing case reloc. */
1070
1071 static void
1072 emit_case_reloc (reloc, state)
1073 struct jcf_relocation *reloc;
1074 struct jcf_partial *state;
1075 {
1076 struct jcf_block *block = state->last_block;
1077 reloc->next = block->u.relocations;
1078 block->u.relocations = reloc;
1079 reloc->offset = BUFFER_LENGTH (&state->bytecode);
1080 reloc->kind = BLOCK_START_RELOC;
1081 OP4 (0);
1082 }
1083
1084 /* Emit a conditional jump to TARGET with a 2-byte relative jump offset
1085 The opcode is OPCODE, the inverted opcode is INV_OPCODE. */
1086
1087 static void
1088 emit_if (target, opcode, inv_opcode, state)
1089 struct jcf_block *target;
1090 int opcode, inv_opcode;
1091 struct jcf_partial *state;
1092 {
1093 OP1 (opcode);
1094 /* value is 1 byte from reloc back to start of instruction. */
1095 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
1096 }
1097
1098 static void
1099 emit_goto (target, state)
1100 struct jcf_block *target;
1101 struct jcf_partial *state;
1102 {
1103 OP1 (OPCODE_goto);
1104 /* Value is 1 byte from reloc back to start of instruction. */
1105 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
1106 }
1107
1108 static void
1109 emit_jsr (target, state)
1110 struct jcf_block *target;
1111 struct jcf_partial *state;
1112 {
1113 OP1 (OPCODE_jsr);
1114 /* Value is 1 byte from reloc back to start of instruction. */
1115 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
1116 }
1117
1118 /* Generate code to evaluate EXP. If the result is true,
1119 branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
1120 TRUE_BRANCH_FIRST is a code geneation hint that the
1121 TRUE_LABEL may follow right after this. (The idea is that we
1122 may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
1123
1124 static void
1125 generate_bytecode_conditional (exp, true_label, false_label,
1126 true_branch_first, state)
1127 tree exp;
1128 struct jcf_block *true_label;
1129 struct jcf_block *false_label;
1130 int true_branch_first;
1131 struct jcf_partial *state;
1132 {
1133 tree exp0, exp1, type;
1134 int save_SP = state->code_SP;
1135 enum java_opcode op, negop;
1136 switch (TREE_CODE (exp))
1137 {
1138 case INTEGER_CST:
1139 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
1140 break;
1141 case COND_EXPR:
1142 {
1143 struct jcf_block *then_label = gen_jcf_label (state);
1144 struct jcf_block *else_label = gen_jcf_label (state);
1145 int save_SP_before, save_SP_after;
1146 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1147 then_label, else_label, 1, state);
1148 define_jcf_label (then_label, state);
1149 save_SP_before = state->code_SP;
1150 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1151 true_label, false_label, 1, state);
1152 save_SP_after = state->code_SP;
1153 state->code_SP = save_SP_before;
1154 define_jcf_label (else_label, state);
1155 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
1156 true_label, false_label,
1157 true_branch_first, state);
1158 if (state->code_SP != save_SP_after)
1159 fatal ("internal error non-matching SP");
1160 }
1161 break;
1162 case TRUTH_NOT_EXPR:
1163 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label, true_label,
1164 ! true_branch_first, state);
1165 break;
1166 case TRUTH_ANDIF_EXPR:
1167 {
1168 struct jcf_block *next_label = gen_jcf_label (state);
1169 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1170 next_label, false_label, 1, state);
1171 define_jcf_label (next_label, state);
1172 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1173 true_label, false_label, 1, state);
1174 }
1175 break;
1176 case TRUTH_ORIF_EXPR:
1177 {
1178 struct jcf_block *next_label = gen_jcf_label (state);
1179 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1180 true_label, next_label, 1, state);
1181 define_jcf_label (next_label, state);
1182 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
1183 true_label, false_label, 1, state);
1184 }
1185 break;
1186 compare_1:
1187 /* Assuming op is one of the 2-operand if_icmp<COND> instructions,
1188 set it to the corresponding 1-operand if<COND> instructions. */
1189 op = op - 6;
1190 /* FALLTHROUGH */
1191 compare_2:
1192 /* The opcodes with their inverses are allocated in pairs.
1193 E.g. The inverse of if_icmplt (161) is if_icmpge (162). */
1194 negop = (op & 1) ? op + 1 : op - 1;
1195 compare_2_ptr:
1196 if (true_branch_first)
1197 {
1198 emit_if (false_label, negop, op, state);
1199 emit_goto (true_label, state);
1200 }
1201 else
1202 {
1203 emit_if (true_label, op, negop, state);
1204 emit_goto (false_label, state);
1205 }
1206 break;
1207 case EQ_EXPR:
1208 op = OPCODE_if_icmpeq;
1209 goto compare;
1210 case NE_EXPR:
1211 op = OPCODE_if_icmpne;
1212 goto compare;
1213 case GT_EXPR:
1214 op = OPCODE_if_icmpgt;
1215 goto compare;
1216 case LT_EXPR:
1217 op = OPCODE_if_icmplt;
1218 goto compare;
1219 case GE_EXPR:
1220 op = OPCODE_if_icmpge;
1221 goto compare;
1222 case LE_EXPR:
1223 op = OPCODE_if_icmple;
1224 goto compare;
1225 compare:
1226 exp0 = TREE_OPERAND (exp, 0);
1227 exp1 = TREE_OPERAND (exp, 1);
1228 type = TREE_TYPE (exp0);
1229 switch (TREE_CODE (type))
1230 {
1231 int opf;
1232 case POINTER_TYPE: case RECORD_TYPE:
1233 switch (TREE_CODE (exp))
1234 {
1235 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
1236 case NE_EXPR: op = OPCODE_if_acmpne; break;
1237 default: abort();
1238 }
1239 if (integer_zerop (exp1) || integer_zerop (exp0))
1240 {
1241 generate_bytecode_insns (integer_zerop (exp1) ? exp0 : exp0,
1242 STACK_TARGET, state);
1243 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
1244 negop = (op & 1) ? op - 1 : op + 1;
1245 NOTE_POP (1);
1246 goto compare_2_ptr;
1247 }
1248 generate_bytecode_insns (exp0, STACK_TARGET, state);
1249 generate_bytecode_insns (exp1, STACK_TARGET, state);
1250 NOTE_POP (2);
1251 goto compare_2;
1252 case REAL_TYPE:
1253 generate_bytecode_insns (exp0, STACK_TARGET, state);
1254 generate_bytecode_insns (exp1, STACK_TARGET, state);
1255 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
1256 opf = OPCODE_fcmpg;
1257 else
1258 opf = OPCODE_fcmpl;
1259 if (TYPE_PRECISION (type) > 32)
1260 {
1261 opf += 2;
1262 NOTE_POP (4);
1263 }
1264 else
1265 NOTE_POP (2);
1266 RESERVE (1);
1267 OP1 (opf);
1268 goto compare_1;
1269 case INTEGER_TYPE:
1270 if (TYPE_PRECISION (type) > 32)
1271 {
1272 generate_bytecode_insns (exp0, STACK_TARGET, state);
1273 generate_bytecode_insns (exp1, STACK_TARGET, state);
1274 NOTE_POP (4);
1275 RESERVE (1);
1276 OP1 (OPCODE_lcmp);
1277 goto compare_1;
1278 }
1279 /* FALLTHOUGH */
1280 default:
1281 if (integer_zerop (exp1))
1282 {
1283 generate_bytecode_insns (exp0, STACK_TARGET, state);
1284 NOTE_POP (1);
1285 goto compare_1;
1286 }
1287 if (integer_zerop (exp0))
1288 {
1289 switch (op)
1290 {
1291 case OPCODE_if_icmplt:
1292 case OPCODE_if_icmpge:
1293 op += 2;
1294 break;
1295 case OPCODE_if_icmpgt:
1296 case OPCODE_if_icmple:
1297 op -= 2;
1298 break;
1299 default:
1300 break;
1301 }
1302 generate_bytecode_insns (exp1, STACK_TARGET, state);
1303 NOTE_POP (1);
1304 goto compare_1;
1305 }
1306 generate_bytecode_insns (exp0, STACK_TARGET, state);
1307 generate_bytecode_insns (exp1, STACK_TARGET, state);
1308 NOTE_POP (2);
1309 goto compare_2;
1310 }
1311
1312 default:
1313 generate_bytecode_insns (exp, STACK_TARGET, state);
1314 NOTE_POP (1);
1315 if (true_branch_first)
1316 {
1317 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
1318 emit_goto (true_label, state);
1319 }
1320 else
1321 {
1322 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
1323 emit_goto (false_label, state);
1324 }
1325 break;
1326 }
1327 if (save_SP != state->code_SP)
1328 fatal ("internal error - SP mismatch");
1329 }
1330
1331 /* Call pending cleanups i.e. those for surrounding CLEANUP_POINT_EXPRs
1332 but only as far out as LIMIT (since we are about to jump to the
1333 emit label that is LIMIT). */
1334
1335 static void
1336 call_cleanups (limit, state)
1337 struct jcf_block *limit;
1338 struct jcf_partial *state;
1339 {
1340 struct jcf_block *block = state->labeled_blocks;
1341 for (; block != limit; block = block->next)
1342 {
1343 if (block->pc == PENDING_CLEANUP_PC)
1344 emit_jsr (block, state);
1345 }
1346 }
1347
1348 static void
1349 generate_bytecode_return (exp, state)
1350 tree exp;
1351 struct jcf_partial *state;
1352 {
1353 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
1354 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
1355 int op;
1356 again:
1357 if (exp != NULL)
1358 {
1359 switch (TREE_CODE (exp))
1360 {
1361 case COMPOUND_EXPR:
1362 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
1363 state);
1364 exp = TREE_OPERAND (exp, 1);
1365 goto again;
1366 case COND_EXPR:
1367 {
1368 struct jcf_block *then_label = gen_jcf_label (state);
1369 struct jcf_block *else_label = gen_jcf_label (state);
1370 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1371 then_label, else_label, 1, state);
1372 define_jcf_label (then_label, state);
1373 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
1374 define_jcf_label (else_label, state);
1375 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
1376 }
1377 return;
1378 default:
1379 generate_bytecode_insns (exp,
1380 returns_void ? IGNORE_TARGET
1381 : STACK_TARGET, state);
1382 }
1383 }
1384 if (returns_void)
1385 {
1386 op = OPCODE_return;
1387 call_cleanups (NULL_PTR, state);
1388 }
1389 else
1390 {
1391 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
1392 if (state->num_finalizers > 0)
1393 {
1394 if (state->return_value_decl == NULL_TREE)
1395 {
1396 state->return_value_decl
1397 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
1398 localvar_alloc (state->return_value_decl, state);
1399 }
1400 emit_store (state->return_value_decl, state);
1401 call_cleanups (NULL_PTR, state);
1402 emit_load (state->return_value_decl, state);
1403 /* If we call localvar_free (state->return_value_decl, state),
1404 then we risk the save decl erroneously re-used in the
1405 finalizer. Instead, we keep the state->return_value_decl
1406 allocated through the rest of the method. This is not
1407 the greatest solution, but it is at least simple and safe. */
1408 }
1409 }
1410 RESERVE (1);
1411 OP1 (op);
1412 }
1413
1414 /* Generate bytecode for sub-expression EXP of METHOD.
1415 TARGET is one of STACK_TARGET or IGNORE_TARGET. */
1416
1417 static void
1418 generate_bytecode_insns (exp, target, state)
1419 tree exp;
1420 int target;
1421 struct jcf_partial *state;
1422 {
1423 tree type;
1424 enum java_opcode jopcode;
1425 int op;
1426 HOST_WIDE_INT value;
1427 int post_op;
1428 int size;
1429 int offset;
1430
1431 if (exp == NULL && target == IGNORE_TARGET)
1432 return;
1433
1434 type = TREE_TYPE (exp);
1435
1436 switch (TREE_CODE (exp))
1437 {
1438 case BLOCK:
1439 if (BLOCK_EXPR_BODY (exp))
1440 {
1441 tree local;
1442 tree body = BLOCK_EXPR_BODY (exp);
1443 for (local = BLOCK_EXPR_DECLS (exp); local; )
1444 {
1445 tree next = TREE_CHAIN (local);
1446 localvar_alloc (local, state);
1447 local = next;
1448 }
1449 /* Avoid deep recursion for long blocks. */
1450 while (TREE_CODE (body) == COMPOUND_EXPR)
1451 {
1452 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
1453 body = TREE_OPERAND (body, 1);
1454 }
1455 generate_bytecode_insns (body, target, state);
1456 for (local = BLOCK_EXPR_DECLS (exp); local; )
1457 {
1458 tree next = TREE_CHAIN (local);
1459 localvar_free (local, state);
1460 local = next;
1461 }
1462 }
1463 break;
1464 case COMPOUND_EXPR:
1465 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
1466 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1467 break;
1468 case EXPR_WITH_FILE_LOCATION:
1469 {
1470 char *saved_input_filename = input_filename;
1471 tree body = EXPR_WFL_NODE (exp);
1472 int saved_lineno = lineno;
1473 if (body == empty_stmt_node)
1474 break;
1475 input_filename = EXPR_WFL_FILENAME (exp);
1476 lineno = EXPR_WFL_LINENO (exp);
1477 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && lineno > 0
1478 && debug_info_level > DINFO_LEVEL_NONE)
1479 put_linenumber (lineno, state);
1480 generate_bytecode_insns (body, target, state);
1481 input_filename = saved_input_filename;
1482 lineno = saved_lineno;
1483 }
1484 break;
1485 case INTEGER_CST:
1486 if (target == IGNORE_TARGET) ; /* do nothing */
1487 else if (TREE_CODE (type) == POINTER_TYPE)
1488 {
1489 if (! integer_zerop (exp))
1490 abort();
1491 RESERVE(1);
1492 OP1 (OPCODE_aconst_null);
1493 NOTE_PUSH (1);
1494 }
1495 else if (TYPE_PRECISION (type) <= 32)
1496 {
1497 push_int_const (TREE_INT_CST_LOW (exp), state);
1498 NOTE_PUSH (1);
1499 }
1500 else
1501 {
1502 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
1503 state);
1504 NOTE_PUSH (2);
1505 }
1506 break;
1507 case REAL_CST:
1508 {
1509 int prec = TYPE_PRECISION (type) >> 5;
1510 RESERVE(1);
1511 if (real_zerop (exp))
1512 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
1513 else if (real_onep (exp))
1514 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
1515 /* FIXME Should also use fconst_2 for 2.0f.
1516 Also, should use iconst_2/ldc followed by i2f/i2d
1517 for other float/double when the value is a small integer. */
1518 else
1519 {
1520 offset = find_constant_index (exp, state);
1521 if (prec == 1)
1522 push_constant1 (offset, state);
1523 else
1524 push_constant2 (offset, state);
1525 }
1526 NOTE_PUSH (prec);
1527 }
1528 break;
1529 case STRING_CST:
1530 push_constant1 (find_string_constant (&state->cpool, exp), state);
1531 NOTE_PUSH (1);
1532 break;
1533 case VAR_DECL:
1534 if (TREE_STATIC (exp))
1535 {
1536 field_op (exp, OPCODE_getstatic, state);
1537 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
1538 break;
1539 }
1540 /* ... fall through ... */
1541 case PARM_DECL:
1542 emit_load (exp, state);
1543 break;
1544 case NON_LVALUE_EXPR:
1545 case INDIRECT_REF:
1546 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1547 break;
1548 case ARRAY_REF:
1549 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
1550 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1551 if (target != IGNORE_TARGET)
1552 {
1553 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
1554 RESERVE(1);
1555 OP1 (jopcode);
1556 if (! TYPE_IS_WIDE (type))
1557 NOTE_POP (1);
1558 }
1559 break;
1560 case COMPONENT_REF:
1561 {
1562 tree obj = TREE_OPERAND (exp, 0);
1563 tree field = TREE_OPERAND (exp, 1);
1564 int is_static = FIELD_STATIC (field);
1565 generate_bytecode_insns (obj,
1566 is_static ? IGNORE_TARGET : target, state);
1567 if (target != IGNORE_TARGET)
1568 {
1569 if (DECL_NAME (field) == length_identifier_node && !is_static
1570 && TYPE_ARRAY_P (TREE_TYPE (obj)))
1571 {
1572 RESERVE (1);
1573 OP1 (OPCODE_arraylength);
1574 }
1575 else
1576 {
1577 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
1578 state);
1579 if (! is_static)
1580 NOTE_POP (1);
1581 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
1582 }
1583 }
1584 }
1585 break;
1586 case TRUTH_ANDIF_EXPR:
1587 case TRUTH_ORIF_EXPR:
1588 case EQ_EXPR:
1589 case NE_EXPR:
1590 case GT_EXPR:
1591 case LT_EXPR:
1592 case GE_EXPR:
1593 case LE_EXPR:
1594 {
1595 struct jcf_block *then_label = gen_jcf_label (state);
1596 struct jcf_block *else_label = gen_jcf_label (state);
1597 struct jcf_block *end_label = gen_jcf_label (state);
1598 generate_bytecode_conditional (exp,
1599 then_label, else_label, 1, state);
1600 define_jcf_label (then_label, state);
1601 push_int_const (1, state);
1602 emit_goto (end_label, state);
1603 define_jcf_label (else_label, state);
1604 push_int_const (0, state);
1605 define_jcf_label (end_label, state);
1606 NOTE_PUSH (1);
1607 }
1608 break;
1609 case COND_EXPR:
1610 {
1611 struct jcf_block *then_label = gen_jcf_label (state);
1612 struct jcf_block *else_label = gen_jcf_label (state);
1613 struct jcf_block *end_label = gen_jcf_label (state);
1614 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1615 then_label, else_label, 1, state);
1616 define_jcf_label (then_label, state);
1617 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
1618 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
1619 /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
1620 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
1621 emit_goto (end_label, state);
1622 define_jcf_label (else_label, state);
1623 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
1624 define_jcf_label (end_label, state);
1625 }
1626 break;
1627 case CASE_EXPR:
1628 {
1629 struct jcf_switch_state *sw_state = state->sw_state;
1630 struct jcf_relocation *reloc = (struct jcf_relocation *)
1631 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
1632 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
1633 reloc->kind = 0;
1634 reloc->label = get_jcf_label_here (state);
1635 reloc->offset = case_value;
1636 reloc->next = sw_state->cases;
1637 sw_state->cases = reloc;
1638 if (sw_state->num_cases == 0)
1639 {
1640 sw_state->min_case = case_value;
1641 sw_state->max_case = case_value;
1642 }
1643 else
1644 {
1645 if (case_value < sw_state->min_case)
1646 sw_state->min_case = case_value;
1647 if (case_value > sw_state->max_case)
1648 sw_state->max_case = case_value;
1649 }
1650 sw_state->num_cases++;
1651 }
1652 break;
1653 case DEFAULT_EXPR:
1654 state->sw_state->default_label = get_jcf_label_here (state);
1655 break;
1656
1657 case SWITCH_EXPR:
1658 {
1659 /* The SWITCH_EXPR has three parts, generated in the following order:
1660 1. the switch_expression (the value used to select the correct case);
1661 2. the switch_body;
1662 3. the switch_instruction (the tableswitch/loopupswitch instruction.).
1663 After code generation, we will re-order then in the order 1, 3, 2.
1664 This is to avoid an extra GOTOs. */
1665 struct jcf_switch_state sw_state;
1666 struct jcf_block *expression_last; /* Last block of the switch_expression. */
1667 struct jcf_block *body_last; /* Last block of the switch_body. */
1668 struct jcf_block *switch_instruction; /* First block of switch_instruction. */
1669 struct jcf_block *instruction_last; /* Last block of the switch_instruction. */
1670 struct jcf_block *body_block;
1671 int switch_length;
1672 sw_state.prev = state->sw_state;
1673 state->sw_state = &sw_state;
1674 sw_state.cases = NULL;
1675 sw_state.num_cases = 0;
1676 sw_state.default_label = NULL;
1677 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1678 expression_last = state->last_block;
1679 body_block = get_jcf_label_here (state); /* Force a new block here. */
1680 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
1681 body_last = state->last_block;
1682
1683 switch_instruction = gen_jcf_label (state);
1684 define_jcf_label (switch_instruction, state);
1685 if (sw_state.default_label == NULL)
1686 sw_state.default_label = gen_jcf_label (state);
1687
1688 if (sw_state.num_cases <= 1)
1689 {
1690 if (sw_state.num_cases == 0)
1691 {
1692 emit_pop (1, state);
1693 NOTE_POP (1);
1694 }
1695 else
1696 {
1697 push_int_const (sw_state.cases->offset, state);
1698 emit_if (sw_state.cases->label,
1699 OPCODE_ifeq, OPCODE_ifne, state);
1700 }
1701 emit_goto (sw_state.default_label, state);
1702 }
1703 else
1704 {
1705 HOST_WIDE_INT i;
1706 /* Copy the chain of relocs into a sorted array. */
1707 struct jcf_relocation **relocs = (struct jcf_relocation **)
1708 xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
1709 /* The relocs arrays is a buffer with a gap.
1710 The assumption is that cases will normally come in "runs". */
1711 int gap_start = 0;
1712 int gap_end = sw_state.num_cases;
1713 struct jcf_relocation *reloc;
1714 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
1715 {
1716 HOST_WIDE_INT case_value = reloc->offset;
1717 while (gap_end < sw_state.num_cases)
1718 {
1719 struct jcf_relocation *end = relocs[gap_end];
1720 if (case_value <= end->offset)
1721 break;
1722 relocs[gap_start++] = end;
1723 gap_end++;
1724 }
1725 while (gap_start > 0)
1726 {
1727 struct jcf_relocation *before = relocs[gap_start-1];
1728 if (case_value >= before->offset)
1729 break;
1730 relocs[--gap_end] = before;
1731 gap_start--;
1732 }
1733 relocs[gap_start++] = reloc;
1734 /* Note we don't check for duplicates. FIXME! */
1735 }
1736
1737 if (2 * sw_state.num_cases
1738 >= sw_state.max_case - sw_state.min_case)
1739 { /* Use tableswitch. */
1740 int index = 0;
1741 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
1742 OP1 (OPCODE_tableswitch);
1743 emit_reloc (RELOCATION_VALUE_0,
1744 SWITCH_ALIGN_RELOC, NULL, state);
1745 emit_switch_reloc (sw_state.default_label, state);
1746 OP4 (sw_state.min_case);
1747 OP4 (sw_state.max_case);
1748 for (i = sw_state.min_case; ; )
1749 {
1750 reloc = relocs[index];
1751 if (i == reloc->offset)
1752 {
1753 emit_case_reloc (reloc, state);
1754 if (i == sw_state.max_case)
1755 break;
1756 index++;
1757 }
1758 else
1759 emit_switch_reloc (sw_state.default_label, state);
1760 i++;
1761 }
1762 }
1763 else
1764 { /* Use lookupswitch. */
1765 RESERVE(9 + 8 * sw_state.num_cases);
1766 OP1 (OPCODE_lookupswitch);
1767 emit_reloc (RELOCATION_VALUE_0,
1768 SWITCH_ALIGN_RELOC, NULL, state);
1769 emit_switch_reloc (sw_state.default_label, state);
1770 OP4 (sw_state.num_cases);
1771 for (i = 0; i < sw_state.num_cases; i++)
1772 {
1773 struct jcf_relocation *reloc = relocs[i];
1774 OP4 (reloc->offset);
1775 emit_case_reloc (reloc, state);
1776 }
1777 }
1778 free (relocs);
1779 }
1780
1781 instruction_last = state->last_block;
1782 if (sw_state.default_label->pc < 0)
1783 define_jcf_label (sw_state.default_label, state);
1784 else /* Force a new block. */
1785 sw_state.default_label = get_jcf_label_here (state);
1786 /* Now re-arrange the blocks so the switch_instruction
1787 comes before the switch_body. */
1788 switch_length = state->code_length - switch_instruction->pc;
1789 switch_instruction->pc = body_block->pc;
1790 instruction_last->next = body_block;
1791 instruction_last->v.chunk->next = body_block->v.chunk;
1792 expression_last->next = switch_instruction;
1793 expression_last->v.chunk->next = switch_instruction->v.chunk;
1794 body_last->next = sw_state.default_label;
1795 body_last->v.chunk->next = NULL;
1796 state->chunk = body_last->v.chunk;
1797 for (; body_block != sw_state.default_label; body_block = body_block->next)
1798 body_block->pc += switch_length;
1799
1800 state->sw_state = sw_state.prev;
1801 break;
1802 }
1803
1804 case RETURN_EXPR:
1805 exp = TREE_OPERAND (exp, 0);
1806 if (exp == NULL_TREE)
1807 exp = empty_stmt_node;
1808 else if (TREE_CODE (exp) != MODIFY_EXPR)
1809 abort ();
1810 else
1811 exp = TREE_OPERAND (exp, 1);
1812 generate_bytecode_return (exp, state);
1813 break;
1814 case LABELED_BLOCK_EXPR:
1815 {
1816 struct jcf_block *end_label = gen_jcf_label (state);
1817 end_label->next = state->labeled_blocks;
1818 state->labeled_blocks = end_label;
1819 end_label->pc = PENDING_EXIT_PC;
1820 end_label->u.labeled_block = exp;
1821 if (LABELED_BLOCK_BODY (exp))
1822 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
1823 if (state->labeled_blocks != end_label)
1824 abort();
1825 state->labeled_blocks = end_label->next;
1826 define_jcf_label (end_label, state);
1827 }
1828 break;
1829 case LOOP_EXPR:
1830 {
1831 tree body = TREE_OPERAND (exp, 0);
1832 #if 0
1833 if (TREE_CODE (body) == COMPOUND_EXPR
1834 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
1835 {
1836 /* Optimize: H: if (TEST) GOTO L; BODY; GOTO H; L:
1837 to: GOTO L; BODY; L: if (!TEST) GOTO L; */
1838 struct jcf_block *head_label;
1839 struct jcf_block *body_label;
1840 struct jcf_block *end_label = gen_jcf_label (state);
1841 struct jcf_block *exit_label = state->labeled_blocks;
1842 head_label = gen_jcf_label (state);
1843 emit_goto (head_label, state);
1844 body_label = get_jcf_label_here (state);
1845 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
1846 define_jcf_label (head_label, state);
1847 generate_bytecode_conditional (TREE_OPERAND (body, 0),
1848 end_label, body_label, 1, state);
1849 define_jcf_label (end_label, state);
1850 }
1851 else
1852 #endif
1853 {
1854 struct jcf_block *head_label = get_jcf_label_here (state);
1855 generate_bytecode_insns (body, IGNORE_TARGET, state);
1856 emit_goto (head_label, state);
1857 }
1858 }
1859 break;
1860 case EXIT_EXPR:
1861 {
1862 struct jcf_block *label = state->labeled_blocks;
1863 struct jcf_block *end_label = gen_jcf_label (state);
1864 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
1865 label, end_label, 0, state);
1866 define_jcf_label (end_label, state);
1867 }
1868 break;
1869 case EXIT_BLOCK_EXPR:
1870 {
1871 struct jcf_block *label = state->labeled_blocks;
1872 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
1873 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
1874 label = label->next;
1875 call_cleanups (label, state);
1876 emit_goto (label, state);
1877 }
1878 break;
1879
1880 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
1881 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
1882 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
1883 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
1884 increment:
1885
1886 exp = TREE_OPERAND (exp, 0);
1887 type = TREE_TYPE (exp);
1888 size = TYPE_IS_WIDE (type) ? 2 : 1;
1889 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1890 && ! TREE_STATIC (exp)
1891 && TREE_CODE (type) == INTEGER_TYPE
1892 && TYPE_PRECISION (type) == 32)
1893 {
1894 if (target != IGNORE_TARGET && post_op)
1895 emit_load (exp, state);
1896 emit_iinc (exp, value, state);
1897 if (target != IGNORE_TARGET && ! post_op)
1898 emit_load (exp, state);
1899 break;
1900 }
1901 if (TREE_CODE (exp) == COMPONENT_REF)
1902 {
1903 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1904 emit_dup (1, 0, state);
1905 /* Stack: ..., objectref, objectref. */
1906 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
1907 NOTE_PUSH (size-1);
1908 /* Stack: ..., objectref, oldvalue. */
1909 offset = 1;
1910 }
1911 else if (TREE_CODE (exp) == ARRAY_REF)
1912 {
1913 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
1914 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
1915 emit_dup (2, 0, state);
1916 /* Stack: ..., array, index, array, index. */
1917 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
1918 RESERVE(1);
1919 OP1 (jopcode);
1920 NOTE_POP (2-size);
1921 /* Stack: ..., array, index, oldvalue. */
1922 offset = 2;
1923 }
1924 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
1925 {
1926 generate_bytecode_insns (exp, STACK_TARGET, state);
1927 /* Stack: ..., oldvalue. */
1928 offset = 0;
1929 }
1930 else
1931 abort ();
1932
1933 if (target != IGNORE_TARGET && post_op)
1934 emit_dup (size, offset, state);
1935 /* Stack, if ARRAY_REF: ..., [result, ] array, index, oldvalue. */
1936 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, oldvalue. */
1937 /* Stack, otherwise: ..., [result, ] oldvalue. */
1938 if (size == 1)
1939 push_int_const (value, state);
1940 else
1941 push_long_const (value, (HOST_WIDE_INT)(value >= 0 ? 0 : -1), state);
1942 NOTE_PUSH (size);
1943 emit_binop (OPCODE_iadd + adjust_typed_op (type, 3), type, state);
1944 if (target != IGNORE_TARGET && ! post_op)
1945 emit_dup (size, offset, state);
1946 /* Stack, if ARRAY_REF: ..., [result, ] array, index, newvalue. */
1947 /* Stack, if COMPONENT_REF: ..., [result, ] objectref, newvalue. */
1948 /* Stack, otherwise: ..., [result, ] newvalue. */
1949 goto finish_assignment;
1950
1951 case MODIFY_EXPR:
1952 {
1953 tree lhs = TREE_OPERAND (exp, 0);
1954 tree rhs = TREE_OPERAND (exp, 1);
1955 int offset = 0;
1956
1957 /* See if we can use the iinc instruction. */
1958 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
1959 && ! TREE_STATIC (lhs)
1960 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
1961 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
1962 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
1963 {
1964 tree arg0 = TREE_OPERAND (rhs, 0);
1965 tree arg1 = TREE_OPERAND (rhs, 1);
1966 HOST_WIDE_INT min_value = -32768;
1967 HOST_WIDE_INT max_value = 32767;
1968 if (TREE_CODE (rhs) == MINUS_EXPR)
1969 {
1970 min_value++;
1971 max_value++;
1972 }
1973 else if (arg1 == lhs)
1974 {
1975 arg0 = arg1;
1976 arg1 = TREE_OPERAND (rhs, 0);
1977 }
1978 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
1979 {
1980 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
1981 value = TREE_INT_CST_LOW (arg1);
1982 if ((hi_value == 0 && value <= max_value)
1983 || (hi_value == -1 && value >= min_value))
1984 {
1985 if (TREE_CODE (rhs) == MINUS_EXPR)
1986 value = -value;
1987 emit_iinc (lhs, value, state);
1988 break;
1989 }
1990 }
1991 }
1992
1993 if (TREE_CODE (lhs) == COMPONENT_REF)
1994 {
1995 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
1996 STACK_TARGET, state);
1997 offset = 1;
1998 }
1999 else if (TREE_CODE (lhs) == ARRAY_REF)
2000 {
2001 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
2002 STACK_TARGET, state);
2003 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
2004 STACK_TARGET, state);
2005 offset = 2;
2006 }
2007 else
2008 offset = 0;
2009 generate_bytecode_insns (rhs, STACK_TARGET, state);
2010 if (target != IGNORE_TARGET)
2011 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
2012 exp = lhs;
2013 }
2014 /* FALLTHOUGH */
2015
2016 finish_assignment:
2017 if (TREE_CODE (exp) == COMPONENT_REF)
2018 {
2019 tree field = TREE_OPERAND (exp, 1);
2020 if (! FIELD_STATIC (field))
2021 NOTE_POP (1);
2022 field_op (field,
2023 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
2024 state);
2025
2026 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
2027 }
2028 else if (TREE_CODE (exp) == VAR_DECL
2029 || TREE_CODE (exp) == PARM_DECL)
2030 {
2031 if (FIELD_STATIC (exp))
2032 {
2033 field_op (exp, OPCODE_putstatic, state);
2034 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
2035 }
2036 else
2037 emit_store (exp, state);
2038 }
2039 else if (TREE_CODE (exp) == ARRAY_REF)
2040 {
2041 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
2042 RESERVE(1);
2043 OP1 (jopcode);
2044 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
2045 }
2046 else
2047 fatal ("internal error (bad lhs to MODIFY_EXPR)");
2048 break;
2049 case PLUS_EXPR:
2050 jopcode = OPCODE_iadd;
2051 goto binop;
2052 case MINUS_EXPR:
2053 jopcode = OPCODE_isub;
2054 goto binop;
2055 case MULT_EXPR:
2056 jopcode = OPCODE_imul;
2057 goto binop;
2058 case TRUNC_DIV_EXPR:
2059 case RDIV_EXPR:
2060 jopcode = OPCODE_idiv;
2061 goto binop;
2062 case TRUNC_MOD_EXPR:
2063 jopcode = OPCODE_irem;
2064 goto binop;
2065 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
2066 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
2067 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
2068 case TRUTH_AND_EXPR:
2069 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
2070 case TRUTH_OR_EXPR:
2071 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
2072 case TRUTH_XOR_EXPR:
2073 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
2074 binop:
2075 {
2076 tree arg0 = TREE_OPERAND (exp, 0);
2077 tree arg1 = TREE_OPERAND (exp, 1);
2078 jopcode += adjust_typed_op (type, 3);
2079 if (arg0 == arg1 && TREE_CODE (arg0) == SAVE_EXPR)
2080 {
2081 /* fold may (e.g) convert 2*x to x+x. */
2082 generate_bytecode_insns (TREE_OPERAND (arg0, 0), target, state);
2083 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
2084 }
2085 else
2086 {
2087 generate_bytecode_insns (arg0, target, state);
2088 generate_bytecode_insns (arg1, target, state);
2089 }
2090 /* For most binary operations, both operands and the result have the
2091 same type. Shift operations are different. Using arg1's type
2092 gets us the correct SP adjustment in all casesd. */
2093 if (target == STACK_TARGET)
2094 emit_binop (jopcode, TREE_TYPE (arg1), state);
2095 break;
2096 }
2097 case TRUTH_NOT_EXPR:
2098 case BIT_NOT_EXPR:
2099 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2100 if (target == STACK_TARGET)
2101 {
2102 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
2103 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
2104 RESERVE (2);
2105 if (is_long)
2106 OP1 (OPCODE_i2l);
2107 NOTE_PUSH (1 + is_long);
2108 OP1 (OPCODE_ixor + is_long);
2109 NOTE_POP (1 + is_long);
2110 }
2111 break;
2112 case NEGATE_EXPR:
2113 jopcode = OPCODE_ineg;
2114 jopcode += adjust_typed_op (type, 3);
2115 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2116 if (target == STACK_TARGET)
2117 emit_unop (jopcode, type, state);
2118 break;
2119 case INSTANCEOF_EXPR:
2120 {
2121 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
2122 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2123 RESERVE (3);
2124 OP1 (OPCODE_instanceof);
2125 OP2 (index);
2126 }
2127 break;
2128 case CONVERT_EXPR:
2129 case NOP_EXPR:
2130 case FLOAT_EXPR:
2131 case FIX_TRUNC_EXPR:
2132 {
2133 tree src = TREE_OPERAND (exp, 0);
2134 tree src_type = TREE_TYPE (src);
2135 tree dst_type = TREE_TYPE (exp);
2136 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
2137 if (target == IGNORE_TARGET || src_type == dst_type)
2138 break;
2139 if (TREE_CODE (dst_type) == POINTER_TYPE)
2140 {
2141 if (TREE_CODE (exp) == CONVERT_EXPR)
2142 {
2143 int index = find_class_constant (&state->cpool,
2144 TREE_TYPE (dst_type));
2145 RESERVE (3);
2146 OP1 (OPCODE_checkcast);
2147 OP2 (index);
2148 }
2149 }
2150 else /* Convert numeric types. */
2151 {
2152 int wide_src = TYPE_PRECISION (src_type) > 32;
2153 int wide_dst = TYPE_PRECISION (dst_type) > 32;
2154 NOTE_POP (1 + wide_src);
2155 RESERVE (1);
2156 if (TREE_CODE (dst_type) == REAL_TYPE)
2157 {
2158 if (TREE_CODE (src_type) == REAL_TYPE)
2159 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
2160 else if (TYPE_PRECISION (src_type) == 64)
2161 OP1 (OPCODE_l2f + wide_dst);
2162 else
2163 OP1 (OPCODE_i2f + wide_dst);
2164 }
2165 else /* Convert to integral type. */
2166 {
2167 if (TREE_CODE (src_type) == REAL_TYPE)
2168 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
2169 else if (wide_dst)
2170 OP1 (OPCODE_i2l);
2171 else if (wide_src)
2172 OP1 (OPCODE_l2i);
2173 if (TYPE_PRECISION (dst_type) < 32)
2174 {
2175 RESERVE (1);
2176 /* Already converted to int, if needed. */
2177 if (TYPE_PRECISION (dst_type) <= 8)
2178 OP1 (OPCODE_i2b);
2179 else if (TREE_UNSIGNED (dst_type))
2180 OP1 (OPCODE_i2c);
2181 else
2182 OP1 (OPCODE_i2s);
2183 }
2184 }
2185 NOTE_PUSH (1 + wide_dst);
2186 }
2187 }
2188 break;
2189
2190 case CLEANUP_POINT_EXPR:
2191 {
2192 struct jcf_block *save_labeled_blocks = state->labeled_blocks;
2193 int can_complete = CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0));
2194 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
2195 if (target != IGNORE_TARGET)
2196 abort ();
2197 while (state->labeled_blocks != save_labeled_blocks)
2198 {
2199 struct jcf_block *finished_label = NULL;
2200 tree return_link;
2201 tree exception_type = build_pointer_type (throwable_type_node);
2202 tree exception_decl = build_decl (VAR_DECL, NULL_TREE,
2203 exception_type);
2204 struct jcf_block *end_label = get_jcf_label_here (state);
2205 struct jcf_block *label = state->labeled_blocks;
2206 struct jcf_handler *handler;
2207 tree cleanup = label->u.labeled_block;
2208 state->labeled_blocks = label->next;
2209 state->num_finalizers--;
2210 if (can_complete)
2211 {
2212 finished_label = gen_jcf_label (state);
2213 emit_jsr (label, state);
2214 emit_goto (finished_label, state);
2215 if (! CAN_COMPLETE_NORMALLY (cleanup))
2216 can_complete = 0;
2217 }
2218 handler = alloc_handler (label->v.start_label, end_label, state);
2219 handler->type = NULL_TREE;
2220 localvar_alloc (exception_decl, state);
2221 NOTE_PUSH (1);
2222 emit_store (exception_decl, state);
2223 emit_jsr (label, state);
2224 emit_load (exception_decl, state);
2225 RESERVE (1);
2226 OP1 (OPCODE_athrow);
2227 NOTE_POP (1);
2228
2229 /* The finally block. */
2230 return_link = build_decl (VAR_DECL, NULL_TREE,
2231 return_address_type_node);
2232 define_jcf_label (label, state);
2233 NOTE_PUSH (1);
2234 localvar_alloc (return_link, state);
2235 emit_store (return_link, state);
2236 generate_bytecode_insns (cleanup, IGNORE_TARGET, state);
2237 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2238 localvar_free (return_link, state);
2239 localvar_free (exception_decl, state);
2240 if (finished_label != NULL)
2241 define_jcf_label (finished_label, state);
2242 }
2243 }
2244 break;
2245
2246 case WITH_CLEANUP_EXPR:
2247 {
2248 struct jcf_block *label;
2249 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
2250 label = gen_jcf_label (state);
2251 label->pc = PENDING_CLEANUP_PC;
2252 label->next = state->labeled_blocks;
2253 state->labeled_blocks = label;
2254 state->num_finalizers++;
2255 label->u.labeled_block = TREE_OPERAND (exp, 2);
2256 label->v.start_label = get_jcf_label_here (state);
2257 if (target != IGNORE_TARGET)
2258 abort ();
2259 }
2260 break;
2261
2262 case TRY_EXPR:
2263 {
2264 tree try_clause = TREE_OPERAND (exp, 0);
2265 struct jcf_block *start_label = get_jcf_label_here (state);
2266 struct jcf_block *end_label; /* End of try clause. */
2267 struct jcf_block *finished_label = gen_jcf_label (state);
2268 tree clause = TREE_OPERAND (exp, 1);
2269 if (target != IGNORE_TARGET)
2270 abort ();
2271 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
2272 end_label = get_jcf_label_here (state);
2273 if (CAN_COMPLETE_NORMALLY (try_clause))
2274 emit_goto (finished_label, state);
2275 while (clause != NULL_TREE)
2276 {
2277 tree catch_clause = TREE_OPERAND (clause, 0);
2278 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
2279 struct jcf_handler *handler = alloc_handler (start_label, end_label, state);
2280 if (exception_decl == NULL_TREE)
2281 handler->type = NULL_TREE;
2282 else
2283 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
2284 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
2285 clause = TREE_CHAIN (clause);
2286 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
2287 emit_goto (finished_label, state);
2288 }
2289 define_jcf_label (finished_label, state);
2290 }
2291 break;
2292 case TRY_FINALLY_EXPR:
2293 {
2294 tree try_block = TREE_OPERAND (exp, 0);
2295 tree finally = TREE_OPERAND (exp, 1);
2296 struct jcf_block *finished_label = gen_jcf_label (state);
2297 struct jcf_block *finally_label = gen_jcf_label (state);
2298 struct jcf_block *start_label = get_jcf_label_here (state);
2299 tree return_link = build_decl (VAR_DECL, NULL_TREE,
2300 return_address_type_node);
2301 tree exception_type = build_pointer_type (throwable_type_node);
2302 tree exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
2303 struct jcf_handler *handler;
2304
2305 finally_label->pc = PENDING_CLEANUP_PC;
2306 finally_label->next = state->labeled_blocks;
2307 state->labeled_blocks = finally_label;
2308 state->num_finalizers++;
2309
2310 generate_bytecode_insns (try_block, target, state);
2311 if (state->labeled_blocks != finally_label)
2312 abort();
2313 state->labeled_blocks = finally_label->next;
2314 emit_jsr (finally_label, state);
2315 if (CAN_COMPLETE_NORMALLY (try_block))
2316 emit_goto (finished_label, state);
2317
2318 /* Handle exceptions. */
2319 localvar_alloc (return_link, state);
2320 handler = alloc_handler (start_label, NULL_PTR, state);
2321 handler->end_label = handler->handler_label;
2322 handler->type = NULL_TREE;
2323 localvar_alloc (exception_decl, state);
2324 NOTE_PUSH (1);
2325 emit_store (exception_decl, state);
2326 emit_jsr (finally_label, state);
2327 emit_load (exception_decl, state);
2328 RESERVE (1);
2329 OP1 (OPCODE_athrow);
2330 NOTE_POP (1);
2331 localvar_free (exception_decl, state);
2332
2333 /* The finally block. First save return PC into return_link. */
2334 define_jcf_label (finally_label, state);
2335 NOTE_PUSH (1);
2336 emit_store (return_link, state);
2337
2338 generate_bytecode_insns (finally, IGNORE_TARGET, state);
2339 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
2340 localvar_free (return_link, state);
2341 define_jcf_label (finished_label, state);
2342 }
2343 break;
2344 case THROW_EXPR:
2345 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
2346 RESERVE (1);
2347 OP1 (OPCODE_athrow);
2348 break;
2349 case NEW_ARRAY_INIT:
2350 {
2351 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
2352 tree array_type = TREE_TYPE (TREE_TYPE (exp));
2353 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2354 HOST_WIDE_INT length = java_array_type_length (array_type);
2355 if (target == IGNORE_TARGET)
2356 {
2357 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
2358 generate_bytecode_insns (TREE_VALUE (values), target, state);
2359 break;
2360 }
2361 push_int_const (length, state);
2362 NOTE_PUSH (1);
2363 RESERVE (3);
2364 if (JPRIMITIVE_TYPE_P (element_type))
2365 {
2366 int atype = encode_newarray_type (element_type);
2367 OP1 (OPCODE_newarray);
2368 OP1 (atype);
2369 }
2370 else
2371 {
2372 int index = find_class_constant (&state->cpool,
2373 TREE_TYPE (element_type));
2374 OP1 (OPCODE_anewarray);
2375 OP2 (index);
2376 }
2377 offset = 0;
2378 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
2379 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
2380 {
2381 int save_SP = state->code_SP;
2382 emit_dup (1, 0, state);
2383 push_int_const (offset, state);
2384 NOTE_PUSH (1);
2385 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
2386 RESERVE (1);
2387 OP1 (jopcode);
2388 state->code_SP = save_SP;
2389 }
2390 }
2391 break;
2392 case NEW_CLASS_EXPR:
2393 {
2394 tree class = TREE_TYPE (TREE_TYPE (exp));
2395 int need_result = target != IGNORE_TARGET;
2396 int index = find_class_constant (&state->cpool, class);
2397 RESERVE (4);
2398 OP1 (OPCODE_new);
2399 OP2 (index);
2400 if (need_result)
2401 OP1 (OPCODE_dup);
2402 NOTE_PUSH (1 + need_result);
2403 }
2404 /* ... fall though ... */
2405 case CALL_EXPR:
2406 {
2407 tree f = TREE_OPERAND (exp, 0);
2408 tree x = TREE_OPERAND (exp, 1);
2409 int save_SP = state->code_SP;
2410 int nargs;
2411 if (TREE_CODE (f) == ADDR_EXPR)
2412 f = TREE_OPERAND (f, 0);
2413 if (f == soft_newarray_node)
2414 {
2415 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
2416 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
2417 STACK_TARGET, state);
2418 RESERVE (2);
2419 OP1 (OPCODE_newarray);
2420 OP1 (type_code);
2421 break;
2422 }
2423 else if (f == soft_multianewarray_node)
2424 {
2425 int ndims;
2426 int idim;
2427 int index = find_class_constant (&state->cpool,
2428 TREE_TYPE (TREE_TYPE (exp)));
2429 x = TREE_CHAIN (x); /* Skip class argument. */
2430 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
2431 for (idim = ndims; --idim >= 0; )
2432 {
2433 x = TREE_CHAIN (x);
2434 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2435 }
2436 RESERVE (4);
2437 OP1 (OPCODE_multianewarray);
2438 OP2 (index);
2439 OP1 (ndims);
2440 break;
2441 }
2442 else if (f == soft_anewarray_node)
2443 {
2444 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
2445 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
2446 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2447 RESERVE (3);
2448 OP1 (OPCODE_anewarray);
2449 OP2 (index);
2450 break;
2451 }
2452 else if (f == soft_monitorenter_node
2453 || f == soft_monitorexit_node
2454 || f == throw_node)
2455 {
2456 if (f == soft_monitorenter_node)
2457 op = OPCODE_monitorenter;
2458 else if (f == soft_monitorexit_node)
2459 op = OPCODE_monitorexit;
2460 else
2461 op = OPCODE_athrow;
2462 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2463 RESERVE (1);
2464 OP1 (op);
2465 NOTE_POP (1);
2466 break;
2467 }
2468 else if (exp == soft_exceptioninfo_call_node)
2469 {
2470 NOTE_PUSH (1); /* Pushed by exception system. */
2471 break;
2472 }
2473 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
2474 {
2475 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
2476 }
2477 nargs = state->code_SP - save_SP;
2478 state->code_SP = save_SP;
2479 if (f == soft_fmod_node)
2480 {
2481 RESERVE (1);
2482 OP1 (OPCODE_drem);
2483 NOTE_PUSH (2);
2484 break;
2485 }
2486 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
2487 NOTE_POP (1); /* Pop implicit this. */
2488 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
2489 {
2490 int index = find_methodref_index (&state->cpool, f);
2491 int interface = 0;
2492 RESERVE (5);
2493 if (METHOD_STATIC (f))
2494 OP1 (OPCODE_invokestatic);
2495 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
2496 || METHOD_PRIVATE (f))
2497 OP1 (OPCODE_invokespecial);
2498 else if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (f))))
2499 {
2500 OP1 (OPCODE_invokeinterface);
2501 interface = 1;
2502 }
2503 else
2504 OP1 (OPCODE_invokevirtual);
2505 OP2 (index);
2506 f = TREE_TYPE (TREE_TYPE (f));
2507 if (TREE_CODE (f) != VOID_TYPE)
2508 {
2509 int size = TYPE_IS_WIDE (f) ? 2 : 1;
2510 if (target == IGNORE_TARGET)
2511 emit_pop (size, state);
2512 else
2513 NOTE_PUSH (size);
2514 }
2515 if (interface)
2516 {
2517 OP1 (nargs);
2518 OP1 (0);
2519 }
2520 break;
2521 }
2522 }
2523 /* fall through */
2524 notimpl:
2525 default:
2526 error("internal error - tree code not implemented: %s",
2527 tree_code_name [(int) TREE_CODE (exp)]);
2528 }
2529 }
2530
2531 static void
2532 perform_relocations (state)
2533 struct jcf_partial *state;
2534 {
2535 struct jcf_block *block;
2536 struct jcf_relocation *reloc;
2537 int pc;
2538 int shrink;
2539
2540 /* Before we start, the pc field of each block is an upper bound on
2541 the block's start pc (it may be less, if previous blocks need less
2542 than their maximum).
2543
2544 The minimum size of each block is in the block's chunk->size. */
2545
2546 /* First, figure out the actual locations of each block. */
2547 pc = 0;
2548 shrink = 0;
2549 for (block = state->blocks; block != NULL; block = block->next)
2550 {
2551 int block_size = block->v.chunk->size;
2552
2553 block->pc = pc;
2554
2555 /* Optimize GOTO L; L: by getting rid of the redundant goto.
2556 Assumes relocations are in reverse order. */
2557 reloc = block->u.relocations;
2558 while (reloc != NULL
2559 && reloc->kind == OPCODE_goto_w
2560 && reloc->label->pc == block->next->pc
2561 && reloc->offset + 2 == block_size)
2562 {
2563 reloc = reloc->next;
2564 block->u.relocations = reloc;
2565 block->v.chunk->size -= 3;
2566 block_size -= 3;
2567 shrink += 3;
2568 }
2569
2570 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
2571 {
2572 if (reloc->kind == SWITCH_ALIGN_RELOC)
2573 {
2574 /* We assume this is the first relocation in this block,
2575 so we know its final pc. */
2576 int where = pc + reloc->offset;
2577 int pad = ((where + 3) & ~3) - where;
2578 block_size += pad;
2579 }
2580 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
2581 {
2582 int delta = reloc->label->pc - (pc + reloc->offset - 1);
2583 int expand = reloc->kind > 0 ? 2 : 5;
2584
2585 if (delta > 0)
2586 delta -= shrink;
2587 if (delta >= -32768 && delta <= 32767)
2588 {
2589 shrink += expand;
2590 reloc->kind = -1;
2591 }
2592 else
2593 block_size += expand;
2594 }
2595 }
2596 pc += block_size;
2597 }
2598
2599 for (block = state->blocks; block != NULL; block = block->next)
2600 {
2601 struct chunk *chunk = block->v.chunk;
2602 int old_size = chunk->size;
2603 int next_pc = block->next == NULL ? pc : block->next->pc;
2604 int new_size = next_pc - block->pc;
2605 unsigned char *new_ptr;
2606 unsigned char *old_buffer = chunk->data;
2607 unsigned char *old_ptr = old_buffer + old_size;
2608 if (new_size != old_size)
2609 {
2610 chunk->data = (unsigned char *)
2611 obstack_alloc (state->chunk_obstack, new_size);
2612 chunk->size = new_size;
2613 }
2614 new_ptr = chunk->data + new_size;
2615
2616 /* We do the relocations from back to front, because
2617 the relocations are in reverse order. */
2618 for (reloc = block->u.relocations; ; reloc = reloc->next)
2619 {
2620 /* new_ptr and old_ptr point into the old and new buffers,
2621 respectively. (If no relocations cause the buffer to
2622 grow, the buffer will be the same buffer, and new_ptr==old_ptr.)
2623 The bytes at higher adress have been copied and relocations
2624 handled; those at lower addresses remain to process. */
2625
2626 /* Lower old index of piece to be copied with no relocation.
2627 I.e. high index of the first piece that does need relocation. */
2628 int start = reloc == NULL ? 0
2629 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
2630 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
2631 ? reloc->offset + 4
2632 : reloc->offset + 2;
2633 int32 value;
2634 int new_offset;
2635 int n = (old_ptr - old_buffer) - start;
2636 new_ptr -= n;
2637 old_ptr -= n;
2638 if (n > 0)
2639 memcpy (new_ptr, old_ptr, n);
2640 if (old_ptr == old_buffer)
2641 break;
2642
2643 new_offset = new_ptr - chunk->data;
2644 new_offset -= (reloc->kind == -1 ? 2 : 4);
2645 if (reloc->kind == 0)
2646 {
2647 old_ptr -= 4;
2648 value = GET_u4 (old_ptr);
2649 }
2650 else if (reloc->kind == BLOCK_START_RELOC)
2651 {
2652 old_ptr -= 4;
2653 value = 0;
2654 new_offset = 0;
2655 }
2656 else if (reloc->kind == SWITCH_ALIGN_RELOC)
2657 {
2658 int where = block->pc + reloc->offset;
2659 int pad = ((where + 3) & ~3) - where;
2660 while (--pad >= 0)
2661 *--new_ptr = 0;
2662 continue;
2663 }
2664 else
2665 {
2666 old_ptr -= 2;
2667 value = GET_u2 (old_ptr);
2668 }
2669 value += reloc->label->pc - (block->pc + new_offset);
2670 *--new_ptr = (unsigned char) value; value >>= 8;
2671 *--new_ptr = (unsigned char) value; value >>= 8;
2672 if (reloc->kind != -1)
2673 {
2674 *--new_ptr = (unsigned char) value; value >>= 8;
2675 *--new_ptr = (unsigned char) value;
2676 }
2677 if (reloc->kind > BLOCK_START_RELOC)
2678 {
2679 /* Convert: OP TARGET to: OP_w TARGET; (OP is goto or jsr). */
2680 --old_ptr;
2681 *--new_ptr = reloc->kind;
2682 }
2683 else if (reloc->kind < -1)
2684 {
2685 /* Convert: ifCOND TARGET to: ifNCOND T; goto_w TARGET; T: */
2686 --old_ptr;
2687 *--new_ptr = OPCODE_goto_w;
2688 *--new_ptr = 3;
2689 *--new_ptr = 0;
2690 *--new_ptr = - reloc->kind;
2691 }
2692 }
2693 if (new_ptr != chunk->data)
2694 fatal ("internal error - perform_relocations");
2695 }
2696 state->code_length = pc;
2697 }
2698
2699 static void
2700 init_jcf_state (state, work)
2701 struct jcf_partial *state;
2702 struct obstack *work;
2703 {
2704 state->chunk_obstack = work;
2705 state->first = state->chunk = NULL;
2706 CPOOL_INIT (&state->cpool);
2707 BUFFER_INIT (&state->localvars);
2708 BUFFER_INIT (&state->bytecode);
2709 }
2710
2711 static void
2712 init_jcf_method (state, method)
2713 struct jcf_partial *state;
2714 tree method;
2715 {
2716 state->current_method = method;
2717 state->blocks = state->last_block = NULL;
2718 state->linenumber_count = 0;
2719 state->first_lvar = state->last_lvar = NULL;
2720 state->lvar_count = 0;
2721 state->labeled_blocks = NULL;
2722 state->code_length = 0;
2723 BUFFER_RESET (&state->bytecode);
2724 BUFFER_RESET (&state->localvars);
2725 state->code_SP = 0;
2726 state->code_SP_max = 0;
2727 state->handlers = NULL;
2728 state->last_handler = NULL;
2729 state->num_handlers = 0;
2730 state->num_finalizers = 0;
2731 state->return_value_decl = NULL_TREE;
2732 }
2733
2734 static void
2735 release_jcf_state (state)
2736 struct jcf_partial *state;
2737 {
2738 CPOOL_FINISH (&state->cpool);
2739 obstack_free (state->chunk_obstack, state->first);
2740 }
2741
2742 /* Generate and return a list of chunks containing the class CLAS
2743 in the .class file representation. The list can be written to a
2744 .class file using write_chunks. Allocate chunks from obstack WORK. */
2745
2746 static struct chunk *
2747 generate_classfile (clas, state)
2748 tree clas;
2749 struct jcf_partial *state;
2750 {
2751 struct chunk *cpool_chunk;
2752 char *source_file;
2753 char *ptr;
2754 int i;
2755 char *fields_count_ptr;
2756 int fields_count = 0;
2757 char *methods_count_ptr;
2758 int methods_count = 0;
2759 static tree SourceFile_node = NULL_TREE;
2760 tree part;
2761 int total_supers
2762 = clas == object_type_node ? 0
2763 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
2764
2765 ptr = append_chunk (NULL, 8, state);
2766 PUT4 (0xCafeBabe); /* Magic number */
2767 PUT2 (3); /* Minor version */
2768 PUT2 (45); /* Major version */
2769
2770 append_chunk (NULL, 0, state);
2771 cpool_chunk = state->chunk;
2772
2773 /* Next allocate the chunk containing acces_flags through fields_counr. */
2774 if (clas == object_type_node)
2775 i = 10;
2776 else
2777 i = 8 + 2 * total_supers;
2778 ptr = append_chunk (NULL, i, state);
2779 i = get_access_flags (TYPE_NAME (clas));
2780 if (! (i & ACC_INTERFACE))
2781 i |= ACC_SUPER;
2782 PUT2 (i); /* acces_flags */
2783 i = find_class_constant (&state->cpool, clas); PUT2 (i); /* this_class */
2784 if (clas == object_type_node)
2785 {
2786 PUT2(0); /* super_class */
2787 PUT2(0); /* interfaces_count */
2788 }
2789 else
2790 {
2791 tree basetypes = TYPE_BINFO_BASETYPES (clas);
2792 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
2793 int j = find_class_constant (&state->cpool, base);
2794 PUT2 (j); /* super_class */
2795 PUT2 (total_supers - 1); /* interfaces_count */
2796 for (i = 1; i < total_supers; i++)
2797 {
2798 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
2799 j = find_class_constant (&state->cpool, base);
2800 PUT2 (j);
2801 }
2802 }
2803 fields_count_ptr = ptr;
2804
2805 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
2806 {
2807 int have_value;
2808 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
2809 continue;
2810 ptr = append_chunk (NULL, 8, state);
2811 i = get_access_flags (part); PUT2 (i);
2812 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
2813 i = find_utf8_constant (&state->cpool, build_java_signature (TREE_TYPE (part)));
2814 PUT2(i);
2815 have_value = DECL_INITIAL (part) != NULL_TREE && FIELD_STATIC (part);
2816 PUT2 (have_value); /* attributes_count */
2817 if (have_value)
2818 {
2819 tree init = DECL_INITIAL (part);
2820 static tree ConstantValue_node = NULL_TREE;
2821 ptr = append_chunk (NULL, 8, state);
2822 if (ConstantValue_node == NULL_TREE)
2823 ConstantValue_node = get_identifier ("ConstantValue");
2824 i = find_utf8_constant (&state->cpool, ConstantValue_node);
2825 PUT2 (i); /* attribute_name_index */
2826 PUT4 (2); /* attribute_length */
2827 i = find_constant_index (init, state); PUT2 (i);
2828 }
2829 fields_count++;
2830 }
2831 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
2832
2833 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
2834 PUT2 (0);
2835
2836 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
2837 {
2838 struct jcf_block *block;
2839 tree function_body = DECL_FUNCTION_BODY (part);
2840 tree body = function_body == NULL_TREE ? NULL_TREE
2841 : BLOCK_EXPR_BODY (function_body);
2842 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
2843 : DECL_NAME (part);
2844 tree type = TREE_TYPE (part);
2845 tree save_function = current_function_decl;
2846 current_function_decl = part;
2847 ptr = append_chunk (NULL, 8, state);
2848 i = get_access_flags (part); PUT2 (i);
2849 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
2850 i = find_utf8_constant (&state->cpool, build_java_signature (type));
2851 PUT2 (i);
2852 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
2853 PUT2 (i); /* attributes_count */
2854 if (body != NULL_TREE)
2855 {
2856 int code_attributes_count = 0;
2857 static tree Code_node = NULL_TREE;
2858 tree t;
2859 char *attr_len_ptr;
2860 struct jcf_handler *handler;
2861 if (Code_node == NULL_TREE)
2862 Code_node = get_identifier ("Code");
2863 ptr = append_chunk (NULL, 14, state);
2864 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
2865 attr_len_ptr = ptr;
2866 init_jcf_method (state, part);
2867 get_jcf_label_here (state); /* Force a first block. */
2868 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
2869 localvar_alloc (t, state);
2870 generate_bytecode_insns (body, IGNORE_TARGET, state);
2871 if (CAN_COMPLETE_NORMALLY (body))
2872 {
2873 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
2874 abort();
2875 RESERVE (1);
2876 OP1 (OPCODE_return);
2877 }
2878 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
2879 localvar_free (t, state);
2880 if (state->return_value_decl != NULL_TREE)
2881 localvar_free (state->return_value_decl, state);
2882 finish_jcf_block (state);
2883 perform_relocations (state);
2884
2885 ptr = attr_len_ptr;
2886 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
2887 if (state->linenumber_count > 0)
2888 {
2889 code_attributes_count++;
2890 i += 8 + 4 * state->linenumber_count;
2891 }
2892 if (state->lvar_count > 0)
2893 {
2894 code_attributes_count++;
2895 i += 8 + 10 * state->lvar_count;
2896 }
2897 UNSAFE_PUT4 (i); /* attribute_length */
2898 UNSAFE_PUT2 (state->code_SP_max); /* max_stack */
2899 UNSAFE_PUT2 (localvar_max); /* max_locals */
2900 UNSAFE_PUT4 (state->code_length);
2901
2902 /* Emit the exception table. */
2903 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
2904 PUT2 (state->num_handlers); /* exception_table_length */
2905 handler = state->handlers;
2906 for (; handler != NULL; handler = handler->next)
2907 {
2908 int type_index;
2909 PUT2 (handler->start_label->pc);
2910 PUT2 (handler->end_label->pc);
2911 PUT2 (handler->handler_label->pc);
2912 if (handler->type == NULL_TREE)
2913 type_index = 0;
2914 else
2915 type_index = find_class_constant (&state->cpool,
2916 handler->type);
2917 PUT2 (type_index);
2918 }
2919
2920 ptr = append_chunk (NULL, 2, state);
2921 PUT2 (code_attributes_count);
2922
2923 /* Write the LineNumberTable attribute. */
2924 if (state->linenumber_count > 0)
2925 {
2926 static tree LineNumberTable_node = NULL_TREE;
2927 ptr = append_chunk (NULL, 8 + 4 * state->linenumber_count, state);
2928 if (LineNumberTable_node == NULL_TREE)
2929 LineNumberTable_node = get_identifier ("LineNumberTable");
2930 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
2931 PUT2 (i); /* attribute_name_index */
2932 i = 2+4*state->linenumber_count; PUT4(i); /* attribute_length */
2933 i = state->linenumber_count; PUT2 (i);
2934 for (block = state->blocks; block != NULL; block = block->next)
2935 {
2936 int line = block->linenumber;
2937 if (line > 0)
2938 {
2939 PUT2 (block->pc);
2940 PUT2 (line);
2941 }
2942 }
2943 }
2944
2945 /* Write the LocalVariableTable attribute. */
2946 if (state->lvar_count > 0)
2947 {
2948 static tree LocalVariableTable_node = NULL_TREE;
2949 struct localvar_info *lvar = state->first_lvar;
2950 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
2951 if (LocalVariableTable_node == NULL_TREE)
2952 LocalVariableTable_node = get_identifier("LocalVariableTable");
2953 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
2954 PUT2 (i); /* attribute_name_index */
2955 i = 2 + 10 * state->lvar_count; PUT4 (i); /* attribute_length */
2956 i = state->lvar_count; PUT2 (i);
2957 for ( ; lvar != NULL; lvar = lvar->next)
2958 {
2959 tree name = DECL_NAME (lvar->decl);
2960 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
2961 i = lvar->start_label->pc; PUT2 (i);
2962 i = lvar->end_label->pc - i; PUT2 (i);
2963 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
2964 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
2965 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
2966 }
2967 }
2968 }
2969 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
2970 {
2971 tree t = DECL_FUNCTION_THROWS (part);
2972 int throws_count = list_length (t);
2973 static tree Exceptions_node = NULL_TREE;
2974 if (Exceptions_node == NULL_TREE)
2975 Exceptions_node = get_identifier ("Exceptions");
2976 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
2977 i = find_utf8_constant (&state->cpool, Exceptions_node);
2978 PUT2 (i); /* attribute_name_index */
2979 i = 2 + 2 * throws_count; PUT4(i); /* attribute_length */
2980 i = throws_count; PUT2 (i);
2981 for (; t != NULL_TREE; t = TREE_CHAIN (t))
2982 {
2983 i = find_class_constant (&state->cpool, TREE_VALUE (t));
2984 PUT2 (i);
2985 }
2986 }
2987 methods_count++;
2988 current_function_decl = save_function;
2989 }
2990 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
2991
2992 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
2993 for (ptr = source_file; ; ptr++)
2994 {
2995 char ch = *ptr;
2996 if (ch == '\0')
2997 break;
2998 if (ch == '/' || ch == '\\')
2999 source_file = ptr+1;
3000 }
3001 ptr = append_chunk (NULL, 10, state);
3002 PUT2 (1); /* attributes_count */
3003
3004 /* generate the SourceFile attribute. */
3005 if (SourceFile_node == NULL_TREE)
3006 SourceFile_node = get_identifier ("SourceFile");
3007 i = find_utf8_constant (&state->cpool, SourceFile_node);
3008 PUT2 (i); /* attribute_name_index */
3009 PUT4 (2);
3010 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
3011 PUT2 (i);
3012
3013 /* New finally generate the contents of the constant pool chunk. */
3014 i = count_constant_pool_bytes (&state->cpool);
3015 ptr = obstack_alloc (state->chunk_obstack, i);
3016 cpool_chunk->data = ptr;
3017 cpool_chunk->size = i;
3018 write_constant_pool (&state->cpool, ptr, i);
3019 return state->first;
3020 }
3021
3022 static char *
3023 make_class_file_name (clas)
3024 tree clas;
3025 {
3026 const char *dname, *slash;
3027 char *cname, *r;
3028 struct stat sb;
3029
3030 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
3031 "", '.', DIR_SEPARATOR,
3032 ".class"));
3033 if (jcf_write_base_directory == NULL)
3034 {
3035 /* Make sure we put the class file into the .java file's
3036 directory, and not into some subdirectory thereof. */
3037 char *t;
3038 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
3039 slash = strrchr (dname, DIR_SEPARATOR);
3040 if (! slash)
3041 {
3042 dname = ".";
3043 slash = dname + 1;
3044 }
3045 t = strrchr (cname, DIR_SEPARATOR);
3046 if (t)
3047 cname = t + 1;
3048 }
3049 else
3050 {
3051 dname = jcf_write_base_directory;
3052 slash = dname + strlen (dname);
3053 }
3054
3055 r = xmalloc (slash - dname + strlen (cname) + 2);
3056 strncpy (r, dname, slash - dname);
3057 r[slash - dname] = DIR_SEPARATOR;
3058 strcpy (&r[slash - dname + 1], cname);
3059
3060 /* We try to make new directories when we need them. We only do
3061 this for directories which "might not" exist. For instance, we
3062 assume the `-d' directory exists, but we don't assume that any
3063 subdirectory below it exists. It might be worthwhile to keep
3064 track of which directories we've created to avoid gratuitous
3065 stat()s. */
3066 dname = r + (slash - dname) + 1;
3067 while (1)
3068 {
3069 cname = strchr (dname, DIR_SEPARATOR);
3070 if (cname == NULL)
3071 break;
3072 *cname = '\0';
3073 if (stat (r, &sb) == -1)
3074 {
3075 /* Try to make it. */
3076 if (mkdir (r, 0755) == -1)
3077 {
3078 fatal ("failed to create directory `%s'", r);
3079 free (r);
3080 return NULL;
3081 }
3082 }
3083 *cname = DIR_SEPARATOR;
3084 /* Skip consecutive separators. */
3085 for (dname = cname + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
3086 ;
3087 }
3088
3089 return r;
3090 }
3091
3092 /* Write out the contens of a class (RECORD_TYPE) CLAS, as a .class file.
3093 The output .class file name is make_class_file_name(CLAS). */
3094
3095 void
3096 write_classfile (clas)
3097 tree clas;
3098 {
3099 struct obstack *work = &temporary_obstack;
3100 struct jcf_partial state[1];
3101 char *class_file_name = make_class_file_name (clas);
3102 struct chunk *chunks;
3103
3104 if (class_file_name != NULL)
3105 {
3106 FILE* stream = fopen (class_file_name, "wb");
3107 if (stream == NULL)
3108 fatal ("failed to open `%s' for writing", class_file_name);
3109 jcf_dependency_add_target (class_file_name);
3110 init_jcf_state (state, work);
3111 chunks = generate_classfile (clas, state);
3112 write_chunks (stream, chunks);
3113 if (fclose (stream))
3114 fatal ("failed to close after writing `%s'", class_file_name);
3115 free (class_file_name);
3116 }
3117 release_jcf_state (state);
3118 }
3119
3120 /* TODO:
3121 string concatenation
3122 synchronized statement
3123 */
This page took 0.187202 seconds and 6 git commands to generate.