// Although the name is EQ this actually // implements EQ, LE and LT - by using the supplied lua function to call. void RaviCodeGenerator::emit_EQ(RaviFunctionDef *def, int A, int B, int C, int j, int jA, llvm::Constant *callee, OpCode opCode, int pc) { // case OP_EQ: { // TValue *rb = RKB(i); // TValue *rc = RKC(i); // Protect( // if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i)) // ci->u.l.savedpc++; // else // donextjump(ci); // ) // } break; emit_debug_trace(def, opCode, pc); // Load pointer to base emit_load_base(def); // Get pointer to register B llvm::Value *regB = emit_gep_register_or_constant(def, B); // Get pointer to register C llvm::Value *regC = emit_gep_register_or_constant(def, C); llvm::Value *result = NULL; switch (opCode) { case OP_RAVI_LT_II: case OP_RAVI_LE_II: case OP_RAVI_EQ_II: { llvm::Instruction *p1 = emit_load_reg_i(def, regB); llvm::Instruction *p2 = emit_load_reg_i(def, regC); switch (opCode) { case OP_RAVI_EQ_II: result = def->builder->CreateICmpEQ(p1, p2, "EQ_II_result"); break; case OP_RAVI_LT_II: result = def->builder->CreateICmpSLT(p1, p2, "LT_II_result"); break; case OP_RAVI_LE_II: result = def->builder->CreateICmpSLE(p1, p2, "LE_II_result"); break; default: assert(0); } result = def->builder->CreateZExt(result, def->types->C_intT, "II_result_int"); } break; case OP_RAVI_LT_FF: case OP_RAVI_LE_FF: case OP_RAVI_EQ_FF: { llvm::Instruction *p1 = emit_load_reg_n(def, regB); llvm::Instruction *p2 = emit_load_reg_n(def, regC); switch (opCode) { case OP_RAVI_EQ_FF: result = def->builder->CreateFCmpOEQ(p1, p2, "EQ_FF_result"); break; case OP_RAVI_LT_FF: result = def->builder->CreateFCmpULT(p1, p2, "LT_FF_result"); break; case OP_RAVI_LE_FF: result = def->builder->CreateFCmpULE(p1, p2, "LE_FF_result"); break; default: assert(0); } result = def->builder->CreateZExt(result, def->types->C_intT, "FF_result_int"); } break; default: // Call luaV_equalobj with register B and C result = CreateCall3(def->builder, callee, def->L, regB, regC); } // Test if result is equal to operand A llvm::Value *result_eq_A = def->builder->CreateICmpEQ( result, llvm::ConstantInt::get(def->types->C_intT, A)); // If result == A then we need to execute the next statement which is a jump llvm::BasicBlock *then_block = llvm::BasicBlock::Create(def->jitState->context(), "if.then", def->f); llvm::BasicBlock *else_block = llvm::BasicBlock::Create(def->jitState->context(), "if.else"); def->builder->CreateCondBr(result_eq_A, then_block, else_block); def->builder->SetInsertPoint(then_block); // if (a > 0) luaF_close(L, ci->u.l.base + a - 1); if (jA > 0) { // jA is the A operand of the Jump instruction // Reload pointer to base as the call to luaV_equalobj() may // have invoked a Lua function and as a result the stack may have // been reallocated - so the previous base pointer could be stale emit_load_base(def); // base + a - 1 llvm::Value *val = emit_gep_register(def, jA - 1); // Call luaF_close CreateCall2(def->builder, def->luaF_closeF, def->L, val); } // Do the jump def->builder->CreateBr(def->jmp_targets[j].jmp1); // Add the else block and make it current so that the next instruction flows // here def->f->getBasicBlockList().push_back(else_block); def->builder->SetInsertPoint(else_block); }
void RaviCodeGenerator::emit_TFORCALL(RaviFunctionDef *def, int A, int B, int C, int j, int jA, int pc) { // case OP_TFORCALL: { // StkId cb = ra + 3; /* call base */ // setobjs2s(L, cb + 2, ra + 2); // setobjs2s(L, cb + 1, ra + 1); // setobjs2s(L, cb, ra); // L->top = cb + 3; /* func. + 2 args (state and index) */ // Protect(luaD_call(L, cb, GETARG_C(i), 1)); // L->top = ci->top; // i = *(ci->u.l.savedpc++); /* go to next instruction */ // ra = RA(i); // lua_assert(GET_OPCODE(i) == OP_TFORLOOP); // goto l_tforloop; // } // case OP_TFORLOOP: { // l_tforloop: // if (!ttisnil(ra + 1)) { /* continue loop? */ // setobjs2s(L, ra, ra + 1); /* save control variable */ // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ // } // } break; bool traced = emit_debug_trace(def, OP_TFORCALL, pc); // Below may invoke metamethod so we set savedpc if (!traced)emit_update_savedpc(def, pc); // Load pointer to base emit_load_base(def); // Get pointer to register A llvm::Value *ra = emit_gep_register(def, A); llvm::Value *ra1 = emit_gep_register(def, A + 1); llvm::Value *ra2 = emit_gep_register(def, A + 2); llvm::Value *cb = emit_gep_register(def, A + 3); llvm::Value *cb1 = emit_gep_register(def, A + 4); llvm::Value *cb2 = emit_gep_register(def, A + 5); emit_assign(def, cb2, ra2); emit_assign(def, cb1, ra1); emit_assign(def, cb, ra); // L->top = cb + 3; /* func. + 2 args (state and index) */ emit_set_L_top_toreg(def, A + 6); // Protect(luaD_call(L, cb, GETARG_C(i))); CreateCall3(def->builder, def->luaD_callF, def->L, cb, def->types->kInt[C]); // reload base emit_load_base(def); // L->top = ci->top; emit_refresh_L_top(def, def->ci_val); ra = emit_gep_register(def, jA); ra1 = emit_gep_register(def, jA + 1); llvm::Value *type = emit_load_type(def, ra1); // Test if type != LUA_TNIL (0) llvm::Value *isnotnil = emit_is_not_value_of_type(def, type, LUA__TNIL, "is.not.nil"); llvm::BasicBlock *then_block = llvm::BasicBlock::Create(def->jitState->context(), "if.not.nil", def->f); llvm::BasicBlock *else_block = llvm::BasicBlock::Create(def->jitState->context(), "if.nil"); def->builder->CreateCondBr(isnotnil, then_block, else_block); def->builder->SetInsertPoint(then_block); emit_assign(def, ra, ra1); // Do the jump def->builder->CreateBr(def->jmp_targets[j].jmp1); // Add the else block and make it current so that the next instruction flows // here def->f->getBasicBlockList().push_back(else_block); def->builder->SetInsertPoint(else_block); }