00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "jcf.h"
00027 #include "tree.h"
00028 #include "real.h"
00029 #include "java-tree.h"
00030 #include "obstack.h"
00031 #undef AND
00032 #include "rtl.h"
00033 #include "flags.h"
00034 #include "java-opcodes.h"
00035 #include "parse.h"
00036 #include "buffer.h"
00037 #include "toplev.h"
00038 #include "ggc.h"
00039
00040 #ifndef DIR_SEPARATOR
00041 #define DIR_SEPARATOR '/'
00042 #endif
00043
00044 extern struct obstack temporary_obstack;
00045
00046
00047
00048
00049 char *jcf_write_base_directory = NULL;
00050
00051
00052
00053 #define RESERVE(N) \
00054 do { CHECK_OP(state); \
00055 if (state->bytecode.ptr + (N) > state->bytecode.limit) \
00056 buffer_grow (&state->bytecode, N); } while (0)
00057
00058
00059
00060
00061 #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
00062
00063
00064
00065 #define OP2(I) \
00066 do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
00067
00068
00069
00070 #define OP4(I) \
00071 do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
00072 OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
00073
00074
00075
00076 #define NOTE_PUSH(I) \
00077 do { state->code_SP += (I); \
00078 if (state->code_SP > state->code_SP_max) \
00079 state->code_SP_max = state->code_SP; } while (0)
00080
00081
00082
00083 #define NOTE_POP(I) \
00084 do { state->code_SP -= (I); if (state->code_SP < 0) abort(); } while (0)
00085
00086
00087
00088 struct chunk
00089 {
00090
00091 struct chunk *next;
00092
00093
00094 unsigned char *data;
00095
00096
00097 int size;
00098 };
00099
00100 #define PENDING_CLEANUP_PC (-3)
00101 #define PENDING_EXIT_PC (-2)
00102 #define UNDEFINED_PC (-1)
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 struct jcf_block
00113 {
00114
00115
00116
00117
00118
00119 struct jcf_block *next;
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 int pc;
00132
00133 int linenumber;
00134
00135
00136
00137
00138 union {
00139 struct chunk *chunk;
00140
00141
00142
00143 struct jcf_block *start_label;
00144 } v;
00145
00146 union {
00147
00148 struct jcf_relocation *relocations;
00149
00150
00151
00152
00153 tree labeled_block;
00154 } u;
00155 };
00156
00157
00158
00159 #define SWITCH_ALIGN_RELOC 4
00160
00161
00162
00163
00164 #define BLOCK_START_RELOC 1
00165
00166 struct jcf_relocation
00167 {
00168
00169 struct jcf_relocation *next;
00170
00171
00172 HOST_WIDE_INT offset;
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 int kind;
00187
00188
00189 struct jcf_block *label;
00190 };
00191
00192 #define RELOCATION_VALUE_0 ((HOST_WIDE_INT)0)
00193 #define RELOCATION_VALUE_1 ((HOST_WIDE_INT)1)
00194
00195
00196
00197 struct jcf_handler
00198 {
00199 struct jcf_handler *next;
00200
00201 struct jcf_block *start_label;
00202 struct jcf_block *end_label;
00203 struct jcf_block *handler_label;
00204
00205
00206 tree type;
00207 };
00208
00209
00210
00211 struct jcf_switch_state
00212 {
00213 struct jcf_switch_state *prev;
00214 struct jcf_block *default_label;
00215
00216 struct jcf_relocation *cases;
00217 int num_cases;
00218 HOST_WIDE_INT min_case, max_case;
00219 };
00220
00221
00222
00223
00224 struct jcf_partial
00225 {
00226 struct chunk *first;
00227 struct chunk *chunk;
00228 struct obstack *chunk_obstack;
00229 tree current_method;
00230
00231
00232 struct jcf_block *blocks;
00233 struct jcf_block *last_block;
00234
00235 struct localvar_info *first_lvar;
00236 struct localvar_info *last_lvar;
00237 int lvar_count;
00238
00239 CPool cpool;
00240
00241 int linenumber_count;
00242
00243
00244
00245 int code_length;
00246
00247
00248 struct jcf_block *labeled_blocks;
00249
00250
00251 int code_SP;
00252
00253
00254 int code_SP_max;
00255
00256
00257 struct buffer localvars;
00258
00259
00260 struct buffer bytecode;
00261
00262
00263 struct jcf_handler *handlers;
00264
00265
00266 struct jcf_handler *last_handler;
00267
00268
00269 int num_handlers;
00270
00271
00272 int num_finalizers;
00273
00274
00275 tree return_value_decl;
00276
00277
00278 struct jcf_switch_state *sw_state;
00279 };
00280
00281 static void generate_bytecode_insns PARAMS ((tree, int, struct jcf_partial *));
00282 static struct chunk * alloc_chunk PARAMS ((struct chunk *, unsigned char *,
00283 int, struct obstack *));
00284 static unsigned char * append_chunk PARAMS ((unsigned char *, int,
00285 struct jcf_partial *));
00286 static void append_chunk_copy PARAMS ((unsigned char *, int,
00287 struct jcf_partial *));
00288 static struct jcf_block * gen_jcf_label PARAMS ((struct jcf_partial *));
00289 static void finish_jcf_block PARAMS ((struct jcf_partial *));
00290 static void define_jcf_label PARAMS ((struct jcf_block *,
00291 struct jcf_partial *));
00292 static struct jcf_block * get_jcf_label_here PARAMS ((struct jcf_partial *));
00293 static void put_linenumber PARAMS ((int, struct jcf_partial *));
00294 static void localvar_alloc PARAMS ((tree, struct jcf_partial *));
00295 static void localvar_free PARAMS ((tree, struct jcf_partial *));
00296 static int get_access_flags PARAMS ((tree));
00297 static void write_chunks PARAMS ((FILE *, struct chunk *));
00298 static int adjust_typed_op PARAMS ((tree, int));
00299 static void generate_bytecode_conditional PARAMS ((tree, struct jcf_block *,
00300 struct jcf_block *, int,
00301 struct jcf_partial *));
00302 static void generate_bytecode_return PARAMS ((tree, struct jcf_partial *));
00303 static void perform_relocations PARAMS ((struct jcf_partial *));
00304 static void init_jcf_state PARAMS ((struct jcf_partial *, struct obstack *));
00305 static void init_jcf_method PARAMS ((struct jcf_partial *, tree));
00306 static void release_jcf_state PARAMS ((struct jcf_partial *));
00307 static struct chunk * generate_classfile PARAMS ((tree, struct jcf_partial *));
00308 static struct jcf_handler *alloc_handler PARAMS ((struct jcf_block *,
00309 struct jcf_block *,
00310 struct jcf_partial *));
00311 static void emit_iinc PARAMS ((tree, HOST_WIDE_INT, struct jcf_partial *));
00312 static void emit_reloc PARAMS ((HOST_WIDE_INT, int, struct jcf_block *,
00313 struct jcf_partial *));
00314 static void push_constant1 PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
00315 static void push_constant2 PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
00316 static void push_int_const PARAMS ((HOST_WIDE_INT, struct jcf_partial *));
00317 static int find_constant_wide PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
00318 struct jcf_partial *));
00319 static void push_long_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
00320 struct jcf_partial *));
00321 static int find_constant_index PARAMS ((tree, struct jcf_partial *));
00322 static void push_long_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
00323 struct jcf_partial *));
00324 static void field_op PARAMS ((tree, int, struct jcf_partial *));
00325 static void maybe_wide PARAMS ((int, int, struct jcf_partial *));
00326 static void emit_dup PARAMS ((int, int, struct jcf_partial *));
00327 static void emit_pop PARAMS ((int, struct jcf_partial *));
00328 static void emit_load_or_store PARAMS ((tree, int, struct jcf_partial *));
00329 static void emit_load PARAMS ((tree, struct jcf_partial *));
00330 static void emit_store PARAMS ((tree, struct jcf_partial *));
00331 static void emit_unop PARAMS ((enum java_opcode, tree, struct jcf_partial *));
00332 static void emit_binop PARAMS ((enum java_opcode, tree, struct jcf_partial *));
00333 static void emit_reloc PARAMS ((HOST_WIDE_INT, int, struct jcf_block *,
00334 struct jcf_partial *));
00335 static void emit_switch_reloc PARAMS ((struct jcf_block *,
00336 struct jcf_partial *));
00337 static void emit_case_reloc PARAMS ((struct jcf_relocation *,
00338 struct jcf_partial *));
00339 static void emit_if PARAMS ((struct jcf_block *, int, int,
00340 struct jcf_partial *));
00341 static void emit_goto PARAMS ((struct jcf_block *, struct jcf_partial *));
00342 static void emit_jsr PARAMS ((struct jcf_block *, struct jcf_partial *));
00343 static void call_cleanups PARAMS ((struct jcf_block *, struct jcf_partial *));
00344 static char *make_class_file_name PARAMS ((tree));
00345 static unsigned char *append_synthetic_attribute PARAMS ((struct jcf_partial *));
00346 static void append_innerclasses_attribute PARAMS ((struct jcf_partial *, tree));
00347 static void append_innerclasses_attribute_entry PARAMS ((struct jcf_partial *, tree, tree));
00348 static void append_gcj_attribute PARAMS ((struct jcf_partial *, tree));
00349
00350
00351
00352
00353
00354 #ifdef ENABLE_JC1_CHECKING
00355 static int CHECK_PUT PARAMS ((void *, struct jcf_partial *, int));
00356
00357 static int
00358 CHECK_PUT (ptr, state, i)
00359 void *ptr;
00360 struct jcf_partial *state;
00361 int i;
00362 {
00363 if ((unsigned char *) ptr < state->chunk->data
00364 || (unsigned char *) ptr + i > state->chunk->data + state->chunk->size)
00365 abort ();
00366
00367 return 0;
00368 }
00369 #else
00370 #define CHECK_PUT(PTR, STATE, I) ((void)0)
00371 #endif
00372
00373 #define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
00374 #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
00375 #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
00376 #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
00377
00378
00379
00380 #define UNSAFE_PUT1(X) (*ptr++ = (X))
00381 #define UNSAFE_PUT2(X) (UNSAFE_PUT1((X) >> 8), UNSAFE_PUT1((X) & 0xFF))
00382 #define UNSAFE_PUT4(X) (UNSAFE_PUT2((X) >> 16), UNSAFE_PUT2((X) & 0xFFFF))
00383 #define UNSAFE_PUTN(P, N) (memcpy(ptr, P, N), ptr += (N))
00384
00385
00386
00387
00388
00389
00390 static struct chunk *
00391 alloc_chunk (last, data, size, work)
00392 struct chunk *last;
00393 unsigned char *data;
00394 int size;
00395 struct obstack *work;
00396 {
00397 struct chunk *chunk = (struct chunk *)
00398 obstack_alloc (work, sizeof(struct chunk));
00399
00400 if (data == NULL && size > 0)
00401 data = obstack_alloc (work, size);
00402
00403 chunk->next = NULL;
00404 chunk->data = data;
00405 chunk->size = size;
00406 if (last != NULL)
00407 last->next = chunk;
00408 return chunk;
00409 }
00410
00411 #ifdef ENABLE_JC1_CHECKING
00412 static int CHECK_OP PARAMS ((struct jcf_partial *));
00413
00414 static int
00415 CHECK_OP (state)
00416 struct jcf_partial *state;
00417 {
00418 if (state->bytecode.ptr > state->bytecode.limit)
00419 abort ();
00420
00421 return 0;
00422 }
00423 #else
00424 #define CHECK_OP(STATE) ((void) 0)
00425 #endif
00426
00427 static unsigned char *
00428 append_chunk (data, size, state)
00429 unsigned char *data;
00430 int size;
00431 struct jcf_partial *state;
00432 {
00433 state->chunk = alloc_chunk (state->chunk, data, size, state->chunk_obstack);
00434 if (state->first == NULL)
00435 state->first = state->chunk;
00436 return state->chunk->data;
00437 }
00438
00439 static void
00440 append_chunk_copy (data, size, state)
00441 unsigned char *data;
00442 int size;
00443 struct jcf_partial *state;
00444 {
00445 unsigned char *ptr = append_chunk (NULL, size, state);
00446 memcpy (ptr, data, size);
00447 }
00448
00449 static struct jcf_block *
00450 gen_jcf_label (state)
00451 struct jcf_partial *state;
00452 {
00453 struct jcf_block *block = (struct jcf_block *)
00454 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_block));
00455 block->next = NULL;
00456 block->linenumber = -1;
00457 block->pc = UNDEFINED_PC;
00458 return block;
00459 }
00460
00461 static void
00462 finish_jcf_block (state)
00463 struct jcf_partial *state;
00464 {
00465 struct jcf_block *block = state->last_block;
00466 struct jcf_relocation *reloc;
00467 int code_length = BUFFER_LENGTH (&state->bytecode);
00468 int pc = state->code_length;
00469 append_chunk_copy (state->bytecode.data, code_length, state);
00470 BUFFER_RESET (&state->bytecode);
00471 block->v.chunk = state->chunk;
00472
00473
00474 pc += block->v.chunk->size;
00475 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
00476 {
00477 int kind = reloc->kind;
00478 if (kind == SWITCH_ALIGN_RELOC)
00479 pc += 3;
00480 else if (kind > BLOCK_START_RELOC)
00481 pc += 2;
00482 else if (kind < -1)
00483 pc += 5;
00484 }
00485 state->code_length = pc;
00486 }
00487
00488 static void
00489 define_jcf_label (label, state)
00490 struct jcf_block *label;
00491 struct jcf_partial *state;
00492 {
00493 if (state->last_block != NULL)
00494 finish_jcf_block (state);
00495 label->pc = state->code_length;
00496 if (state->blocks == NULL)
00497 state->blocks = label;
00498 else
00499 state->last_block->next = label;
00500 state->last_block = label;
00501 label->next = NULL;
00502 label->u.relocations = NULL;
00503 }
00504
00505 static struct jcf_block *
00506 get_jcf_label_here (state)
00507 struct jcf_partial *state;
00508 {
00509 if (state->last_block != NULL && BUFFER_LENGTH (&state->bytecode) == 0)
00510 return state->last_block;
00511 else
00512 {
00513 struct jcf_block *label = gen_jcf_label (state);
00514 define_jcf_label (label, state);
00515 return label;
00516 }
00517 }
00518
00519
00520
00521 static void
00522 put_linenumber (line, state)
00523 int line;
00524 struct jcf_partial *state;
00525 {
00526 struct jcf_block *label = get_jcf_label_here (state);
00527 if (label->linenumber > 0)
00528 {
00529 label = gen_jcf_label (state);
00530 define_jcf_label (label, state);
00531 }
00532 label->linenumber = line;
00533 state->linenumber_count++;
00534 }
00535
00536
00537
00538
00539 static struct jcf_handler *
00540 alloc_handler (start_label, end_label, state)
00541 struct jcf_block *start_label;
00542 struct jcf_block *end_label;
00543 struct jcf_partial *state;
00544 {
00545 struct jcf_handler *handler = (struct jcf_handler *)
00546 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_handler));
00547 handler->start_label = start_label;
00548 handler->end_label = end_label;
00549 handler->handler_label = get_jcf_label_here (state);
00550 if (state->handlers == NULL)
00551 state->handlers = handler;
00552 else
00553 state->last_handler->next = handler;
00554 state->last_handler = handler;
00555 handler->next = NULL;
00556 state->num_handlers++;
00557 return handler;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566 #define DECL_LOCAL_INDEX(DECL) DECL_ALIGN(DECL)
00567
00568 struct localvar_info
00569 {
00570 struct localvar_info *next;
00571
00572 tree decl;
00573 struct jcf_block *start_label;
00574 struct jcf_block *end_label;
00575 };
00576
00577 #define localvar_buffer ((struct localvar_info**) state->localvars.data)
00578 #define localvar_max \
00579 ((struct localvar_info**) state->localvars.ptr - localvar_buffer)
00580
00581 static void
00582 localvar_alloc (decl, state)
00583 tree decl;
00584 struct jcf_partial *state;
00585 {
00586 struct jcf_block *start_label = get_jcf_label_here (state);
00587 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
00588 int index;
00589 register struct localvar_info *info;
00590 register struct localvar_info **ptr = localvar_buffer;
00591 register struct localvar_info **limit
00592 = (struct localvar_info**) state->localvars.ptr;
00593 for (index = 0; ptr < limit; index++, ptr++)
00594 {
00595 if (ptr[0] == NULL
00596 && (! wide || ((ptr+1) < limit && ptr[1] == NULL)))
00597 break;
00598 }
00599 if (ptr == limit)
00600 {
00601 buffer_grow (&state->localvars, 2 * sizeof (struct localvar_info*));
00602 ptr = (struct localvar_info**) state->localvars.data + index;
00603 state->localvars.ptr = (unsigned char *) (ptr + 1 + wide);
00604 }
00605 info = (struct localvar_info *)
00606 obstack_alloc (state->chunk_obstack, sizeof (struct localvar_info));
00607 ptr[0] = info;
00608 if (wide)
00609 ptr[1] = (struct localvar_info *)(~0);
00610 DECL_LOCAL_INDEX (decl) = index;
00611 info->decl = decl;
00612 info->start_label = start_label;
00613
00614 if (debug_info_level > DINFO_LEVEL_TERSE
00615 && DECL_NAME (decl) != NULL_TREE)
00616 {
00617
00618 info->next = NULL;
00619 if (state->last_lvar != NULL)
00620 state->last_lvar->next = info;
00621 else
00622 state->first_lvar = info;
00623 state->last_lvar = info;
00624 state->lvar_count++;
00625 }
00626 }
00627
00628 static void
00629 localvar_free (decl, state)
00630 tree decl;
00631 struct jcf_partial *state;
00632 {
00633 struct jcf_block *end_label = get_jcf_label_here (state);
00634 int index = DECL_LOCAL_INDEX (decl);
00635 register struct localvar_info **ptr = &localvar_buffer [index];
00636 register struct localvar_info *info = *ptr;
00637 int wide = TYPE_IS_WIDE (TREE_TYPE (decl));
00638
00639 info->end_label = end_label;
00640
00641 if (info->decl != decl)
00642 abort ();
00643 ptr[0] = NULL;
00644 if (wide)
00645 {
00646 if (ptr[1] != (struct localvar_info *)(~0))
00647 abort ();
00648 ptr[1] = NULL;
00649 }
00650 }
00651
00652
00653 #define STACK_TARGET 1
00654 #define IGNORE_TARGET 2
00655
00656
00657
00658
00659 static int
00660 get_access_flags (decl)
00661 tree decl;
00662 {
00663 int flags = 0;
00664 int isfield = TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL;
00665 if (CLASS_PUBLIC (decl))
00666 flags |= ACC_PUBLIC;
00667 if (CLASS_FINAL (decl))
00668 flags |= ACC_FINAL;
00669 if (isfield || TREE_CODE (decl) == FUNCTION_DECL)
00670 {
00671 if (TREE_PROTECTED (decl))
00672 flags |= ACC_PROTECTED;
00673 if (TREE_PRIVATE (decl))
00674 flags |= ACC_PRIVATE;
00675 }
00676 else if (TREE_CODE (decl) == TYPE_DECL)
00677 {
00678 if (CLASS_SUPER (decl))
00679 flags |= ACC_SUPER;
00680 if (CLASS_ABSTRACT (decl))
00681 flags |= ACC_ABSTRACT;
00682 if (CLASS_INTERFACE (decl))
00683 flags |= ACC_INTERFACE;
00684 if (CLASS_STATIC (decl))
00685 flags |= ACC_STATIC;
00686 if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
00687 || LOCAL_CLASS_P (TREE_TYPE (decl)))
00688 flags |= ACC_PRIVATE;
00689 if (CLASS_STRICTFP (decl))
00690 flags |= ACC_STRICT;
00691 }
00692 else
00693 abort ();
00694
00695 if (TREE_CODE (decl) == FUNCTION_DECL)
00696 {
00697 if (METHOD_NATIVE (decl))
00698 flags |= ACC_NATIVE;
00699 if (METHOD_STATIC (decl))
00700 flags |= ACC_STATIC;
00701 if (METHOD_SYNCHRONIZED (decl))
00702 flags |= ACC_SYNCHRONIZED;
00703 if (METHOD_ABSTRACT (decl))
00704 flags |= ACC_ABSTRACT;
00705 if (METHOD_STRICTFP (decl))
00706 flags |= ACC_STRICT;
00707 }
00708 if (isfield)
00709 {
00710 if (FIELD_STATIC (decl))
00711 flags |= ACC_STATIC;
00712 if (FIELD_VOLATILE (decl))
00713 flags |= ACC_VOLATILE;
00714 if (FIELD_TRANSIENT (decl))
00715 flags |= ACC_TRANSIENT;
00716 }
00717 return flags;
00718 }
00719
00720
00721
00722 static void
00723 write_chunks (stream, chunks)
00724 FILE* stream;
00725 struct chunk *chunks;
00726 {
00727 for (; chunks != NULL; chunks = chunks->next)
00728 fwrite (chunks->data, chunks->size, 1, stream);
00729 }
00730
00731
00732
00733
00734 static void
00735 push_constant1 (index, state)
00736 HOST_WIDE_INT index;
00737 struct jcf_partial *state;
00738 {
00739 RESERVE (3);
00740 if (index < 256)
00741 {
00742 OP1 (OPCODE_ldc);
00743 OP1 (index);
00744 }
00745 else
00746 {
00747 OP1 (OPCODE_ldc_w);
00748 OP2 (index);
00749 }
00750 }
00751
00752
00753
00754
00755 static void
00756 push_constant2 (index, state)
00757 HOST_WIDE_INT index;
00758 struct jcf_partial *state;
00759 {
00760 RESERVE (3);
00761 OP1 (OPCODE_ldc2_w);
00762 OP2 (index);
00763 }
00764
00765
00766
00767
00768 static void
00769 push_int_const (i, state)
00770 HOST_WIDE_INT i;
00771 struct jcf_partial *state;
00772 {
00773 RESERVE(3);
00774 if (i >= -1 && i <= 5)
00775 OP1(OPCODE_iconst_0 + i);
00776 else if (i >= -128 && i < 128)
00777 {
00778 OP1(OPCODE_bipush);
00779 OP1(i);
00780 }
00781 else if (i >= -32768 && i < 32768)
00782 {
00783 OP1(OPCODE_sipush);
00784 OP2(i);
00785 }
00786 else
00787 {
00788 i = find_constant1 (&state->cpool, CONSTANT_Integer,
00789 (jword)(i & 0xFFFFFFFF));
00790 push_constant1 (i, state);
00791 }
00792 }
00793
00794 static int
00795 find_constant_wide (lo, hi, state)
00796 HOST_WIDE_INT lo, hi;
00797 struct jcf_partial *state;
00798 {
00799 HOST_WIDE_INT w1, w2;
00800 lshift_double (lo, hi, -32, 64, &w1, &w2, 1);
00801 return find_constant2 (&state->cpool, CONSTANT_Long,
00802 (jword)(w1 & 0xFFFFFFFF), (jword)(lo & 0xFFFFFFFF));
00803 }
00804
00805
00806
00807
00808 static int
00809 find_constant_index (value, state)
00810 tree value;
00811 struct jcf_partial *state;
00812 {
00813 if (TREE_CODE (value) == INTEGER_CST)
00814 {
00815 if (TYPE_PRECISION (TREE_TYPE (value)) <= 32)
00816 return find_constant1 (&state->cpool, CONSTANT_Integer,
00817 (jword)(TREE_INT_CST_LOW (value) & 0xFFFFFFFF));
00818 else
00819 return find_constant_wide (TREE_INT_CST_LOW (value),
00820 TREE_INT_CST_HIGH (value), state);
00821 }
00822 else if (TREE_CODE (value) == REAL_CST)
00823 {
00824 long words[2];
00825 if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
00826 {
00827 words[0] = etarsingle (TREE_REAL_CST (value)) & 0xFFFFFFFF;
00828 return find_constant1 (&state->cpool, CONSTANT_Float,
00829 (jword)words[0]);
00830 }
00831 else
00832 {
00833 etardouble (TREE_REAL_CST (value), words);
00834 return find_constant2 (&state->cpool, CONSTANT_Double,
00835 (jword)(words[1-FLOAT_WORDS_BIG_ENDIAN] &
00836 0xFFFFFFFF),
00837 (jword)(words[FLOAT_WORDS_BIG_ENDIAN] &
00838 0xFFFFFFFF));
00839 }
00840 }
00841 else if (TREE_CODE (value) == STRING_CST)
00842 return find_string_constant (&state->cpool, value);
00843
00844 else
00845 abort ();
00846 }
00847
00848
00849
00850
00851 static void
00852 push_long_const (lo, hi, state)
00853 HOST_WIDE_INT lo, hi;
00854 struct jcf_partial *state;
00855 {
00856 HOST_WIDE_INT highpart, dummy;
00857 jint lowpart = WORD_TO_INT (lo);
00858
00859 rshift_double (lo, hi, 32, 64, &highpart, &dummy, 1);
00860
00861 if (highpart == 0 && (lowpart == 0 || lowpart == 1))
00862 {
00863 RESERVE(1);
00864 OP1(OPCODE_lconst_0 + lowpart);
00865 }
00866 else if ((highpart == 0 && lowpart > 0 && lowpart < 32768)
00867 || (highpart == -1 && lowpart < 0 && lowpart >= -32768))
00868 {
00869 push_int_const (lowpart, state);
00870 RESERVE (1);
00871 OP1 (OPCODE_i2l);
00872 }
00873 else
00874 push_constant2 (find_constant_wide (lo, hi, state), state);
00875 }
00876
00877 static void
00878 field_op (field, opcode, state)
00879 tree field;
00880 int opcode;
00881 struct jcf_partial *state;
00882 {
00883 int index = find_fieldref_index (&state->cpool, field);
00884 RESERVE (3);
00885 OP1 (opcode);
00886 OP2 (index);
00887 }
00888
00889
00890
00891
00892
00893 static int
00894 adjust_typed_op (type, max)
00895 tree type;
00896 int max;
00897 {
00898 switch (TREE_CODE (type))
00899 {
00900 case POINTER_TYPE:
00901 case RECORD_TYPE: return 4;
00902 case BOOLEAN_TYPE:
00903 return TYPE_PRECISION (type) == 32 || max < 5 ? 0 : 5;
00904 case CHAR_TYPE:
00905 return TYPE_PRECISION (type) == 32 || max < 6 ? 0 : 6;
00906 case INTEGER_TYPE:
00907 switch (TYPE_PRECISION (type))
00908 {
00909 case 8: return max < 5 ? 0 : 5;
00910 case 16: return max < 7 ? 0 : 7;
00911 case 32: return 0;
00912 case 64: return 1;
00913 }
00914 break;
00915 case REAL_TYPE:
00916 switch (TYPE_PRECISION (type))
00917 {
00918 case 32: return 2;
00919 case 64: return 3;
00920 }
00921 break;
00922 default:
00923 break;
00924 }
00925 abort ();
00926 }
00927
00928 static void
00929 maybe_wide (opcode, index, state)
00930 int opcode, index;
00931 struct jcf_partial *state;
00932 {
00933 if (index >= 256)
00934 {
00935 RESERVE (4);
00936 OP1 (OPCODE_wide);
00937 OP1 (opcode);
00938 OP2 (index);
00939 }
00940 else
00941 {
00942 RESERVE (2);
00943 OP1 (opcode);
00944 OP1 (index);
00945 }
00946 }
00947
00948
00949
00950
00951
00952
00953 static void
00954 emit_dup (size, offset, state)
00955 int size, offset;
00956 struct jcf_partial *state;
00957 {
00958 int kind;
00959 if (size == 0)
00960 return;
00961 RESERVE(1);
00962 if (offset == 0)
00963 kind = size == 1 ? OPCODE_dup : OPCODE_dup2;
00964 else if (offset == 1)
00965 kind = size == 1 ? OPCODE_dup_x1 : OPCODE_dup2_x1;
00966 else if (offset == 2)
00967 kind = size == 1 ? OPCODE_dup_x2 : OPCODE_dup2_x2;
00968 else
00969 abort();
00970 OP1 (kind);
00971 NOTE_PUSH (size);
00972 }
00973
00974 static void
00975 emit_pop (size, state)
00976 int size;
00977 struct jcf_partial *state;
00978 {
00979 RESERVE (1);
00980 OP1 (OPCODE_pop - 1 + size);
00981 }
00982
00983 static void
00984 emit_iinc (var, value, state)
00985 tree var;
00986 HOST_WIDE_INT value;
00987 struct jcf_partial *state;
00988 {
00989 int slot = DECL_LOCAL_INDEX (var);
00990
00991 if (value < -128 || value > 127 || slot >= 256)
00992 {
00993 RESERVE (6);
00994 OP1 (OPCODE_wide);
00995 OP1 (OPCODE_iinc);
00996 OP2 (slot);
00997 OP2 (value);
00998 }
00999 else
01000 {
01001 RESERVE (3);
01002 OP1 (OPCODE_iinc);
01003 OP1 (slot);
01004 OP1 (value);
01005 }
01006 }
01007
01008 static void
01009 emit_load_or_store (var, opcode, state)
01010 tree var;
01011 int opcode;
01012 struct jcf_partial *state;
01013 {
01014 tree type = TREE_TYPE (var);
01015 int kind = adjust_typed_op (type, 4);
01016 int index = DECL_LOCAL_INDEX (var);
01017 if (index <= 3)
01018 {
01019 RESERVE (1);
01020 OP1 (opcode + 5 + 4 * kind + index);
01021 }
01022 else
01023 maybe_wide (opcode + kind, index, state);
01024 }
01025
01026 static void
01027 emit_load (var, state)
01028 tree var;
01029 struct jcf_partial *state;
01030 {
01031 emit_load_or_store (var, OPCODE_iload, state);
01032 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
01033 }
01034
01035 static void
01036 emit_store (var, state)
01037 tree var;
01038 struct jcf_partial *state;
01039 {
01040 emit_load_or_store (var, OPCODE_istore, state);
01041 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (var)) ? 2 : 1);
01042 }
01043
01044 static void
01045 emit_unop (opcode, type, state)
01046 enum java_opcode opcode;
01047 tree type ATTRIBUTE_UNUSED;
01048 struct jcf_partial *state;
01049 {
01050 RESERVE(1);
01051 OP1 (opcode);
01052 }
01053
01054 static void
01055 emit_binop (opcode, type, state)
01056 enum java_opcode opcode;
01057 tree type;
01058 struct jcf_partial *state;
01059 {
01060 int size = TYPE_IS_WIDE (type) ? 2 : 1;
01061 RESERVE(1);
01062 OP1 (opcode);
01063 NOTE_POP (size);
01064 }
01065
01066 static void
01067 emit_reloc (value, kind, target, state)
01068 HOST_WIDE_INT value;
01069 int kind;
01070 struct jcf_block *target;
01071 struct jcf_partial *state;
01072 {
01073 struct jcf_relocation *reloc = (struct jcf_relocation *)
01074 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
01075 struct jcf_block *block = state->last_block;
01076 reloc->next = block->u.relocations;
01077 block->u.relocations = reloc;
01078 reloc->offset = BUFFER_LENGTH (&state->bytecode);
01079 reloc->label = target;
01080 reloc->kind = kind;
01081 if (kind == 0 || kind == BLOCK_START_RELOC)
01082 OP4 (value);
01083 else if (kind != SWITCH_ALIGN_RELOC)
01084 OP2 (value);
01085 }
01086
01087 static void
01088 emit_switch_reloc (label, state)
01089 struct jcf_block *label;
01090 struct jcf_partial *state;
01091 {
01092 emit_reloc (RELOCATION_VALUE_0, BLOCK_START_RELOC, label, state);
01093 }
01094
01095
01096
01097
01098 static void
01099 emit_case_reloc (reloc, state)
01100 struct jcf_relocation *reloc;
01101 struct jcf_partial *state;
01102 {
01103 struct jcf_block *block = state->last_block;
01104 reloc->next = block->u.relocations;
01105 block->u.relocations = reloc;
01106 reloc->offset = BUFFER_LENGTH (&state->bytecode);
01107 reloc->kind = BLOCK_START_RELOC;
01108 OP4 (0);
01109 }
01110
01111
01112
01113
01114 static void
01115 emit_if (target, opcode, inv_opcode, state)
01116 struct jcf_block *target;
01117 int opcode, inv_opcode;
01118 struct jcf_partial *state;
01119 {
01120 RESERVE(3);
01121 OP1 (opcode);
01122
01123 emit_reloc (RELOCATION_VALUE_1, - inv_opcode, target, state);
01124 }
01125
01126 static void
01127 emit_goto (target, state)
01128 struct jcf_block *target;
01129 struct jcf_partial *state;
01130 {
01131 RESERVE(3);
01132 OP1 (OPCODE_goto);
01133
01134 emit_reloc (RELOCATION_VALUE_1, OPCODE_goto_w, target, state);
01135 }
01136
01137 static void
01138 emit_jsr (target, state)
01139 struct jcf_block *target;
01140 struct jcf_partial *state;
01141 {
01142 RESERVE(3);
01143 OP1 (OPCODE_jsr);
01144
01145 emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
01146 }
01147
01148
01149
01150
01151
01152
01153
01154 static void
01155 generate_bytecode_conditional (exp, true_label, false_label,
01156 true_branch_first, state)
01157 tree exp;
01158 struct jcf_block *true_label;
01159 struct jcf_block *false_label;
01160 int true_branch_first;
01161 struct jcf_partial *state;
01162 {
01163 tree exp0, exp1, type;
01164 int save_SP = state->code_SP;
01165 enum java_opcode op, negop;
01166 switch (TREE_CODE (exp))
01167 {
01168 case INTEGER_CST:
01169 emit_goto (integer_zerop (exp) ? false_label : true_label, state);
01170 break;
01171 case COND_EXPR:
01172 {
01173 struct jcf_block *then_label = gen_jcf_label (state);
01174 struct jcf_block *else_label = gen_jcf_label (state);
01175 int save_SP_before, save_SP_after;
01176 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
01177 then_label, else_label, 1, state);
01178 define_jcf_label (then_label, state);
01179 save_SP_before = state->code_SP;
01180 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
01181 true_label, false_label, 1, state);
01182 save_SP_after = state->code_SP;
01183 state->code_SP = save_SP_before;
01184 define_jcf_label (else_label, state);
01185 generate_bytecode_conditional (TREE_OPERAND (exp, 2),
01186 true_label, false_label,
01187 true_branch_first, state);
01188 if (state->code_SP != save_SP_after)
01189 abort ();
01190 }
01191 break;
01192 case TRUTH_NOT_EXPR:
01193 generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
01194 true_label, ! true_branch_first, state);
01195 break;
01196 case TRUTH_ANDIF_EXPR:
01197 {
01198 struct jcf_block *next_label = gen_jcf_label (state);
01199 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
01200 next_label, false_label, 1, state);
01201 define_jcf_label (next_label, state);
01202 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
01203 true_label, false_label, 1, state);
01204 }
01205 break;
01206 case TRUTH_ORIF_EXPR:
01207 {
01208 struct jcf_block *next_label = gen_jcf_label (state);
01209 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
01210 true_label, next_label, 1, state);
01211 define_jcf_label (next_label, state);
01212 generate_bytecode_conditional (TREE_OPERAND (exp, 1),
01213 true_label, false_label, 1, state);
01214 }
01215 break;
01216 compare_1:
01217
01218
01219 op = op - 6;
01220
01221 compare_2:
01222
01223
01224 negop = (op & 1) ? op + 1 : op - 1;
01225 compare_2_ptr:
01226 if (true_branch_first)
01227 {
01228 emit_if (false_label, negop, op, state);
01229 emit_goto (true_label, state);
01230 }
01231 else
01232 {
01233 emit_if (true_label, op, negop, state);
01234 emit_goto (false_label, state);
01235 }
01236 break;
01237 case EQ_EXPR:
01238 op = OPCODE_if_icmpeq;
01239 goto compare;
01240 case NE_EXPR:
01241 op = OPCODE_if_icmpne;
01242 goto compare;
01243 case GT_EXPR:
01244 op = OPCODE_if_icmpgt;
01245 goto compare;
01246 case LT_EXPR:
01247 op = OPCODE_if_icmplt;
01248 goto compare;
01249 case GE_EXPR:
01250 op = OPCODE_if_icmpge;
01251 goto compare;
01252 case LE_EXPR:
01253 op = OPCODE_if_icmple;
01254 goto compare;
01255 compare:
01256 exp0 = TREE_OPERAND (exp, 0);
01257 exp1 = TREE_OPERAND (exp, 1);
01258 type = TREE_TYPE (exp0);
01259 switch (TREE_CODE (type))
01260 {
01261 int opf;
01262 case POINTER_TYPE: case RECORD_TYPE:
01263 switch (TREE_CODE (exp))
01264 {
01265 case EQ_EXPR: op = OPCODE_if_acmpeq; break;
01266 case NE_EXPR: op = OPCODE_if_acmpne; break;
01267 default: abort();
01268 }
01269 if (integer_zerop (exp1) || integer_zerop (exp0))
01270 {
01271 generate_bytecode_insns (integer_zerop (exp0) ? exp1 : exp0,
01272 STACK_TARGET, state);
01273 op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
01274 negop = (op & 1) ? op - 1 : op + 1;
01275 NOTE_POP (1);
01276 goto compare_2_ptr;
01277 }
01278 generate_bytecode_insns (exp0, STACK_TARGET, state);
01279 generate_bytecode_insns (exp1, STACK_TARGET, state);
01280 NOTE_POP (2);
01281 goto compare_2;
01282 case REAL_TYPE:
01283 generate_bytecode_insns (exp0, STACK_TARGET, state);
01284 generate_bytecode_insns (exp1, STACK_TARGET, state);
01285 if (op == OPCODE_if_icmplt || op == OPCODE_if_icmple)
01286 opf = OPCODE_fcmpg;
01287 else
01288 opf = OPCODE_fcmpl;
01289 if (TYPE_PRECISION (type) > 32)
01290 {
01291 opf += 2;
01292 NOTE_POP (4);
01293 }
01294 else
01295 NOTE_POP (2);
01296 RESERVE (1);
01297 OP1 (opf);
01298 goto compare_1;
01299 case INTEGER_TYPE:
01300 if (TYPE_PRECISION (type) > 32)
01301 {
01302 generate_bytecode_insns (exp0, STACK_TARGET, state);
01303 generate_bytecode_insns (exp1, STACK_TARGET, state);
01304 NOTE_POP (4);
01305 RESERVE (1);
01306 OP1 (OPCODE_lcmp);
01307 goto compare_1;
01308 }
01309
01310 default:
01311 if (integer_zerop (exp1))
01312 {
01313 generate_bytecode_insns (exp0, STACK_TARGET, state);
01314 NOTE_POP (1);
01315 goto compare_1;
01316 }
01317 if (integer_zerop (exp0))
01318 {
01319 switch (op)
01320 {
01321 case OPCODE_if_icmplt:
01322 case OPCODE_if_icmpge:
01323 op += 2;
01324 break;
01325 case OPCODE_if_icmpgt:
01326 case OPCODE_if_icmple:
01327 op -= 2;
01328 break;
01329 default:
01330 break;
01331 }
01332 generate_bytecode_insns (exp1, STACK_TARGET, state);
01333 NOTE_POP (1);
01334 goto compare_1;
01335 }
01336 generate_bytecode_insns (exp0, STACK_TARGET, state);
01337 generate_bytecode_insns (exp1, STACK_TARGET, state);
01338 NOTE_POP (2);
01339 goto compare_2;
01340 }
01341
01342 default:
01343 generate_bytecode_insns (exp, STACK_TARGET, state);
01344 NOTE_POP (1);
01345 if (true_branch_first)
01346 {
01347 emit_if (false_label, OPCODE_ifeq, OPCODE_ifne, state);
01348 emit_goto (true_label, state);
01349 }
01350 else
01351 {
01352 emit_if (true_label, OPCODE_ifne, OPCODE_ifeq, state);
01353 emit_goto (false_label, state);
01354 }
01355 break;
01356 }
01357 if (save_SP != state->code_SP)
01358 abort ();
01359 }
01360
01361
01362
01363
01364
01365 static void
01366 call_cleanups (limit, state)
01367 struct jcf_block *limit;
01368 struct jcf_partial *state;
01369 {
01370 struct jcf_block *block = state->labeled_blocks;
01371 for (; block != limit; block = block->next)
01372 {
01373 if (block->pc == PENDING_CLEANUP_PC)
01374 emit_jsr (block, state);
01375 }
01376 }
01377
01378 static void
01379 generate_bytecode_return (exp, state)
01380 tree exp;
01381 struct jcf_partial *state;
01382 {
01383 tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
01384 int returns_void = TREE_CODE (return_type) == VOID_TYPE;
01385 int op;
01386 again:
01387 if (exp != NULL)
01388 {
01389 switch (TREE_CODE (exp))
01390 {
01391 case COMPOUND_EXPR:
01392 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
01393 state);
01394 exp = TREE_OPERAND (exp, 1);
01395 goto again;
01396 case COND_EXPR:
01397 {
01398 struct jcf_block *then_label = gen_jcf_label (state);
01399 struct jcf_block *else_label = gen_jcf_label (state);
01400 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
01401 then_label, else_label, 1, state);
01402 define_jcf_label (then_label, state);
01403 generate_bytecode_return (TREE_OPERAND (exp, 1), state);
01404 define_jcf_label (else_label, state);
01405 generate_bytecode_return (TREE_OPERAND (exp, 2), state);
01406 }
01407 return;
01408 default:
01409 generate_bytecode_insns (exp,
01410 returns_void ? IGNORE_TARGET
01411 : STACK_TARGET, state);
01412 }
01413 }
01414 if (returns_void)
01415 {
01416 op = OPCODE_return;
01417 call_cleanups (NULL, state);
01418 }
01419 else
01420 {
01421 op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
01422 if (state->num_finalizers > 0)
01423 {
01424 if (state->return_value_decl == NULL_TREE)
01425 {
01426 state->return_value_decl
01427 = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
01428 localvar_alloc (state->return_value_decl, state);
01429 }
01430 emit_store (state->return_value_decl, state);
01431 call_cleanups (NULL, state);
01432 emit_load (state->return_value_decl, state);
01433
01434
01435
01436
01437
01438 }
01439 }
01440 RESERVE (1);
01441 OP1 (op);
01442 }
01443
01444
01445
01446
01447 static void
01448 generate_bytecode_insns (exp, target, state)
01449 tree exp;
01450 int target;
01451 struct jcf_partial *state;
01452 {
01453 tree type, arg;
01454 enum java_opcode jopcode;
01455 int op;
01456 HOST_WIDE_INT value;
01457 int post_op;
01458 int size;
01459 int offset;
01460
01461 if (exp == NULL && target == IGNORE_TARGET)
01462 return;
01463
01464 type = TREE_TYPE (exp);
01465
01466 switch (TREE_CODE (exp))
01467 {
01468 case BLOCK:
01469 if (BLOCK_EXPR_BODY (exp))
01470 {
01471 tree local;
01472 tree body = BLOCK_EXPR_BODY (exp);
01473 for (local = BLOCK_EXPR_DECLS (exp); local; )
01474 {
01475 tree next = TREE_CHAIN (local);
01476 localvar_alloc (local, state);
01477 local = next;
01478 }
01479
01480 while (TREE_CODE (body) == COMPOUND_EXPR)
01481 {
01482 generate_bytecode_insns (TREE_OPERAND (body, 0), target, state);
01483 body = TREE_OPERAND (body, 1);
01484 }
01485 generate_bytecode_insns (body, target, state);
01486 for (local = BLOCK_EXPR_DECLS (exp); local; )
01487 {
01488 tree next = TREE_CHAIN (local);
01489 localvar_free (local, state);
01490 local = next;
01491 }
01492 }
01493 break;
01494 case COMPOUND_EXPR:
01495 generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET, state);
01496
01497
01498
01499 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 0)))
01500 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
01501 break;
01502 case EXPR_WITH_FILE_LOCATION:
01503 {
01504 const char *saved_input_filename = input_filename;
01505 tree body = EXPR_WFL_NODE (exp);
01506 int saved_lineno = lineno;
01507 if (body == empty_stmt_node)
01508 break;
01509 input_filename = EXPR_WFL_FILENAME (exp);
01510 lineno = EXPR_WFL_LINENO (exp);
01511 if (EXPR_WFL_EMIT_LINE_NOTE (exp) && lineno > 0
01512 && debug_info_level > DINFO_LEVEL_NONE)
01513 put_linenumber (lineno, state);
01514 generate_bytecode_insns (body, target, state);
01515 input_filename = saved_input_filename;
01516 lineno = saved_lineno;
01517 }
01518 break;
01519 case INTEGER_CST:
01520 if (target == IGNORE_TARGET) ;
01521 else if (TREE_CODE (type) == POINTER_TYPE)
01522 {
01523 if (! integer_zerop (exp))
01524 abort();
01525 RESERVE(1);
01526 OP1 (OPCODE_aconst_null);
01527 NOTE_PUSH (1);
01528 }
01529 else if (TYPE_PRECISION (type) <= 32)
01530 {
01531 push_int_const (TREE_INT_CST_LOW (exp), state);
01532 NOTE_PUSH (1);
01533 }
01534 else
01535 {
01536 push_long_const (TREE_INT_CST_LOW (exp), TREE_INT_CST_HIGH (exp),
01537 state);
01538 NOTE_PUSH (2);
01539 }
01540 break;
01541 case REAL_CST:
01542 {
01543 int prec = TYPE_PRECISION (type) >> 5;
01544 RESERVE(1);
01545 if (real_zerop (exp) && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (exp)))
01546 OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
01547 else if (real_onep (exp))
01548 OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
01549
01550
01551
01552 else
01553 {
01554 offset = find_constant_index (exp, state);
01555 if (prec == 1)
01556 push_constant1 (offset, state);
01557 else
01558 push_constant2 (offset, state);
01559 }
01560 NOTE_PUSH (prec);
01561 }
01562 break;
01563 case STRING_CST:
01564 push_constant1 (find_string_constant (&state->cpool, exp), state);
01565 NOTE_PUSH (1);
01566 break;
01567 case VAR_DECL:
01568 if (TREE_STATIC (exp))
01569 {
01570 field_op (exp, OPCODE_getstatic, state);
01571 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
01572 break;
01573 }
01574
01575 case PARM_DECL:
01576 emit_load (exp, state);
01577 break;
01578 case NON_LVALUE_EXPR:
01579 case INDIRECT_REF:
01580 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
01581 break;
01582 case ARRAY_REF:
01583 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
01584 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
01585 if (target != IGNORE_TARGET)
01586 {
01587 jopcode = OPCODE_iaload + adjust_typed_op (type, 7);
01588 RESERVE(1);
01589 OP1 (jopcode);
01590 if (! TYPE_IS_WIDE (type))
01591 NOTE_POP (1);
01592 }
01593 break;
01594 case COMPONENT_REF:
01595 {
01596 tree obj = TREE_OPERAND (exp, 0);
01597 tree field = TREE_OPERAND (exp, 1);
01598 int is_static = FIELD_STATIC (field);
01599 generate_bytecode_insns (obj,
01600 is_static ? IGNORE_TARGET : target, state);
01601 if (target != IGNORE_TARGET)
01602 {
01603 if (DECL_NAME (field) == length_identifier_node && !is_static
01604 && TYPE_ARRAY_P (TREE_TYPE (obj)))
01605 {
01606 RESERVE (1);
01607 OP1 (OPCODE_arraylength);
01608 }
01609 else
01610 {
01611 field_op (field, is_static ? OPCODE_getstatic : OPCODE_getfield,
01612 state);
01613 if (! is_static)
01614 NOTE_POP (1);
01615 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
01616 }
01617 }
01618 }
01619 break;
01620 case TRUTH_ANDIF_EXPR:
01621 case TRUTH_ORIF_EXPR:
01622 case EQ_EXPR:
01623 case NE_EXPR:
01624 case GT_EXPR:
01625 case LT_EXPR:
01626 case GE_EXPR:
01627 case LE_EXPR:
01628 {
01629 struct jcf_block *then_label = gen_jcf_label (state);
01630 struct jcf_block *else_label = gen_jcf_label (state);
01631 struct jcf_block *end_label = gen_jcf_label (state);
01632 generate_bytecode_conditional (exp,
01633 then_label, else_label, 1, state);
01634 define_jcf_label (then_label, state);
01635 push_int_const (1, state);
01636 emit_goto (end_label, state);
01637 define_jcf_label (else_label, state);
01638 push_int_const (0, state);
01639 define_jcf_label (end_label, state);
01640 NOTE_PUSH (1);
01641 }
01642 break;
01643 case COND_EXPR:
01644 {
01645 struct jcf_block *then_label = gen_jcf_label (state);
01646 struct jcf_block *else_label = gen_jcf_label (state);
01647 struct jcf_block *end_label = gen_jcf_label (state);
01648 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
01649 then_label, else_label, 1, state);
01650 define_jcf_label (then_label, state);
01651 generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
01652 if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
01653
01654 || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
01655 emit_goto (end_label, state);
01656 define_jcf_label (else_label, state);
01657 generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
01658 define_jcf_label (end_label, state);
01659
01660 if (TREE_TYPE (exp) != void_type_node)
01661 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
01662 }
01663 break;
01664 case CASE_EXPR:
01665 {
01666 struct jcf_switch_state *sw_state = state->sw_state;
01667 struct jcf_relocation *reloc = (struct jcf_relocation *)
01668 obstack_alloc (state->chunk_obstack, sizeof (struct jcf_relocation));
01669 HOST_WIDE_INT case_value = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
01670 reloc->kind = 0;
01671 reloc->label = get_jcf_label_here (state);
01672 reloc->offset = case_value;
01673 reloc->next = sw_state->cases;
01674 sw_state->cases = reloc;
01675 if (sw_state->num_cases == 0)
01676 {
01677 sw_state->min_case = case_value;
01678 sw_state->max_case = case_value;
01679 }
01680 else
01681 {
01682 if (case_value < sw_state->min_case)
01683 sw_state->min_case = case_value;
01684 if (case_value > sw_state->max_case)
01685 sw_state->max_case = case_value;
01686 }
01687 sw_state->num_cases++;
01688 }
01689 break;
01690 case DEFAULT_EXPR:
01691 state->sw_state->default_label = get_jcf_label_here (state);
01692 break;
01693
01694 case SWITCH_EXPR:
01695 {
01696
01697
01698
01699
01700
01701
01702 struct jcf_switch_state sw_state;
01703 struct jcf_block *expression_last;
01704 struct jcf_block *body_last;
01705 struct jcf_block *switch_instruction;
01706 struct jcf_block *instruction_last;
01707 struct jcf_block *body_block;
01708 int switch_length;
01709 sw_state.prev = state->sw_state;
01710 state->sw_state = &sw_state;
01711 sw_state.cases = NULL;
01712 sw_state.num_cases = 0;
01713 sw_state.default_label = NULL;
01714 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
01715 expression_last = state->last_block;
01716
01717 body_block = gen_jcf_label (state);
01718 define_jcf_label (body_block, state);
01719 generate_bytecode_insns (TREE_OPERAND (exp, 1), IGNORE_TARGET, state);
01720 body_last = state->last_block;
01721
01722 switch_instruction = gen_jcf_label (state);
01723 define_jcf_label (switch_instruction, state);
01724 if (sw_state.default_label == NULL)
01725 sw_state.default_label = gen_jcf_label (state);
01726
01727 if (sw_state.num_cases <= 1)
01728 {
01729 if (sw_state.num_cases == 0)
01730 {
01731 emit_pop (1, state);
01732 NOTE_POP (1);
01733 }
01734 else
01735 {
01736 push_int_const (sw_state.cases->offset, state);
01737 NOTE_PUSH (1);
01738 emit_if (sw_state.cases->label,
01739 OPCODE_if_icmpeq, OPCODE_if_icmpne, state);
01740 }
01741 emit_goto (sw_state.default_label, state);
01742 }
01743 else
01744 {
01745 HOST_WIDE_INT i;
01746
01747 struct jcf_relocation **relocs = (struct jcf_relocation **)
01748 xmalloc (sw_state.num_cases * sizeof (struct jcf_relocation *));
01749
01750
01751 int gap_start = 0;
01752 int gap_end = sw_state.num_cases;
01753 struct jcf_relocation *reloc;
01754 for (reloc = sw_state.cases; reloc != NULL; reloc = reloc->next)
01755 {
01756 HOST_WIDE_INT case_value = reloc->offset;
01757 while (gap_end < sw_state.num_cases)
01758 {
01759 struct jcf_relocation *end = relocs[gap_end];
01760 if (case_value <= end->offset)
01761 break;
01762 relocs[gap_start++] = end;
01763 gap_end++;
01764 }
01765 while (gap_start > 0)
01766 {
01767 struct jcf_relocation *before = relocs[gap_start-1];
01768 if (case_value >= before->offset)
01769 break;
01770 relocs[--gap_end] = before;
01771 gap_start--;
01772 }
01773 relocs[gap_start++] = reloc;
01774
01775
01776 }
01777
01778 if (2 * sw_state.num_cases
01779 >= sw_state.max_case - sw_state.min_case)
01780 {
01781 int index = 0;
01782 RESERVE (13 + 4 * (sw_state.max_case - sw_state.min_case + 1));
01783 OP1 (OPCODE_tableswitch);
01784 emit_reloc (RELOCATION_VALUE_0,
01785 SWITCH_ALIGN_RELOC, NULL, state);
01786 emit_switch_reloc (sw_state.default_label, state);
01787 OP4 (sw_state.min_case);
01788 OP4 (sw_state.max_case);
01789 for (i = sw_state.min_case; ; )
01790 {
01791 reloc = relocs[index];
01792 if (i == reloc->offset)
01793 {
01794 emit_case_reloc (reloc, state);
01795 if (i == sw_state.max_case)
01796 break;
01797 index++;
01798 }
01799 else
01800 emit_switch_reloc (sw_state.default_label, state);
01801 i++;
01802 }
01803 }
01804 else
01805 {
01806 RESERVE(9 + 8 * sw_state.num_cases);
01807 OP1 (OPCODE_lookupswitch);
01808 emit_reloc (RELOCATION_VALUE_0,
01809 SWITCH_ALIGN_RELOC, NULL, state);
01810 emit_switch_reloc (sw_state.default_label, state);
01811 OP4 (sw_state.num_cases);
01812 for (i = 0; i < sw_state.num_cases; i++)
01813 {
01814 struct jcf_relocation *reloc = relocs[i];
01815 OP4 (reloc->offset);
01816 emit_case_reloc (reloc, state);
01817 }
01818 }
01819 free (relocs);
01820 }
01821
01822 instruction_last = state->last_block;
01823 if (sw_state.default_label->pc < 0)
01824 define_jcf_label (sw_state.default_label, state);
01825 else
01826 sw_state.default_label = get_jcf_label_here (state);
01827
01828
01829 switch_length = state->code_length - switch_instruction->pc;
01830 switch_instruction->pc = body_block->pc;
01831 instruction_last->next = body_block;
01832 instruction_last->v.chunk->next = body_block->v.chunk;
01833 expression_last->next = switch_instruction;
01834 expression_last->v.chunk->next = switch_instruction->v.chunk;
01835 body_last->next = sw_state.default_label;
01836 body_last->v.chunk->next = NULL;
01837 state->chunk = body_last->v.chunk;
01838 for (; body_block != sw_state.default_label; body_block = body_block->next)
01839 body_block->pc += switch_length;
01840
01841 state->sw_state = sw_state.prev;
01842 break;
01843 }
01844
01845 case RETURN_EXPR:
01846 exp = TREE_OPERAND (exp, 0);
01847 if (exp == NULL_TREE)
01848 exp = empty_stmt_node;
01849 else if (TREE_CODE (exp) != MODIFY_EXPR)
01850 abort ();
01851 else
01852 exp = TREE_OPERAND (exp, 1);
01853 generate_bytecode_return (exp, state);
01854 break;
01855 case LABELED_BLOCK_EXPR:
01856 {
01857 struct jcf_block *end_label = gen_jcf_label (state);
01858 end_label->next = state->labeled_blocks;
01859 state->labeled_blocks = end_label;
01860 end_label->pc = PENDING_EXIT_PC;
01861 end_label->u.labeled_block = exp;
01862 if (LABELED_BLOCK_BODY (exp))
01863 generate_bytecode_insns (LABELED_BLOCK_BODY (exp), target, state);
01864 if (state->labeled_blocks != end_label)
01865 abort();
01866 state->labeled_blocks = end_label->next;
01867 define_jcf_label (end_label, state);
01868 }
01869 break;
01870 case LOOP_EXPR:
01871 {
01872 tree body = TREE_OPERAND (exp, 0);
01873 #if 0
01874 if (TREE_CODE (body) == COMPOUND_EXPR
01875 && TREE_CODE (TREE_OPERAND (body, 0)) == EXIT_EXPR)
01876 {
01877
01878
01879 struct jcf_block *head_label;
01880 struct jcf_block *body_label;
01881 struct jcf_block *end_label = gen_jcf_label (state);
01882 struct jcf_block *exit_label = state->labeled_blocks;
01883 head_label = gen_jcf_label (state);
01884 emit_goto (head_label, state);
01885 body_label = get_jcf_label_here (state);
01886 generate_bytecode_insns (TREE_OPERAND (body, 1), target, state);
01887 define_jcf_label (head_label, state);
01888 generate_bytecode_conditional (TREE_OPERAND (body, 0),
01889 end_label, body_label, 1, state);
01890 define_jcf_label (end_label, state);
01891 }
01892 else
01893 #endif
01894 {
01895 struct jcf_block *head_label = get_jcf_label_here (state);
01896 generate_bytecode_insns (body, IGNORE_TARGET, state);
01897 if (CAN_COMPLETE_NORMALLY (body))
01898 emit_goto (head_label, state);
01899 }
01900 }
01901 break;
01902 case EXIT_EXPR:
01903 {
01904 struct jcf_block *label = state->labeled_blocks;
01905 struct jcf_block *end_label = gen_jcf_label (state);
01906 generate_bytecode_conditional (TREE_OPERAND (exp, 0),
01907 label, end_label, 0, state);
01908 define_jcf_label (end_label, state);
01909 }
01910 break;
01911 case EXIT_BLOCK_EXPR:
01912 {
01913 struct jcf_block *label = state->labeled_blocks;
01914 if (TREE_OPERAND (exp, 1) != NULL) goto notimpl;
01915 while (label->u.labeled_block != TREE_OPERAND (exp, 0))
01916 label = label->next;
01917 call_cleanups (label, state);
01918 emit_goto (label, state);
01919 }
01920 break;
01921
01922 case PREDECREMENT_EXPR: value = -1; post_op = 0; goto increment;
01923 case PREINCREMENT_EXPR: value = 1; post_op = 0; goto increment;
01924 case POSTDECREMENT_EXPR: value = -1; post_op = 1; goto increment;
01925 case POSTINCREMENT_EXPR: value = 1; post_op = 1; goto increment;
01926 increment:
01927
01928 arg = TREE_OPERAND (exp, 1);
01929 exp = TREE_OPERAND (exp, 0);
01930 type = TREE_TYPE (exp);
01931 size = TYPE_IS_WIDE (type) ? 2 : 1;
01932 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
01933 && ! TREE_STATIC (exp)
01934 && TREE_CODE (type) == INTEGER_TYPE
01935 && TYPE_PRECISION (type) == 32)
01936 {
01937 if (target != IGNORE_TARGET && post_op)
01938 emit_load (exp, state);
01939 emit_iinc (exp, value, state);
01940 if (target != IGNORE_TARGET && ! post_op)
01941 emit_load (exp, state);
01942 break;
01943 }
01944 if (TREE_CODE (exp) == COMPONENT_REF)
01945 {
01946 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
01947 emit_dup (1, 0, state);
01948
01949 field_op (TREE_OPERAND (exp, 1), OPCODE_getfield, state);
01950 NOTE_PUSH (size-1);
01951
01952 offset = 1;
01953 }
01954 else if (TREE_CODE (exp) == ARRAY_REF)
01955 {
01956 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
01957 generate_bytecode_insns (TREE_OPERAND (exp, 1), STACK_TARGET, state);
01958 emit_dup (2, 0, state);
01959
01960 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (exp), 7);
01961 RESERVE(1);
01962 OP1 (jopcode);
01963 NOTE_POP (2-size);
01964
01965 offset = 2;
01966 }
01967 else if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
01968 {
01969 generate_bytecode_insns (exp, STACK_TARGET, state);
01970
01971 offset = 0;
01972 }
01973 else
01974 abort ();
01975
01976 if (target != IGNORE_TARGET && post_op)
01977 emit_dup (size, offset, state);
01978
01979
01980
01981 generate_bytecode_insns (arg, STACK_TARGET, state);
01982 emit_binop ((value >= 0 ? OPCODE_iadd : OPCODE_isub)
01983 + adjust_typed_op (type, 3),
01984 type, state);
01985 if (target != IGNORE_TARGET && ! post_op)
01986 emit_dup (size, offset, state);
01987
01988
01989
01990 goto finish_assignment;
01991
01992 case MODIFY_EXPR:
01993 {
01994 tree lhs = TREE_OPERAND (exp, 0);
01995 tree rhs = TREE_OPERAND (exp, 1);
01996 int offset = 0;
01997
01998
01999 if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
02000 && ! TREE_STATIC (lhs)
02001 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
02002 && TYPE_PRECISION (TREE_TYPE (lhs)) == 32
02003 && (TREE_CODE (rhs) == PLUS_EXPR || TREE_CODE (rhs) == MINUS_EXPR))
02004 {
02005 tree arg0 = TREE_OPERAND (rhs, 0);
02006 tree arg1 = TREE_OPERAND (rhs, 1);
02007 HOST_WIDE_INT min_value = -32768;
02008 HOST_WIDE_INT max_value = 32767;
02009 if (TREE_CODE (rhs) == MINUS_EXPR)
02010 {
02011 min_value++;
02012 max_value++;
02013 }
02014 else if (arg1 == lhs)
02015 {
02016 arg0 = arg1;
02017 arg1 = TREE_OPERAND (rhs, 0);
02018 }
02019 if (lhs == arg0 && TREE_CODE (arg1) == INTEGER_CST)
02020 {
02021 HOST_WIDE_INT hi_value = TREE_INT_CST_HIGH (arg1);
02022 value = TREE_INT_CST_LOW (arg1);
02023 if ((hi_value == 0 && value <= max_value)
02024 || (hi_value == -1 && value >= min_value))
02025 {
02026 if (TREE_CODE (rhs) == MINUS_EXPR)
02027 value = -value;
02028 emit_iinc (lhs, value, state);
02029 if (target != IGNORE_TARGET)
02030 emit_load (lhs, state);
02031 break;
02032 }
02033 }
02034 }
02035
02036 if (TREE_CODE (lhs) == COMPONENT_REF)
02037 {
02038 generate_bytecode_insns (TREE_OPERAND (lhs, 0),
02039 STACK_TARGET, state);
02040 offset = 1;
02041 }
02042 else if (TREE_CODE (lhs) == ARRAY_REF)
02043 {
02044 generate_bytecode_insns (TREE_OPERAND(lhs, 0),
02045 STACK_TARGET, state);
02046 generate_bytecode_insns (TREE_OPERAND(lhs, 1),
02047 STACK_TARGET, state);
02048 offset = 2;
02049 }
02050 else
02051 offset = 0;
02052
02053
02054
02055
02056 if (TREE_CODE_CLASS (TREE_CODE (rhs)) == '2'
02057 && lhs == TREE_OPERAND (rhs, 0))
02058 {
02059 if (TREE_CODE (lhs) == COMPONENT_REF)
02060 {
02061 tree field = TREE_OPERAND (lhs, 1);
02062 if (! FIELD_STATIC (field))
02063 {
02064
02065
02066 emit_dup (TYPE_IS_WIDE (field) ? 2 : 1, 0, state);
02067 NOTE_POP (1);
02068 }
02069 field_op (field, (FIELD_STATIC (field)
02070 ? OPCODE_getstatic
02071 : OPCODE_getfield),
02072 state);
02073
02074 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
02075 }
02076 else if (TREE_CODE (lhs) == VAR_DECL
02077 || TREE_CODE (lhs) == PARM_DECL)
02078 {
02079 if (FIELD_STATIC (lhs))
02080 {
02081 field_op (lhs, OPCODE_getstatic, state);
02082 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
02083 }
02084 else
02085 emit_load (lhs, state);
02086 }
02087 else if (TREE_CODE (lhs) == ARRAY_REF)
02088 {
02089
02090
02091 emit_dup (2, 0, state);
02092 NOTE_POP (2);
02093 jopcode = OPCODE_iaload + adjust_typed_op (TREE_TYPE (lhs), 7);
02094 RESERVE (1);
02095 OP1 (jopcode);
02096 NOTE_PUSH (TYPE_IS_WIDE (TREE_TYPE (lhs)) ? 2 : 1);
02097 }
02098 else
02099 abort ();
02100
02101
02102
02103 rhs = build (TREE_CODE (rhs), TREE_TYPE (rhs),
02104 NULL_TREE, TREE_OPERAND (rhs, 1));
02105 }
02106
02107 generate_bytecode_insns (rhs, STACK_TARGET, state);
02108 if (target != IGNORE_TARGET)
02109 emit_dup (TYPE_IS_WIDE (type) ? 2 : 1 , offset, state);
02110 exp = lhs;
02111 }
02112
02113
02114 finish_assignment:
02115 if (TREE_CODE (exp) == COMPONENT_REF)
02116 {
02117 tree field = TREE_OPERAND (exp, 1);
02118 if (! FIELD_STATIC (field))
02119 NOTE_POP (1);
02120 field_op (field,
02121 FIELD_STATIC (field) ? OPCODE_putstatic : OPCODE_putfield,
02122 state);
02123
02124 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (field)) ? 2 : 1);
02125 }
02126 else if (TREE_CODE (exp) == VAR_DECL
02127 || TREE_CODE (exp) == PARM_DECL)
02128 {
02129 if (FIELD_STATIC (exp))
02130 {
02131 field_op (exp, OPCODE_putstatic, state);
02132 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
02133 }
02134 else
02135 emit_store (exp, state);
02136 }
02137 else if (TREE_CODE (exp) == ARRAY_REF)
02138 {
02139 jopcode = OPCODE_iastore + adjust_typed_op (TREE_TYPE (exp), 7);
02140 RESERVE (1);
02141 OP1 (jopcode);
02142 NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 4 : 3);
02143 }
02144 else
02145 abort ();
02146 break;
02147 case PLUS_EXPR:
02148 jopcode = OPCODE_iadd;
02149 goto binop;
02150 case MINUS_EXPR:
02151 jopcode = OPCODE_isub;
02152 goto binop;
02153 case MULT_EXPR:
02154 jopcode = OPCODE_imul;
02155 goto binop;
02156 case TRUNC_DIV_EXPR:
02157 case RDIV_EXPR:
02158 jopcode = OPCODE_idiv;
02159 goto binop;
02160 case TRUNC_MOD_EXPR:
02161 jopcode = OPCODE_irem;
02162 goto binop;
02163 case LSHIFT_EXPR: jopcode = OPCODE_ishl; goto binop;
02164 case RSHIFT_EXPR: jopcode = OPCODE_ishr; goto binop;
02165 case URSHIFT_EXPR: jopcode = OPCODE_iushr; goto binop;
02166 case TRUTH_AND_EXPR:
02167 case BIT_AND_EXPR: jopcode = OPCODE_iand; goto binop;
02168 case TRUTH_OR_EXPR:
02169 case BIT_IOR_EXPR: jopcode = OPCODE_ior; goto binop;
02170 case TRUTH_XOR_EXPR:
02171 case BIT_XOR_EXPR: jopcode = OPCODE_ixor; goto binop;
02172 binop:
02173 {
02174 tree arg0 = TREE_OPERAND (exp, 0);
02175 tree arg1 = TREE_OPERAND (exp, 1);
02176 jopcode += adjust_typed_op (type, 3);
02177 if (arg0 == arg1 && TREE_CODE (arg0) == SAVE_EXPR)
02178 {
02179
02180 generate_bytecode_insns (TREE_OPERAND (arg0, 0), target, state);
02181 emit_dup (TYPE_PRECISION (TREE_TYPE (arg0)) > 32 ? 2 : 1, 0, state);
02182 }
02183 else
02184 {
02185
02186
02187
02188 if (arg0 != NULL_TREE)
02189 generate_bytecode_insns (arg0, target, state);
02190 if (jopcode >= OPCODE_lshl && jopcode <= OPCODE_lushr)
02191 arg1 = convert (int_type_node, arg1);
02192 generate_bytecode_insns (arg1, target, state);
02193 }
02194
02195
02196
02197 if (target == STACK_TARGET)
02198 emit_binop (jopcode, TREE_TYPE (arg1), state);
02199 break;
02200 }
02201 case TRUTH_NOT_EXPR:
02202 case BIT_NOT_EXPR:
02203 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
02204 if (target == STACK_TARGET)
02205 {
02206 int is_long = TYPE_PRECISION (TREE_TYPE (exp)) > 32;
02207 push_int_const (TREE_CODE (exp) == BIT_NOT_EXPR ? -1 : 1, state);
02208 RESERVE (2);
02209 if (is_long)
02210 OP1 (OPCODE_i2l);
02211 NOTE_PUSH (1 + is_long);
02212 OP1 (OPCODE_ixor + is_long);
02213 NOTE_POP (1 + is_long);
02214 }
02215 break;
02216 case NEGATE_EXPR:
02217 jopcode = OPCODE_ineg;
02218 jopcode += adjust_typed_op (type, 3);
02219 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
02220 if (target == STACK_TARGET)
02221 emit_unop (jopcode, type, state);
02222 break;
02223 case INSTANCEOF_EXPR:
02224 {
02225 int index = find_class_constant (&state->cpool, TREE_OPERAND (exp, 1));
02226 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
02227 RESERVE (3);
02228 OP1 (OPCODE_instanceof);
02229 OP2 (index);
02230 }
02231 break;
02232 case SAVE_EXPR:
02233 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
02234 break;
02235 case CONVERT_EXPR:
02236 case NOP_EXPR:
02237 case FLOAT_EXPR:
02238 case FIX_TRUNC_EXPR:
02239 {
02240 tree src = TREE_OPERAND (exp, 0);
02241 tree src_type = TREE_TYPE (src);
02242 tree dst_type = TREE_TYPE (exp);
02243 generate_bytecode_insns (TREE_OPERAND (exp, 0), target, state);
02244 if (target == IGNORE_TARGET || src_type == dst_type)
02245 break;
02246 if (TREE_CODE (dst_type) == POINTER_TYPE)
02247 {
02248 if (TREE_CODE (exp) == CONVERT_EXPR)
02249 {
02250 int index = find_class_constant (&state->cpool,
02251 TREE_TYPE (dst_type));
02252 RESERVE (3);
02253 OP1 (OPCODE_checkcast);
02254 OP2 (index);
02255 }
02256 }
02257 else
02258 {
02259 int wide_src = TYPE_PRECISION (src_type) > 32;
02260 int wide_dst = TYPE_PRECISION (dst_type) > 32;
02261 NOTE_POP (1 + wide_src);
02262 RESERVE (1);
02263 if (TREE_CODE (dst_type) == REAL_TYPE)
02264 {
02265 if (TREE_CODE (src_type) == REAL_TYPE)
02266 OP1 (wide_dst ? OPCODE_f2d : OPCODE_d2f);
02267 else if (TYPE_PRECISION (src_type) == 64)
02268 OP1 (OPCODE_l2f + wide_dst);
02269 else
02270 OP1 (OPCODE_i2f + wide_dst);
02271 }
02272 else
02273 {
02274 if (TREE_CODE (src_type) == REAL_TYPE)
02275 OP1 (OPCODE_f2i + wide_dst + 3 * wide_src);
02276 else if (wide_dst)
02277 OP1 (OPCODE_i2l);
02278 else if (wide_src)
02279 OP1 (OPCODE_l2i);
02280 if (TYPE_PRECISION (dst_type) < 32)
02281 {
02282 RESERVE (1);
02283
02284 if (TYPE_PRECISION (dst_type) <= 8)
02285 OP1 (OPCODE_i2b);
02286 else if (TREE_UNSIGNED (dst_type))
02287 OP1 (OPCODE_i2c);
02288 else
02289 OP1 (OPCODE_i2s);
02290 }
02291 }
02292 NOTE_PUSH (1 + wide_dst);
02293 }
02294 }
02295 break;
02296
02297 case TRY_EXPR:
02298 {
02299 tree try_clause = TREE_OPERAND (exp, 0);
02300 struct jcf_block *start_label = get_jcf_label_here (state);
02301 struct jcf_block *end_label;
02302 struct jcf_block *finished_label = gen_jcf_label (state);
02303 tree clause = TREE_OPERAND (exp, 1);
02304 if (target != IGNORE_TARGET)
02305 abort ();
02306 generate_bytecode_insns (try_clause, IGNORE_TARGET, state);
02307 end_label = get_jcf_label_here (state);
02308 if (end_label == start_label)
02309 break;
02310 if (CAN_COMPLETE_NORMALLY (try_clause))
02311 emit_goto (finished_label, state);
02312 while (clause != NULL_TREE)
02313 {
02314 tree catch_clause = TREE_OPERAND (clause, 0);
02315 tree exception_decl = BLOCK_EXPR_DECLS (catch_clause);
02316 struct jcf_handler *handler = alloc_handler (start_label,
02317 end_label, state);
02318 if (exception_decl == NULL_TREE)
02319 handler->type = NULL_TREE;
02320 else
02321 handler->type = TREE_TYPE (TREE_TYPE (exception_decl));
02322 generate_bytecode_insns (catch_clause, IGNORE_TARGET, state);
02323 clause = TREE_CHAIN (clause);
02324 if (CAN_COMPLETE_NORMALLY (catch_clause) && clause != NULL_TREE)
02325 emit_goto (finished_label, state);
02326 }
02327 define_jcf_label (finished_label, state);
02328 }
02329 break;
02330
02331 case TRY_FINALLY_EXPR:
02332 {
02333 struct jcf_block *finished_label = NULL;
02334 struct jcf_block *finally_label, *start_label, *end_label;
02335 struct jcf_handler *handler;
02336 tree try_block = TREE_OPERAND (exp, 0);
02337 tree finally = TREE_OPERAND (exp, 1);
02338 tree return_link = NULL_TREE, exception_decl = NULL_TREE;
02339
02340 tree exception_type;
02341
02342 finally_label = gen_jcf_label (state);
02343 start_label = get_jcf_label_here (state);
02344
02345
02346
02347
02348 if (CAN_COMPLETE_NORMALLY (finally))
02349 {
02350 finally_label->pc = PENDING_CLEANUP_PC;
02351 finally_label->next = state->labeled_blocks;
02352 state->labeled_blocks = finally_label;
02353 state->num_finalizers++;
02354 }
02355
02356 generate_bytecode_insns (try_block, target, state);
02357
02358 if (CAN_COMPLETE_NORMALLY (finally))
02359 {
02360 if (state->labeled_blocks != finally_label)
02361 abort();
02362 state->labeled_blocks = finally_label->next;
02363 }
02364 end_label = get_jcf_label_here (state);
02365
02366 if (end_label == start_label)
02367 {
02368 state->num_finalizers--;
02369 define_jcf_label (finally_label, state);
02370 generate_bytecode_insns (finally, IGNORE_TARGET, state);
02371 break;
02372 }
02373
02374 if (CAN_COMPLETE_NORMALLY (finally))
02375 {
02376 return_link = build_decl (VAR_DECL, NULL_TREE,
02377 return_address_type_node);
02378 finished_label = gen_jcf_label (state);
02379 }
02380
02381 if (CAN_COMPLETE_NORMALLY (try_block))
02382 {
02383 if (CAN_COMPLETE_NORMALLY (finally))
02384 {
02385 emit_jsr (finally_label, state);
02386 emit_goto (finished_label, state);
02387 }
02388 else
02389 emit_goto (finally_label, state);
02390 }
02391
02392
02393
02394 exception_type = build_pointer_type (throwable_type_node);
02395 if (CAN_COMPLETE_NORMALLY (finally))
02396 {
02397
02398
02399 exception_decl = build_decl (VAR_DECL, NULL_TREE, exception_type);
02400 localvar_alloc (return_link, state);
02401 }
02402 handler = alloc_handler (start_label, end_label, state);
02403 handler->type = NULL_TREE;
02404 if (CAN_COMPLETE_NORMALLY (finally))
02405 {
02406 localvar_alloc (exception_decl, state);
02407 NOTE_PUSH (1);
02408 emit_store (exception_decl, state);
02409 emit_jsr (finally_label, state);
02410 emit_load (exception_decl, state);
02411 RESERVE (1);
02412 OP1 (OPCODE_athrow);
02413 NOTE_POP (1);
02414 }
02415 else
02416 {
02417
02418
02419
02420 NOTE_PUSH (1);
02421 emit_pop (1, state);
02422 NOTE_POP (1);
02423 }
02424
02425
02426
02427
02428 define_jcf_label (finally_label, state);
02429 if (CAN_COMPLETE_NORMALLY (finally))
02430 {
02431 NOTE_PUSH (1);
02432 emit_store (return_link, state);
02433 }
02434
02435 generate_bytecode_insns (finally, IGNORE_TARGET, state);
02436 if (CAN_COMPLETE_NORMALLY (finally))
02437 {
02438 maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
02439 localvar_free (exception_decl, state);
02440 localvar_free (return_link, state);
02441 define_jcf_label (finished_label, state);
02442 }
02443 }
02444 break;
02445 case THROW_EXPR:
02446 generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
02447 RESERVE (1);
02448 OP1 (OPCODE_athrow);
02449 break;
02450 case NEW_ARRAY_INIT:
02451 {
02452 tree values = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
02453 tree array_type = TREE_TYPE (TREE_TYPE (exp));
02454 tree element_type = TYPE_ARRAY_ELEMENT (array_type);
02455 HOST_WIDE_INT length = java_array_type_length (array_type);
02456 if (target == IGNORE_TARGET)
02457 {
02458 for ( ; values != NULL_TREE; values = TREE_CHAIN (values))
02459 generate_bytecode_insns (TREE_VALUE (values), target, state);
02460 break;
02461 }
02462 push_int_const (length, state);
02463 NOTE_PUSH (1);
02464 RESERVE (3);
02465 if (JPRIMITIVE_TYPE_P (element_type))
02466 {
02467 int atype = encode_newarray_type (element_type);
02468 OP1 (OPCODE_newarray);
02469 OP1 (atype);
02470 }
02471 else
02472 {
02473 int index = find_class_constant (&state->cpool,
02474 TREE_TYPE (element_type));
02475 OP1 (OPCODE_anewarray);
02476 OP2 (index);
02477 }
02478 offset = 0;
02479 jopcode = OPCODE_iastore + adjust_typed_op (element_type, 7);
02480 for ( ; values != NULL_TREE; values = TREE_CHAIN (values), offset++)
02481 {
02482 int save_SP = state->code_SP;
02483 emit_dup (1, 0, state);
02484 push_int_const (offset, state);
02485 NOTE_PUSH (1);
02486 generate_bytecode_insns (TREE_VALUE (values), STACK_TARGET, state);
02487 RESERVE (1);
02488 OP1 (jopcode);
02489 state->code_SP = save_SP;
02490 }
02491 }
02492 break;
02493 case JAVA_EXC_OBJ_EXPR:
02494 NOTE_PUSH (1);
02495 break;
02496 case NEW_CLASS_EXPR:
02497 {
02498 tree class = TREE_TYPE (TREE_TYPE (exp));
02499 int need_result = target != IGNORE_TARGET;
02500 int index = find_class_constant (&state->cpool, class);
02501 RESERVE (4);
02502 OP1 (OPCODE_new);
02503 OP2 (index);
02504 if (need_result)
02505 OP1 (OPCODE_dup);
02506 NOTE_PUSH (1 + need_result);
02507 }
02508
02509 case CALL_EXPR:
02510 {
02511 tree f = TREE_OPERAND (exp, 0);
02512 tree x = TREE_OPERAND (exp, 1);
02513 int save_SP = state->code_SP;
02514 int nargs;
02515 if (TREE_CODE (f) == ADDR_EXPR)
02516 f = TREE_OPERAND (f, 0);
02517 if (f == soft_newarray_node)
02518 {
02519 int type_code = TREE_INT_CST_LOW (TREE_VALUE (x));
02520 generate_bytecode_insns (TREE_VALUE (TREE_CHAIN (x)),
02521 STACK_TARGET, state);
02522 RESERVE (2);
02523 OP1 (OPCODE_newarray);
02524 OP1 (type_code);
02525 break;
02526 }
02527 else if (f == soft_multianewarray_node)
02528 {
02529 int ndims;
02530 int idim;
02531 int index = find_class_constant (&state->cpool,
02532 TREE_TYPE (TREE_TYPE (exp)));
02533 x = TREE_CHAIN (x);
02534 ndims = TREE_INT_CST_LOW (TREE_VALUE (x));
02535 for (idim = ndims; --idim >= 0; )
02536 {
02537 x = TREE_CHAIN (x);
02538 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
02539 }
02540 RESERVE (4);
02541 OP1 (OPCODE_multianewarray);
02542 OP2 (index);
02543 OP1 (ndims);
02544 break;
02545 }
02546 else if (f == soft_anewarray_node)
02547 {
02548 tree cl = TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (exp)));
02549 int index = find_class_constant (&state->cpool, TREE_TYPE (cl));
02550 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
02551 RESERVE (3);
02552 OP1 (OPCODE_anewarray);
02553 OP2 (index);
02554 break;
02555 }
02556 else if (f == soft_monitorenter_node
02557 || f == soft_monitorexit_node
02558 || f == throw_node)
02559 {
02560 if (f == soft_monitorenter_node)
02561 op = OPCODE_monitorenter;
02562 else if (f == soft_monitorexit_node)
02563 op = OPCODE_monitorexit;
02564 else
02565 op = OPCODE_athrow;
02566 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
02567 RESERVE (1);
02568 OP1 (op);
02569 NOTE_POP (1);
02570 break;
02571 }
02572 for ( ; x != NULL_TREE; x = TREE_CHAIN (x))
02573 {
02574 generate_bytecode_insns (TREE_VALUE (x), STACK_TARGET, state);
02575 }
02576 nargs = state->code_SP - save_SP;
02577 state->code_SP = save_SP;
02578 if (f == soft_fmod_node)
02579 {
02580 RESERVE (1);
02581 OP1 (OPCODE_drem);
02582 NOTE_PUSH (2);
02583 break;
02584 }
02585 if (TREE_CODE (exp) == NEW_CLASS_EXPR)
02586 NOTE_POP (1);
02587 if (TREE_CODE (f) == FUNCTION_DECL && DECL_CONTEXT (f) != NULL_TREE)
02588 {
02589 tree context = DECL_CONTEXT (f);
02590 int index, interface = 0;
02591 RESERVE (5);
02592 if (METHOD_STATIC (f))
02593 OP1 (OPCODE_invokestatic);
02594 else if (DECL_CONSTRUCTOR_P (f) || CALL_USING_SUPER (exp)
02595 || METHOD_PRIVATE (f))
02596 OP1 (OPCODE_invokespecial);
02597 else
02598 {
02599 if (CLASS_INTERFACE (TYPE_NAME (context)))
02600 {
02601 tree arg1 = TREE_VALUE (TREE_OPERAND (exp, 1));
02602 context = TREE_TYPE (TREE_TYPE (arg1));
02603 if (CLASS_INTERFACE (TYPE_NAME (context)))
02604 interface = 1;
02605 }
02606 if (interface)
02607 OP1 (OPCODE_invokeinterface);
02608 else
02609 OP1 (OPCODE_invokevirtual);
02610 }
02611 index = find_methodref_with_class_index (&state->cpool, f, context);
02612 OP2 (index);
02613 if (interface)
02614 {
02615 if (nargs <= 0)
02616 abort ();
02617
02618 OP1 (nargs);
02619 OP1 (0);
02620 }
02621 f = TREE_TYPE (TREE_TYPE (f));
02622 if (TREE_CODE (f) != VOID_TYPE)
02623 {
02624 int size = TYPE_IS_WIDE (f) ? 2 : 1;
02625 if (target == IGNORE_TARGET)
02626 emit_pop (size, state);
02627 else
02628 NOTE_PUSH (size);
02629 }
02630 break;
02631 }
02632 }
02633
02634 notimpl:
02635 default:
02636 error("internal error in generate_bytecode_insn - tree code not implemented: %s",
02637 tree_code_name [(int) TREE_CODE (exp)]);
02638 }
02639 }
02640
02641 static void
02642 perform_relocations (state)
02643 struct jcf_partial *state;
02644 {
02645 struct jcf_block *block;
02646 struct jcf_relocation *reloc;
02647 int pc;
02648 int shrink;
02649
02650
02651
02652
02653
02654
02655
02656
02657 pc = 0;
02658 shrink = 0;
02659 for (block = state->blocks; block != NULL; block = block->next)
02660 {
02661 int block_size = block->v.chunk->size;
02662
02663 block->pc = pc;
02664
02665
02666
02667 reloc = block->u.relocations;
02668 while (reloc != NULL
02669 && reloc->kind == OPCODE_goto_w
02670 && reloc->label->pc == block->next->pc
02671 && reloc->offset + 2 == block_size)
02672 {
02673 reloc = reloc->next;
02674 block->u.relocations = reloc;
02675 block->v.chunk->size -= 3;
02676 block_size -= 3;
02677 shrink += 3;
02678 }
02679
02680 for (reloc = block->u.relocations; reloc != NULL; reloc = reloc->next)
02681 {
02682 if (reloc->kind == SWITCH_ALIGN_RELOC)
02683 {
02684
02685
02686 int where = pc + reloc->offset;
02687 int pad = ((where + 3) & ~3) - where;
02688 block_size += pad;
02689 }
02690 else if (reloc->kind < -1 || reloc->kind > BLOCK_START_RELOC)
02691 {
02692 int delta = reloc->label->pc - (pc + reloc->offset - 1);
02693 int expand = reloc->kind > 0 ? 2 : 5;
02694
02695 if (delta > 0)
02696 delta -= shrink;
02697 if (delta >= -32768 && delta <= 32767)
02698 {
02699 shrink += expand;
02700 reloc->kind = -1;
02701 }
02702 else
02703 block_size += expand;
02704 }
02705 }
02706 pc += block_size;
02707 }
02708
02709 for (block = state->blocks; block != NULL; block = block->next)
02710 {
02711 struct chunk *chunk = block->v.chunk;
02712 int old_size = chunk->size;
02713 int next_pc = block->next == NULL ? pc : block->next->pc;
02714 int new_size = next_pc - block->pc;
02715 unsigned char *new_ptr;
02716 unsigned char *old_buffer = chunk->data;
02717 unsigned char *old_ptr = old_buffer + old_size;
02718 if (new_size != old_size)
02719 {
02720 chunk->data = (unsigned char *)
02721 obstack_alloc (state->chunk_obstack, new_size);
02722 chunk->size = new_size;
02723 }
02724 new_ptr = chunk->data + new_size;
02725
02726
02727
02728 for (reloc = block->u.relocations; ; reloc = reloc->next)
02729 {
02730
02731
02732
02733
02734
02735
02736
02737
02738 int start = reloc == NULL ? 0
02739 : reloc->kind == SWITCH_ALIGN_RELOC ? reloc->offset
02740 : (reloc->kind == 0 || reloc->kind == BLOCK_START_RELOC)
02741 ? reloc->offset + 4
02742 : reloc->offset + 2;
02743 int32 value;
02744 int new_offset;
02745 int n = (old_ptr - old_buffer) - start;
02746 new_ptr -= n;
02747 old_ptr -= n;
02748 if (n > 0)
02749 memcpy (new_ptr, old_ptr, n);
02750 if (old_ptr == old_buffer)
02751 break;
02752
02753 new_offset = new_ptr - chunk->data;
02754 new_offset -= (reloc->kind == -1 ? 2 : 4);
02755 if (reloc->kind == 0)
02756 {
02757 old_ptr -= 4;
02758 value = GET_u4 (old_ptr);
02759 }
02760 else if (reloc->kind == BLOCK_START_RELOC)
02761 {
02762 old_ptr -= 4;
02763 value = 0;
02764 new_offset = 0;
02765 }
02766 else if (reloc->kind == SWITCH_ALIGN_RELOC)
02767 {
02768 int where = block->pc + reloc->offset;
02769 int pad = ((where + 3) & ~3) - where;
02770 while (--pad >= 0)
02771 *--new_ptr = 0;
02772 continue;
02773 }
02774 else
02775 {
02776 old_ptr -= 2;
02777 value = GET_u2 (old_ptr);
02778 }
02779 value += reloc->label->pc - (block->pc + new_offset);
02780 *--new_ptr = (unsigned char) value; value >>= 8;
02781 *--new_ptr = (unsigned char) value; value >>= 8;
02782 if (reloc->kind != -1)
02783 {
02784 *--new_ptr = (unsigned char) value; value >>= 8;
02785 *--new_ptr = (unsigned char) value;
02786 }
02787 if (reloc->kind > BLOCK_START_RELOC)
02788 {
02789
02790 --old_ptr;
02791 *--new_ptr = reloc->kind;
02792 }
02793 else if (reloc->kind < -1)
02794 {
02795
02796 --old_ptr;
02797 *--new_ptr = OPCODE_goto_w;
02798 *--new_ptr = 3;
02799 *--new_ptr = 0;
02800 *--new_ptr = - reloc->kind;
02801 }
02802 }
02803 if (new_ptr != chunk->data)
02804 abort ();
02805 }
02806 state->code_length = pc;
02807 }
02808
02809 static void
02810 init_jcf_state (state, work)
02811 struct jcf_partial *state;
02812 struct obstack *work;
02813 {
02814 state->chunk_obstack = work;
02815 state->first = state->chunk = NULL;
02816 CPOOL_INIT (&state->cpool);
02817 BUFFER_INIT (&state->localvars);
02818 BUFFER_INIT (&state->bytecode);
02819 }
02820
02821 static void
02822 init_jcf_method (state, method)
02823 struct jcf_partial *state;
02824 tree method;
02825 {
02826 state->current_method = method;
02827 state->blocks = state->last_block = NULL;
02828 state->linenumber_count = 0;
02829 state->first_lvar = state->last_lvar = NULL;
02830 state->lvar_count = 0;
02831 state->labeled_blocks = NULL;
02832 state->code_length = 0;
02833 BUFFER_RESET (&state->bytecode);
02834 BUFFER_RESET (&state->localvars);
02835 state->code_SP = 0;
02836 state->code_SP_max = 0;
02837 state->handlers = NULL;
02838 state->last_handler = NULL;
02839 state->num_handlers = 0;
02840 state->num_finalizers = 0;
02841 state->return_value_decl = NULL_TREE;
02842 }
02843
02844 static void
02845 release_jcf_state (state)
02846 struct jcf_partial *state;
02847 {
02848 CPOOL_FINISH (&state->cpool);
02849 obstack_free (state->chunk_obstack, state->first);
02850 }
02851
02852
02853
02854
02855
02856 static struct chunk *
02857 generate_classfile (clas, state)
02858 tree clas;
02859 struct jcf_partial *state;
02860 {
02861 struct chunk *cpool_chunk;
02862 const char *source_file, *s;
02863 char *ptr;
02864 int i;
02865 char *fields_count_ptr;
02866 int fields_count = 0;
02867 char *methods_count_ptr;
02868 int methods_count = 0;
02869 static tree SourceFile_node = NULL_TREE;
02870 tree part;
02871 int total_supers
02872 = clas == object_type_node ? 0
02873 : TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (clas));
02874
02875 ptr = append_chunk (NULL, 8, state);
02876 PUT4 (0xCafeBabe);
02877 PUT2 (3);
02878 PUT2 (45);
02879
02880 append_chunk (NULL, 0, state);
02881 cpool_chunk = state->chunk;
02882
02883
02884 if (clas == object_type_node)
02885 i = 10;
02886 else
02887 i = 8 + 2 * total_supers;
02888 ptr = append_chunk (NULL, i, state);
02889 i = get_access_flags (TYPE_NAME (clas));
02890 if (! (i & ACC_INTERFACE))
02891 i |= ACC_SUPER;
02892 PUT2 (i);
02893 i = find_class_constant (&state->cpool, clas); PUT2 (i);
02894 if (clas == object_type_node)
02895 {
02896 PUT2(0);
02897 PUT2(0);
02898 }
02899 else
02900 {
02901 tree basetypes = TYPE_BINFO_BASETYPES (clas);
02902 tree base = BINFO_TYPE (TREE_VEC_ELT (basetypes, 0));
02903 int j = find_class_constant (&state->cpool, base);
02904 PUT2 (j);
02905 PUT2 (total_supers - 1);
02906 for (i = 1; i < total_supers; i++)
02907 {
02908 base = BINFO_TYPE (TREE_VEC_ELT (basetypes, i));
02909 j = find_class_constant (&state->cpool, base);
02910 PUT2 (j);
02911 }
02912 }
02913 fields_count_ptr = ptr;
02914
02915 for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
02916 {
02917 int have_value, attr_count = 0;
02918 if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
02919 continue;
02920 ptr = append_chunk (NULL, 8, state);
02921 i = get_access_flags (part); PUT2 (i);
02922 i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
02923 i = find_utf8_constant (&state->cpool,
02924 build_java_signature (TREE_TYPE (part)));
02925 PUT2(i);
02926 have_value = DECL_INITIAL (part) != NULL_TREE
02927 && FIELD_STATIC (part) && CONSTANT_VALUE_P (DECL_INITIAL (part))
02928 && FIELD_FINAL (part)
02929 && (JPRIMITIVE_TYPE_P (TREE_TYPE (part))
02930 || TREE_TYPE (part) == string_ptr_type_node);
02931 if (have_value)
02932 attr_count++;
02933
02934 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
02935 attr_count++;
02936
02937 PUT2 (attr_count);
02938 if (have_value)
02939 {
02940 tree init = DECL_INITIAL (part);
02941 static tree ConstantValue_node = NULL_TREE;
02942 if (TREE_TYPE (part) != TREE_TYPE (init))
02943 fatal_error ("field initializer type mismatch");
02944 ptr = append_chunk (NULL, 8, state);
02945 if (ConstantValue_node == NULL_TREE)
02946 ConstantValue_node = get_identifier ("ConstantValue");
02947 i = find_utf8_constant (&state->cpool, ConstantValue_node);
02948 PUT2 (i);
02949 PUT4 (2);
02950 i = find_constant_index (init, state); PUT2 (i);
02951 }
02952
02953 if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
02954 ptr = append_synthetic_attribute (state);
02955 fields_count++;
02956 }
02957 ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
02958
02959 ptr = methods_count_ptr = append_chunk (NULL, 2, state);
02960 PUT2 (0);
02961
02962 for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
02963 {
02964 struct jcf_block *block;
02965 tree function_body = DECL_FUNCTION_BODY (part);
02966 tree body = function_body == NULL_TREE ? NULL_TREE
02967 : BLOCK_EXPR_BODY (function_body);
02968 tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
02969 : DECL_NAME (part);
02970 tree type = TREE_TYPE (part);
02971 tree save_function = current_function_decl;
02972 int synthetic_p = 0;
02973 current_function_decl = part;
02974 ptr = append_chunk (NULL, 8, state);
02975 i = get_access_flags (part); PUT2 (i);
02976 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
02977 i = find_utf8_constant (&state->cpool, build_java_signature (type));
02978 PUT2 (i);
02979 i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
02980
02981
02982 if (DECL_FINIT_P (part)
02983 || DECL_INSTINIT_P (part)
02984 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
02985 || TYPE_DOT_CLASS (clas) == part)
02986 {
02987 i++;
02988 synthetic_p = 1;
02989 }
02990
02991 PUT2 (i);
02992
02993 if (synthetic_p)
02994 ptr = append_synthetic_attribute (state);
02995
02996 if (body != NULL_TREE)
02997 {
02998 int code_attributes_count = 0;
02999 static tree Code_node = NULL_TREE;
03000 tree t;
03001 char *attr_len_ptr;
03002 struct jcf_handler *handler;
03003 if (Code_node == NULL_TREE)
03004 Code_node = get_identifier ("Code");
03005 ptr = append_chunk (NULL, 14, state);
03006 i = find_utf8_constant (&state->cpool, Code_node); PUT2 (i);
03007 attr_len_ptr = ptr;
03008 init_jcf_method (state, part);
03009 get_jcf_label_here (state);
03010 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
03011 localvar_alloc (t, state);
03012 generate_bytecode_insns (body, IGNORE_TARGET, state);
03013 if (CAN_COMPLETE_NORMALLY (body))
03014 {
03015 if (TREE_CODE (TREE_TYPE (type)) != VOID_TYPE)
03016 abort();
03017 RESERVE (1);
03018 OP1 (OPCODE_return);
03019 }
03020 for (t = DECL_ARGUMENTS (part); t != NULL_TREE; t = TREE_CHAIN (t))
03021 localvar_free (t, state);
03022 if (state->return_value_decl != NULL_TREE)
03023 localvar_free (state->return_value_decl, state);
03024 finish_jcf_block (state);
03025 perform_relocations (state);
03026
03027 ptr = attr_len_ptr;
03028 i = 8 + state->code_length + 4 + 8 * state->num_handlers;
03029 if (state->linenumber_count > 0)
03030 {
03031 code_attributes_count++;
03032 i += 8 + 4 * state->linenumber_count;
03033 }
03034 if (state->lvar_count > 0)
03035 {
03036 code_attributes_count++;
03037 i += 8 + 10 * state->lvar_count;
03038 }
03039 UNSAFE_PUT4 (i);
03040 UNSAFE_PUT2 (state->code_SP_max);
03041 UNSAFE_PUT2 (localvar_max);
03042 UNSAFE_PUT4 (state->code_length);
03043
03044
03045 ptr = append_chunk (NULL, 2 + 8 * state->num_handlers, state);
03046 PUT2 (state->num_handlers);
03047 handler = state->handlers;
03048 for (; handler != NULL; handler = handler->next)
03049 {
03050 int type_index;
03051 PUT2 (handler->start_label->pc);
03052 PUT2 (handler->end_label->pc);
03053 PUT2 (handler->handler_label->pc);
03054 if (handler->type == NULL_TREE)
03055 type_index = 0;
03056 else
03057 type_index = find_class_constant (&state->cpool,
03058 handler->type);
03059 PUT2 (type_index);
03060 }
03061
03062 ptr = append_chunk (NULL, 2, state);
03063 PUT2 (code_attributes_count);
03064
03065
03066 if (state->linenumber_count > 0)
03067 {
03068 static tree LineNumberTable_node = NULL_TREE;
03069 ptr = append_chunk (NULL,
03070 8 + 4 * state->linenumber_count, state);
03071 if (LineNumberTable_node == NULL_TREE)
03072 LineNumberTable_node = get_identifier ("LineNumberTable");
03073 i = find_utf8_constant (&state->cpool, LineNumberTable_node);
03074 PUT2 (i);
03075 i = 2+4*state->linenumber_count; PUT4(i);
03076 i = state->linenumber_count; PUT2 (i);
03077 for (block = state->blocks; block != NULL; block = block->next)
03078 {
03079 int line = block->linenumber;
03080 if (line > 0)
03081 {
03082 PUT2 (block->pc);
03083 PUT2 (line);
03084 }
03085 }
03086 }
03087
03088
03089 if (state->lvar_count > 0)
03090 {
03091 static tree LocalVariableTable_node = NULL_TREE;
03092 struct localvar_info *lvar = state->first_lvar;
03093 ptr = append_chunk (NULL, 8 + 10 * state->lvar_count, state);
03094 if (LocalVariableTable_node == NULL_TREE)
03095 LocalVariableTable_node = get_identifier("LocalVariableTable");
03096 i = find_utf8_constant (&state->cpool, LocalVariableTable_node);
03097 PUT2 (i);
03098 i = 2 + 10 * state->lvar_count; PUT4 (i);
03099 i = state->lvar_count; PUT2 (i);
03100 for ( ; lvar != NULL; lvar = lvar->next)
03101 {
03102 tree name = DECL_NAME (lvar->decl);
03103 tree sig = build_java_signature (TREE_TYPE (lvar->decl));
03104 i = lvar->start_label->pc; PUT2 (i);
03105 i = lvar->end_label->pc - i; PUT2 (i);
03106 i = find_utf8_constant (&state->cpool, name); PUT2 (i);
03107 i = find_utf8_constant (&state->cpool, sig); PUT2 (i);
03108 i = DECL_LOCAL_INDEX (lvar->decl); PUT2 (i);
03109 }
03110 }
03111 }
03112 if (DECL_FUNCTION_THROWS (part) != NULL_TREE)
03113 {
03114 tree t = DECL_FUNCTION_THROWS (part);
03115 int throws_count = list_length (t);
03116 static tree Exceptions_node = NULL_TREE;
03117 if (Exceptions_node == NULL_TREE)
03118 Exceptions_node = get_identifier ("Exceptions");
03119 ptr = append_chunk (NULL, 8 + 2 * throws_count, state);
03120 i = find_utf8_constant (&state->cpool, Exceptions_node);
03121 PUT2 (i);
03122 i = 2 + 2 * throws_count; PUT4(i);
03123 i = throws_count; PUT2 (i);
03124 for (; t != NULL_TREE; t = TREE_CHAIN (t))
03125 {
03126 i = find_class_constant (&state->cpool, TREE_VALUE (t));
03127 PUT2 (i);
03128 }
03129 }
03130 methods_count++;
03131 current_function_decl = save_function;
03132 }
03133 ptr = methods_count_ptr; UNSAFE_PUT2 (methods_count);
03134
03135 source_file = DECL_SOURCE_FILE (TYPE_NAME (clas));
03136 for (s = source_file; ; s++)
03137 {
03138 char ch = *s;
03139 if (ch == '\0')
03140 break;
03141 if (ch == '/' || ch == '\\')
03142 source_file = s+1;
03143 }
03144 ptr = append_chunk (NULL, 10, state);
03145
03146 i = 1;
03147 if (INNER_CLASS_TYPE_P (clas) || DECL_INNER_CLASS_LIST (TYPE_NAME (clas)))
03148 i++;
03149 if (clas == object_type_node)
03150 i++;
03151 PUT2 (i);
03152
03153
03154 if (SourceFile_node == NULL_TREE)
03155 {
03156 SourceFile_node = get_identifier ("SourceFile");
03157 ggc_add_tree_root (&SourceFile_node, 1);
03158 }
03159
03160 i = find_utf8_constant (&state->cpool, SourceFile_node);
03161 PUT2 (i);
03162 PUT4 (2);
03163 i = find_utf8_constant (&state->cpool, get_identifier (source_file));
03164 PUT2 (i);
03165 append_gcj_attribute (state, clas);
03166 append_innerclasses_attribute (state, clas);
03167
03168
03169 i = count_constant_pool_bytes (&state->cpool);
03170 ptr = obstack_alloc (state->chunk_obstack, i);
03171 cpool_chunk->data = ptr;
03172 cpool_chunk->size = i;
03173 write_constant_pool (&state->cpool, ptr, i);
03174 return state->first;
03175 }
03176
03177 static unsigned char *
03178 append_synthetic_attribute (state)
03179 struct jcf_partial *state;
03180 {
03181 static tree Synthetic_node = NULL_TREE;
03182 unsigned char *ptr = append_chunk (NULL, 6, state);
03183 int i;
03184
03185 if (Synthetic_node == NULL_TREE)
03186 {
03187 Synthetic_node = get_identifier ("Synthetic");
03188 ggc_add_tree_root (&Synthetic_node, 1);
03189 }
03190 i = find_utf8_constant (&state->cpool, Synthetic_node);
03191 PUT2 (i);
03192 PUT4 (0);
03193
03194 return ptr;
03195 }
03196
03197 static void
03198 append_gcj_attribute (state, class)
03199 struct jcf_partial *state;
03200 tree class;
03201 {
03202 unsigned char *ptr;
03203 int i;
03204
03205 if (class != object_type_node)
03206 return;
03207
03208 ptr = append_chunk (NULL, 6, state);
03209 i = find_utf8_constant (&state->cpool,
03210 get_identifier ("gnu.gcj.gcj-compiled"));
03211 PUT2 (i);
03212 PUT4 (0);
03213 }
03214
03215 static void
03216 append_innerclasses_attribute (state, class)
03217 struct jcf_partial *state;
03218 tree class;
03219 {
03220 static tree InnerClasses_node = NULL_TREE;
03221 tree orig_decl = TYPE_NAME (class);
03222 tree current, decl;
03223 int length = 0, i;
03224 unsigned char *ptr, *length_marker, *number_marker;
03225
03226 if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
03227 return;
03228
03229 ptr = append_chunk (NULL, 8, state);
03230
03231 if (InnerClasses_node == NULL_TREE)
03232 {
03233 InnerClasses_node = get_identifier ("InnerClasses");
03234 ggc_add_tree_root (&InnerClasses_node, 1);
03235 }
03236 i = find_utf8_constant (&state->cpool, InnerClasses_node);
03237 PUT2 (i);
03238 length_marker = ptr; PUT4 (0);
03239 number_marker = ptr; PUT2 (0);
03240
03241
03242
03243 while (class && INNER_CLASS_TYPE_P (class))
03244 {
03245 const char *n;
03246
03247 decl = TYPE_NAME (class);
03248 n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
03249 IDENTIFIER_LENGTH (DECL_NAME (decl));
03250
03251 while (n[-1] != '$')
03252 n--;
03253 append_innerclasses_attribute_entry (state, decl, get_identifier (n));
03254 length++;
03255
03256 class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
03257 }
03258
03259 decl = orig_decl;
03260 for (current = DECL_INNER_CLASS_LIST (decl);
03261 current; current = TREE_CHAIN (current))
03262 {
03263 append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
03264 TREE_VALUE (current));
03265 length++;
03266 }
03267
03268 ptr = length_marker; PUT4 (8*length+2);
03269 ptr = number_marker; PUT2 (length);
03270 }
03271
03272 static void
03273 append_innerclasses_attribute_entry (state, decl, name)
03274 struct jcf_partial *state;
03275 tree decl, name;
03276 {
03277 int icii, icaf;
03278 int ocii = 0, ini = 0;
03279 unsigned char *ptr = append_chunk (NULL, 8, state);
03280
03281 icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
03282
03283
03284
03285
03286
03287 if (!ANONYMOUS_CLASS_P (TREE_TYPE (decl)))
03288 {
03289 ocii = find_class_constant (&state->cpool,
03290 TREE_TYPE (DECL_CONTEXT (decl)));
03291 ini = find_utf8_constant (&state->cpool, name);
03292 }
03293 icaf = get_access_flags (decl);
03294
03295 PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
03296 }
03297
03298 static char *
03299 make_class_file_name (clas)
03300 tree clas;
03301 {
03302 const char *dname, *cname, *slash;
03303 char *r;
03304 struct stat sb;
03305
03306 cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
03307 "", '.', DIR_SEPARATOR,
03308 ".class"));
03309 if (jcf_write_base_directory == NULL)
03310 {
03311
03312
03313 char *t;
03314 dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
03315 slash = strrchr (dname, DIR_SEPARATOR);
03316 if (! slash)
03317 {
03318 dname = ".";
03319 slash = dname + 1;
03320 }
03321 t = strrchr (cname, DIR_SEPARATOR);
03322 if (t)
03323 cname = t + 1;
03324 }
03325 else
03326 {
03327 dname = jcf_write_base_directory;
03328 slash = dname + strlen (dname);
03329 }
03330
03331 r = xmalloc (slash - dname + strlen (cname) + 2);
03332 strncpy (r, dname, slash - dname);
03333 r[slash - dname] = DIR_SEPARATOR;
03334 strcpy (&r[slash - dname + 1], cname);
03335
03336
03337
03338
03339
03340
03341
03342 dname = r + (slash - dname) + 1;
03343 while (1)
03344 {
03345 char *s = strchr (dname, DIR_SEPARATOR);
03346 if (s == NULL)
03347 break;
03348 *s = '\0';
03349 if (stat (r, &sb) == -1
03350
03351 && mkdir (r, 0755) == -1)
03352 fatal_io_error ("can't create directory %s", r);
03353
03354 *s = DIR_SEPARATOR;
03355
03356 for (dname = s + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
03357 ;
03358 }
03359
03360 return r;
03361 }
03362
03363
03364
03365
03366 void
03367 write_classfile (clas)
03368 tree clas;
03369 {
03370 struct obstack *work = &temporary_obstack;
03371 struct jcf_partial state[1];
03372 char *class_file_name = make_class_file_name (clas);
03373 struct chunk *chunks;
03374
03375 if (class_file_name != NULL)
03376 {
03377 FILE *stream;
03378 char *temporary_file_name;
03379
03380
03381
03382
03383 temporary_file_name = concat (class_file_name, ".tmp", NULL);
03384 stream = fopen (temporary_file_name, "wb");
03385 if (stream == NULL)
03386 fatal_io_error ("can't open %s for writing", temporary_file_name);
03387
03388 jcf_dependency_add_target (class_file_name);
03389 init_jcf_state (state, work);
03390 chunks = generate_classfile (clas, state);
03391 write_chunks (stream, chunks);
03392 if (fclose (stream))
03393 fatal_io_error ("error closing %s", temporary_file_name);
03394 if (rename (temporary_file_name, class_file_name) == -1)
03395 {
03396 remove (temporary_file_name);
03397 fatal_io_error ("can't create %s", class_file_name);
03398 }
03399 free (temporary_file_name);
03400 free (class_file_name);
03401 }
03402 release_jcf_state (state);
03403 }
03404
03405
03406
03407
03408