예제 #1
0
// 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);
}
예제 #2
0
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);
}