home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / jvm.e < prev    next >
Text File  |  1999-06-05  |  26KB  |  921 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class JVM
  17.    --
  18.    -- Handling of Java Virtual Machine byte code generation.
  19.    --
  20.  
  21. inherit CODE_PRINTER;
  22.  
  23. creation make
  24.  
  25. feature {NONE}
  26.  
  27.    make is
  28.       do
  29.       end;
  30.  
  31. feature
  32.  
  33.    current_frame: RUN_FEATURE;
  34.          -- Current method or current field.
  35.  
  36.    argument_offset_of(an: ARGUMENT_NAME): INTEGER is
  37.       require
  38.          an /= Void
  39.       do
  40.          Result := current_frame.jvm_argument_offset(an);
  41.       ensure
  42.          Result >= 0
  43.       end;
  44.  
  45.    local_offset_of(ln: LOCAL_NAME): INTEGER is
  46.       require
  47.          ln /= Void
  48.       do
  49.          Result := current_frame.jvm_local_variable_offset(ln);
  50.       ensure
  51.          Result >= 0
  52.       end;
  53.  
  54.    result_offset: INTEGER is
  55.       do
  56.          Result := current_frame.jvm_result_offset;
  57.       end;
  58.  
  59.    std_is_equal(rc: RUN_CLASS; wa: ARRAY[RUN_FEATURE_2]) is
  60.          -- Produce byte code to compare two operands at top of stack.
  61.          -- Result `1'  (true) or `0' (false) is left at top of stack.
  62.       require
  63.          not rc.current_type.is_basic_eiffel_expanded
  64.       local
  65.          ca: like code_attribute;
  66.          rf2: RUN_FEATURE_2;
  67.          point1, point2, space, i: INTEGER;
  68.       do
  69.          ca := code_attribute;
  70.          if wa = Void then
  71.             if rc.current_type.is_expanded then
  72.                ca.opcode_pop2;
  73.                ca.opcode_iconst_1;
  74.             else
  75.                ca.opcode_swap;
  76.                ca.opcode_pop;
  77.                rc.opcode_instanceof;
  78.             end;
  79.          else
  80.             ca.branches.clear; -- pop2 then false
  81.             if rc.current_type.is_reference then
  82.                ca.opcode_dup;
  83.                rc.opcode_instanceof;
  84.                ca.branches.add_last(ca.opcode_ifeq);
  85.             end;
  86.             from
  87.                i := wa.upper;
  88.             until
  89.                i = 0
  90.             loop
  91.                rf2 := wa.item(i);
  92.                space := rf2.result_type.jvm_stack_space - 1;
  93.                if i > 1 then
  94.                   ca.opcode_dup2;
  95.                end;
  96.                space := rc.opcode_getfield(rf2);
  97.                if space = 0 then
  98.                   ca.opcode_swap;
  99.                else
  100.                   ca.opcode_dup2_x1;
  101.                   ca.opcode_pop2;
  102.                end;
  103.                space := rc.opcode_getfield(rf2);
  104.                if i > 1 then
  105.                   ca.branches.add_last(rf2.result_type.jvm_if_x_ne);
  106.                else
  107.                   point1 := rf2.result_type.jvm_if_x_ne;
  108.                end;
  109.                i := i - 1;
  110.             end;
  111.             ca.opcode_iconst_1;
  112.             point2 := ca.opcode_goto;
  113.             ca.resolve_branches;
  114.             ca.opcode_pop2;
  115.             ca.resolve_u2_branch(point1);
  116.             ca.opcode_iconst_0;
  117.             ca.resolve_u2_branch(point2);
  118.          end;
  119.       end;
  120.  
  121.    fields_by_fields_copy(wa: ARRAY[RUN_FEATURE_2]) is
  122.          -- Stack : ..., destination, model => ..., destination
  123.          -- Assume the checkcast is already done.
  124.       local
  125.          ca: like code_attribute;
  126.          rf2: RUN_FEATURE_2;
  127.          idx, space, i: INTEGER;
  128.       do
  129.          ca := code_attribute;
  130.          if wa /= Void then
  131.             from
  132.                i := wa.upper;
  133.             until
  134.                i = 0
  135.             loop
  136.                ca.opcode_dup2;
  137.                rf2 := wa.item(i);
  138.                idx := constant_pool.idx_fieldref(rf2);
  139.                space := rf2.result_type.jvm_stack_space;
  140.                ca.opcode_getfield(idx,space - 1);
  141.                ca.opcode_putfield(idx,-(space + 1));
  142.                i := i - 1;
  143.             end;
  144.          end;
  145.          ca.opcode_pop;
  146.       end;
  147.  
  148. feature {RUN_FEATURE}
  149.  
  150.    add_field(rf: RUN_FEATURE) is
  151.       require
  152.          rf /= Void
  153.       do
  154.          check
  155.             not fields.fast_has(rf)
  156.          end;
  157.          fields.add_last(rf);
  158.       ensure
  159.          fields.fast_has(rf)
  160.       end;
  161.  
  162. feature {SMALL_EIFFEL}
  163.  
  164.    mkdir is
  165.          -- Create a new directory to store class files.
  166.       require
  167.          small_eiffel.is_ready
  168.       do
  169.          if output_name = Void then
  170.             output_name := run_control.root_class.twin;
  171.             output_name.to_lower;
  172.          elseif output_name.has_suffix(class_suffix) then
  173.             output_name.remove_suffix(class_suffix);
  174.          end;
  175.          echo.put_string("Trying to prepare directory %"");
  176.          echo.put_string(output_name);
  177.          echo.put_string("%" to store Java byte code.%N");
  178.          file_tools.mkdir(output_name);
  179.       ensure
  180.          output_name /= Void
  181.       end;
  182.  
  183.    write_jvm_root_class is
  184.       local
  185.          idx: INTEGER;
  186.          cp: like constant_pool;
  187.          ca: like code_attribute;
  188.       do
  189.          cp := constant_pool;
  190.          ca := code_attribute;
  191.          system_tools.class_file_path(out_file_path,output_name,fz_jvm_root);
  192.          bfw_connect(out_file,out_file_path);
  193.          start_basic;
  194.          this_class_idx := cp.idx_class2(jvm_root_class);
  195.          super_class_idx := cp.idx_java_lang_object;
  196.          -- Fields :
  197.          args_field;
  198.          manifest_string_pool.jvm_define_fields;
  199.          once_routine_pool.jvm_define_fields;
  200.          if run_control.no_check then
  201.             field_info.add(9,cp.idx_utf8(fz_58),cp.idx_utf8(fz_41));
  202.          end;
  203.          -- Methods :
  204.          method_info.add_init(fz_java_lang_object);
  205.          -- The _initialize_eiffel_runtime static method :
  206.          current_frame := Void;
  207.          method_info.start(9,fz_28,fz_23);
  208.          -- Set `args' field to store command line arguments.
  209.          ca.opcode_aload_0;
  210.          ca.opcode_putstatic(args_field_idx,-1);
  211.          manifest_string_pool.jvm_initialize_fields;
  212.          once_routine_pool.jvm_initialize_fields;
  213.          if run_control.no_check then
  214.             idx := cp.idx_fieldref3(jvm_root_class,fz_58,fz_41);
  215.             ca.opcode_iconst_0;
  216.             ca.opcode_putstatic(idx,-1);
  217.          end;
  218.          ca.opcode_return;
  219.          method_info.finish;
  220.          --    For switches :
  221.          switch_collection.jvm_define;
  222.          finish_class;
  223.       end;
  224.  
  225.    write_main_class(rf3: RUN_FEATURE_3) is
  226.          -- Write Java Byte Code for main class to call `rf3'.
  227.       require
  228.          rf3 /= Void;
  229.          small_eiffel.is_ready
  230.       local
  231.          idx: INTEGER;
  232.          cp: like constant_pool;
  233.          ca: like code_attribute;
  234.       do
  235.          cp := constant_pool;
  236.          ca := code_attribute;
  237.          out_file_path.copy(output_name);
  238.          out_file_path.append(class_suffix);
  239.          bfw_connect(out_file,out_file_path);
  240.          start_basic;
  241.          this_class_idx := cp.idx_class2(output_name);
  242.          super_class_idx := cp.idx_java_lang_object;
  243.          -- Methods :
  244.          --    The main method :
  245.          current_frame := Void;
  246.          method_info.add_init(fz_java_lang_object);
  247.          method_info.start(9,fz_main,fz_23);
  248.          ca.opcode_aload_0;
  249.          idx := cp.idx_methodref3(jvm_root_class,fz_28,fz_23);
  250.          ca.opcode_invokestatic(idx,0);
  251.          rf3.run_class.jvm_basic_new;
  252.          idx := cp.idx_methodref(rf3);
  253.          ca.opcode_invokevirtual(idx,-1);
  254.          ca.opcode_return;
  255.          method_info.finish;
  256.          finish_class;
  257.       end;
  258.  
  259. feature {CODE_ATTRIBUTE}
  260.  
  261.    max_locals: INTEGER is
  262.       do
  263.          if current_frame /= Void then
  264.             Result := current_frame.jvm_max_locals;
  265.          else
  266.             Result := 4;
  267.          end;
  268.       end;
  269.  
  270. feature {RUN_CLASS,SWITCH_COLLECTION}
  271.  
  272.    set_current_frame(cf: like current_frame) is
  273.       do
  274.          current_frame := cf;
  275.       end;
  276.  
  277. feature {CP_INFO}
  278.  
  279.    b_put_u1(byte: CHARACTER) is
  280.       require
  281.          byte.code <= 255
  282.       do
  283.          out_file.put_byte(byte);
  284.       end;
  285.  
  286. feature {CONSTANT_POOL,FIELD_INFO,METHOD_INFO}
  287.  
  288.    b_put_u2(u2: INTEGER) is
  289.       do
  290.          b_put_u1((u2 // 256).to_character);
  291.          b_put_u1((u2 \\ 256).to_character);
  292.       end;
  293.  
  294. feature {CP_INFO,FIELD_INFO,METHOD_INFO}
  295.  
  296.    b_put_byte_string(str: STRING) is
  297.       require
  298.          str /= Void
  299.       local
  300.          i: INTEGER;
  301.       do
  302.          from
  303.             i := 1;
  304.          until
  305.             i > str.count
  306.          loop
  307.             b_put_u1(str.item(i));
  308.             i := i + 1;
  309.          end;
  310.       end;
  311.  
  312. feature {NATIVE_SMALL_EIFFEL}
  313.  
  314.    push_se_argc is
  315.       local
  316.          ca: like code_attribute;
  317.       do
  318.          ca := code_attribute;
  319.          ca.opcode_getstatic(args_field_idx,1);
  320.          ca.opcode_arraylength;
  321.          ca.opcode_iconst_1;
  322.          ca.opcode_iadd;
  323.       end;
  324.  
  325.    push_se_argv is
  326.       local
  327.          point1, point2, i: INTEGER;
  328.          ca: like code_attribute;
  329.       do
  330.          ca := code_attribute;
  331.          ca.opcode_getstatic(args_field_idx,1);
  332.          i := push_ith_argument(1)
  333.          ca.opcode_dup;
  334.          point1 := ca.opcode_ifeq;
  335.          ca.opcode_iconst_1;
  336.          ca.opcode_isub;
  337.          ca.opcode_aaload;
  338.          point2 := ca.opcode_goto;
  339.          ca.resolve_u2_branch(point1);
  340.          ca.opcode_pop2;
  341.          i := constant_pool.idx_string(output_name);
  342.          ca.opcode_ldc(i);
  343.          ca.resolve_u2_branch(point2);
  344.          ca.opcode_java_string2eiffel_string;
  345.       end;
  346.  
  347. feature {CALL_PROC_CALL}
  348.  
  349.    call_proc_call_mapping(cpc: CALL_PROC_CALL) is
  350.       local
  351.          target: EXPRESSION;
  352.          target_type: TYPE;
  353.          rc: RUN_CLASS;
  354.          running: ARRAY[RUN_CLASS];
  355.          switch: SWITCH;
  356.          rf: RUN_FEATURE;
  357.          result_type: TYPE;
  358.       do
  359.          target := cpc.target;
  360.          target_type := target.result_type.run_type;
  361.          rf := cpc.run_feature;
  362.          if target.is_current then
  363.             push_direct(cpc);
  364.             rf.mapping_jvm;
  365.             pop
  366.          elseif target.is_manifest_string then
  367.             push_direct(cpc);
  368.             rf.mapping_jvm;
  369.             pop
  370.          elseif target_type.is_expanded then
  371.             push_direct(cpc);
  372.             rf.mapping_jvm;
  373.             pop
  374.          else
  375.             running := target_type.run_class.running;
  376.             check
  377.                running /= Void
  378.             end;
  379.             if running.count = 1 then
  380.                push_check(cpc);
  381.                rf := running.first.dynamic(rf);
  382.                rf.mapping_jvm;
  383.                pop
  384.             else
  385.                switch_count := switch_count + 1;
  386.                switch.jvm_mapping(cpc);
  387.             end;
  388.          end;
  389.          result_type := rf.result_type;
  390.          -- Optional checkcast for result :
  391.          if result_type /= Void then
  392.             if not result_type.is_none then
  393.                rc := result_type.run_class;
  394.                if rc /= Void then
  395.                   running := rc.running;
  396.                   if running /= Void and then running.count = 1 then
  397.                      running.first.opcode_checkcast;
  398.                   end;
  399.                end;
  400.             end;
  401.          end;
  402.       end;
  403.  
  404. feature {RUN_CLASS}
  405.  
  406.    prepare_fields is
  407.       local
  408.          i: INTEGER;
  409.          rf: RUN_FEATURE;
  410.       do
  411.          from
  412.             i := fields.upper;
  413.          until
  414.             i < 0
  415.          loop
  416.             rf := fields.item(i);
  417.             rf.jvm_define;
  418.             i := i - 1;
  419.          end;
  420.       end;
  421.  
  422.    prepare_methods is
  423.       local
  424.          i: INTEGER;
  425.       do
  426.          from
  427.             i := methods.upper;
  428.          until
  429.             i < 0
  430.          loop
  431.             set_current_frame(methods.item(i));
  432.             current_frame.jvm_define;
  433.             i := i - 1;
  434.          end;
  435.       end;
  436.  
  437.    start_new_class(rc: RUN_CLASS) is
  438.       require
  439.          output_name /= Void
  440.       local
  441.          name_idx, type_idx: INTEGER;
  442.          cp: like constant_pool;
  443.       do
  444.          cp := constant_pool;
  445.          start_basic;
  446.          tmp_string.copy(rc.unqualified_name);
  447.          system_tools.class_file_path(out_file_path,output_name,tmp_string);
  448.          bfw_connect(out_file,out_file_path);
  449.          this_class_idx := rc.jvm_constant_pool_index;
  450.          super_class_idx := cp.idx_jvm_root_class;
  451.          method_info.add_init(jvm_root_class);
  452.          -- <clinit> :
  453.          method_info.start(9,fz_76,fz_29);
  454.          if run_control.generating_type_used then
  455.             name_idx := cp.idx_utf8(as_generating_type);
  456.             type_idx := cp.idx_eiffel_string_descriptor;
  457.             field_info.add(9,name_idx,type_idx);
  458.             name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
  459.             code_attribute.opcode_aconst_null;
  460.             code_attribute.opcode_putstatic(name_idx,-1);
  461.          end;
  462.          if run_control.generating_type_used then
  463.             name_idx := cp.idx_utf8(as_generator);
  464.             field_info.add(9,name_idx,type_idx);
  465.             name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
  466.             code_attribute.opcode_aconst_null;
  467.             code_attribute.opcode_putstatic(name_idx,-1);
  468.          end;
  469.          code_attribute.opcode_return;
  470.          method_info.finish;
  471.          rc.jvm_define_class_invariant;
  472.       end;
  473.  
  474.    finish_class is
  475.          -- Really print the class file.
  476.       do
  477.          put_magic;
  478.          put_minor_version;
  479.          put_major_version;
  480.          constant_pool.write_bytes;
  481.          b_put_u2(access_flags);
  482.          b_put_u2(this_class_idx);
  483.          b_put_u2(super_class_idx);
  484.          -- interfaces_count :
  485.          b_put_u2(0);
  486.          field_info.write_bytes;
  487.          method_info.write_bytes;
  488.          -- attributes_count :
  489.          b_put_u2(0);
  490.          out_file.disconnect;
  491.       end;
  492.  
  493.    push_expanded_initialize(rf: RUN_FEATURE) is
  494.       do
  495.          stack_push(C_expanded_initialize);
  496.          stack_rf.put(rf,top);
  497.       end;
  498.  
  499.    define_class_invariant_method(ci: CLASS_INVARIANT) is
  500.       require
  501.          run_control.invariant_check;
  502.          ci /= Void
  503.       local
  504.          ca: like code_attribute;
  505.          cp: like constant_pool;
  506.       do
  507.          ca := code_attribute;
  508.          cp := constant_pool;
  509.          method_info.start(1,fz_invariant,fz_29);
  510.          stack_push(C_switch);
  511.          ci.compile_to_jvm(true);
  512.          pop;
  513.          ca.opcode_return;
  514.          method_info.finish;
  515.       end;
  516.  
  517. feature {NATIVE}
  518.  
  519.    inside_twin(cpy: RUN_FEATURE) is
  520.       do
  521.          stack_push(C_inside_twin);
  522.          stack_rf.put(cpy,top);
  523.          cpy.mapping_jvm;
  524.          pop;
  525.       end;
  526.  
  527. feature {CREATION_CALL}
  528.  
  529.    inside_new(rf: RUN_FEATURE; cpc: CALL_PROC_CALL) is
  530.       require
  531.          rf /= Void;
  532.          cpc /= Void
  533.       do
  534.          stack_push(C_inside_new);
  535.          stack_rf.put(rf,top);
  536.          stack_cpc.put(cpc,top);
  537.          rf.mapping_jvm;
  538.          pop;
  539.       end;
  540.  
  541. feature {RUN_FEATURE,NATIVE}
  542.  
  543.    add_method(rf: RUN_FEATURE) is
  544.       require
  545.          rf /= Void
  546.       do
  547.          check
  548.             not methods.fast_has(rf)
  549.          end;
  550.          methods.add_last(rf);
  551.       ensure
  552.          methods.fast_has(rf)
  553.       end;
  554.  
  555.    target_position: POSITION is
  556.       local
  557.          code: INTEGER;
  558.       do
  559.          code := stack_code.item(top);
  560.          inspect
  561.             code
  562.          when C_direct_call, C_check_id then
  563.             Result := stack_cpc.item(top).start_position;
  564.          when C_inside_twin then
  565.          when C_switch then
  566.          when C_expanded_initialize then
  567.          when C_inside_new then
  568.             Result := stack_cpc.item(top).start_position;
  569.          else
  570.          end;
  571.       end;
  572.  
  573.    push_target is
  574.          -- Produce java byte code in order to push target on the
  575.          -- jvm stack.
  576.       local
  577.          code: INTEGER;
  578.       do
  579.          code := stack_code.item(top);
  580.          inspect
  581.             code
  582.          when C_direct_call then
  583.             stack_cpc.item(top).target.compile_to_jvm;
  584.          when C_check_id then
  585.             opcode_check_id_for(stack_cpc.item(top).target);
  586.          when C_switch then
  587.             code_attribute.opcode_aload_0;
  588.          when C_expanded_initialize then
  589.             code_attribute.opcode_dup;
  590.          when C_inside_new then
  591.             code_attribute.opcode_dup;
  592.          when C_inside_twin then
  593.             code_attribute.opcode_aload_1;
  594.          end;
  595.       end;
  596.  
  597.    push_target_as_target is
  598.          -- Same as `push_target' but with class invariant check
  599.          -- and the checkcast opcode.
  600.       local
  601.          target: EXPRESSION;
  602.          rc: RUN_CLASS;
  603.          code: INTEGER;
  604.       do
  605.          code := stack_code.item(top);
  606.          inspect
  607.             code
  608.          when C_direct_call then
  609.             target := stack_cpc.item(top).target;
  610.             target.compile_target_to_jvm;
  611.          when C_check_id then
  612.             target := stack_cpc.item(top).target;
  613.             opcode_check_id_for(target);
  614.          when C_switch then
  615.             code_attribute.opcode_aload_0;
  616.             rc := stack_rf.item(top).current_type.run_class;
  617.             rc.opcode_checkcast;
  618.          when C_expanded_initialize then
  619.             code_attribute.opcode_dup;
  620.          when C_inside_new then
  621.             code_attribute.opcode_dup;
  622.          when C_inside_twin then
  623.             code_attribute.opcode_aload_1;
  624.          when C_precursor then
  625.             stack_rf.item(top).current_type.jvm_push_local(0);
  626.          end;
  627.       end;
  628.  
  629.    drop_target is
  630.       local
  631.          code: INTEGER;
  632.          cpc: CALL_PROC_CALL;
  633.          e: EXPRESSION;
  634.       do
  635.          code := stack_code.item(top);
  636.          inspect
  637.             code
  638.          when C_direct_call, C_check_id then
  639.             cpc := stack_cpc.item(top);
  640.             e ?= cpc;
  641.             if e = Void or else not e.can_be_dropped then
  642.                cpc.target.compile_to_jvm;
  643.                if cpc.run_feature.current_type.jvm_stack_space = 1 then
  644.                   code_attribute.opcode_pop;
  645.                else
  646.                   code_attribute.opcode_pop2;
  647.                end;
  648.             end;
  649.          when C_switch then
  650.          when C_expanded_initialize then
  651.          when C_inside_new then
  652.          when C_inside_twin then
  653.          end;
  654.       end;
  655.  
  656.    drop_ith_argument(i: INTEGER) is
  657.       local
  658.          space: INTEGER;
  659.       do
  660.          from
  661.             space := push_ith_argument(i);
  662.          until
  663.             space = 0
  664.          loop
  665.             code_attribute.opcode_pop;
  666.             space := space - 1;
  667.          end;
  668.       end;
  669.  
  670.    push_arguments: INTEGER is
  671.       local
  672.          code: INTEGER;
  673.          cpc: CALL_PROC_CALL;
  674.          eal: EFFECTIVE_ARG_LIST;
  675.          rf, dyn_rf: RUN_FEATURE;
  676.          fal: FORMAL_ARG_LIST;
  677.       do
  678.          code := stack_code.item(top);
  679.          inspect
  680.             code
  681.          when C_direct_call, C_check_id then
  682.             cpc := stack_cpc.item(top);
  683.             eal := cpc.arguments;
  684.             if eal /= Void then
  685.                rf := cpc.run_feature;
  686.                fal := rf.arguments;
  687.                Result := eal.compile_to_jvm(fal);
  688.             end;
  689.          when C_switch then
  690.             rf := stack_static_rf.item(top);
  691.             dyn_rf := stack_rf.item(top);
  692.             fal := rf.arguments;
  693.             if fal /= Void then
  694.                Result := fal.jvm_switch_push(dyn_rf.arguments);
  695.             end;
  696.          when C_expanded_initialize then
  697.             check
  698.                stack_rf.item(top).arguments = Void
  699.             end;
  700.          when C_inside_new then
  701.             cpc := stack_cpc.item(top);
  702.             eal := cpc.arguments;
  703.             if eal /= Void then
  704.                rf := stack_rf.item(top);
  705.                fal := rf.arguments;
  706.                Result := eal.compile_to_jvm(fal);
  707.             end;
  708.          when C_inside_twin then
  709.             Result := push_ith_argument(1);
  710.          when C_precursor then
  711.             eal := stack_args.item(top);
  712.             if eal /= Void then
  713.                rf := stack_rf.item(top);
  714.                fal := rf.arguments;
  715.                Result := eal.compile_to_jvm(fal);
  716.             end;
  717.          end;
  718.       end;
  719.  
  720.    push_ith_argument(i: INTEGER): INTEGER is
  721.       local
  722.          code: INTEGER;
  723.          cpc: CALL_PROC_CALL;
  724.          eal: EFFECTIVE_ARG_LIST;
  725.          rf, dyn_rf: RUN_FEATURE;
  726.          fal: FORMAL_ARG_LIST;
  727.       do
  728.          code := stack_code.item(top);
  729.          inspect
  730.             code
  731.          when C_direct_call, C_check_id then
  732.             cpc := stack_cpc.item(top);
  733.             eal := cpc.arguments;
  734.             rf := cpc.run_feature;
  735.             fal := rf.arguments;
  736.             Result := eal.compile_to_jvm_ith(fal,i);
  737.          when C_switch then
  738.             rf := stack_static_rf.item(top);
  739.             dyn_rf := stack_rf.item(top);
  740.             fal := rf.arguments;
  741.             Result := fal.jvm_switch_push_ith(dyn_rf.arguments,i);
  742.          when C_expanded_initialize then
  743.             check
  744.                false
  745.             end;
  746.          when C_inside_new then
  747.             cpc := stack_cpc.item(top);
  748.             eal := cpc.arguments;
  749.             rf := stack_rf.item(top);
  750.             fal := rf.arguments;
  751.             Result := eal.compile_to_jvm_ith(fal,i);
  752.          when C_inside_twin then
  753.             code_attribute.opcode_aload_0;
  754.             Result := 1;
  755.          end;
  756.       end;
  757.  
  758. feature {SWITCH}
  759.  
  760.    push_switch(rf, static_rf: RUN_FEATURE) is
  761.       require
  762.          rf /= Void;
  763.          static_rf /= Void;
  764.          rf.run_class.dynamic(static_rf) = rf
  765.       do
  766.          stack_push(C_switch);
  767.          stack_rf.put(rf,top);
  768.          stack_static_rf.put(static_rf,top);
  769.       end;
  770.  
  771. feature {NONE}
  772.  
  773.    fields: FIXED_ARRAY[RUN_FEATURE] is
  774.       once
  775.          !!Result.with_capacity(4);
  776.       end;
  777.  
  778.    methods: FIXED_ARRAY[RUN_FEATURE] is
  779.       once
  780.          !!Result.with_capacity(64);
  781.       end;
  782.  
  783.    access_flags: INTEGER is 33;
  784.          -- To allow any external access.
  785.  
  786.    this_class_idx: INTEGER;
  787.  
  788.    super_class_idx: INTEGER;
  789.  
  790.    start_basic is
  791.       do
  792.          fields.clear;
  793.          methods.clear;
  794.          constant_pool.clear;
  795.          field_info.clear;
  796.          method_info.clear;
  797.       end;
  798.  
  799.    put_magic is
  800.          -- CAFEBABE ;-)
  801.       do
  802.          b_put_byte_string("%/202/%/254/%/186/%/190/");
  803.       end;
  804.  
  805.    put_minor_version is
  806.       do
  807.          b_put_u2(3);
  808.       end;
  809.  
  810.    put_major_version is
  811.       do
  812.          b_put_byte_string("%/0/%/45/");
  813.       end;
  814.  
  815.    args_field is
  816.          -- Define `args' field to store command line arguments.
  817.       local
  818.          args_idx, jaos_idx: INTEGER;
  819.          cp: like constant_pool;
  820.       do
  821.          cp := constant_pool;
  822.          args_idx := cp.idx_utf8(fz_74);
  823.          jaos_idx := cp.idx_utf8(fz_75);
  824.          field_info.add(9,args_idx,jaos_idx);
  825.       end;
  826.  
  827.    args_field_idx: INTEGER is
  828.       local
  829.          cp: like constant_pool;
  830.       do
  831.          cp := constant_pool;
  832.          Result := cp.idx_fieldref3(jvm_root_class,fz_74,fz_75);
  833.       end;
  834.  
  835.    out_file: BINARY_FILE_WRITE is
  836.          -- Current output class file.
  837.       once
  838.          !!Result.make;
  839.       end;
  840.  
  841.    out_file_path: STRING is
  842.       once
  843.          !!Result.make(32);
  844.       end;
  845.  
  846.    tmp_string: STRING is
  847.       once
  848.          !!Result.make(16);
  849.       end;
  850.  
  851.    push_direct(cpc: CALL_PROC_CALL) is
  852.       require
  853.          cpc /= Void
  854.       do
  855.          stack_push(C_direct_call);
  856.          stack_cpc.put(cpc,top);
  857.          direct_call_count := direct_call_count + 1;
  858.       end;
  859.  
  860.    push_check(cpc: CALL_PROC_CALL) is
  861.       require
  862.          cpc /= Void
  863.       do
  864.          stack_push(C_check_id);
  865.          stack_cpc.put(cpc,top);
  866.       end;
  867.  
  868.    opcode_check_id_for(e: EXPRESSION) is
  869.          -- Produce byte-code for `e' with non-void check and id
  870.          -- check.
  871.          -- Finally, also add a `checkcast' opcode.
  872.       require
  873.          e.result_type.run_class.running.count = 1
  874.       local
  875.          point1, point2: INTEGER;
  876.          rc: RUN_CLASS;
  877.          ct: TYPE;
  878.          ca: like code_attribute;
  879.       do
  880.          e.compile_to_jvm;
  881.          rc := e.result_type.run_class.running.first;
  882.          ct := rc.current_type;
  883.          if run_control.no_check then
  884.             ca := code_attribute;
  885.             ca.opcode_dup;
  886.             point1 := ca.opcode_ifnull;
  887.             ca.opcode_dup;
  888.             rc.opcode_instanceof;
  889.             point2 := ca.opcode_ifne;
  890.             ca.resolve_u2_branch(point1);
  891.             ca.opcode_dup;
  892.             ca.runtime_error_bad_target(e.start_position,ct,Void);
  893.             ca.resolve_u2_branch(point2);
  894.             rc.jvm_check_class_invariant;
  895.          end;
  896.          rc.opcode_checkcast;
  897.       end;
  898.  
  899.    bfw_connect(bfw: BINARY_FILE_WRITE; path: STRING) is
  900.       require
  901.          not bfw.is_connected;
  902.          path /= Void
  903.       do
  904.          bfw.connect_to(path);
  905.          if bfw.is_connected then
  906.             echo.put_string("Writing %"");
  907.             echo.put_string(path);
  908.             echo.put_string("%" file.%N");
  909.          else
  910.             echo.w_put_string("Cannot write file %"");
  911.             echo.w_put_string(path);
  912.             echo.w_put_string(fz_b0);
  913.             die_with_code(exit_failure_code);
  914.          end;
  915.       ensure
  916.          bfw.is_connected
  917.       end;
  918.  
  919. end -- JVM
  920.  
  921.