Exemplo n.º 1
0
Arquivo: code.c Projeto: WeiY/ktap
void codegen_nil(FuncState *fs, int from, int n)
{
	Instruction *previous;
	int l = from + n - 1;  /* last register to set nil */

	if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
		previous = &fs->f->code[fs->pc-1];
		if (GET_OPCODE(*previous) == OP_LOADNIL) {
			int pfrom = GETARG_A(*previous);
			int pl = pfrom + GETARG_B(*previous);

			if ((pfrom <= from && from <= pl + 1) ||
				(from <= pfrom && pfrom <= l + 1)) {  /* can connect both? */
				if (pfrom < from)
					from = pfrom;  /* from = min(from, pfrom) */
				if (pl > l)
					l = pl;  /* l = max(l, pl) */
				SETARG_A(*previous, from);
				SETARG_B(*previous, l - from);
				return;
			}
		}  /* else go through */
	}
	codegen_codeABC(fs, OP_LOADNIL, from, n - 1, 0);  /* else no optimization */
}
Exemplo n.º 2
0
static void constructor (LexState *ls, expdesc *t) {
  /* constructor -> ?? */
  int force_size_na = 0;
  int force_size_nh = 0;
  FuncState *fs = ls->fs;
  int line = ls->linenumber;
  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
  struct ConsControl cc;
  cc.na = cc.nh = cc.tostore = 0;
  cc.t = t;
  init_exp(t, VRELOCABLE, pc);
  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */
  check(ls, '{');
  if (testnext(ls, '&')) {
    if (ls->t.token != TK_NUMBER)
      luaX_syntaxerror(ls, luaO_pushfstring(ls->L, "size expected following & (line %d)", ls->linenumber));
    force_size_nh = (int)ls->t.seminfo.r;
	next(ls);
    if (testnext(ls, '&')) {
      if (ls->t.token != TK_NUMBER)
        luaX_syntaxerror(ls, luaO_pushfstring(ls->L, "size expected following & (line %d)", ls->linenumber));
      force_size_na = (int)ls->t.seminfo.r;
      next(ls);
	}
  }
  do {
    lua_assert(cc.v.k == VVOID || cc.tostore > 0);
    testnext(ls, ';');  /* compatibility only */
    if (ls->t.token == '}') break;
    closelistfield(fs, &cc);
    switch(ls->t.token) {
      case TK_NAME: {  /* may be listfields or recfields */
        lookahead(ls);
        if (ls->lookahead.token != '=')  /* expression? */
          listfield(ls, &cc);
        else
          recfield(ls, &cc);
        break;
      }
      case '[': {  /* constructor_item -> recfield */
        recfield(ls, &cc);
        break;
      }
      default: {  /* constructor_part -> listfield */
        listfield(ls, &cc);
        break;
      }
    }
  } while (testnext(ls, ',') || testnext(ls, ';'));
  check_match(ls, '}', '{', line);
  lastlistfield(fs, &cc);
  if (force_size_na > cc.na)
	cc.na = force_size_na;
  if (force_size_nh > cc.nh)
    cc.nh = force_size_nh;
  if (cc.na > 0)
  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
  SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1);  /* set initial table size */
}
Exemplo n.º 3
0
void luaK_setoneret (FuncState *fs, expdesc *e) {
    if (e->k == VCALL) {  /* expression is an open function call? */
        e->k = VNONRELOC;
        e->u.s.info = GETARG_A(getcode(fs, e));
    } else if (e->k == VVARARG) {
        SETARG_B(getcode(fs, e), 2);
        e->k = VRELOCABLE;  /* can relocate its simple result */
    }
}
Exemplo n.º 4
0
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
    if (e->k == VCALL) {  /* expression is an open function call? */
        SETARG_C(getcode(fs, e), nresults + 1);
    } else if (e->k == VVARARG) {
        SETARG_B(getcode(fs, e), nresults + 1);
        SETARG_A(getcode(fs, e), fs->freereg);
        luaK_reserveregs(fs, 1);
    }
}
Exemplo n.º 5
0
/*
** Fix an expression to return one result.
** If expression is not a multi-ret expression (function call or
** vararg), it already returns one result, so nothing needs to be done.
** Function calls become VNONRELOC expressions (as its result comes
** fixed in the base register of the call), while vararg expressions
** become VRELOCABLE (as OP_VARARG puts its results where it wants).
** (Calls are created returning one result, so that does not need
** to be fixed.)
*/
void luaK_setoneret (FuncState *fs, expdesc *e) {
  if (e->k == VCALL) {  /* expression is an open function call? */
    /* already returns 1 value */
    lua_assert(GETARG_C(getinstruction(fs, e)) == 2);
    e->k = VNONRELOC;  /* result has fixed position */
    e->u.info = GETARG_A(getinstruction(fs, e));
  }
  else if (e->k == VVARARG) {
    SETARG_B(getinstruction(fs, e), 2);
    e->k = VRELOCABLE;  /* can relocate its simple result */
  }
}
Exemplo n.º 6
0
/*
** Fix an expression to return the number of results 'nresults'.
** Either 'e' is a multi-ret expression (function call or vararg)
** or 'nresults' is LUA_MULTRET (as any expression can satisfy that).
*/
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
  if (e->k == VCALL) {  /* expression is an open function call? */
    SETARG_C(getinstruction(fs, e), nresults + 1);
  }
  else if (e->k == VVARARG) {
    Instruction *pc = &getinstruction(fs, e);
    SETARG_B(*pc, nresults + 1);
    SETARG_A(*pc, fs->freereg);
    luaK_reserveregs(fs, 1);
  }
  else lua_assert(nresults == LUA_MULTRET);
}
Exemplo n.º 7
0
Arquivo: lcode.c Projeto: galek/ravi
void luaK_setoneret (FuncState *fs, expdesc *e) {
  if (e->k == VCALL) {  /* expression is an open function call? */
    e->k = VNONRELOC;
    e->u.info = GETARG_A(getcode(fs, e));
    DEBUG_EXPR(raviY_printf(fs, "luaK_setoneret (VCALL->VNONRELOC) %e\n", e));
  }
  else if (e->k == VVARARG) {
    SETARG_B(getcode(fs, e), 2);
    DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set B to 2\n", e->u.info, getcode(fs,e)));
    e->k = VRELOCABLE;  /* can relocate its simple result */
    DEBUG_EXPR(raviY_printf(fs, "luaK_setoneret (VVARARG->VNONRELOC) %e\n", e));
  }
}
Exemplo n.º 8
0
Arquivo: lcode.c Projeto: galek/ravi
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
  if (e->k == VCALL) {  /* expression is an open function call? */
    SETARG_C(getcode(fs, e), nresults+1);
    DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set C to %d\n", e->u.info, getcode(fs,e), nresults+1));
  }
  else if (e->k == VVARARG) {
    SETARG_B(getcode(fs, e), nresults+1);
    DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set B to %d\n", e->u.info, getcode(fs,e), nresults + 1));
    SETARG_A(getcode(fs, e), fs->freereg);
    DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set A to %d\n", e->u.info, getcode(fs,e), fs->freereg));
    luaK_reserveregs(fs, 1);
  }
}
Exemplo n.º 9
0
void luaK_nil (FuncState *fs, int from, int n) {
  Instruction *previous;
  if (fs->pc > fs->lasttarget &&  /* no jumps to current position? */
      GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) {
    int pfrom = GETARG_A(*previous);
    int pto = GETARG_B(*previous);
    if (pfrom <= from && from <= pto+1) {  /* can connect both? */
      if (from+n-1 > pto)
        SETARG_B(*previous, from+n-1);
      return;
    }
  }
  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
}
Exemplo n.º 10
0
void luaK_posfix (FuncState *fs, BinOpr op,
                  expdesc *e1, expdesc *e2, int line) {
  switch (op) {
    case OPR_AND: {
      lua_assert(e1->t == NO_JUMP);  /* list must be closed */
      luaK_dischargevars(fs, e2);
      luaK_concat(fs, &e2->f, e1->f);
      *e1 = *e2;
      break;
    }
    case OPR_OR: {
      lua_assert(e1->f == NO_JUMP);  /* list must be closed */
      luaK_dischargevars(fs, e2);
      luaK_concat(fs, &e2->t, e1->t);
      *e1 = *e2;
      break;
    }
    case OPR_CONCAT: {
      luaK_exp2val(fs, e2);
      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
        lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
        freeexp(fs, e1);
        SETARG_B(getcode(fs, e2), e1->u.info);
        e1->k = VRELOCABLE; e1->u.info = e2->u.info;
      }
      else {
        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
        codearith(fs, OP_CONCAT, e1, e2, line);
      }
      break;
    }
    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
    case OPR_IDIV: case OPR_MOD: case OPR_POW:
    case OPR_BAND: case OPR_BOR: case OPR_BXOR:
    case OPR_SHL: case OPR_SHR: {
      codearith(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line);
      break;
    }
    case OPR_EQ: case OPR_LT: case OPR_LE: {
      codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
      break;
    }
    case OPR_NE: case OPR_GT: case OPR_GE: {
      codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
      break;
    }
    default: lua_assert(0);
  }
}
Exemplo n.º 11
0
static void constructor(LexState* ls, expdesc* t)
{
	/* constructor -> ?? */
	FuncState* fs = ls->fs;
	int line = ls->linenumber;
	int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
	struct ConsControl cc;
	cc.na = cc.nh = cc.tostore = 0;
	cc.t = t;
	init_exp(t, VRELOCABLE, pc);
	init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
	luaK_exp2nextreg(ls->fs, t);	/* fix it at stack top (for gc) */
	checknext(ls, '{');
	do
	{
		lua_assert(cc.v.k == VVOID || cc.tostore > 0);
		if (ls->t.token == '}') break;
		closelistfield(fs, &cc);
		switch (ls->t.token)
		{
			case TK_NAME:	 /* may be listfields or recfields */
			{
				luaX_lookahead(ls);
				if (ls->lookahead.token != '=')	 /* expression? */
					listfield(ls, &cc);
				else
					recfield(ls, &cc);
				break;
			}
			case '[':    /* constructor_item -> recfield */
			{
				recfield(ls, &cc);
				break;
			}
			default:    /* constructor_part -> listfield */
			{
				listfield(ls, &cc);
				break;
			}
		}
	}
	while (testnext(ls, ',') || testnext(ls, ';'));
	check_match(ls, '}', '{', line);
	lastlistfield(fs, &cc);
	SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
	SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));	/* set initial table size */
}
Exemplo n.º 12
0
void luaK_nil (FuncState *fs, int from, int n) {
    Instruction *previous;
    if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
        if (fs->pc == 0) {  /* function start? */
            if (from >= fs->nactvar)
                return;  /* positions are already clean */
        } else {
            previous = &fs->f->code[fs->pc - 1];
            if (GET_OPCODE(*previous) == OP_LOADNIL) {
                int pfrom = GETARG_A(*previous);
                int pto = GETARG_B(*previous);
                if (pfrom <= from && from <= pto + 1) { /* can connect both? */
                    if (from + n - 1 > pto)
                        SETARG_B(*previous, from + n - 1);
                    return;
                }
            }
        }
    }
    luaK_codeABC(fs, OP_LOADNIL, from, from + n - 1, 0); /* else no optimization */
}
Exemplo n.º 13
0
TrCallSite *TrVM::lookup(TrBlock *b, OBJ receiver, OBJ msg, TrInst *ip)
{
   TrVM *vm = this;
   
   OBJ method = TrObject_method(this, receiver, msg);
   
   TrInst *boing = (ip - 1);
   /* TODO: do not prealloc TrCallSite here, every one is a memory leak and a new
    one is created on polymorphic calls. */
   b->sites.emplace_back();
   TrCallSite *s = &b->sites.back();
   s->klass = TR_CLASS(receiver);
   s->miss = 0;
   s->method = method;
   s->message = msg;
   if (unlikely(method == TR_NIL))
   {
      s->method = TrObject_method(this, receiver, tr_intern("method_missing"));
      s->method_missing = 1;
   }
   
   /* Implement Monomorphic method cache by replacing the previous instruction (BOING)
    w/ CACHE that uses the CallSite to find the method instead of doing a full lookup. */
   if (GET_OPCODE(*boing) == TR_OP_CACHE)
   {
      /* Existing call site */
      /* TODO: maybe take existing call site hit miss into consideration to replace it with this one.
       For now, we just don't replace it, the first one is always the cached one. */
   }
   else
   {
      /* New call site, we cache it fo shizzly! */
      SET_OPCODE(*boing, TR_OP_CACHE);
      SETARG_A(*boing, GETARG_A(*ip)); /* receiver register */
      SETARG_B(*boing, 1); /* jmp */
      SETARG_C(*boing, b->sites.size()-1); /* CallSite index */
   }
   
   return s;
}
Exemplo n.º 14
0
Arquivo: lcode.c Projeto: galek/ravi
/* Emit bytecode to set a range of registers to nil. */
void luaK_nil (FuncState *fs, int from, int n) {
  Instruction *previous;
  int l = from + n - 1;  /* last register to set nil */
  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
    previous = &fs->f->code[fs->pc-1];
    if (GET_OPCODE(*previous) == OP_LOADNIL) { /* Try to merge with the previous instruction. */
      int pfrom = GETARG_A(*previous);
      int pl = pfrom + GETARG_B(*previous);
      if ((pfrom <= from && from <= pl + 1) ||
          (from <= pfrom && pfrom <= l + 1)) {  /* can connect both? */
        if (pfrom < from) from = pfrom;  /* from = min(from, pfrom) */
        if (pl > l) l = pl;  /* l = max(l, pl) */
        SETARG_A(*previous, from);
        DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set A to %d\n", fs->pc - 1, *previous, from));
        SETARG_B(*previous, l - from);
        DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set B to %d\n", fs->pc - 1, *previous, (l - from)));
        return;
      }
    }  /* else go through */
  }
  luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0);  /* else no optimization */
}
Exemplo n.º 15
0
static void constructor (LexState *ls, expdesc *t) {
  /* constructor -> ?? */
  FuncState *fs = ls->fs;
  int line = ls->linenumber;
  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
  struct ConsControl cc;
  cc.na = cc.nh = cc.tostore = 0;
  cc.t = t;
  init_exp(t, VRELOCABLE, pc);
  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */
  checknext(ls, '{');
#if LUA_OPTIONAL_COMMA
  for (;;) {
#else
  do {
#endif /* LUA_OPTIONAL_COMMA */
    lua_assert(cc.v.k == VVOID || cc.tostore > 0);
    if (ls->t.token == '}') break;
    closelistfield(fs, &cc);
    switch(ls->t.token) {
      case TK_NAME: {  /* may be listfields or recfields */
        luaX_lookahead(ls);
        if (ls->lookahead.token != '=')  /* expression? */
          listfield(ls, &cc);
        else
          recfield(ls, &cc);
        break;
      }
      case '[': {  /* constructor_item -> recfield */
        recfield(ls, &cc);
        break;
      }
      default: {  /* constructor_part -> listfield */
        listfield(ls, &cc);
        break;
      }
    }
#if LUA_OPTIONAL_COMMA
	if (ls->t.token == ',' || ls->t.token == ';')
		next(ls);
	else if (ls->t.token == '}')
		break;
  }
#else
  } while (testnext(ls, ',') || testnext(ls, ';'));
#endif /* LUA_OPTIONAL_COMMA */
  check_match(ls, '}', '{', line);
  lastlistfield(fs, &cc);
  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */
}

