private static bool PatchTestReg(FuncState fs, int node, int reg) { InstructionPtr pi = GetJumpControl(fs, node); if (pi.Value.GET_OPCODE() != OpCode.OP_TESTSET) { return(false); // cannot patch other instructions } if (reg != NO_REG && reg != pi.Value.GETARG_B()) { pi.Value = pi.Value.SETARG_A(reg); } else { pi.Value = Instruction.CreateABC(OpCode.OP_TEST, pi.Value.GETARG_B(), 0, pi.Value.GETARG_C()); } return(true); }
public static void PatchClose( FuncState fs, int list, int level ) { level++; // argument is +1 to reserve 0 as non-op while( list != NO_JUMP ) { int next = GetJump( fs, list ); var pi = new InstructionPtr( fs.Proto.Code, list );; Utl.Assert( pi.Value.GET_OPCODE() == OpCode.OP_JMP && ( pi.Value.GETARG_A() == 0 || pi.Value.GETARG_A() >= level ) ); pi.Value = pi.Value.SETARG_A( level ); list = next; } }
private static InstructionPtr GetJumpControl( FuncState fs, int pc ) { InstructionPtr pi = new InstructionPtr( fs.Proto.Code, pc ); if( pc >= 1 && TestTMode( (pi-1).Value.GET_OPCODE() )) return (pi-1); else return pi; }
public static void CodeNil( FuncState fs, int from, int n ) { int l = from + n - 1; // last register to set nil if( fs.Pc > fs.LastTarget ) // no jumps to current position? { var previous = new InstructionPtr( fs.Proto.Code, fs.Pc-1 ); if( previous.Value.GET_OPCODE() == OpCode.OP_LOADNIL ) { int pfrom = previous.Value.GETARG_A(); int pl = pfrom + previous.Value.GETARG_B(); // can connect both? if( (pfrom <= from && from <= pl + 1) || (from <= pfrom && pfrom <= l + 1)) { if( pfrom < from ) from = pfrom; // from=min(from,pfrom) if( pl > l ) l = pl; // l=max(l,pl) previous.Value = previous.Value.SETARG_A( from ); previous.Value = previous.Value.SETARG_B( l - from ); return; } } // else go through } // else no optimization CodeABC( fs, OpCode.OP_LOADNIL, from, n-1, 0 ); }
public static int pcRel(InstructionPtr pc, Proto p) { debug_assert(pc.codes == p.code); return(pc.pc - 1); }