cvsuser     03/11/15 20:28:10

  Added:       imcc     sub.c fastcall.c
  Log:
  More IMCC rearchitecture.
  * .sub directive now deprecates .pcc_sub directive.
    .sub now uses PCC convention by default.
  * All other .pcc directives are still used but will
    be eventually deprecated.
  * Modularize calling conventions and add generic API.
    sub.c is the generic API and wraps pcc.c and fastcall.c
  * Add stubs for a 2nd FASTCALL convention which can be enabled by
    compiler pragma.  Currently fastcall does not work.
  * Add .pragma directive to the lexer.
  * Add check for 0 arguments in PCC subs to skip code generate for proto/nonproto
    argument checking if there are no args. (Leo check this if it is the right
    thing to do?)
  * Various comments and optional tracing added to existing code.
  
  Revision  Changes    Path
  1.1                  parrot/imcc/sub.c
  
  Index: sub.c
  ===================================================================
  /*
   * sub.c
   *
   * Calling Conventions API for generating subs definitions, calls, etc.
   *
   * Called by the code generators, optimizers and flow graph code which
   * are mostly independant of the low-level call conventions.
   *
   * Depending on compiler pragmas this API will callout to one of several
   * supported code generators. (see pcc.c or fastcall.c)
   *
   * The default is PCC (prototyped and non-prototyped).
   * PCC (Parrot Calling Convention) is the default for Perl6 and other
   * languages that want to interface with Perl6 on Parrot. PCC works
   * well with continuations and co-routines.
   *
   * Plans are for a FASTCALL convention which can be enabled with: 
   * .pragma fastcall
   * which will allow library developers (or non-Perl languages) to turn
   * on very efficient calling conventions. It could also be used for internal
   * libs that do not callout to PCC routines, but present PCC entry points
   * for the module itself.
   *
   * Currently the only fully functional convention is PCC but the generic
   * API allows us to experiment with calling conventions side by
   * side without completely breaking IMCC everytime we tweak something.
   * The side effect is the subroutine code generators and optimizers can be
   * very modular and less interlocked to a specific convention.
   *
   */ 
      
  #include <stdlib.h>
  #include <string.h>
  #include <assert.h>
  #include "imc.h"
  #include "parser.h"
  
  /*
   * Expand a subroutine definition depending on the active
   * calling convention. (FAST or PCC)
   */
  void
  expand_sub(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
  {
      /* IMC_FASTSUB */
  #if IMC_TRACE
      PIO_eprintf("expand_sub\n");
  #endif
      /* For expand sub, we check the unit->type only, since the
       * pragma might be overridden.
       */
      if(pragmas.fastcall) {
          expand_fast_sub(interp, unit, ins);
      }
      /* IMC_PCCSUB */
      else {
          expand_pcc_sub(interp, unit, ins);
      }
  }
  
  
  /*
   * Expand return instructions depending on active
   * calling convention (FAST or PCC).
   */
  void
  expand_sub_ret(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
  {
  #if IMC_TRACE
      PIO_eprintf("expand_sub_ret\n");
  #endif
      /* IMC_FASTSUB */
      if(pragmas.fastcall) {
          expand_fast_sub_ret(interp, unit, ins);
      }
      /* IMC_PCCSUB */
      else {
          expand_pcc_sub_ret(interp, unit, ins);
      }
  }
  
  /*
   * Expand a sub call depending on active calling convention.
   * (FAST or PCC).
   */
  void
  expand_sub_call(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
  {
  #if IMC_TRACE
      PIO_eprintf("expand_sub_call\n");
  #endif
      /* IMC_FASTSUB */
      if(pragmas.fastcall) {
          expand_fast_sub_call(interp, unit, ins);
      }
      /* IMC_PCCSUB */
      else {
          expand_pcc_sub_call(interp, unit, ins);
      }
  }
  
  
  /*
   * Peephole optimizer for subroutine Unit depending on its calling convention.
   * Currently the same optimizer works for both.
   */
  void
  sub_optimize(Parrot_Interp interp, IMC_Unit * unit)
  {
      /* IMC_FASTSUB */
      if(pragmas.fastcall) {
          pcc_sub_optimize(interp, unit);
      }
      /* IMC_PCCSUB */
      else {
          pcc_sub_optimize(interp, unit);
      }
  }
  
  
  
  
  
   
  
  
  
  1.1                  parrot/imcc/fastcall.c
  
  Index: fastcall.c
  ===================================================================
  /*
   * fastcall.c
   *
   * A specific call convention implementation. Called by the generic
   * API for subs (see sub.c).
   *
   * FASTCALL convention can be enabled with: 
   * .pragma fastcall 
   * at the start of an IMC module.
   *
   * This will allow library developers (or non-Perl languages) to turn
   * on very efficient optimizations and a lightweight calling convention.
   * It could also be used for internal libs that do not callout to PCC
   * routines, but present PCC entry points for the module itself.
   *
   * XXX FIXME: FASTCALL is not currently finished and may not be completely
   * compatible with PCC convention. (ie. you can't mix and match, for now at least)
   */
  
  #include <stdlib.h>
  #include <string.h>
  #include <assert.h>
  #include "imc.h"
  #include "parser.h"
  
  /* XXX FIXME: This call convention is not finished, so using
   * .pragma fastcall will cause IMCC to exit.
   */
  
  
  /*
   * Utilty instruction routine. Creates and inserts an instruction
   * into the current block in one call.
   */
  static Instruction *
  insINS(struct Parrot_Interp *interpreter, IMC_Unit * unit, Instruction *ins,
          char *name, SymReg **regs, int n)
  {
      Instruction *tmp = INS(interpreter, unit, name, NULL, regs, n, 0, 0);
      insert_ins(unit, ins, tmp);
      return tmp;
  }
  
  
  /*
   * XXX Unimplemented. (Proof of concept only)
   *
   * Expand a FASTCALL sub, whatever that happens to be. Currently
   * it means passing and returning arguments on the stack
   * Enabled by .pragma fastcall
   */
  void
  expand_fast_sub(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
  {   
      SymReg *arg, *sub, *regs[IMCC_MAX_REGS];
      int i, n;
  
  #if IMC_TRACE
      PIO_eprintf("expand_fast_sub\n");
  #endif
      
      sub = ins->r[1];
      n = sub->pcc_sub->nargs;
      for (i = 0; i < n; i++) {
         regs[0] = arg = sub->pcc_sub->args[i];
         ins = insINS(interp, unit, ins, "restore", regs, 1);
      }
  
  }
  
  /*
   * XXX Unimplemented. (Proof of concept only) 
   */
  void
  expand_fast_sub_ret(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
  {
      SymReg *sub, *ret, *regs[IMCC_MAX_REGS];
      int i;
  
  #if IMC_TRACE
      PIO_eprintf("expand_fast_sub_ret\n");
  #endif
  
      sub = ins->r[1];
      for (i = 0; i < sub->pcc_sub->nret; i++) {
         regs[0] = ret = sub->pcc_sub->ret[i];
         ins = insINS(interp, unit, ins, "save", regs, 1);
      }
  }
  
  /*
   * XXX Unimplemented. (Proof of concept only)
   * Currently not compatible with .pcc_call since .pcc_call
   * uses an identifier (not a label) as its argument.
   * We need to hide the call implementation and have each call convention
   * generate necessary code.
   */
  void
  expand_fast_sub_call(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
  {
      SymReg *sub, *ret, *arg, *regs[IMCC_MAX_REGS];
      int i;
  
  #if IMC_TRACE
      PIO_eprintf("expand_fast_sub_call\n");
  #endif
  
      sub = ins->r[0];
      for(i = 0; i < sub->pcc_sub->nargs; i++) {
          regs[0] = arg = sub->pcc_sub->args[i];
          ins = insINS(interp, unit, ins, "save", regs, 1);
      }
  
      regs[0] = sub->pcc_sub->sub;
      ins = insINS(interp, unit, ins, "bsr", regs, 1);
  
      /* XXX: Only supports prototyped subs for now */
  
      for(i = 0; i < sub->pcc_sub->nret; i++) {
          ret = sub->pcc_sub->ret[i];
          regs[0] = mk_temp_reg(ret->set);
          ins = insINS(interp, unit, ins, "restore", regs, 1);
      }
  }
  
  
  
  
  

Reply via email to