home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / switch.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  9.6 KB  |  422 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://www.loria.fr/SmallEiffel
  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. expanded class SWITCH
  17.    --
  18.    -- Set of tools (no attributes) to handle one switching site.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. feature {NONE}
  24.  
  25.    running: ARRAY[RUN_CLASS] is
  26.      -- The global one.
  27.       once
  28.      !!Result.with_capacity(256,1);
  29.       end;
  30.    
  31. feature 
  32.    
  33.    c_define(up_rf: RUN_FEATURE) is
  34.      -- Define the switching C function for `up_rf'.
  35.       require
  36.      cpp.on_c
  37.       local
  38.      boost: BOOLEAN;
  39.      arguments:  FORMAL_ARG_LIST;
  40.      t: TYPE;
  41.      i: INTEGER;
  42.       do
  43.      boost := run_control.boost;
  44.      arguments := up_rf.arguments;
  45.      t := up_rf.result_type;
  46.      ts.clear;
  47.      if t = Void then
  48.         ts.append(fz_void);
  49.      else
  50.         t := t.run_type;
  51.         t.c_type_for_result_in(ts);
  52.      end;
  53.      ts.extend(' ');
  54.      ts.extend('X');
  55.      up_rf.current_type.id.append_in(ts);
  56.      up_rf.name.mapping_c_in(ts);
  57.      if boost then
  58.         ts.append("(void *C");
  59.      else
  60.         ts.append("(int l,int c,int f, void *C");
  61.      end;
  62.      if arguments /= Void then
  63.         from  
  64.            i := 1;
  65.         until
  66.            i > arguments.count
  67.         loop
  68.            ts.extend(',');
  69.            t := arguments.type(i).run_type;
  70.            t.c_type_for_argument_in(ts);
  71.            ts.append(" a");
  72.            i.append_in(ts);
  73.            i := i + 1;
  74.         end;
  75.      end;
  76.      ts.extend(')');
  77.      cpp.put_c_heading(ts);
  78.      cpp.swap_on_c;
  79.      cpp.put_string("int id=");
  80.      running.copy(up_rf.current_type.run_class.running);
  81.      sort_running(running);
  82.      if boost then
  83.         cpp.put_string("((T0*)C)->id;%N");
  84.      else
  85.         cpp.put_string("vc(C,l,c,f)->id;%N");
  86.      end;
  87.      if run_control.all_check then
  88.         c_switch(up_rf);
  89.      else
  90.         c_dicho(up_rf,1,running.upper);
  91.      end;
  92.      cpp.put_string(fz_12);
  93.       ensure     
  94.      cpp.on_c
  95.       end;
  96.  
  97. feature {C_PRETTY_PRINTER}
  98.  
  99.    put_arguments(up_rf: RUN_FEATURE; fal: FORMAL_ARG_LIST) is
  100.      -- Produce C code for arguments of `fal' used
  101.      -- inside the switching C function.
  102.       require
  103.      cpp.on_c;
  104.      fal.count = up_rf.arguments.count
  105.       local
  106.      i, up: INTEGER;
  107.       do
  108.      from  
  109.         i := 1;
  110.         up := fal.count;
  111.      until
  112.         i > up
  113.      loop
  114.         if i > 1 then
  115.            cpp.put_character(',');
  116.         end;
  117.         put_ith_argument(up_rf,fal,i);
  118.         i := i + 1;
  119.      end;
  120.       ensure
  121.      cpp.on_c
  122.       end;
  123.    
  124.    put_ith_argument(up_rf: RUN_FEATURE; fal: FORMAL_ARG_LIST; index: INTEGER) is
  125.      -- Produce C code for argument `index' of `fal' used
  126.      -- inside the switching C function.
  127.       require
  128.      cpp.on_c;
  129.      fal.count = up_rf.arguments.count;
  130.      1 <= index;
  131.      index <= fal.count
  132.       local
  133.      eal: like fal;
  134.      at, ft: TYPE;
  135.       do
  136.      eal := up_rf.arguments;
  137.      at := eal.type(index).run_type;
  138.      ft := fal.type(index).run_type;
  139.      if at.is_reference and then ft.is_basic_eiffel_expanded then
  140.         cpp.put_character('(');
  141.         ft.cast_to_ref;
  142.         cpp.put_character('a');
  143.         cpp.put_integer(index);
  144.         cpp.put_string(")->_item");
  145.      else
  146.         cpp.put_character('a');
  147.         cpp.put_integer(index);
  148.      end;
  149.       ensure
  150.      cpp.on_c
  151.       end;
  152.    
  153. feature {NONE}
  154.    
  155.    c_dicho(up_rf: RUN_FEATURE; bi, bs: INTEGER) is
  156.      -- Produce dichotomic inspection code for Current id.
  157.       require
  158.      bi <= bs
  159.       local
  160.      m: INTEGER;
  161.      dyn_rc: RUN_CLASS;
  162.      dyn_rf: RUN_FEATURE;
  163.       do
  164.      if bi = bs then
  165.         dyn_rc := running.item(bi);
  166.         dyn_rf := dyn_rc.dynamic(up_rf);
  167.         tail_opening(up_rf.result_type,dyn_rf.result_type);
  168.         cpp.push_switch(dyn_rf,up_rf);
  169.         dyn_rf.mapping_c;
  170.         cpp.pop;
  171.         tail_closing(up_rf.result_type,dyn_rf.result_type);
  172.      else        
  173.         m := (bi + bs) // 2;
  174.         dyn_rc := running.item(m);
  175.         cpp.put_string("if (id <= ");
  176.         cpp.put_integer(dyn_rc.id);
  177.         cpp.put_string(") {%N");
  178.         c_dicho(up_rf,bi,m);
  179.         cpp.put_string("} else {%N");
  180.         c_dicho(up_rf,m + 1,bs);
  181.         cpp.put_character('}');
  182.      end;
  183.       end;
  184.  
  185.    c_switch(up_rf: RUN_FEATURE) is
  186.      -- Produce C switch inspection code for Current id.
  187.       local
  188.      i: INTEGER;
  189.      dyn_rc: RUN_CLASS;
  190.      dyn_rf: RUN_FEATURE;
  191.       do
  192.      cpp.put_string("switch(id){%N"); 
  193.      from
  194.         i := 1;
  195.      until
  196.         i > running.upper
  197.      loop
  198.         dyn_rc := running.item(i);
  199.         dyn_rf := dyn_rc.dynamic(up_rf);
  200.         cpp.put_string("case "); 
  201.         cpp.put_integer(dyn_rc.id);
  202.         cpp.put_character(':');
  203.         tail_opening(up_rf.result_type,dyn_rf.result_type);
  204.         cpp.push_switch(dyn_rf,up_rf);
  205.         dyn_rf.mapping_c;
  206.         cpp.pop;
  207.         tail_closing(up_rf.result_type,dyn_rf.result_type);
  208.         cpp.put_string("%Nbreak;%N"); 
  209.         i := i + 1;
  210.      end;
  211.      if run_control.no_check then
  212.         cpp.put_string("default: error2(C,l,c,f);%N");
  213.      end;
  214.      cpp.put_string(fz_12);
  215.       end;
  216.  
  217. feature {C_PRETTY_PRINTER,SWITCH}
  218.  
  219.    name(up_rf: RUN_FEATURE): STRING is
  220.       do
  221.      tmp_name.clear;
  222.      tmp_name.extend('X');
  223.      up_rf.current_type.id.append_in(tmp_name);
  224.      tmp_name.append(up_rf.name.to_key);
  225.      Result := tmp_name;
  226.       end;
  227.  
  228. feature {NONE}
  229.  
  230.    tmp_name: STRING is
  231.       once
  232.      !!Result.make(32);
  233.       end;
  234.  
  235. feature
  236.  
  237.    jvm_descriptor(up_rf: RUN_FEATURE): STRING is
  238.       local
  239.      arguments:  FORMAL_ARG_LIST;
  240.      rt: TYPE;
  241.       do
  242.      arguments := up_rf.arguments;
  243.      tmp_jvmd.clear;
  244.      tmp_jvmd.extend('(');
  245.      tmp_jvmd.append(jvm_root_descriptor);
  246.      if arguments /= Void then
  247.         arguments.jvm_descriptor_in(tmp_jvmd);
  248.      end;
  249.      rt := up_rf.result_type;
  250.      if rt = Void then
  251.         tmp_jvmd.append(fz_19);
  252.      else
  253.         rt := rt.run_type;
  254.         tmp_jvmd.extend(')');
  255.         if rt.is_reference then
  256.            tmp_jvmd.append(jvm_root_descriptor);
  257.         else
  258.            rt.jvm_descriptor_in(tmp_jvmd);
  259.         end;
  260.      end;
  261.      Result := tmp_jvmd;
  262.       end;
  263.  
  264. feature {NONE}
  265.  
  266.    tmp_string: STRING is
  267.       once
  268.      !!Result.make(32);
  269.       end;
  270.  
  271.    tmp_jvmd: STRING is
  272.       once
  273.      !!Result.make(32);
  274.       end;
  275.  
  276. feature 
  277.  
  278.    idx_methodref(up_rf: RUN_FEATURE): INTEGER is
  279.       require
  280.      up_rf /= Void
  281.       do
  282.      Result := constant_pool.idx_methodref3(jvm_root_class,
  283.                         name(up_rf),
  284.                         jvm_descriptor(up_rf));
  285.       end;
  286.    
  287. feature {JVM}
  288.  
  289.    jvm_mapping(cpc: CALL_PROC_CALL) is
  290.       require
  291.      cpc /= Void
  292.       local
  293.      idx, stack_level: INTEGER;
  294.      up_rf: RUN_FEATURE;
  295.      target: EXPRESSION;
  296.      eal: EFFECTIVE_ARG_LIST;
  297.      fal: FORMAL_ARG_LIST;
  298.      switch: SWITCH;
  299.       do
  300.      target := cpc.target;
  301.      up_rf := cpc.run_feature;
  302.      eal := cpc.arguments;
  303.      target.compile_to_jvm;
  304.      stack_level := 1;
  305.      if eal /= Void then
  306.         fal := up_rf.arguments;
  307.         stack_level := stack_level + eal.compile_to_jvm(fal);
  308.      end;
  309.      idx := switch.idx_methodref(up_rf);
  310.      code_attribute.opcode_invokestatic(idx,-stack_level);
  311.       end;
  312.  
  313. feature {SWITCH_COLLECTION}
  314.  
  315.    jvm_define(up_rf: RUN_FEATURE) is
  316.       local
  317.      rt: TYPE;
  318.       do
  319.      -- Define the Java switching static method for `up_rf'.
  320.      method_info.start(9,name(up_rf),jvm_descriptor(up_rf));
  321.      running.copy(up_rf.current_type.run_class.running);
  322.      rt := up_rf.result_type;
  323.      if rt /= Void then
  324.         rt := rt.run_type;
  325.      end;
  326.      jvm_switch(up_rf,rt);
  327.      method_info.finish;
  328.       end;
  329.  
  330. feature {NONE}
  331.  
  332.    ts: STRING is
  333.       once
  334.      !!Result.make(256);
  335.       end;
  336.  
  337.    tail_opening(x_type, r_type: TYPE) is
  338.       do
  339.      if x_type /= Void then
  340.         tmp_string.copy(fz_return);
  341.         tmp_string.extend('(');
  342.         tmp_string.extend('(');
  343.         x_type.c_type_for_result_in(tmp_string);
  344.         tmp_string.extend(')');
  345.         tmp_string.extend('(');
  346.         cpp.put_string(tmp_string);
  347.         if r_type.is_expanded and then x_type.is_reference then
  348.            r_type.to_reference;
  349.            cpp.put_character('(');
  350.         end;
  351.      end;
  352.       end;
  353.  
  354.    tail_closing(x_type, r_type: TYPE) is
  355.       do
  356.      if x_type /= Void then
  357.         if r_type.is_expanded and then x_type.is_reference then
  358.            cpp.put_character(')');
  359.         end;
  360.         cpp.put_string(fz_16);
  361.      end;
  362.       end;
  363.  
  364. feature {NONE}
  365.  
  366.    jvm_switch(up_rf: RUN_FEATURE; rt: TYPE) is
  367.      -- Produce Java sequential switch code.
  368.       require
  369.      rt /= Void implies rt.run_type = rt
  370.       local
  371.      space, point, idx, i: INTEGER;
  372.      dyn_rc: RUN_CLASS;
  373.      dyn_rf: RUN_FEATURE;
  374.      boost: BOOLEAN;
  375.      ca: like code_attribute;
  376.       do
  377.      ca := code_attribute;
  378.      from
  379.         boost := run_control.boost;
  380.         i := running.upper;
  381.      until
  382.         i = 0
  383.      loop
  384.         dyn_rc := running.item(i);
  385.         dyn_rf := dyn_rc.dynamic(up_rf);
  386.         if i = 1 and then boost then
  387.         else
  388.            ca.opcode_aload_0;
  389.            idx := dyn_rf.run_class.fully_qualified_constant_pool_index;
  390.            ca.opcode_instanceof(idx);
  391.            point := ca.opcode_ifeq;
  392.         end;
  393.         jvm.push_switch(dyn_rf,up_rf);
  394.         dyn_rf.mapping_jvm;
  395.         jvm.pop;
  396.         if rt = Void then
  397.            ca.opcode_return;
  398.         else
  399.            space := dyn_rf.result_type.jvm_convert_to(rt);
  400.            rt.jvm_return_code;
  401.         end;
  402.         if i = 1 and then boost then
  403.         else
  404.            ca.resolve_u2_branch(point);
  405.         end;
  406.         i := i - 1;
  407.      end;
  408.      if boost then
  409.      else
  410.         ca.opcode_system_err_println(idx_error01);
  411.         ca.opcode_iconst_1;
  412.         ca.opcode_system_exit
  413.      end;
  414.       end;
  415.  
  416.    idx_error01: INTEGER is
  417.       do
  418.      Result := constant_pool.idx_string("Bad target for dynamic dispatch.");
  419.       end;
  420.  
  421. end
  422.