/* }====================================================================== */



static void parlist (LexState *ls) {
  /* parlist -> [ param { `,' param } ] */
  FuncState *fs = ls->fs;
  Proto *f = fs->f;
  int nparams = 0;
  f->is_vararg = 0;
  if (ls->t.token != ')') {  /* is `parlist' not empty? */
    do {
      switch (ls->t.token) {
        case TK_NAME: {  /* param -> NAME */
          new_localvar(ls, str_checkname(ls), nparams++);
          break;
        }
        case TK_DOTS: {  /* param -> `...' */
          luaX_next(ls);
#if defined(LUA_COMPAT_VARARG)
          /* use `arg' as default name */
          new_localvarliteral(ls, "arg", nparams++);
          f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
#endif
          f->is_vararg |= VARARG_ISVARARG;
          break;
        }
        default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
      }
    } while (!f->is_vararg && testnext(ls, ','));
  }
  adjustlocalvars(ls, nparams);
  f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */
}
Exemplo n.º 16
0
void luaK_setcallreturns (FuncState *fs, int nresults) {
  if (luaK_lastisopen(fs)) {  /* expression is an open function call? */
    SETARG_B(fs->f->code[fs->pc-1], nresults);  /* set number of results */
    luaK_deltastack(fs, nresults);  /* push results */
  }
}