cvsuser     04/02/22 10:54:14

  Modified:    imcc     pcc.c
               imcc/t/syn pcc.t
  Log:
  imcc pdd03
  * unify call and return conventiosn
  * fix non_proto case - args are no more in P3
  * common code is now in pcc_{get,put}_args
  * param checking is currently not done
  
  Revision  Changes    Path
  1.43      +261 -473  parrot/imcc/pcc.c
  
  Index: pcc.c
  ===================================================================
  RCS file: /cvs/public/parrot/imcc/pcc.c,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -w -r1.42 -r1.43
  --- pcc.c     22 Feb 2004 13:59:54 -0000      1.42
  +++ pcc.c     22 Feb 2004 18:54:11 -0000      1.43
  @@ -55,6 +55,10 @@
   
   static const char regsets[] = "ISPN";
   
  +/* forward def */
  +static Instruction *
  +pcc_emit_flatten(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins,
  +        SymReg *arg, int i, int *flatten);
   
   
   
  @@ -63,7 +67,7 @@
    * into the current block in one call.
    */
   static Instruction *
  -insINS(struct Parrot_Interp *interpreter, IMC_Unit * unit, Instruction *ins,
  +insINS(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);
  @@ -71,186 +75,270 @@
       return tmp;
   }
   
  +/*
  + * get or create the SymReg
  + */
  +static SymReg*
  +get_pasm_reg(char *name)
  +{
  +    SymReg *r;
  +
  +    if ((r = _get_sym(cur_unit->hash, name)))
  +        return r;
  +    return mk_pasm_reg(str_dup(name));
  +}
  +
  +static SymReg*
  +get_const(char *name, int type)
  +{
  +    SymReg *r;
  +
  +    if ((r = _get_sym(ghash, name)) && r->set == type)
  +        return r;
  +    return mk_const(str_dup(name), type);
  +}
  +
   static Instruction *
  -set_I_const(struct Parrot_Interp *interpreter, IMC_Unit * unit, Instruction *ins,
  +set_I_const(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins,
               int regno, int value)
   {
       SymReg *ix, *regs[IMCC_MAX_REGS], *arg;
       char buf[128];
   
       sprintf(buf, "I%d", regno);
  -    ix = mk_pasm_reg(str_dup(buf));
  +    ix = get_pasm_reg(buf);
       sprintf(buf, "%d", value);
  -    arg = mk_const(str_dup(buf), 'I');
  +    arg = get_const(buf, 'I');
       regs[0] = ix;
       regs[1] = arg;
       return insINS(interpreter, unit, ins, "set", regs, 2);
   }
   
  -static void
  -pcc_emit_err(Parrot_Interp interpreter, IMC_Unit * unit, SymReg *err, const char 
*msg)
  -{
  -    SymReg *p0;
  -    SymReg *regs[IMCC_MAX_REGS];
  -
  -    /* err_label:
  -     *   new $P0, .Exception
  -     *   set $P0["_message"], msg
  -     *   throw $P0
  -     *   ret
  -     */
  -    INS_LABEL(unit, err, 1);
  -    p0 = mk_symreg(str_dup("$P0"), 'P');
  -    iNEW(interpreter, unit, p0, str_dup("Exception"), NULL, 1);
  -    regs[0] = p0;
  -    regs[1] = mk_const(str_dup("\"_message\""), 'S');
  -    regs[2] = mk_const(str_dup(msg), 'S');
  -    INS(interpreter, unit, "set", NULL, regs, 3, 2, 1);
  -    INS(interpreter, unit, "throw", NULL, regs, 1, 0, 1);
  -    INS(interpreter, unit, "ret", NULL, regs, 0, 0, 1);
  -}
  -
  +/*
  + * get arguments or return results
  + * used by expand_pcc_sub_call and expand_pcc_sub
  + */
   static Instruction *
  -pcc_emit_check_param(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins,
  -        SymReg *sub, SymReg *i0, SymReg *p3, int first, int type)
  +pcc_get_args(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins,
  +        struct pcc_sub_t *pcc_sub, int n, int proto, SymReg **args, int call)
   {
  -    SymReg *check_sub, *regs[IMCC_MAX_REGS], *check_type, *what, *check_pmc;
  -    char buf[256];
  -    char * s;
  -    SymReg *err_nparam, *err_type;
  +    int next[4], i, j, set;
  +    SymReg *p3, *regs[IMCC_MAX_REGS], *arg;
  +    char buf[128];
   
  +    p3 = NULL;
  +    for (i = 0; i < REGSET_MAX; i++)
  +        next[i] = FIRST_PARAM_REG;
  +    /* insert params */
  +    for (i = 0; i < n; i++) {
  +        arg = args[i];
  +        for (j = 0; j < REGSET_MAX; j++) {
  +            set = j;
       /*
  -     * generate check subroutine if not done yet
  +             * if this is non-prototyped, register set is always P
        */
  -    s = str_dup("?what");
  -    *s = IMCC_INTERNAL_CHAR; /* Avoid an sprintf/copy */
  -    what = mk_symreg(s, 'I');
  -    strcpy(buf, "_?check_params");
  -    buf[1] = IMCC_INTERNAL_CHAR;  /* Avoid an sprintf/copy */
  -    check_sub = _get_sym(ghash, buf);
  -    if (!check_sub) {
  -
  -        check_sub = mk_address(str_dup(buf), U_add_uniq_label);
  -        /* we just append to the current ins stream */
  -        INS_LABEL(unit, check_sub, 1);
  -        /*
  -         * first time check: amount of params, elements in P3
  -         * we can globber I0
  -         */
  -        s = str_dup("_?check_err_nparam");
  -        s[1] = IMCC_INTERNAL_CHAR;
  -        err_nparam = mk_address(s, U_add_uniq_label);
  -        if (p3) {
  -            if (!i0)
  -                i0 = mk_pasm_reg(str_dup("I0"));
  -            regs[0] = i0;
  -            regs[1] = p3;
  -            /* set I0, P3 */
  -            INS(interpreter, unit, "set", NULL, regs, 2, 0, 1);
  -            /* lt I0, nparam, check_err_nparam */
  -            /* the param count in passed by the sub in what
  +            if (arg->set != regsets[set])
  +                continue;
  +            /*
  +             * non-prototyped reg sets don't match
               */
  -            regs[0] = i0;
  +            if (!proto && arg->set != 'P') {
  +                /* we need a native type and get P
  +                 *
  +                 * set arg, $Pn
  +                 */
  +                set = REGSET_P;
  +                if (next[REGSET_P] > LAST_PARAM_REG)
  +                    goto overflow;
  +                regs[0] = arg;
  +                sprintf(buf, "P%d", next[set]++);
  +                regs[1] = get_pasm_reg(buf);
  +                /* e.g. set $I0, I5 */
  +                ins = insINS(interpreter, unit, ins, "set", regs, 2);
  +                break;
           }
  -        else {
  -            SymReg *i2 = mk_pasm_reg(str_dup("I2"));
  -            regs[0] = i2;
  +            if (next[set] > LAST_PARAM_REG) {
  +                goto overflow;
           }
  -
  -        regs[1] = what;
  -        regs[2] = err_nparam;
  -        INS(interpreter, unit, "lt", NULL, regs, 3, 0, 1);
  -        INS(interpreter, unit, "ret", NULL, regs, 0, 0, 1);
  -        /* emit err handler routines
  -         * param count
  +            /*
  +             * if register number already matches - fine
            */
  -        pcc_emit_err(interpreter, unit, err_nparam, "\"wrong param count\"");
  +            if (arg->color == next[set]) {
  +                next[set]++;
  +                break;
       }
  -
  -    s = str_dup("_?check_param_type");
  -    s[1] = IMCC_INTERNAL_CHAR;  /* Avoid sprintf call */
  -    check_type = _get_sym(ghash, s);
  -    if (!check_type && type) {
  -        /*
  -         * type check entry to check sub
  +            /* assign register to that param
  +             *
  +             * if this subroutine calls another subroutine
  +             * new registers are assigned so that
  +             * they don't interfer with this sub's params
            */
  -        check_type = mk_address(s, U_add_uniq_label);
  -        INS_LABEL(unit, check_type, 1);
  +            if (call) {
  +                if (pcc_sub->calls_a_sub) {
  +move_reg:
  +                    regs[0] = arg;
  +                    arg->reg->want_regno = next[set];
  +                    sprintf(buf, "%c%d", arg->set, next[set]++);
  +                    regs[1] = get_pasm_reg(buf);
  +                    arg->used = regs[1];
  +                    /* e.g. set $I0, I5 */
  +                    ins = insINS(interpreter, unit, ins, "set", regs, 2);
  +                }
  +                else {
           /*
  -         * param type check, we get the entry type in what
  +                     * if no sub is called from here
  +                     * just use the passed register numbers
            */
  -        /* typeof I0, P3[0] */
  -        regs[0] = i0;
  +                    arg->reg->color = next[set]++;
  +                }
  +            }
  +            else
  +                goto move_reg;
  +        }
  +        continue;
  +overflow:
  +        if (!p3)
  +            p3 = get_pasm_reg("P3");
  +        /* this uses register numbers (if any)
  +         * from the first prototyped pass
  +         */
  +        regs[0] = arg;
           regs[1] = p3;
  -        regs[2] = mk_const(str_dup("0"), 'I');
  -        INS(interpreter, unit, "typeof", NULL, regs, 3, 4, 1);
  +        ins = insINS(interpreter, unit, ins, "shift", regs, 2);
  +    } /* n params */
  +    return ins;
  +}
   
  -        s = str_dup("_?check_err_type");
  -        s[1] = IMCC_INTERNAL_CHAR;   /* Avoid sprintf */
  -        err_type = mk_address(s, U_add_uniq_label);
  -        regs[0] = i0;
  -        regs[1] = what;
  -        regs[2] = err_type;
  -        INS(interpreter, unit, "ne", NULL, regs, 3, 0, 1);
  -        INS(interpreter, unit, "ret", NULL, regs, 0, 0, 1);
  +/*
  + * put arguments or return results
  + */
  +static Instruction*
  +pcc_put_args(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins,
  +        struct pcc_sub_t *pcc_sub, int n, int proto, SymReg **args)
  +{
  +    int next[4], i, j, set;
  +    SymReg *p3, *regs[IMCC_MAX_REGS], *arg, *arg_reg, *reg;
  +    char buf[128];
  +    Instruction *tmp;
  +    int flatten;
   
  +    p3 = NULL;
  +    UNUSED(pcc_sub);
  +    flatten = 0;
  +    for (i = 0; i < REGSET_MAX; i++)
  +        next[i] = FIRST_PARAM_REG;
  +    for (i = 0; i < n; i++) {
           /*
  -         * PMC type check entry to check sub
  +         * if prototyped, first 11 I,S,N go into regs
            */
  -        s = str_dup("_?check_param_type_pmc");
  -        s[1] = IMCC_INTERNAL_CHAR;    /* Avoid sprintf */
  -        check_pmc = mk_address(s, U_add_uniq_label);
  -        INS_LABEL(unit, check_pmc, 1);
  +        arg = args[i];
  +#if IMC_TRACE
  +        PIO_eprintf(NULL, "    arg(%c%s)%s\n", arg->set,
  +                (arg->type & (VTCONST|VT_CONSTP)) ? "c":"", arg->name);
  +#endif
  +        arg_reg = arg->reg;
  +        for (j = 0; j < REGSET_MAX; j++) {
  +            set = j;
           /*
  -         * either type = enum_type_PMC || > 0
  +             * if this is non-prototyped, register set is always P
            */
  -        /* typeof I0, P3[0] */
  -        regs[0] = i0;
  -        regs[1] = p3;
  -        regs[2] = mk_const(str_dup("0"), 'I');
  -        INS(interpreter, unit, "typeof", NULL, regs, 3, 4, 1);
  -        regs[0] = i0;
  -        regs[1] = mk_const(str_dup("0"), 'I');
  -        regs[2] = check_type;
  -        INS(interpreter, unit, "lt", NULL, regs, 3, 0, 1);
  -        INS(interpreter, unit, "ret", NULL, regs, 0, 0, 1);
  +            if (arg->set != regsets[set])
  +                continue;
           /*
  -         * param type
  +             * non-prototyped reg sets don't match
            */
  -        pcc_emit_err(interpreter, unit, err_type, "\"wrong param type\"");
  +            if (!proto && arg_reg->set != 'P') {
  +                set = REGSET_P;
  +                if (next[REGSET_P] > LAST_PARAM_REG)
  +                    goto overflow;
  +                /* make a new P reg and assign value */
  +                sprintf(buf, "P%d", next[set]++);
  +                reg = get_pasm_reg(buf);
  +                tmp = iNEW(interpreter, unit, reg, str_dup("PerlUndef"),
  +                        NULL, 0);
  +                insert_ins(unit, ins, tmp);
  +                ins = tmp;
  +                regs[0] = reg;
  +                regs[1] = arg_reg;
  +                ins = insINS(interpreter, unit, ins, "set", regs, 2);
  +                break;
       }
  -    if (first) {
  -        /* emit first time check
  -         * what is param count
  +            if (next[set] > LAST_PARAM_REG) {
  +                goto overflow;
  +            }
  +            /*
  +             * if register number already matches - fine
            */
  -        regs[0] = what;
  -        sprintf(buf, "%d", sub->pcc_sub->nargs);
  -        regs[1] = mk_const(str_dup(buf), 'I');
  -        ins = insINS(interpreter, unit, ins, "set", regs, 2);
  -        regs[0] = check_sub;
  -        ins = insINS(interpreter, unit, ins, "bsr", regs, 1);
  +            if (arg->color == next[set] && arg->type & VTREGISTER) {
  +                next[set]++;
  +                break;
       }
  -    if (!type)
  -        return ins;
  -    /* emit type check what is type */
  -    regs[0] = what;
  -    sprintf(buf, "%d", type);
  -    regs[1] = mk_const(str_dup(buf), 'I');
  +            if (arg->type & VTREGISTER) {
  +                if (set == REGSET_P &&
  +                        (flatten || (arg_reg->type & VT_FLATTEN)))
  +                    goto flatten;
  +                arg_reg->want_regno = next[set];
  +            }
  +            sprintf(buf, "%c%d", arg_reg->set, next[set]++);
  +            reg = mk_pasm_reg(str_dup(buf));
  +            regs[0] = reg;
  +            regs[1] = arg_reg;
       ins = insINS(interpreter, unit, ins, "set", regs, 2);
  -    if(enum_type_PMC == type)
  -        sprintf(buf, "_%ccheck_param_type_pmc", IMCC_INTERNAL_CHAR);
  -    else
  -        sprintf(buf, "_%ccheck_param_type", IMCC_INTERNAL_CHAR);
  -    check_type = _get_sym(ghash, buf);
  -    if(!check_type) {
  -        PIO_eprintf(NULL, "imcc: fatal: pcc_emit_check_param: symbol %s not 
found\n", buf);
  -        exit(1);
  +            /* remember reg for life analysis */
  +            arg->used = reg;
  +
  +            continue;
  +overflow:
  +            if (!p3) {
  +                p3 = mk_pasm_reg(str_dup("P3"));
  +                tmp = iNEW(interpreter, unit, p3, str_dup("PerlArray"), NULL, 0);
  +                insert_ins(unit, ins, tmp);
  +                ins = tmp;
       }
  -    regs[0] = check_type;
  -    ins = insINS(interpreter, unit, ins, "bsr", regs, 1);
  -    return ins;
  +            if (flatten || (arg_reg->type & VT_FLATTEN))
  +                goto flatten;
  +#if IMC_TRACE_HIGH
  +            PIO_eprintf(NULL, "expand_pcc_sub_call: overflow (%c%s)%s\n",
  +                    arg->set,
  +                    (arg->type & (VTCONST|VT_CONSTP)) ? "c":"",  arg->name);
  +#endif
  +            regs[0] = p3;
  +            regs[1] = arg_reg;
  +            ins = insINS(interpreter, unit, ins, "push", regs, 2);
  +        }
  +        continue;
  +flatten:
  +        /* if we had a flattening arg, we must continue emitting
  +         * code to do all at runtime
  +         */
  +        ins = pcc_emit_flatten(interpreter, unit, ins, arg_reg, i, &flatten);
  +    } /* for i */
  +
  +    /* set prototyped: I0  (1=prototyped, 0=non-prototyped) */
  +    ins = set_I_const(interpreter, unit, ins, REG_PROTO_FLAG, proto);
  +
  +    /* Ireg param count in: I1 */
  +    ins = set_I_const(interpreter, unit, ins, REG_I_PARAM_COUNT,
  +            next[REGSET_I] - FIRST_PARAM_REG);
  +
  +    /* Sreg param count in: I2 */
  +    ins = set_I_const(interpreter, unit, ins, REG_S_PARAM_COUNT,
  +            next[REGSET_S] - FIRST_PARAM_REG);
  +
  +    /* set items in PRegs: I3 */
  +    if (flatten) {
  +        regs[0] = mk_pasm_reg(str_dup("I3"));;
  +        regs[1] = mk_const(str_dup("5"), 'I');
  +        ins = insINS(interpreter, unit, ins, "sub", regs, 2);
   }
  +    else
  +        ins = set_I_const(interpreter, unit, ins, 3, next[2] - FIRST_PARAM_REG);
   
  +    /* Nreg param count in: I4 */
  +    ins = set_I_const(interpreter, unit, ins, REG_N_PARAM_COUNT,
  +            next[REGSET_N] - FIRST_PARAM_REG);
  +    return ins;
  +}
   
   /*
    * Expand a PCC (Parrot Calling Convention) subroutine
  @@ -260,11 +348,11 @@
   void
   expand_pcc_sub(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins)
   {
  -    SymReg *arg, *sub;
  -    int next[4], i, set, nargs;
  +    SymReg *sub;
  +    int nargs;
       int proto, ps, pe;
       Instruction *tmp;
  -    SymReg *p3, *i0, *regs[IMCC_MAX_REGS], *label1, *label2;
  +    SymReg *i0, *regs[IMCC_MAX_REGS], *label1, *label2;
       char buf[128];
   
   #if IMC_TRACE
  @@ -279,13 +367,13 @@
       if(sub->pcc_sub->nargs <= 0)
           goto NONAMEDPARAMS;
   
  -    p3 = i0 = NULL;
  +    i0 = NULL;
       label1 = label2 = NULL;
       ps = pe = sub->pcc_sub->pragma & P_PROTOTYPED;
       if (sub->pcc_sub->pragma & P_NONE) {
        ps = 0; pe = 1;
        /* subroutine can handle both */
  -     i0 = mk_pasm_reg(str_dup("I0"));
  +     i0 = get_pasm_reg("I0");
        regs[0] = i0;
        sprintf(buf, "_%csub_%s_p1", IMCC_INTERNAL_CHAR, sub->name);
           regs[1] = label1 = mk_address(str_dup(buf), U_add_uniq_label);
  @@ -293,84 +381,9 @@
   
       }
       for (proto = ps; proto <= pe; ++proto) {
  -     for (i = 0; i < REGSET_MAX; i++)
  -         next[i] = FIRST_PARAM_REG;
  -     /* insert params */
        nargs = sub->pcc_sub->nargs;
  -     for (i = 0; i < nargs; i++) {
  -         arg = sub->pcc_sub->args[i];
  -         if (proto == 1 ||
  -                 (arg->set == 'P' && next[REGSET_P] < 16)) {
  -             for (set = 0; set < REGSET_MAX; set++) {
  -                 if (arg->set == regsets[set]) {
  -                     if (next[set] > LAST_PARAM_REG) {
  -#if IMC_TRACE
  -                            PIO_eprintf(NULL, "expand_sub nextreg[%d]: switching to 
arg overflow\n", next[set]);
  -#endif
  -                         goto overflow;
  -                        }
  -                     if (arg->color == next[set]) {
  -                         next[set]++;
  -                         break;
  -                     }
  -                        /* if unprototyped check param count */
  -                        if (ps != pe && !proto)
  -                            ins = pcc_emit_check_param(interpreter, unit,
  -                                    ins, sub, i0, NULL, i == 0, 0);
  -                     /* assign register to that param
  -                         *
  -                         * if this subroutine calls another subroutine
  -                         * new registers are assigned so that
  -                         * they don't interfer with this sub's params
  -                         */
  -                        if (sub->pcc_sub->calls_a_sub) {
  -                            regs[0] = arg;
  -                            arg->reg->want_regno = next[set];
  -                            sprintf(buf, "%c%d", arg->set, next[set]++);
  -                            regs[1] = mk_pasm_reg(str_dup(buf));
  -                            /* e.g. set $I0, I5 */
  -                            ins = insINS(interpreter, unit, ins, "set", regs, 2);
  -                        }
  -                        else {
  -                            /*
  -                             * if no sub is called from here
  -                             * just use the passed register numbers
  -                             */
  -                            arg->reg->color = next[set]++;
  -                        }
  -                     break;
  -                 }
  -             }
  -         }
  -         else {
  -                int type;
  -                /*
  -                 * TODO overflow tests
  -                 */
  -overflow:
  -             if (!p3)
  -                 p3 = mk_pasm_reg(str_dup("P3"));
  -                switch (sub->pcc_sub->args[i]->set) {
  -                    case 'I': type = enum_type_INTVAL; break;
  -                    case 'S': type = enum_type_STRING; break;
  -                    case 'N': type = enum_type_FLOATVAL; break;
  -                    case 'P': type = enum_type_PMC; break;
  -                    default: type = -1;
  -                }
  -                /*
  -                 * emit code to inspect the argument type
  -                 * if something is wrong, an exception gets thrown
  -                 */
  -                ins = pcc_emit_check_param(interpreter, unit, ins, sub, i0, p3,
  -                        i == 0, type);
  -                /* this uses register numbers (if any)
  -                 * from the first prototyped pass
  -                 */
  -             regs[0] = sub->pcc_sub->args[i];
  -             regs[1] = p3;
  -             ins = insINS(interpreter, unit, ins, "shift", regs, 2);
  -         }
  -     } /* n params */
  +        ins = pcc_get_args(interpreter, unit, ins, sub->pcc_sub, nargs,
  +                proto, sub->pcc_sub->args, 1);
           if (ps != pe) {
               if (!proto) {
                   /* branch to the end */
  @@ -396,7 +409,7 @@
        */
       if (sub->pcc_sub->calls_a_sub) {
           regs[0] = sub->pcc_sub->cc_sym = mk_temp_reg('P');
  -        regs[1] = mk_pasm_reg(str_dup("P1"));
  +        regs[1] = get_pasm_reg("P1");
           insINS(interpreter, unit, ins, "set", regs, 2);
       }
   }
  @@ -408,21 +421,15 @@
   void
   expand_pcc_sub_ret(Parrot_Interp interpreter, IMC_Unit * unit, Instruction *ins)
   {
  -    SymReg *arg, *sub, *reg, *regs[IMCC_MAX_REGS], *p3;
  -    int next[4], i, set, n, arg_count;
  +    SymReg *sub, *reg, *regs[IMCC_MAX_REGS];
  +    int  n, arg_count;
       Instruction *tmp;
  -    char buf[128];
  -    int n_p3;
   
   #if IMC_TRACE
       PIO_eprintf(NULL, "expand_pcc_sub_ret\n");
   #endif
   
       arg_count = ins->type & ITPCCYIELD ? 0 : 1;
  -    for (i = 0; i < 4; i++)
  -        next[i] = 5;
  -    p3 = NULL;
  -    n_p3 = 0;
       tmp = NULL;
       /*
        * if we have preserved the return continuation
  @@ -446,83 +453,8 @@
           ins = tmp;
       sub->pcc_sub->pragma = P_PROTOTYPED;
       n = sub->pcc_sub->nret;
  -    for (i = 0; i < n; i++) {
  -        arg = sub->pcc_sub->ret[i];
  -        if ((sub->pcc_sub->pragma & P_PROTOTYPED) ||
  -                (arg->set == 'P' && next[2] < 16)) {
  -            /*
  -             * prototyped
  -             */
  -            /* if arg is constant, set register */
  -            switch (arg->type) {
  -                case VT_CONSTP:
  -                    arg = arg->reg;
  -                    /* goon */
  -                case VTCONST:
  -lazy:
  -                    for (set = 0; set < REGSET_MAX; set++) {
  -                        if (arg->set == regsets[set]) {
  -                            if (next[set] > LAST_PARAM_REG)
  -                                goto overflow;
  -                            if (arg->color == next[set]) {
  -                                next[set]++;
  -                                break;
  -                            }
  -                            sprintf(buf, "%c%d", arg->set, next[set]++);
  -                            reg = mk_pasm_reg(str_dup(buf));
  -                            regs[0] = reg;
  -                            regs[1] = arg;
  -                            ins = insINS(interpreter, unit, ins, "set", regs, 2);
  -                            sub->pcc_sub->ret[i]->used = reg;
  -                            break;
  -                        }
  -                    }
  -                    break;
  -                default:
  -                    if (arg->type & VTREGISTER) {
  -                        for (set = 0; set < REGSET_MAX; set++)
  -                            if (arg->set == regsets[set]) {
  -                                arg->reg->want_regno = next[set];
  -                                sub->pcc_sub->ret[i]->used = arg->reg;
  -                                break;
  -                            }
  -                            /* TODO for now just emit a register move */
  -                            goto lazy;
  -                    }
  -            }
  -        }
  -        else {
  -            /* non prototyped or overflow */
  -overflow:
  -            if (!p3) {
  -                p3 = mk_pasm_reg(str_dup("P3"));
  -                tmp = iNEW(interpreter, unit, p3, str_dup("SArray"), NULL, 0);
  -                insert_ins(unit, ins, tmp);
  -                ins = tmp;
  -                sprintf(buf, "%d", n);
  -                regs[0] = p3;
  -                regs[1] = mk_const(str_dup(buf), 'I');
  -                ins = insINS(interpreter, unit, ins, "set", regs, 2);
  -            }
  -            regs[0] = p3;
  -            regs[1] = arg;
  -            ins = insINS(interpreter, unit, ins, "push", regs, 2);
  -            n_p3++;
  -        }
  -
  -    }
  -
  -    /*
  -     * setup I regs
  -     */
  -
  -    /* If prototyped, I0 = 1, else I0 = 0 */
  -    ins = set_I_const(interpreter, unit, ins, 0,
  -            sub->pcc_sub->pragma & P_PROTOTYPED);
  -
  -    /* Setup argument counts */
  -    for (i = 0; i < REGSET_MAX; i++)
  -        ins = set_I_const(interpreter, unit, ins, i + 1, next[i] - 5);
  +    ins = pcc_put_args(interpreter, unit, ins, sub->pcc_sub, n,
  +                1, sub->pcc_sub->ret);
   
       /*
        * we have a pcc_begin_yield
  @@ -809,15 +741,12 @@
   void
   expand_pcc_sub_call(Parrot_Interp interp, IMC_Unit * unit, Instruction *ins)
   {
  -    SymReg *arg, *sub, *reg, *arg_reg, *regs[IMCC_MAX_REGS];
  -    int next[4], i, set, n;
  +    SymReg *arg, *sub, *reg, *regs[IMCC_MAX_REGS];
  +    int  n;
       Instruction *tmp, *call_ins;
       int need_cc;
  -    char buf[128];
  -    SymReg *p3;
  -    int n_p3;
       int tail_call;
  -    int flatten;
  +    int proto;
   
   #if IMC_TRACE
       PIO_eprintf(NULL, "expand_pcc_sub_call\n");
  @@ -826,13 +755,8 @@
       tail_call = check_tail_call(interp, unit, ins);
       if (tail_call)
           debug(interp, DEBUG_OPT1, "found tail call %I \n", ins);
  -    for (i = 0; i < REGSET_MAX; i++)
  -        next[i] = FIRST_PARAM_REG;
       call_ins = ins;
       sub = ins->r[0];
  -    p3 = NULL;
  -    n_p3 = 0;
  -    flatten = 0;
   
       /*
        * See if we need to create a temporary sub object
  @@ -866,92 +790,9 @@
       PIO_eprintf(NULL, ")\n");
   #endif
       n = sub->pcc_sub->nargs;
  -    for (i = 0; i < n; i++) {
  -        /*
  -         * if prototyped, first 11 I,S,N go into regs
  -         */
  -        arg = sub->pcc_sub->args[i];
  -#if IMC_TRACE
  -        PIO_eprintf(NULL, "    arg(%c%s)%s\n", arg->set,
  -                          (arg->type & (VTCONST|VT_CONSTP)) ? "c":"", arg->name);
  -#endif
  -        arg_reg = arg->reg;
  -        if ((sub->pcc_sub->pragma & P_PROTOTYPED) ||
  -                (arg->set == 'P' && next[2] < 16)) {
  -            switch (arg->type) {
  -                /* if arg is constant, set register */
  -                case VT_CONSTP:
  -                case VTCONST:
  -lazy:
  -                    for (set = 0; set < REGSET_MAX; set++) {
  -                        if (arg_reg->set == regsets[set]) {
  -                            if (arg_reg->type != VTCONST &&
  -                                    arg_reg->color == next[set]) {
  -                                next[set]++;
  -                                break;
  -                            }
  -                            if (next[set] == 16)
  -                                goto overflow;
  -                            sprintf(buf, "%c%d", arg_reg->set, next[set]++);
  -                            reg = mk_pasm_reg(str_dup(buf));
  -                            regs[0] = reg;
  -                            regs[1] = arg_reg;
  -                            ins = insINS(interp, unit, ins, "set", regs, 2);
  -                            /* remember reg for life analysis */
  -                            sub->pcc_sub->args[i]->used = reg;
  -
  -                            break;
  -                        }
  -                    }
  -                    break;
  -                default:
  -                    if (arg->type & VTREGISTER) {
  -                        /* TODO for now just emit a register move */
  -                        for (set = 0; set < REGSET_MAX; set++)
  -                            if (arg->set == regsets[set]) {
  -                                if (set == 2 &&
  -                                        (flatten ||
  -                                         (arg_reg->type & VT_FLATTEN)))
  -                                    goto flatten;
  -                                arg_reg->want_regno = next[set];
  -                                sub->pcc_sub->args[i]->used = arg_reg;
  -                                break;
  -                            }
  -                        goto lazy;
  -                    }
  -            }
  -        }
  -        else {
  -            /* non prototyped or overflow */
  -overflow:
  -            if (!p3) {
  -                p3 = mk_pasm_reg(str_dup("P3"));
  -                tmp = iNEW(interp, unit, p3, str_dup("SArray"), NULL, 0);
  -                insert_ins(unit, ins, tmp);
  -                ins = tmp;
  -                sprintf(buf, "%d", n);
  -                regs[0] = p3;
  -                regs[1] = mk_const(str_dup(buf), 'I');
  -                ins = insINS(interp, unit, ins, "set", regs, 2);
  -            }
  -            if (flatten || (arg_reg->type & VT_FLATTEN))
  -                goto flatten;
  -#if IMC_TRACE_HIGH
  -            PIO_eprintf(NULL, "expand_pcc_sub_call: overflow (%c%s)%s\n", arg->set,
  -                        (arg->type & (VTCONST|VT_CONSTP)) ? "c":"",  arg->name);
  -#endif
  -            regs[0] = p3;
  -            regs[1] = arg_reg;
  -            ins = insINS(interp, unit, ins, "push", regs, 2);
  -            n_p3++;
  -        }
  -        continue;
  -flatten:
  -        /* if we had a flattening arg, we must continue emitting
  -         * code to do all at runtime
  -         */
  -        ins = pcc_emit_flatten(interp, unit, ins, arg_reg, i, &flatten);
  -    } /* for i */
  +    proto = sub->pcc_sub->pragma & P_PROTOTYPED;
  +    ins = pcc_put_args(interp, unit, ins, sub->pcc_sub, n,
  +                proto, sub->pcc_sub->args);
   
       /*
        * if we have a tail call then
  @@ -1002,30 +843,6 @@
       else if (!sub->pcc_sub->nci)
           need_cc = 1;
   
  -    /* set prototyped: I0  (1=prototyped, 0=non-prototyped) */
  -    ins = set_I_const(interp, unit, ins, REG_PROTO_FLAG,
  -            sub->pcc_sub->pragma & P_PROTOTYPED);
  -
  -    /* Ireg param count in: I1 */
  -    ins = set_I_const(interp, unit, ins, REG_I_PARAM_COUNT,
  -                                            next[REGSET_I] - FIRST_PARAM_REG);
  -
  -    /* Sreg param count in: I2 */
  -    ins = set_I_const(interp, unit, ins, REG_S_PARAM_COUNT,
  -                                            next[REGSET_S] - FIRST_PARAM_REG);
  -
  -    /* set items in PRegs: I3 */
  -    if (flatten) {
  -        regs[0] = mk_pasm_reg(str_dup("I3"));;
  -        regs[1] = mk_const(str_dup("5"), 'I');
  -        ins = insINS(interp, unit, ins, "sub", regs, 2);
  -    }
  -    else
  -        ins = set_I_const(interp, unit, ins, 3, next[2] - FIRST_PARAM_REG);
  -
  -    /* Nreg param count in: I4 */
  -    ins = set_I_const(interp, unit, ins, REG_N_PARAM_COUNT,
  -                                            next[REGSET_N] - FIRST_PARAM_REG);
   
   #if 0
       /* TODO method calls */
  @@ -1063,40 +880,11 @@
       ins = insINS(interp, unit, ins, "restoretop", regs, 0);
       /*
        * handle return results
  -     * TODO: overflow
        */
  -    for (i = 0; i < 4; i++)
  -        next[i] = 5;
       n = sub->pcc_sub->nret;
  -    for (i = 0; i < n; i++) {
  -        arg = sub->pcc_sub->ret[i];
  -        if ((sub->pcc_sub->pragma & P_PROTOTYPED) ||
  -                (arg->set == 'P' && next[2] <= LAST_PARAM_REG)) {
  -            for (set = 0; set < REGSET_MAX; set++) {
  -                if (arg->set == regsets[set]) {
  -                    if (arg->reg->color == next[set]) {
  -                        next[set]++;
  -                        break;
  -                    }
  -                    arg->reg->want_regno = next[set];
  -                    sprintf(buf, "%c%d", arg->set, next[set]++);
  -                    reg = mk_pasm_reg(str_dup(buf));
  -                    regs[0] = arg;
  -                    regs[1] = reg;
  -                    ins = insINS(interp, unit, ins, "set", regs, 2);
  -                    sub->pcc_sub->ret[i]->used = reg;
  -                    break;
  -                }
  -            }
  -        }
  -        else {
  -            if (!p3)
  -                p3 = mk_pasm_reg(str_dup("P3"));
  -            regs[0] = arg;
  -            regs[1] = p3;
  -            ins = insINS(interp, unit, ins, "shift", regs, 2);
  -        }
  -    }
  +    proto = 1;  /* XXX how to specify return proto or not */
  +    ins = pcc_get_args(interp, unit, ins, sub->pcc_sub, n,
  +                proto, sub->pcc_sub->ret, 0);
   }
   
   /*
  
  
  
  1.33      +1 -185    parrot/imcc/t/syn/pcc.t
  
  Index: pcc.t
  ===================================================================
  RCS file: /cvs/public/parrot/imcc/t/syn/pcc.t,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -w -r1.32 -r1.33
  --- pcc.t     20 Feb 2004 08:34:22 -0000      1.32
  +++ pcc.t     22 Feb 2004 18:54:14 -0000      1.33
  @@ -1,6 +1,6 @@
   #!perl
   use strict;
  -use TestCompiler tests => 36;
  +use TestCompiler tests => 30;
   
   ##############################
   # Parrot Calling Conventions
  @@ -317,190 +317,6 @@
   back
   OUT
   
  -output_like(<<'CODE', <<'OUT', "wrong param count exception S arg");
  -.sub _main
  -    .local Sub sub
  -    newsub sub, .Sub, _sub
  -    .pcc_begin non_prototyped
  -    .arg $S0
  -    .pcc_call sub
  -    ret:
  -    .pcc_end
  -    print "back\n"
  -    end
  -.end
  -
  -.pcc_sub _sub
  -    .param string k
  -    .param string l
  -    print k
  -    print l
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -CODE
  -/wrong param count/
  -OUT
  -
  -output_like(<<'CODE', <<'OUT', "wrong param count exception P arg");
  -.sub _main
  -    .local Sub sub
  -    newsub sub, .Sub, _sub
  -    .pcc_begin non_prototyped
  -    .arg $P0
  -    .pcc_call sub
  -    ret:
  -    .pcc_end
  -    print "back\n"
  -    end
  -.end
  -
  -.pcc_sub _sub
  -    .param pmc k
  -    .param pmc l
  -    print k
  -    print l
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -CODE
  -/wrong param count/
  -OUT
  -
  -output_like(<<'CODE', <<'OUT', "wrong param count exception, call 2 subs");
  -.sub _main
  -    .local Sub sub
  -    newsub sub, .Sub, _sub
  -    $S0 = "ok 1\n"
  -    $S1 = "ok 2\n"
  -    .pcc_begin non_prototyped
  -    .arg $S0
  -    .arg $S1
  -    .pcc_call sub
  -    ret:
  -    .pcc_end
  -    newsub sub, .Sub, _sub2
  -    .pcc_begin non_prototyped
  -    .arg $S0
  -    .pcc_call sub
  -    ret2:
  -    .pcc_end
  -    print "back\n"
  -    end
  -.end
  -
  -.pcc_sub _sub
  -    .param string k
  -    .param string l
  -    print k
  -    print l
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -
  -.pcc_sub _sub2
  -    .param string k
  -    .param string l
  -    print k
  -    print l
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -CODE
  -/ok 1
  -ok 2
  -wrong param count
  -/
  -OUT
  -
  -
  -output_is(<<'CODE', <<'OUT', "wrong param count exception, catch it");
  -.sub _main
  -    .local Sub ex_handler
  -    newsub ex_handler, .Exception_Handler, _handler
  -    set_eh ex_handler
  -    .local Sub sub
  -    newsub sub, .Sub, _sub
  -    .pcc_begin non_prototyped
  -    .arg $S0
  -    .pcc_call sub
  -    ret:
  -    .pcc_end
  -    print "back\n"
  -    end
  -.end
  -
  -.sub _handler
  -    set S0, P5["_message"]   # P5 is the exception object
  -    eq S0, "wrong param count", ok
  -    print "not "
  -ok:
  -    print "ok\n"
  -    end
  -.end
  -
  -.pcc_sub _sub
  -    .param string k
  -    .param string l
  -    print k
  -    print l
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -CODE
  -ok
  -OUT
  -
  -output_like(<<'CODE', <<'OUT', "wrong param type exception");
  -.sub _main
  -    .local Sub sub
  -    newsub sub, .Sub, _sub
  -    .pcc_begin non_prototyped
  -    .arg $S0
  -    .pcc_call sub
  -    ret:
  -    .pcc_end
  -    print "back\n"
  -    end
  -.end
  -
  -.pcc_sub _sub
  -    .param int k
  -    print k
  -    print "n"
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -CODE
  -/wrong param type/
  -OUT
  -
  -output_like(<<'CODE', <<'OUT', "wrong param type exception - 2 params");
  -.sub _main
  -    .local Sub sub
  -    $S0 = "ok 1\n"
  -    newsub sub, .Sub, _sub
  -    .pcc_begin non_prototyped
  -    .arg $S0
  -    .arg $I0
  -    .pcc_call sub
  -    ret:
  -    .pcc_end
  -    print "back\n"
  -    end
  -.end
  -
  -.pcc_sub _sub
  -    .param string k
  -    .param string l
  -    print k
  -    print l
  -   .pcc_begin_return
  -   .pcc_end_return
  -.end
  -CODE
  -/wrong param type/
  -OUT
   
   ####################
   # coroutine iterator
  
  
  

Reply via email to