Esempio n. 1
0
//-1 error
//1  tc
//0 normal
//2 retry
int
check_an_msg(ushort flag, uchar * domain, int *bk)
{
    uint get = 0;
    flag = ntohs(flag);
    //printf("flag is 0x%x\n",flag);
    get = GET_QR(flag);
    if (get == QR_Q)            //query
    {
        printf("answer set Q sign\n");
        return -1;
    }
    get = GET_OPCODE(flag);     //ignore.
    get = GET_AA(flag);         //ignore
    get = GET_TC(flag);
    if (get == 1)
        return 1;               //tc
    get = GET_RD(flag);         //ignore
    get = GET_ERROR(flag);
    if ((get != 0) && (get != NAME_ERROR))      //soa
    {
        switch (get) {
        case SERVER_FAIL:
            //printf("2server fail\n");
            break;
            //case NAME_ERROR: SOA
            //*bk = 1;
            //printf("3name error\n");
            //break;
        case FORMAT_ERROR:
            //*bk = 1;
            //printf("1format error\n");
            break;
        case NOT_IMPL:
            //printf("4not implation\n");
            break;
        case REFUSED:
            //printf("5server refused\n");
            break;
        }
        return 2;
    }
    return 0;
}
Esempio n. 2
0
/*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
static int findsetreg (Proto *p, int lastpc, int reg) {
  int pc;
  int setreg = -1;  /* keep last instruction that changed 'reg' */
  int jmptarget = 0;  /* any code before this address is conditional */
  for (pc = 0; pc < lastpc; pc++) {
    Instruction i = p->code[pc];
    OpCode op = GET_OPCODE(i);
    int a = GETARG_A(i);
    switch (op) {
      case OP_LOADNIL: {
        int b = GETARG_B(i);
        if (a <= reg && reg <= a + b)  /* set registers from 'a' to 'a+b' */
          setreg = filterpc(pc, jmptarget);
        break;
      }
      case OP_TFORCALL: {
        if (reg >= a + 2)  /* affect all regs above its base */
          setreg = filterpc(pc, jmptarget);
        break;
      }
      case OP_CALL:
      case OP_TAILCALL: {
        if (reg >= a)  /* affect all registers above base */
          setreg = filterpc(pc, jmptarget);
        break;
      }
      case OP_JMP: {
        int b = GETARG_sBx(i);
        int dest = pc + 1 + b;
        /* jump is forward and do not skip 'lastpc'? */
        if (pc < dest && dest <= lastpc) {
          if (dest > jmptarget)
            jmptarget = dest;  /* update 'jmptarget' */
        }
        break;
      }
      default:
        if (testAMode(op) && reg == a)  /* any instruction that set A */
          setreg = filterpc(pc, jmptarget);
        break;
    }
  }
  return setreg;
}
Esempio n. 3
0
llvm::Value* Logical::PerformIntOp(llvm::Value* a, llvm::Value* b) {
    auto name = "result";
    switch (GET_OPCODE(cs_.instr_)) {
        case OP_BAND:
            return cs_.B_.CreateAnd(a, b, name);
        case OP_BOR:
            return cs_.B_.CreateOr(a, b, name);
        case OP_BXOR:
            return cs_.B_.CreateXor(a, b, name);
        case OP_SHL:
            return cs_.CreateCall("luaV_shiftl", {a, b}, name);
        case OP_SHR:
            return cs_.CreateCall("luaV_shiftl", {a, cs_.B_.CreateNeg(b)}, name);
        default:
            break;
    }
    assert(false);
    return nullptr;
}
Esempio n. 4
0
static void PrintCode(const Proto* tf)
{
 const Instruction* code=tf->code;
 const Instruction* p=code;
 for (;;)
 {
  int at=p-code+1;
  Instruction i=*p;
  int line=luaG_getline(tf->lineinfo,at-1,1,NULL);
  printf("%6d\t",at);
  if (line>=0) printf("[%d]\t",line); else printf("[-]\t");
  switch (GET_OPCODE(i)) {
#include "print.h"
  }
  printf("\n");
  if (i==OP_END) break;
  p++;
 }
}
Esempio n. 5
0
static void luaK_patchlistaux (FuncState *fs, int list, int target,
                               OpCode special, int special_target) {
  Instruction *code = fs->f->code;
  while (list != NO_JUMP) {
    int next = luaK_getjump(fs, list);
    Instruction *i = &code[list];
    OpCode op = GET_OPCODE(*i);
    if (op == special)  /* this `op' already has a value */
      luaK_fixjump(fs, list, special_target);
    else {
      luaK_fixjump(fs, list, target);  /* do the patch */
      if (op == OP_JMPONT)  /* remove eventual values */
        SET_OPCODE(*i, OP_JMPT);
      else if (op == OP_JMPONF)
        SET_OPCODE(*i, OP_JMPF);
    }
    list = next;
  }
}
Esempio n. 6
0
static void
tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs,
                            int nseg, int error)
{

    struct tws_request *req = (struct tws_request *)arg;
    struct tws_softc *sc = req->sc;
    u_int16_t sgls = nseg;
    void *sgl_ptr;
    struct tws_cmd_generic *gcmd;

    if ( error == EFBIG )
        TWS_TRACE(sc, "not enough data segs", 0, nseg);


    if ( req->flags & TWS_DIR_IN )
        bus_dmamap_sync(req->sc->data_tag, req->dma_map,
                                            BUS_DMASYNC_PREREAD);
    if ( req->flags & TWS_DIR_OUT )
        bus_dmamap_sync(req->sc->data_tag, req->dma_map,
                                        BUS_DMASYNC_PREWRITE);
    if ( segs ) {
        if ( (req->type == TWS_PASSTHRU_REQ &&
             GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) !=
                            TWS_FW_CMD_EXECUTE_SCSI) ||
              req->type == TWS_GETSET_PARAM_REQ) {
            gcmd = &req->cmd_pkt->cmd.pkt_g.generic;
            sgl_ptr = (u_int32_t *)(gcmd) + gcmd->size;
            gcmd->size += sgls *
                          ((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 :2 );
            tws_fill_sg_list(req->sc, segs, sgl_ptr, sgls);

        } else {
            tws_fill_sg_list(req->sc, segs,
                      (void *)req->cmd_pkt->cmd.pkt_a.sg_list, sgls);
            req->cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= sgls ;
        }
    }


    req->error_code = tws_submit_command(req->sc, req);

}
Esempio n. 7
0
/*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
static int findsetreg (Proto *p, int lastpc, int reg) {
  int pc;
  int setreg = -1;  /* keep last instruction that changed 'reg' */
  for (pc = 0; pc < lastpc; pc++) {
    Instruction i = p->code[pc];
    OpCode op = GET_OPCODE(i);
    int a = GETARG_A(i);
    switch (op) {
      case OP_LOADNIL: {
        int b = GETARG_B(i);
        if (a <= reg && reg <= a + b)  /* set registers from 'a' to 'a+b' */
          setreg = pc;
        break;
      }
      case OP_TFORCALL: {
        if (reg >= a + 2) setreg = pc;  /* affect all regs above its base */
        break;
      }
      case OP_CALL:
      case OP_TAILCALL: {
        if (reg >= a) setreg = pc;  /* affect all registers above base */
        break;
      }
      case OP_JMP: {
        int b = GETARG_sBx(i);
        int dest = pc + 1 + b;
        /* jump is forward and do not skip `lastpc'? */
        if (pc < dest && dest <= lastpc)
          pc += b;  /* do the jump */
        break;
      }
      case OP_TEST: {
        if (reg == a) setreg = pc;  /* jumped code can change 'a' */
        break;
      }
      default:
        if (testAMode(op) && reg == a)  /* any instruction that set A */
          setreg = pc;
        break;
    }
  }
  return setreg;
}
Esempio n. 8
0
/*
** Create a OP_LOADNIL instruction, but try to optimize: if the previous
** instruction is also OP_LOADNIL and ranges are compatible, adjust
** range of previous instruction instead of emitting a new one. (For
** instance, 'local a; local b' will generate a single opcode.)
*/
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) {  /* previous is LOADNIL? */
      int pfrom = GETARG_A(*previous);  /* get previous range */
      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 */
  }
  luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0);  /* else no optimization */
}
Esempio n. 9
0
llvm::Value* Arith::PerformIntOp(llvm::Value* lhs, llvm::Value* rhs) {
    auto name = "result";
    switch (GET_OPCODE(cs_.instr_)) {
        case OP_ADD:
            return cs_.B_.CreateAdd(lhs, rhs, name);
        case OP_SUB:
            return cs_.B_.CreateSub(lhs, rhs, name);
        case OP_MUL:
            return cs_.B_.CreateMul(lhs, rhs, name);
        case OP_MOD:
            return cs_.CreateCall("luaV_mod", {cs_.values_.state, lhs, rhs},
                    name);
        case OP_IDIV:
            return cs_.CreateCall("luaV_div", {cs_.values_.state, lhs, rhs},
                    name);
        default:
            break;
    }
    assert(false);
    return nullptr;
}
Esempio n. 10
0
void tgVM_exec(tgState* T) {
  tgOpcode op;
  tgValue *base = T->stack;
  for (;;) {
    op = GET_OPCODE(T);
    switch (op) {
      case OP_ADDRR:
        arith_op(T, tgAdd);
        break;
      case OP_SUBRR:
        arith_op(T, tgSub);
        break;
      case OP_MULRR:
        arith_op(T, tgMul);
        break;
      case OP_DIVRR:
        arith_op(T, tgDiv);
        break;
    }
  }
}
Esempio n. 11
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 */
}
Esempio n. 12
0
static void OptConstants(Proto* tf)
{
 Instruction* p;
 int n=tf->nknum+tf->nkstr;
 Hash* map=luaH_new(L,n);
 int m=MapConstants(tf,map);
#ifdef DEBUG
 printf("%p n=%d m=%d %s\n",tf,n,m,(m==n)?"nothing to optimize":"yes!");
#endif
 if (m==n) return;
 for (p=tf->code;; p++)
 {
  Instruction i=*p;
  int op=GET_OPCODE(i);
  switch (op)
  {
   TObject o;
   int j,k;
   case OP_PUSHNUM: case OP_PUSHNEGNUM:
    j=GETARG_U(i);
    ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j];
    k=MapConstant(map,-1,&o);
    if (k!=j) *p=CREATE_U(op,k);
    break;
   case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED:
   case OP_PUSHSELF:   case OP_SETGLOBAL:
    j=GETARG_U(i);
    ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j];
    k=MapConstant(map,-1,&o);
    if (k!=j) *p=CREATE_U(op,k);
    break;
   case OP_END:
    PackConstants(tf,map);
    luaH_free(L,map);
    return;
   default:
    break;
  }
 }
}
Esempio n. 13
0
static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
    if (isLua(ci)) {  /* a Lua function? */
        Proto *p = ci_func(ci)->l.p;
        int pc = currentpc(ci);
        Instruction i;
        *name = luaF_getlocalname(p, stackpos+1, pc);
        if (*name)  /* is a local? */
            return "local";
        i = luaG_symbexec(p, pc, stackpos);  /* try symbolic execution */
        lua_assert(pc != -1);
        switch (GET_OPCODE(i)) {
        case OP_GETGLOBAL: {
            int g = GETARG_Bx(i);  /* global index */
            lua_assert(ttisstring(&p->k[g]));
            *name = svalue(&p->k[g]);
            return "global";
        }
        case OP_MOVE: {
            int a = GETARG_A(i);
            int b = GETARG_B(i);  /* move from `b' to `a' */
            if (b < a)
                return getobjname(ci, b, name);  /* get name for `b' */
            break;
        }
        case OP_GETTABLE: {
            int k = GETARG_C(i);  /* key index */
            *name = kname(p, k);
            return "field";
        }
        case OP_SELF: {
            int k = GETARG_C(i);  /* key index */
            *name = kname(p, k);
            return "method";
        }
        default:
            break;
        }
    }
    return NULL;  /* no useful name found */
}
Esempio n. 14
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;
}
Esempio n. 15
0
File: lcode.c Progetto: 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 */
}
Esempio n. 16
0
File: luac.c Progetto: jcubic/ToME
static void OptConstants(Proto* tf)
{
	Instruction* p;
	int n=tf->nknum+tf->nkstr;
	Hash* map=luaH_new(compile_lua_state,n);
	int m=MapConstants(tf,map);

	if (m==n) return;
	for (p=tf->code;; p++)
	{
		Instruction i=*p;
		int op=GET_OPCODE(i);
		switch (op)
		{
			TObject o;
			int j,k;
		case OP_PUSHNUM: case OP_PUSHNEGNUM:
			j=GETARG_U(i);
			ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j];
			k=MapConstant(map,-1,&o);
			if (k!=j) *p=CREATE_U(op,k);
			break;
		case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED:
		case OP_PUSHSELF:   case OP_SETGLOBAL:
			j=GETARG_U(i);
			ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j];
			k=MapConstant(map,-1,&o);
			if (k!=j) *p=CREATE_U(op,k);
			break;
		case OP_END:
			PackConstants(tf,map);
			luaH_free(compile_lua_state,map);
			return;
		default:
			break;
		}
	}
}
Esempio n. 17
0
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
  TMS tm;
  Proto *p = ci_func(ci)->p;  /* calling function */
  int pc = currentpc(ci);  /* calling instruction index */
  Instruction i = p->code[pc];  /* calling instruction */
  switch (GET_OPCODE(i)) {
    case OP_CALL:
    case OP_TAILCALL:  /* get function name */
      return getobjname(p, pc, GETARG_A(i), name);
    case OP_TFORCALL: {  /* for iterator */
      *name = "for iterator";
       return "for iterator";
    }
    /* all other instructions can call only through metamethods */
    case OP_SELF:
    case OP_GETTABUP:
    case OP_GETTABLE: tm = TM_INDEX; break;
    case OP_SETTABUP:
    case OP_SETTABLE: tm = TM_NEWINDEX; break;
    case OP_EQ: tm = TM_EQ; break;
    case OP_ADD: tm = TM_ADD; break;
    case OP_SUB: tm = TM_SUB; break;
    case OP_MUL: tm = TM_MUL; break;
    case OP_DIV: tm = TM_DIV; break;
    case OP_IDIV: tm = TM_IDIV; break;
    case OP_MOD: tm = TM_MOD; break;
    case OP_POW: tm = TM_POW; break;
    case OP_UNM: tm = TM_UNM; break;
    case OP_LEN: tm = TM_LEN; break;
    case OP_LT: tm = TM_LT; break;
    case OP_LE: tm = TM_LE; break;
    case OP_CONCAT: tm = TM_CONCAT; break;
    default:
      return NULL;  /* else no useful name can be found */
  }
  *name = getstr(G(L)->tmname[tm]);
  return "metamethod";
}
Esempio n. 18
0
File: mrdb.c Progetto: Asmod4n/mruby
static int32_t
check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
{
  struct RClass* c;
  mrb_sym sym;
  int32_t bpno;
  mrb_bool isCfunc;

  mrb_debug_context *dbg = mrb_debug_context_get(mrb);

  isCfunc = FALSE;
  bpno = dbg->method_bpno;
  dbg->method_bpno = 0;

  switch(GET_OPCODE(*pc)) {
    case OP_SEND:
    case OP_SENDB:
      c = mrb_class(mrb, regs[GETARG_A(*pc)]);
      sym = irep->syms[GETARG_B(*pc)];
      break;
    case OP_SUPER:
      c = mrb->c->ci->target_class->super;
      sym = mrb->c->ci->mid;
      break;
    default:
      sym = 0;
      break;
  }
  if(sym != 0) {
    dbg->method_bpno = mrb_debug_check_breakpoint_method(mrb, dbg, c, sym, &isCfunc);
    if(isCfunc) {
      bpno = dbg->method_bpno;
      dbg->method_bpno = 0;
    }
  }
  dbg->isCfunc = isCfunc;
  return bpno;
}
Esempio n. 19
0
const char* getfuncname2 (LuaThread *L, LuaStackFrame *ci, std::string& name) {
  THREAD_CHECK(L);
  TMS tm;
  LuaProto *p = ci->getFunc()->getLClosure()->proto_;  /* calling function */
  int pc = ci->getCurrentPC();  /* calling instruction index */
  Instruction i = p->instructions_[pc];  /* calling instruction */
  switch (GET_OPCODE(i)) {
    case OP_CALL:
    case OP_TAILCALL:  /* get function name */
      return getobjname2(p, pc, GETARG_A(i), name);
    case OP_TFORCALL: {  /* for iterator */
      name = "for iterator";
      return "for iterator";
    }
    /* all other instructions can call only through metamethods */
    case OP_SELF:
    case OP_GETTABUP:
    case OP_GETTABLE: tm = TM_INDEX; break;
    case OP_SETTABUP:
    case OP_SETTABLE: tm = TM_NEWINDEX; break;
    case OP_EQ: tm = TM_EQ; break;
    case OP_ADD: tm = TM_ADD; break;
    case OP_SUB: tm = TM_SUB; break;
    case OP_MUL: tm = TM_MUL; break;
    case OP_DIV: tm = TM_DIV; break;
    case OP_MOD: tm = TM_MOD; break;
    case OP_POW: tm = TM_POW; break;
    case OP_UNM: tm = TM_UNM; break;
    case OP_LEN: tm = TM_LEN; break;
    case OP_LT: tm = TM_LT; break;
    case OP_LE: tm = TM_LE; break;
    case OP_CONCAT: tm = TM_CONCAT; break;
    default:
      return NULL;  /* else no useful name can be found */
  }
  name = G(L)->tagmethod_names_[tm]->c_str();
  return "metamethod";
}
Esempio n. 20
0
llvm::Value* Arith::PerformFloatOp(llvm::Value* lhs, llvm::Value* rhs) {
    auto name = "result";
    switch (GET_OPCODE(cs_.instr_)) {
        case OP_ADD:
            return cs_.B_.CreateFAdd(lhs, rhs, name);
        case OP_SUB:
            return cs_.B_.CreateFSub(lhs, rhs, name);
        case OP_MUL:
            return cs_.B_.CreateFMul(lhs, rhs, name);
        case OP_MOD:
            return cs_.CreateCall("LLLNumMod", {lhs, rhs}, name);
        case OP_POW:
            return cs_.CreateCall(STRINGFY2(l_mathop(pow)), {lhs, rhs}, name);
        case OP_DIV:
            return cs_.B_.CreateFDiv(lhs, rhs, name);
        case OP_IDIV:
            return cs_.CreateCall(STRINGFY2(l_mathop(floor)),
                    {cs_.B_.CreateFDiv(lhs, rhs, name)}, "floor");
        default:
            break;
    }
    assert(false);
    return nullptr;
}
Esempio n. 21
0
static void luaK_patchlistaux (FuncState *fs, int list,
          int ttarget, int treg, int ftarget, int freg, int dtarget) {
  while (list != NO_JUMP) {
    int next = luaK_getjump(fs, list);
    Instruction *i = getjumpcontrol(fs, list);
    if (GET_OPCODE(*i) != OP_TEST) {
      lua_assert(dtarget != NO_JUMP);
      luaK_fixjump(fs, list, dtarget);  /* jump to default target */
    }
    else {
      if (GETARG_C(*i)) {
        lua_assert(ttarget != NO_JUMP);
        patchtestreg(i, treg);
        luaK_fixjump(fs, list, ttarget);
      }
      else {
        lua_assert(ftarget != NO_JUMP);
        patchtestreg(i, freg);
        luaK_fixjump(fs, list, ftarget);
      }
    }
    list = next;
  }
}
Esempio n. 22
0
void luaV_execute (lua_State *L, int nexeccalls) {
  LClosure *cl;
  StkId base;
  TValue *k;
  const Instruction *pc;
 reentry:  /* entry point */
  lua_assert(isLua(L->ci));
  pc = L->savedpc;
  cl = &clvalue(L->ci->func)->l;
  base = L->base;
  k = cl->p->k;
  /* main loop of interpreter */
  for (;;) {
    const Instruction i = *pc++;
    StkId ra;
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
      traceexec(L, pc);
      if (L->status == LUA_YIELD) {  /* did hook yield? */
        L->savedpc = pc - 1;
        return;
      }
      base = L->base;
    }
    /* warning!! several calls may realloc the stack and invalidate `ra' */
    ra = RA(i);
    lua_assert(base == L->base && L->base == L->ci->base);
    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
    switch (GET_OPCODE(i)) {
      case OP_MOVE: {
        setobjs2s(L, ra, RB(i));
        continue;
      }
      case OP_LOADK: {
        setobj2s(L, ra, KBx(i));
        continue;
      }
      case OP_LOADBOOL: {
        setbvalue(ra, GETARG_B(i));
        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
        continue;
      }
      case OP_LOADNIL: {
        TValue *rb = RB(i);
        do {
          setnilvalue(rb--);
        } while (rb >= ra);
        continue;
      }
      case OP_GETUPVAL: {
        int b = GETARG_B(i);
        setobj2s(L, ra, cl->upvals[b]->v);
        continue;
      }
      case OP_GETGLOBAL: {
        TValue g;
        TValue *rb = KBx(i);
        sethvalue(L, &g, cl->env);
        lua_assert(ttisstring(rb));
        Protect(luaV_gettable(L, &g, rb, ra));
        continue;
      }
      case OP_GETTABLE: {
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
        continue;
      }
      case OP_SETGLOBAL: {
        TValue g;
        sethvalue(L, &g, cl->env);
        lua_assert(ttisstring(KBx(i)));
        Protect(luaV_settable(L, &g, KBx(i), ra));
        continue;
      }
      case OP_SETUPVAL: {
        UpVal *uv = cl->upvals[GETARG_B(i)];
        setobj(L, uv->v, ra);
        luaC_barrier(L, uv, ra);
        continue;
      }
      case OP_SETTABLE: {
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
        continue;
      }
      case OP_NEWTABLE: {
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
        Protect(luaC_checkGC(L));
        continue;
      }
      case OP_SELF: {
        StkId rb = RB(i);
        setobjs2s(L, ra+1, rb);
        Protect(luaV_gettable(L, rb, RKC(i), ra));
        continue;
      }
      case OP_ADD: {
        arith_op(luai_numadd, TM_ADD);
        continue;
      }
      case OP_SUB: {
        arith_op(luai_numsub, TM_SUB);
        continue;
      }
      case OP_MUL: {
        arith_op(luai_nummul, TM_MUL);
        continue;
      }
      case OP_DIV: {
        arith_op(luai_numdiv, TM_DIV);
        continue;
      }
      case OP_MOD: {
        arith_op(luai_nummod, TM_MOD);
        continue;
      }
      case OP_POW: {
        arith_op(luai_numpow, TM_POW);
        continue;
      }
      case OP_UNM: {
        TValue *rb = RB(i);
        if (ttisnumber(rb)) {
          lua_Number nb = nvalue(rb);
          setnvalue(ra, luai_numunm(nb));
        }
        else {
          Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
        }
        continue;
      }
      case OP_NOT: {
        int res = l_isfalse(RB(i));  /* next assignment may change this value */
        setbvalue(ra, res);
        continue;
      }
      case OP_LEN: {
        const TValue *rb = RB(i);
        switch (ttype(rb)) {
          case LUA_TTABLE: {
            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
            break;
          }
          case LUA_TSTRING: {
            setnvalue(ra, cast_num(tsvalue(rb)->len));
            break;
          }
          default: {  /* try metamethod */
            Protect(
              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
                luaG_typeerror(L, rb, "get length of");
            )
          }
        }
        continue;
      }
      case OP_CONCAT: {
        int b = GETARG_B(i);
        int c = GETARG_C(i);
        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
        setobjs2s(L, RA(i), base+b);
        continue;
      }
      case OP_JMP: {
        dojump(L, pc, GETARG_sBx(i));
        continue;
      }
      case OP_EQ: {
        TValue *rb = RKB(i);
        TValue *rc = RKC(i);
        Protect(
          if (equalobj(L, rb, rc) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
      case OP_LT: {
        Protect(
          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
      case OP_LE: {
        Protect(
          if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
            dojump(L, pc, GETARG_sBx(*pc));
        )
        pc++;
        continue;
      }
Esempio n. 23
0
File: lvm.c Progetto: uvbs/wx2Server
/*
** Executes the given Lua function. Parameters are between [base,top).
** Returns n such that the the results are between [n,top).
*/
StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
  const Proto *const tf = cl->f.l;
  StkId top;  /* keep top local, for performance */
  const Instruction *pc = tf->code;
  TString **const kstr = tf->kstr;
  const lua_Hook linehook = L->linehook;
  infovalue(base-1)->pc = &pc;
  luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK);
  if (tf->is_vararg)  /* varargs? */
    adjust_varargs(L, base, tf->numparams);
  else
    luaD_adjusttop(L, base, tf->numparams);
  top = L->top;
  /* main loop of interpreter */
  for (;;) {
    const Instruction i = *pc++;
    if (linehook)
      traceexec(L, base, top, linehook);
    switch (GET_OPCODE(i)) {
      case OP_END: {
        L->top = top;
        return top;
      }
      case OP_RETURN: {
        L->top = top;
        return base+GETARG_U(i);
      }
      case OP_CALL: {
        int nres = GETARG_B(i);
        if (nres == MULT_RET) nres = LUA_MULTRET;
        L->top = top;
        luaD_call(L, base+GETARG_A(i), nres);
        top = L->top;
        break;
      }
      case OP_TAILCALL: {
        L->top = top;
        luaD_call(L, base+GETARG_A(i), LUA_MULTRET);
        return base+GETARG_B(i);
      }
      case OP_PUSHNIL: {
        int n = GETARG_U(i);
        LUA_ASSERT(n>0, "invalid argument");
        do {
          ttype(top++) = LUA_TNIL;
        } while (--n > 0);
        break;
      }
      case OP_POP: {
        top -= GETARG_U(i);
        break;
      }
      case OP_PUSHINT: {
        ttype(top) = LUA_TNUMBER;
        nvalue(top) = (Number)GETARG_S(i);
        top++;
        break;
      }
      case OP_PUSHSTRING: {
        ttype(top) = LUA_TSTRING;
        tsvalue(top) = kstr[GETARG_U(i)];
        top++;
        break;
      }
      case OP_PUSHNUM: {
        ttype(top) = LUA_TNUMBER;
        nvalue(top) = tf->knum[GETARG_U(i)];
        top++;
        break;
      }
      case OP_PUSHNEGNUM: {
        ttype(top) = LUA_TNUMBER;
        nvalue(top) = -tf->knum[GETARG_U(i)];
        top++;
        break;
      }
      case OP_PUSHUPVALUE: {
        *top++ = cl->upvalue[GETARG_U(i)];
        break;
      }
      case OP_GETLOCAL: {
        *top++ = *(base+GETARG_U(i));
        break;
      }
      case OP_GETGLOBAL: {
        L->top = top;
        *top = *luaV_getglobal(L, kstr[GETARG_U(i)]);
        top++;
        break;
      }
      case OP_GETTABLE: {
        L->top = top;
        top--;
        *(top-1) = *luaV_gettable(L, top-1);
        break;
      }
      case OP_GETDOTTED: {
        ttype(top) = LUA_TSTRING;
        tsvalue(top) = kstr[GETARG_U(i)];
        L->top = top+1;
        *(top-1) = *luaV_gettable(L, top-1);
        break;
      }
      case OP_GETINDEXED: {
        *top = *(base+GETARG_U(i));
        L->top = top+1;
        *(top-1) = *luaV_gettable(L, top-1);
        break;
      }
      case OP_PUSHSELF: {
        TObject receiver;
        receiver = *(top-1);
        ttype(top) = LUA_TSTRING;
        tsvalue(top++) = kstr[GETARG_U(i)];
        L->top = top;
        *(top-2) = *luaV_gettable(L, top-2);
        *(top-1) = receiver;
        break;
      }
      case OP_CREATETABLE: {
        L->top = top;
        luaC_checkGC(L);
        hvalue(top) = luaH_new(L, GETARG_U(i));
        ttype(top) = LUA_TTABLE;
        top++;
        break;
      }
      case OP_SETLOCAL: {
        *(base+GETARG_U(i)) = *(--top);
        break;
      }
      case OP_SETGLOBAL: {
        L->top = top;
        luaV_setglobal(L, kstr[GETARG_U(i)]);
        top--;
        break;
      }
      case OP_SETTABLE: {
        StkId t = top-GETARG_A(i);
        L->top = top;
        luaV_settable(L, t, t+1);
        top -= GETARG_B(i);  /* pop values */
        break;
      }
      case OP_SETLIST: {
        int aux = GETARG_A(i) * LFIELDS_PER_FLUSH;
        int n = GETARG_B(i);
        Hash *arr = hvalue(top-n-1);
        L->top = top-n;  /* final value of `top' (in case of errors) */
        for (; n; n--)
          *luaH_setint(L, arr, n+aux) = *(--top);
        break;
      }
      case OP_SETMAP: {
        int n = GETARG_U(i);
        StkId finaltop = top-2*n;
        Hash *arr = hvalue(finaltop-1);
        L->top = finaltop;  /* final value of `top' (in case of errors) */
        for (; n; n--) {
          top-=2;
          *luaH_set(L, arr, top) = *(top+1);
        }
        break;
      }
      case OP_ADD: {
        if (tonumber(top-2) || tonumber(top-1))
          call_arith(L, top, TM_ADD);
        else
          nvalue(top-2) += nvalue(top-1);
        top--;
        break;
      }
      case OP_ADDI: {
        if (tonumber(top-1)) {
          ttype(top) = LUA_TNUMBER;
          nvalue(top) = (Number)GETARG_S(i);
          call_arith(L, top+1, TM_ADD);
        }
        else
          nvalue(top-1) += (Number)GETARG_S(i);
        break;
      }
      case OP_SUB: {
        if (tonumber(top-2) || tonumber(top-1))
          call_arith(L, top, TM_SUB);
        else
          nvalue(top-2) -= nvalue(top-1);
        top--;
        break;
      }
      case OP_MULT: {
        if (tonumber(top-2) || tonumber(top-1))
          call_arith(L, top, TM_MUL);
        else
          nvalue(top-2) *= nvalue(top-1);
        top--;
        break;
      }
      case OP_DIV: {
        if (tonumber(top-2) || tonumber(top-1))
          call_arith(L, top, TM_DIV);
        else
          nvalue(top-2) /= nvalue(top-1);
        top--;
        break;
      }
      case OP_POW: {
        if (!call_binTM(L, top, TM_POW))
          lua_error(L, "undefined operation");
        top--;
        break;
      }
      case OP_CONCAT: {
        int n = GETARG_U(i);
        luaV_strconc(L, n, top);
        top -= n-1;
        L->top = top;
        luaC_checkGC(L);
        break;
      }
      case OP_MINUS: {
        if (tonumber(top-1)) {
          ttype(top) = LUA_TNIL;
          call_arith(L, top+1, TM_UNM);
        }
        else
          nvalue(top-1) = -nvalue(top-1);
        break;
      }
      case OP_NOT: {
        ttype(top-1) =
           (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL;
        nvalue(top-1) = 1;
        break;
      }
      case OP_JMPNE: {
        top -= 2;
        if (!luaO_equalObj(top, top+1)) dojump(pc, i);
        break;
      }
      case OP_JMPEQ: {
        top -= 2;
        if (luaO_equalObj(top, top+1)) dojump(pc, i);
        break;
      }
      case OP_JMPLT: {
        top -= 2;
        if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i);
        break;
      }
      case OP_JMPLE: {  /* a <= b  ===  !(b<a) */
        top -= 2;
        if (!luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i);
        break;
      }
      case OP_JMPGT: {  /* a > b  ===  (b<a) */
        top -= 2;
        if (luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i);
        break;
      }
      case OP_JMPGE: {  /* a >= b  ===  !(a<b) */
        top -= 2;
        if (!luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i);
        break;
      }
      case OP_JMPT: {
        if (ttype(--top) != LUA_TNIL) dojump(pc, i);
        break;
      }
      case OP_JMPF: {
        if (ttype(--top) == LUA_TNIL) dojump(pc, i);
        break;
      }
      case OP_JMPONT: {
        if (ttype(top-1) == LUA_TNIL) top--;
        else dojump(pc, i);
        break;
      }
      case OP_JMPONF: {
        if (ttype(top-1) != LUA_TNIL) top--;
        else dojump(pc, i);
        break;
      }
      case OP_JMP: {
        dojump(pc, i);
        break;
      }
      case OP_PUSHNILJMP: {
        ttype(top++) = LUA_TNIL;
        pc++;
        break;
      }
      case OP_FORPREP: {
        if (tonumber(top-1))
          lua_error(L, "`for' step must be a number");
        if (tonumber(top-2))
          lua_error(L, "`for' limit must be a number");
        if (tonumber(top-3))
          lua_error(L, "`for' initial value must be a number");
        if (nvalue(top-1) > 0 ?
            nvalue(top-3) > nvalue(top-2) :
            nvalue(top-3) < nvalue(top-2)) {  /* `empty' loop? */
          top -= 3;  /* remove control variables */
          dojump(pc, i);  /* jump to loop end */
        }
        break;
      }
      case OP_FORLOOP: {
        LUA_ASSERT(ttype(top-1) == LUA_TNUMBER, "invalid step");
        LUA_ASSERT(ttype(top-2) == LUA_TNUMBER, "invalid limit");
        if (ttype(top-3) != LUA_TNUMBER)
          lua_error(L, "`for' index must be a number");
        nvalue(top-3) += nvalue(top-1);  /* increment index */
        if (nvalue(top-1) > 0 ?
            nvalue(top-3) > nvalue(top-2) :
            nvalue(top-3) < nvalue(top-2))
          top -= 3;  /* end loop: remove control variables */
        else
          dojump(pc, i);  /* repeat loop */
        break;
      }
      case OP_LFORPREP: {
        Node *node;
        if (ttype(top-1) != LUA_TTABLE)
          lua_error(L, "`for' table must be a table");
        node = luaH_next(L, hvalue(top-1), &luaO_nilobject);
        if (node == NULL) {  /* `empty' loop? */
          top--;  /* remove table */
          dojump(pc, i);  /* jump to loop end */
        }
        else {
          top += 2;  /* index,value */
          *(top-2) = *key(node);
          *(top-1) = *val(node);
        }
        break;
      }
      case OP_LFORLOOP: {
        Node *node;
        LUA_ASSERT(ttype(top-3) == LUA_TTABLE, "invalid table");
        node = luaH_next(L, hvalue(top-3), top-2);
        if (node == NULL)  /* end loop? */
          top -= 3;  /* remove table, key, and value */
        else {
          *(top-2) = *key(node);
          *(top-1) = *val(node);
          dojump(pc, i);  /* repeat loop */
        }
        break;
      }
      case OP_CLOSURE: {
        L->top = top;
        luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i));
        top = L->top;
        luaC_checkGC(L);
        break;
      }
    }
  }
}
Esempio n. 24
0
File: luac.c Progetto: bysdxt/xLua
static void PrintCode(const Proto* f)
{
 const Instruction* code=f->code;
 int pc,n=f->sizecode;
 for (pc=0; pc<n; pc++)
 {
  Instruction i=code[pc];
  OpCode o=GET_OPCODE(i);
  int a=GETARG_A(i);
  int b=GETARG_B(i);
  int c=GETARG_C(i);
  int ax=GETARG_Ax(i);
  int bx=GETARG_Bx(i);
  int sbx=GETARG_sBx(i);
  int line=getfuncline(f,pc);
  printf("\t%d\t",pc+1);
  if (line>0) printf("[%d]\t",line); else printf("[-]\t");
  printf("%-9s\t",luaP_opnames[o]);
  switch (getOpMode(o))
  {
   case iABC:
    printf("%d",a);
    if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b);
    if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c);
    break;
   case iABx:
    printf("%d",a);
    if (getBMode(o)==OpArgK) printf(" %d",MYK(bx));
    if (getBMode(o)==OpArgU) printf(" %d",bx);
    break;
   case iAsBx:
    printf("%d %d",a,sbx);
    break;
   case iAx:
    printf("%d",MYK(ax));
    break;
  }
  switch (o)
  {
   case OP_LOADK:
    printf("\t; "); PrintConstant(f,bx);
    break;
   case OP_GETUPVAL:
   case OP_SETUPVAL:
    printf("\t; %s",UPVALNAME(b));
    break;
   case OP_GETTABUP:
    printf("\t; %s",UPVALNAME(b));
    if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
    break;
   case OP_SETTABUP:
    printf("\t; %s",UPVALNAME(a));
    if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); }
    if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
    break;
   case OP_GETTABLE:
   case OP_SELF:
    if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
    break;
   case OP_SETTABLE:
   case OP_ADD:
   case OP_SUB:
   case OP_MUL:
   case OP_POW:
   case OP_DIV:
   case OP_IDIV:
   case OP_BAND:
   case OP_BOR:
   case OP_BXOR:
   case OP_SHL:
   case OP_SHR:
   case OP_EQ:
   case OP_LT:
   case OP_LE:
    if (ISK(b) || ISK(c))
    {
     printf("\t; ");
     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
     printf(" ");
     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
    }
    break;
   case OP_JMP:
   case OP_FORLOOP:
   case OP_FORPREP:
   case OP_TFORLOOP:
    printf("\t; to %d",sbx+pc+2);
    break;
   case OP_CLOSURE:
    printf("\t; %p",VOID(f->p[bx]));
    break;
   case OP_SETLIST:
    if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c);
    break;
   case OP_EXTRAARG:
    printf("\t; "); PrintConstant(f,ax);
    break;
   default:
    break;
  }
  printf("\n");
 }
}
Esempio n. 25
0
static Instruction symbexec(const Proto* pt, int lastpc, int reg)
{
	int pc;
	int last;  /* stores position of last instruction that changed `reg' */
	last = pt->sizecode - 1; /* points to final return (a `neutral' instruction) */
	check(precheck(pt));
	for (pc = 0; pc < lastpc; pc++)
	{
		Instruction i = pt->code[pc];
		OpCode op = GET_OPCODE(i);
		int a = GETARG_A(i);
		int b = 0;
		int c = 0;
		check(op < NUM_OPCODES);
		checkreg(pt, a);
		switch (getOpMode(op))
		{
			case iABC:
			{
				b = GETARG_B(i);
				c = GETARG_C(i);
				check(checkArgMode(pt, b, getBMode(op)));
				check(checkArgMode(pt, c, getCMode(op)));
				break;
			}
			case iABx:
			{
				b = GETARG_Bx(i);
				if (getBMode(op) == OpArgK) check(b < pt->sizek);
				break;
			}
			case iAsBx:
			{
				b = GETARG_sBx(i);
				if (getBMode(op) == OpArgR)
				{
					int dest = pc + 1 + b;
					check(0 <= dest && dest < pt->sizecode);
					if (dest > 0)
					{
						int j;
						/* check that it does not jump to a setlist count; this
						   is tricky, because the count from a previous setlist may
						   have the same value of an invalid setlist; so, we must
						   go all the way back to the first of them (if any) */
						for (j = 0; j < dest; j++)
						{
							Instruction d = pt->code[dest - 1 - j];
							if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
						}
						/* if 'j' is even, previous value is not a setlist (even if
						   it looks like one) */
						check((j & 1) == 0);
					}
				}
				break;
			}
		}
		if (testAMode(op))
		{
			if (a == reg) last = pc;	/* change register `a' */
		}
		if (testTMode(op))
		{
			check(pc + 2 < pt->sizecode); /* check skip */
			check(GET_OPCODE(pt->code[pc + 1]) == OP_JMP);
		}
		switch (op)
		{
			case OP_LOADBOOL:
			{
				if (c == 1)    /* does it jump? */
				{
					check(pc + 2 < pt->sizecode); /* check its jump */
					check(GET_OPCODE(pt->code[pc + 1]) != OP_SETLIST ||
					      GETARG_C(pt->code[pc + 1]) != 0);
				}
				break;
			}
			case OP_LOADNIL:
			{
				if (a <= reg && reg <= b)
					last = pc;  /* set registers from `a' to `b' */
				break;
			}
			case OP_GETUPVAL:
			case OP_SETUPVAL:
			{
				check(b < pt->nups);
				break;
			}
			case OP_GETGLOBAL:
			case OP_SETGLOBAL:
			{
				check(ttisstring(&pt->k[b]));
				break;
			}
			case OP_SELF:
			{
				checkreg(pt, a + 1);
				if (reg == a + 1) last = pc;
				break;
			}
			case OP_CONCAT:
			{
				check(b < c);  /* at least two operands */
				break;
			}
			case OP_TFORLOOP:
			{
				check(c >= 1);	/* at least one result (control variable) */
				checkreg(pt, a + 2 + c); /* space for results */
				if (reg >= a + 2) last = pc; /* affect all regs above its base */
				break;
			}
			case OP_FORLOOP:
			case OP_FORPREP:
				checkreg(pt, a + 3);
				/* go through */
			case OP_JMP:
			{
				int dest = pc + 1 + b;
				/* not full check and jump is forward and do not skip `lastpc'? */
				if (reg != NO_REG && pc < dest && dest <= lastpc)
					pc += b;  /* do the jump */
				break;
			}
			case OP_CALL:
			case OP_TAILCALL:
			{
				if (b != 0)
				{
					checkreg(pt, a + b - 1);
				}
				c--;  /* c = num. returns */
				if (c == LUA_MULTRET)
				{
					check(checkopenop(pt, pc));
				}
				else if (c != 0)
					checkreg(pt, a + c - 1);
				if (reg >= a) last = pc;  /* affect all registers above base */
				break;
			}
			case OP_RETURN:
			{
				b--;  /* b = num. returns */
				if (b > 0) checkreg(pt, a + b - 1);
				break;
			}
			case OP_SETLIST:
			{
				if (b > 0) checkreg(pt, a + b);
				if (c == 0)
				{
					pc++;
					check(pc < pt->sizecode - 1);
				}
				break;
			}
			case OP_CLOSURE:
			{
				int nup, j;
				check(b < pt->sizep);
				nup = pt->p[b]->nups;
				check(pc + nup < pt->sizecode);
				for (j = 1; j <= nup; j++)
				{
					OpCode op1 = GET_OPCODE(pt->code[pc + j]);
					check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
				}
				if (reg != NO_REG)  /* tracing? */
					pc += nup;  /* do not 'execute' these pseudo-instructions */
				break;
			}
			case OP_VARARG:
			{
				check((pt->is_vararg & VARARG_ISVARARG) &&
				      !(pt->is_vararg & VARARG_NEEDSARG));
				b--;
				if (b == LUA_MULTRET) check(checkopenop(pt, pc));
				checkreg(pt, a + b - 1);
				break;
			}
			default:
				break;
		}
	}
	return pt->code[last];
}
Esempio n. 26
0
static void PrintCode(const Proto* f)
{
    const Instruction* code=f->code;
    int pc,n=f->sizecode;
    for (pc=0; pc<n; pc++)
    {
        Instruction i=code[pc];
        OpCode o=GET_OPCODE(i);
        int a=GETARG_A(i);
        int b=GETARG_B(i);
        int c=GETARG_C(i);
        int bc=GETARG_Bx(i);
        int sbc=GETARG_sBx(i);
        int line=getline(f,pc);
#if 0
        printf("%0*lX",Sizeof(i)*2,i);
#endif
        printf("\t%d\t",pc+1);
        if (line>0) printf("[%d]\t",line);
        else printf("[-]\t");
        printf("%-9s\t",luaP_opnames[o]);
        switch (getOpMode(o))
        {
        case iABC:
            printf("%d %d %d",a,b,c);
            break;
        case iABx:
            printf("%d %d",a,bc);
            break;
        case iAsBx:
            printf("%d %d",a,sbc);
            break;
        }
        switch (o)
        {
        case OP_LOADK:
            printf("\t; ");
            PrintConstant(f,bc);
            break;
        case OP_GETUPVAL:
        case OP_SETUPVAL:
            printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
            break;
        case OP_GETGLOBAL:
        case OP_SETGLOBAL:
            printf("\t; %s",svalue(&f->k[bc]));
            break;
        case OP_GETTABLE:
        case OP_SELF:
            if (c>=MAXSTACK) {
                printf("\t; ");
                PrintConstant(f,c-MAXSTACK);
            }
            break;
        case OP_SETTABLE:
        case OP_ADD:
        case OP_SUB:
        case OP_MUL:
        case OP_DIV:
        case OP_POW:
        case OP_EQ:
        case OP_LT:
        case OP_LE:
            if (b>=MAXSTACK || c>=MAXSTACK)
            {
                printf("\t; ");
                if (b>=MAXSTACK) PrintConstant(f,b-MAXSTACK);
                else printf("-");
                printf(" ");
                if (c>=MAXSTACK) PrintConstant(f,c-MAXSTACK);
            }
            break;
        case OP_JMP:
        case OP_FORLOOP:
        case OP_TFORPREP:
            printf("\t; to %d",sbc+pc+2);
            break;
        case OP_CLOSURE:
            printf("\t; %p",VOID(f->p[bc]));
            break;
        default:
            break;
        }
        printf("\n");
    }
}
Esempio n. 27
0
static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
  int pc;
  int last;  /* stores position of last instruction that changed `reg' */
  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */
  check(precheck(pt));
  for (pc = 0; pc < lastpc; pc++) {
    Instruction i = pt->code[pc];
    OpCode op = GET_OPCODE(i);
    int a = GETARG_A(i);
    int b = 0;
    int c = 0;
    check(op < NUM_OPCODES);
    checkreg(pt, a);
    switch (getOpMode(op)) {
      case iABC: {
        b = GETARG_B(i);
        c = GETARG_C(i);
        check(checkArgMode(pt, b, getBMode(op)));
        check(checkArgMode(pt, c, getCMode(op)));
        break;
      }
      case iABx: {
        b = GETARG_Bx(i);
        if (getBMode(op) == OpArgK) check(b < pt->sizek);
        break;
      }
      case iAsBx: {
        b = GETARG_sBx(i);
        if (getBMode(op) == OpArgR) {
          int dest = pc+1+b;
          check(0 <= dest && dest < pt->sizecode);
          if (dest > 0) {
            /* cannot jump to a setlist count */
            Instruction d = pt->code[dest-1];
            check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
          }
        }
        break;
      }
    }
    if (testAMode(op)) {
      if (a == reg) last = pc;  /* change register `a' */
    }
    if (testTMode(op)) {
      check(pc+2 < pt->sizecode);  /* check skip */
      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
    }
    switch (op) {
      case OP_LOADBOOL: {
        check(c == 0 || pc+2 < pt->sizecode);  /* check its jump */
        break;
      }
      case OP_LOADNIL: {
        if (a <= reg && reg <= b)
          last = pc;  /* set registers from `a' to `b' */
        break;
      }
      case OP_GETUPVAL:
      case OP_SETUPVAL: {
        check(b < pt->nups);
        break;
      }
      case OP_GETGLOBAL:
      case OP_SETGLOBAL: {
        check(ttisstring(&pt->k[b]));
        break;
      }
      case OP_SELF: {
        checkreg(pt, a+1);
        if (reg == a+1) last = pc;
        break;
      }
      case OP_CONCAT: {
        check(b < c);  /* at least two operands */
        break;
      }
      case OP_TFORLOOP: {
        check(c >= 1);  /* at least one result (control variable) */
        checkreg(pt, a+2+c);  /* space for results */
        if (reg >= a+2) last = pc;  /* affect all regs above its base */
        break;
      }
      case OP_FORLOOP:
      case OP_FORPREP:
        checkreg(pt, a+3);
        /* go through */
      case OP_JMP: {
        int dest = pc+1+b;
        /* not full check and jump is forward and do not skip `lastpc'? */
        if (reg != NO_REG && pc < dest && dest <= lastpc)
          pc += b;  /* do the jump */
        break;
      }
      case OP_CALL:
      case OP_TAILCALL: {
        if (b != 0) {
          checkreg(pt, a+b-1);
        }
        c--;  /* c = num. returns */
        if (c == LUA_MULTRET) {
          check(checkopenop(pt, pc));
        }
        else if (c != 0)
          checkreg(pt, a+c-1);
        if (reg >= a) last = pc;  /* affect all registers above base */
        break;
      }
      case OP_RETURN: {
        b--;  /* b = num. returns */
        if (b > 0) checkreg(pt, a+b-1);
        break;
      }
      case OP_SETLIST: {
        if (b > 0) checkreg(pt, a + b);
        if (c == 0) pc++;
        break;
      }
      case OP_CLOSURE: {
        int nup;
        check(b < pt->sizep);
        nup = pt->p[b]->nups;
        check(pc + nup < pt->sizecode);
        for (; nup>0; nup--) {
          OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
        }
        break;
      }
      case OP_VARARG: {
        check((pt->is_vararg & VARARG_ISVARARG) &&
             !(pt->is_vararg & VARARG_NEEDSARG));
        b--;
        if (b == LUA_MULTRET) check(checkopenop(pt, pc));
        checkreg(pt, a+b-1);
        break;
      }
      default: break;
    }
  }
  return pt->code[last];
}
Esempio n. 28
0
static void PrintCode(const Proto* f)
{
 const Instruction* code=f->code;
 int pc,n=f->sizecode;
 for (pc=0; pc<n; pc++)
 {
  Instruction i=code[pc];
  OpCode o=GET_OPCODE(i);
  int a=GETARG_A(i);
  int b=GETARG_B(i);
  int c=GETARG_C(i);
  int bx=GETARG_Bx(i);
  int sbx=GETARG_sBx(i);
  int line=getline(f,pc);
  printf("\t%d\t",pc+1);
  if (line>0) printf("[%d]\t",line); else printf("[-]\t");
  printf("%-9s\t",luaP_opnames[o]);
  switch (getOpMode(o))
  {
   case iABC:
    printf("%d",a);
    if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
    if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
    break;
   case iABx:
    if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
    break;
   case iAsBx:
    if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
    break;
  }
  switch (o)
  {
   case OP_LOADK:
    printf("\t; "); PrintConstant(f,bx);
    break;
   case OP_GETUPVAL:
   case OP_SETUPVAL:
    printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
    break;
   case OP_GETGLOBAL:
   case OP_SETGLOBAL:
    printf("\t; %s",svalue(&f->k[bx]));
    break;
   case OP_GETTABLE:
   case OP_SELF:
    if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
    break;
   case OP_SETTABLE:
   case OP_ADD:
   case OP_SUB:
   case OP_MUL:
   case OP_DIV:
   case OP_POW:
   case OP_EQ:
   case OP_LT:
   case OP_LE:
    if (ISK(b) || ISK(c))
    {
     printf("\t; ");
     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
     printf(" ");
     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
    }
    break;
   case OP_JMP:
   case OP_FORLOOP:
   case OP_FORPREP:
    printf("\t; to %d",sbx+pc+2);
    break;
   case OP_CLOSURE:
    printf("\t; %p",VOID(f->p[bx]));
    break;
   case OP_SETLIST:
    if (c==0) printf("\t; %d",(int)code[++pc]);
    else printf("\t; %d",c);
    break;
   default:
    break;
  }
  printf("\n");
 }
}
Esempio n. 29
0
int luaU_guess_locals(Proto* f, int main) {
	intArray blocklist;
	LocVarArray locallist;
	int regassign[MAXARG_A+1];
	int regusage[MAXARG_A+1];
	int regblock[MAXARG_A+1];
	int lastfree;
	int i,i2,x,pc;
	int func_endpc = FUNC_BLOCK_END(f);

	if (f->lineinfo != NULL) {
		return 0;
	}

	if (f->sizelocvars > 0) {
		return 0;
	}

	intArray_Init(&blocklist, MAXARG_A+1);
	addi(blocklist, func_endpc);

	LocVarArray_Init(&locallist, MAXARG_A+1);

	lastfree = 0;
	for (i=0; i<f->maxstacksize; i++) {
		regassign[i] = 0;
		regusage[i] = 0;
		regblock[i] = 0;
	}

	// parameters
	for (i = 0; i < f->numparams; i++) {
		add(locallist,0,func_endpc);
		regassign[lastfree] = 0;
		regusage[lastfree] = 1;
		regblock[lastfree] = func_endpc;
		lastfree++;
	}

	// vararg
	if (NEED_ARG(f)) {
		add(locallist,0,func_endpc);
		lastfree++;
		regassign[lastfree] = 0;
		regusage[lastfree] = 1;
		regblock[lastfree] = func_endpc;
		lastfree++;
	}

#if LUA_VERSION_NUM == 501
	// nil optimizations
	{
		Instruction i = f->code[0];
		OpCode o = GET_OPCODE(i);
		int a = GETARG_A(i);
		int b = GETARG_B(i);
		int c = GETARG_C(i);
		int ixx,num_nil = -1;
		switch (o) {
		// read Ra only
		case OP_SETGLOBAL:
		case OP_SETUPVAL:
		case OP_TESTSET:
			num_nil = a;
			break;
		// read Rb only
		case OP_MOVE:
		case OP_UNM:
		case OP_NOT:
		case OP_LEN:
			if (!ISK(b)) {
					num_nil = b;
			}
			break;
		// read Rb and Rc
		case OP_GETTABLE:
		case OP_SETTABLE:
		case OP_SELF:
		case OP_ADD:
		case OP_SUB:
		case OP_MUL:
		case OP_DIV:
		case OP_MOD:
		case OP_POW:
		case OP_EQ:
		case OP_LT:
		case OP_LE:
			if (!ISK(b)) {
				num_nil = b;
			}
			if (!ISK(c)) {
				num_nil = MAX(num_nil, c);
			}
			break;
		case OP_RETURN:
			// read Ra to a+b-2
			// only return 1 value
			// move before return multiple values
			num_nil = MAX(num_nil, a+b-2);
			break;
		}
		for (ixx = lastfree; ixx <= num_nil; ixx++) {
			if (ixx!=num_nil) {
				add(locallist,0,last(blocklist));
				lastfree++;
			}
			regassign[lastfree] = 0;
			regusage[lastfree] = 1;
			regblock[lastfree] = last(blocklist);
			lastfree++;
		}
	}
#endif

	// start code checking
	for (pc = 0; pc < f->sizecode; pc++) {
		Instruction instr = f->code[pc];
		OpCode o = GET_OPCODE(instr);
		int a = GETARG_A(instr);
		int b = GETARG_B(instr);
		int c = GETARG_C(instr);
		int bc = GETARG_Bx(instr);
		int sbc = GETARG_sBx(instr);
		int dest = 0;
		int setreg = -1;
		int setregto = -1;
		int setreg2 = -1;
		int loadreg = -1;
		int loadreg2 = -1;
		int loadreg3 = -1;
		int loadregto = -1;
		int intlocfrom = -1;
		int intlocto = -1;
		if ((o==OP_JMP) || (o==OP_FORPREP)) {
			dest = pc + sbc + 2;
		} else if ((pc+1!=f->sizecode) && (GET_OPCODE(f->code[pc+1])==OP_JMP)) {
			dest = pc + 1 + GETARG_sBx(f->code[pc+1]) + 2;
		}

		// check which registers were read or written to.
		switch (o) {
		case OP_MOVE:
			setreg = a;
			if (b<=a) {
				intlocfrom = b;
				intlocto = b;
			}
			loadreg = b;
			break;
		case OP_UNM:
		case OP_NOT:
		case OP_LEN:
			setreg = a;
			loadreg = b;
			break;
		case OP_LOADNIL:
			setreg = a;
			setregto = b;
			break;
		case OP_LOADK:
#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
		case OP_LOADKX:
#endif
		case OP_GETUPVAL:
#if LUA_VERSION_NUM == 501
		case OP_GETGLOBAL:
#endif
#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
		case OP_GETTABUP:
#endif
		case OP_LOADBOOL:
		case OP_NEWTABLE:
		case OP_CLOSURE:
			setreg = a;
			break;
		case OP_GETTABLE:
			setreg = a;
			loadreg = b;
			if (!ISK(c)) {
				loadreg2 = c;
			}
			break;
#if LUA_VERSION_NUM == 501
		case OP_SETGLOBAL:
#endif
		case OP_SETUPVAL:
			loadreg = a;
			break;
#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
		case OP_SETTABUP:
			if (!ISK(b)) {
				loadreg2 = b;
			}
			if (!ISK(c)) {
				if (loadreg2==-1) {
					loadreg2 = c;
				} else {
					loadreg3 = c;
				}
			}
			break;
#endif
		case OP_SETTABLE:
			loadreg = a;
			if (!ISK(b)) {
				loadreg2 = b;
			}
			if (!ISK(c)) {
				if (loadreg2==-1) {
					loadreg2 = c;
				} else {
					loadreg3 = c;
				}
				if ((a+1!=c) && (c>a)) {
					intlocto = c-1;
				}
			}
			intlocfrom = 0;
			if (a-1>=intlocto) {
				intlocto = a-1;
			}
			break;
		case OP_ADD:
		case OP_SUB:
		case OP_MUL:
		case OP_DIV:
		case OP_POW:
		case OP_MOD:
			setreg = a;
			if (!ISK(b)) {
				loadreg = b;
			}
			if (!ISK(c)) {
				if (loadreg==-1) {
					loadreg = c;
				} else {
					loadreg2 = c;
				}
			}
			break;
		case OP_CONCAT:
			setreg = a;
			loadreg = b;
			loadregto = c;
			break;
		case OP_CALL:
			if (c==0) {
				setreg = a;
				setregto = f->maxstacksize;
			} else if (c>=2) {
				setreg = a;
				setregto = a+c-2;
			} else if (c==1) {
				intlocfrom = 0;
				intlocto = a-1;
			}
			if (b==0) {
				loadreg = a;
				loadregto = f->maxstacksize;
			} else {
				loadreg = a;
				loadregto = a+b-1;
			}
			break;
		case OP_RETURN:
			if (b==0) {
				loadreg = a;
				loadregto = f->maxstacksize;
			} else if (b>=2) {
				loadreg = a;
				loadregto = a+b-2;
			}
			break;
		case OP_TAILCALL:
			if (b==0) {
				loadreg = a;
				loadregto = f->maxstacksize;
			} else {
				loadreg = a;
				loadregto = a+b-1;
			}
			break;
		case OP_VARARG:
			if (b==0) {
				setreg = a;
				setregto = f->maxstacksize;
			} else {
				setreg = a;
				setregto = a+b-1;
			}
			break;
		case OP_SELF:
			setreg = a;
			setregto = a+1;
			loadreg = b;
			if (a>b) {
				intlocfrom = 0;
				intlocto = b;
			}
			if (!ISK(c)) {
				loadreg2 = c;
			}
			break;
		case OP_EQ:
		case OP_LT:
		case OP_LE:
			if (!ISK(b)) {
				loadreg = b;
			}
			if (!ISK(c)) {
				if (loadreg==-1) {
					loadreg = c;
				} else {
					loadreg2 = c;
				}
			}
			break;
		case OP_TEST:
			loadreg = a;
			break;
		case OP_TESTSET: 
			setreg = a;
			loadreg = b;
			break;
		case OP_SETLIST:
			loadreg = a;
			if (b==0) {
				loadregto = f->maxstacksize;
			} else {
				loadregto = a+b;
			}
			break;
		case OP_FORLOOP:
#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
		case OP_TFORCALL:
#endif
		case OP_TFORLOOP:
			break;
		case OP_FORPREP:
			loadreg = a;
			loadregto = a+2;
			setreg = a;
			setregto = a+3;
			intlocfrom = a;
			intlocto = a+3;
			regassign[a] = pc;
			regassign[a+1] = pc;
			regassign[a+2] = pc;
			regassign[a+3] = pc+1;
			regblock[a] = dest;
			regblock[a+1] = dest;
			regblock[a+2] = dest;
			regblock[a+3] = dest-1;

			addi(blocklist, dest-1);
			if (GET_OPCODE(f->code[dest-2])==OP_JMP) {
				last(blocklist)--;
			}
			break;
		case OP_JMP:
			if (GET_OPCODE(f->code[dest-1]) == LUADEC_TFORLOOP) {
				int a = GETARG_A(f->code[dest-1]);
				int c = GETARG_C(f->code[dest-1]);
				setreg = a;
				setregto = a+c+2;
				loadreg = a;
				loadregto = a+2;
				intlocfrom = a;
				intlocto = a+c+2;
				regassign[a] = pc;
				regassign[a+1] = pc;
				regassign[a+2] = pc;
				regblock[a] = dest+1;
				regblock[a+1] = dest+1;
				regblock[a+2] = dest+1;
				for (x=a+3;x<=a+c+2;x++) {
					regassign[x] = pc+1;
					regblock[x] = dest-1;
				}
			}
			if (dest>pc) {
				addi(blocklist, dest-1);
				if (GET_OPCODE(f->code[dest-2])==OP_JMP) {
					last(blocklist)--;
				}
			}
			break;
#if LUA_VERSION_NUM == 501
		case OP_CLOSE:
#endif
#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
		case OP_EXTRAARG:
#endif
		default:
			break;
		}
		
		for (i=1; i<blocklist.size; i++) {
			x = blocklist.values[i];
			i2 = i-1;
			while ((i2>=0) && (blocklist.values[i2]<x)) {
				blocklist.values[i2+1] = blocklist.values[i2];
				i2 = i2-1;
			}
			blocklist.values[i2+1] = x;
		}

		if (loadreg!=-1) {
			if (loadregto==-1)
				loadregto = loadreg;
			for (i=loadreg;i<=loadregto;i++) {
				regusage[i]--;
			}
			if (loadreg2!=-1) regusage[loadreg2]--;
			if (loadreg3!=-1) regusage[loadreg3]--;
		}

		if (setreg!=-1) {
			if (setregto==-1)
				setregto = setreg;
			for (i=setreg;i<=setregto;i++) {
				regusage[i]++;
			}
			if (setreg2!=-1) regusage[setreg2]++;
		}

		i2 = lastfree-1;
		for (i=lastfree; i<f->maxstacksize; i++) {
			if ((regusage[i]<0) || (regusage[i]>1)) {
				i2 = i;
			}
			if ((intlocfrom!=-1) && ((intlocfrom<=i) && (i<=intlocto))) {
				i2 = i;
			}
		}

		for (i=setreg; i<=setregto; i++) {
			if (i>i2) {
				regassign[i] = pc+1;
				regblock[i] = last(blocklist);
			}
		}

		for (i=lastfree; i<=i2; i++) {
			//fprintf(stderr,"%d %d %d %d\n",i,regassign[i],regblock[i],block);
			add(locallist,regassign[i],regblock[i]);
			lastfree++;
		}

		while (blocklist.size > 0 && last(blocklist) <= pc+1) {
			intArray_Pop(&blocklist);
		}
		if (blocklist.size == 0) {
			fprintf(stderr, "cannot find blockend > %d , pc = %d, f->sizecode = %d\n", pc+1, pc, f->sizecode);
		}
		while ((lastfree!=0) && (regblock[lastfree-1] <= pc+1)) {
			lastfree--;
			regusage[lastfree]=0;
		}
	}
	intArray_Clear(&blocklist);

	// print out information
	{
		int length = locallist.size;
		f->sizelocvars = length;
		if (f->sizelocvars>0) {
			f->locvars = luaM_newvector(glstate,f->sizelocvars,LocVar);
			for (i = 0; i < length; i++) {
				char names[10];
				sprintf(names,"l_%d_%d",main,i);
				f->locvars[i].varname = luaS_new(glstate, names);
				f->locvars[i].startpc = locallist.values[i].startpc;
				f->locvars[i].endpc = locallist.values[i].endpc;
			}
		}
	}
	LocVarArray_Clear(&locallist);

	// run with all functions
	for (i=0; i<f->sizep; i++) {
		luaU_guess_locals(f->p[i],main+i+1);
	}
	return 1;
}
Esempio n. 30
0
static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
  int pc;
  int last;  /* stores position of last instruction that changed `reg' */
  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */
  check(precheck(pt));
  for (pc = 0; pc < lastpc; pc++) {
    const Instruction i = pt->code[pc];
    OpCode op = GET_OPCODE(i);
    int a = GETARG_A(i);
    int b = 0;
    int c = 0;
    checkreg(pt, a);
    switch (getOpMode(op)) {
      case iABC: {
        b = GETARG_B(i);
        c = GETARG_C(i);
        if (testOpMode(op, OpModeBreg)) {
          checkreg(pt, b);
        }
        else if (testOpMode(op, OpModeBrk))
          check(checkRK(pt, b));
        if (testOpMode(op, OpModeCrk))
          check(checkRK(pt, c));
        break;
      }
      case iABx: {
        b = GETARG_Bx(i);
        if (testOpMode(op, OpModeK)) check(b < pt->sizek);
        break;
      }
      case iAsBx: {
        b = GETARG_sBx(i);
        break;
      }
    }
    if (testOpMode(op, OpModesetA)) {
      if (a == reg) last = pc;  /* change register `a' */
    }
    if (testOpMode(op, OpModeT)) {
      check(pc+2 < pt->sizecode);  /* check skip */
      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
    }
    switch (op) {
      case OP_LOADBOOL: {
        check(c == 0 || pc+2 < pt->sizecode);  /* check its jump */
        break;
      }
      case OP_LOADNIL: {
        if (a <= reg && reg <= b)
          last = pc;  /* set registers from `a' to `b' */
        break;
      }
      case OP_GETUPVAL:
      case OP_SETUPVAL: {
        check(b < pt->nups);
        break;
      }
      case OP_GETGLOBAL:
      case OP_SETGLOBAL: {
        check(ttisstring(&pt->k[b]));
        break;
      }
      case OP_SELF: {
        checkreg(pt, a+1);
        if (reg == a+1) last = pc;
        break;
      }
      case OP_CONCAT: {
        /* `c' is a register, and at least two operands */
        check(c < MAXSTACK && b < c);
        break;
      }
      case OP_TFORLOOP:
        checkreg(pt, a+c+5);
        if (reg >= a) last = pc;  /* affect all registers above base */
        /* go through */
      case OP_FORLOOP:
        checkreg(pt, a+2);
        /* go through */
      case OP_JMP: {
        int dest = pc+1+b;
	check(0 <= dest && dest < pt->sizecode);
        /* not full check and jump is forward and do not skip `lastpc'? */
        if (reg != NO_REG && pc < dest && dest <= lastpc)
          pc += b;  /* do the jump */
        break;
      }
      case OP_CALL:
      case OP_TAILCALL: {
        if (b != 0) {
          checkreg(pt, a+b-1);
        }
        c--;  /* c = num. returns */
        if (c == LUA_MULTRET) {
          check(checkopenop(pt, pc));
        }
        else if (c != 0)
          checkreg(pt, a+c-1);
        if (reg >= a) last = pc;  /* affect all registers above base */
        break;
      }
      case OP_RETURN: {
        b--;  /* b = num. returns */
        if (b > 0) checkreg(pt, a+b-1);
        break;
      }
      case OP_SETLIST: {
        checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1);
        break;
      }
      case OP_CLOSURE: {
        int nup;
        check(b < pt->sizep);
        nup = pt->p[b]->nups;
        check(pc + nup < pt->sizecode);
        for (; nup>0; nup--) {
          OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
        }
        break;
      }
      default: break;
    }
  }
  return pt->code[last];
}