Beispiel #1
0
// Bitwise AND, OR and XOR when both operands are known to be
// integers
void RaviCodeGenerator::emit_BITWISE_BINARY_OP(RaviFunctionDef *def, OpCode op,
                                               int A, int B, int C, int pc) {
  emit_debug_trace(def, op, pc);
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);

  llvm::Value *lhs = emit_load_register_or_constant_i(def, B);
  llvm::Value *rhs = emit_load_register_or_constant_i(def, C);

  llvm::Value *result = NULL;

  switch (op) {
  case OP_RAVI_BAND_II:
    result = def->builder->CreateAnd(lhs, rhs, "OP_RAVI_BAND_II_result");
    break;
  case OP_RAVI_BOR_II:
    result = def->builder->CreateOr(lhs, rhs, "OP_RAVI_BOR_II_result");
    break;
  case OP_RAVI_BXOR_II:
    result = def->builder->CreateXor(lhs, rhs, "OP_RAVI_BXOR_II_result");
    break;
  default:
    fprintf(stderr, "unexpected value of opcode %d\n", (int)op);
    abort();
  }
  emit_store_reg_i_withtype(def, result, ra);
}
Beispiel #2
0
// R(A) := -R(B), integer
// NOT yet used
void RaviCodeGenerator::emit_UNMI(RaviFunctionDef *def, int A, int B, int pc) {
  (void)pc;
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);
  llvm::Value *rb = emit_gep_register_or_constant(def, B);
  llvm::Instruction *lhs = emit_load_reg_i(def, rb);
  llvm::Value *result = def->builder->CreateNeg(lhs, "", false, true);
  emit_store_reg_i_withtype(def, result, ra);
}
Beispiel #3
0
// R(A) := RK(B) - RK(C), float-float
void RaviCodeGenerator::emit_SUBFF(RaviFunctionDef *def, int A, int B, int C,
                                   int pc) {
  emit_debug_trace(def, OP_RAVI_SUBFF, pc);
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);
  llvm::Value *rb = emit_load_register_or_constant_n(def, B);
  llvm::Value *rc = emit_load_register_or_constant_n(def, C);
  llvm::Value *result = def->builder->CreateFSub(rb, rc);
  emit_store_reg_n_withtype(def, result, ra);
}
Beispiel #4
0
//	R(A) := ~R(B); known integer operand
void RaviCodeGenerator::emit_BNOT_I(RaviFunctionDef *def, int A, int B,
                                    int pc) {
  emit_debug_trace(def, OP_RAVI_BNOT_I, pc);
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);
  llvm::Value *lhs = emit_load_register_or_constant_i(def, B);
  llvm::Value *rhs = llvm::ConstantInt::get(def->types->lua_IntegerT, -1);
  llvm::Value *result = def->builder->CreateXor(lhs, rhs, "");
  emit_store_reg_i_withtype(def, result, ra);
}
Beispiel #5
0
void RaviCodeGenerator::emit_TESTSET(RaviFunctionDef *def, int A, int B, int C,
                                     int j, int jA, int pc) {

  //  case OP_TESTSET: {
  //    TValue *rb = RB(i);
  //    if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
  //      ci->u.l.savedpc++;
  //    else {
  //      setobjs2s(L, ra, rb);
  //      donextjump(ci);
  //    }
  //  } break;

  emit_debug_trace(def, OP_TESTSET, pc);
  // Load pointer to base
  emit_load_base(def);

  // Get pointer to register B
  llvm::Value *rb = emit_gep_register(def, B);
  // v = C ? is_false(ra) : !is_false(ra)
  llvm::Value *v = C ? emit_boolean_testfalse(def, rb, false)
                     : emit_boolean_testfalse(def, rb, true);

  // Test NOT v
  llvm::Value *result = def->builder->CreateNot(v);
  // If !v 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, then_block, else_block);
  def->builder->SetInsertPoint(then_block);

  // Get pointer to register A
  llvm::Value *ra = emit_gep_register(def, A);
  emit_assign(def, ra, rb);

  // if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
  if (jA > 0) {
    // jA is the A operand of the Jump instruction

    // 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);
}
Beispiel #6
0
// R(A) := RK(B) + RK(C), int+int
void RaviCodeGenerator::emit_ADDII(RaviFunctionDef *def, int A, int B, int C,
                                   int pc) {
  emit_debug_trace(def, OP_RAVI_ADDII, pc);
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);
  llvm::Value *rb = emit_load_register_or_constant_i(def, B);
  llvm::Value *rc = emit_load_register_or_constant_i(def, C);
  llvm::Value *result =
      def->builder->CreateAdd(rb, rc, "OP_RAVI_ADDII_result", false, true);
  emit_store_reg_i_withtype(def, result, ra);
}
Beispiel #7
0
// R(A) := RK(B) + RK(C), float+int
void RaviCodeGenerator::emit_ADDFI(RaviFunctionDef *def, int A, int B, int C,
                                   int pc) {
  emit_debug_trace(def, OP_RAVI_ADDFI, pc);
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);
  llvm::Value *rb = emit_load_register_or_constant_n(def, B);
  llvm::Value *rc = emit_load_register_or_constant_i(def, C);
  llvm::Value *result = def->builder->CreateFAdd(
      rb, def->builder->CreateSIToFP(rc, def->types->lua_NumberT));
  emit_store_reg_n_withtype(def, result, ra);
}
Beispiel #8
0
void RaviCodeGenerator::emit_NOT(RaviFunctionDef *def, int A, int B, int pc) {
  //  case OP_NOT: {
  //    TValue *rb = RB(i);
  //    int res = l_isfalse(rb);  /* next assignment may change this value */
  //    setbvalue(ra, res);
  //  } break;
  emit_debug_trace(def, OP_NOT, pc);
  emit_load_base(def);
  // Get pointer to register B
  llvm::Value *rb = emit_gep_register(def, B);
  llvm::Value *v = emit_boolean_testfalse(def, rb, false);
  llvm::Value *result = def->builder->CreateZExt(v, def->types->C_intT, "i");
  llvm::Value *ra = emit_gep_register(def, A);
  emit_store_reg_b_withtype(def, result, ra);
}
Beispiel #9
0
void RaviCodeGenerator::emit_BITWISE_SHIFT_OP(RaviFunctionDef *def, OpCode op,
                                              int A, int B, int C, int pc) {
  bool traced = emit_debug_trace(def, op, pc);
  emit_load_base(def);
  llvm::Value *ra = emit_gep_register(def, A);

  // If the RHS is a constant and we know that LHS is
  // and integer then we can optimize the code generation
  if (op == OP_RAVI_SHL_II && ISK(C)) {
    lua_Integer y = def->p->k[INDEXK(C)].value_.i;
    emit_bitwise_shiftl(def, ra, B, y);
  } else if (op == OP_RAVI_SHR_II && ISK(C)) {
    lua_Integer y = def->p->k[INDEXK(C)].value_.i;
    emit_bitwise_shiftl(def, ra, B, -y);
  } else {
    // RHS is not a constant
    llvm::Value *rc = emit_gep_register_or_constant(def, C);
    llvm::Value *rb = emit_gep_register_or_constant(def, B);

    // Since the Lua OP_SHL and OP_SHR bytecodes
    // could invoke metamethods we need to set
    // 'savedpc'
    switch (op) {
    case OP_SHL:
      if (!traced) emit_update_savedpc(def, pc);
    case OP_RAVI_SHL_II:
      CreateCall4(def->builder, def->raviV_op_shlF, def->L, ra, rb, rc);
      break;
    case OP_SHR:
      if (!traced) emit_update_savedpc(def, pc);
    case OP_RAVI_SHR_II:
      CreateCall4(def->builder, def->raviV_op_shrF, def->L, ra, rb, rc);
      break;
    default:
      fprintf(stderr, "unexpected value of opcode %d\n", (int)op);
      abort();
    }
  }
}
Beispiel #10
0
void RaviCodeGenerator::emit_TFORLOOP(RaviFunctionDef *def, int A, int j,
                                      int pc) {
  //  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;

  emit_debug_trace(def, OP_TFORLOOP, 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 *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);
}
Beispiel #11
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);
}
Beispiel #12
0
void RaviCodeGenerator::emit_iFORPREP(RaviFunctionDef *def, int A, int pc,
                                      int step_one, int pc1) {

  RaviBranchDef &forloop_target = def->jmp_targets[pc];

  llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());

  forloop_target.ilimit =
      TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "ilimit");
  if (!step_one) {
    forloop_target.istep =
        TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "istep");
  }
  forloop_target.iidx =
      TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "iidx");

  //    lua_Integer initv = ivalue(init);
  //    setivalue(init, initv - ivalue(pstep));

  emit_debug_trace(def, step_one ? OP_RAVI_FORPREP_I1 : OP_RAVI_FORPREP_IP,
                   pc1);
  // Load pointer to base
  emit_load_base(def);

  //  TValue *init = ra;
  //  TValue *pstep = ra + 2;
  llvm::Value *init = emit_gep_register(def, A);
  llvm::Value *plimit = emit_gep_register(def, A + 1);
  llvm::Value *pstep = nullptr;
  if (!step_one)
    pstep = emit_gep_register(def, A + 2);

  // Get ivalue(pstep)
  llvm::Instruction *limit_ivalue = emit_load_reg_i(def, plimit);
  llvm::Instruction *init_ivalue = emit_load_reg_i(def, init);

  if (!step_one) {
    //    setivalue(init, initv - ivalue(pstep));
    llvm::Instruction *step_ivalue = emit_load_reg_i(def, pstep);
    llvm::Value *idx = def->builder->CreateSub(init_ivalue, step_ivalue,
                                               "initv-pstep.i", false, true);

    // Save idx
    emit_store_local_n(def, idx, forloop_target.iidx);

    // Save step
    emit_store_local_n(def, step_ivalue, forloop_target.istep);
  } else {
    //    setivalue(init, initv - ivalue(pstep));
    llvm::Value *idx = def->builder->CreateSub(
        init_ivalue, def->types->kluaInteger[1], "initv-pstep.i", false, true);

    // Save idx
    emit_store_local_n(def, idx, forloop_target.iidx);
  }

  // Save limit
  emit_store_local_n(def, limit_ivalue, forloop_target.ilimit);

  // We are done so jump to forloop
  lua_assert(def->jmp_targets[pc].jmp1);
  def->builder->CreateBr(def->jmp_targets[pc].jmp1);
}
Beispiel #13
0
void RaviCodeGenerator::emit_FORPREP(RaviFunctionDef *def, int A, int pc,
                                     int pc1) {

  // case OP_FORPREP: {
  //  if (ttisinteger(init) && ttisinteger(pstep) &&
  //    forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
  //    /* all values are integer */
  //    lua_Integer initv = (stopnow ? 0 : ivalue(init));
  //    setivalue(plimit, ilimit);
  //    setivalue(init, initv - ivalue(pstep));
  //  }
  //  else {  /* try making all values floats */
  //    if (!tonumber(plimit, &nlimit))
  //      luaG_runerror(L, "'for' limit must be a number");
  //    setfltvalue(plimit, nlimit);
  //    if (!tonumber(pstep, &nstep))
  //      luaG_runerror(L, "'for' step must be a number");
  //    setfltvalue(pstep, nstep);
  //    if (!tonumber(init, &ninit))
  //      luaG_runerror(L, "'for' initial value must be a number");
  //    setfltvalue(init, luai_numsub(L, ninit, nstep));
  //  }
  //  ci->u.l.savedpc += GETARG_sBx(i);
  //} break;

  emit_debug_trace(def, OP_FORPREP, pc1);
  // Load pointer to base
  emit_load_base(def);

  //  lua_Integer ilimit;
  //  int stopnow;
  //  lua_Number ninit; lua_Number nlimit; lua_Number nstep;
  llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());

  llvm::Value *ilimit =
      TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "ilimit");
  llvm::Value *stopnow =
      TmpB.CreateAlloca(def->types->C_intT, nullptr, "stopnow");
  llvm::Value *nlimit =
      TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nlimit");
  llvm::Value *ninit =
      TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "ninit");
  llvm::Value *nstep =
      TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nstep");

  //  TValue *init = ra;
  //  TValue *plimit = ra + 1;
  //  TValue *pstep = ra + 2;
  llvm::Value *init = emit_gep_register(def, A);
  llvm::Value *plimit = emit_gep_register(def, A + 1);
  llvm::Value *pstep = emit_gep_register(def, A + 2);

  //  if (ttisinteger(init) && ttisinteger(pstep) &&
  //    forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {

  // Get init->tt_
  llvm::Instruction *pinit_tt = emit_load_type(def, init);

  // Compare init->tt_ == LUA_TNUMINT
  llvm::Value *cmp1 =
      emit_is_value_of_type(def, pinit_tt, LUA__TNUMINT, "init.is.integer");

  // Get pstep->tt_
  llvm::Instruction *pstep_tt = emit_load_type(def, pstep);

  // Compare pstep->tt_ == LUA_TNUMINT
  llvm::Value *icmp2 =
      emit_is_value_of_type(def, pstep_tt, LUA__TNUMINT, "step.is.integer");

  // Get ivalue(pstep)
  llvm::Instruction *pstep_ivalue = emit_load_reg_i(def, pstep);

  // Call forlimit()
  llvm::Value *forlimit_ret = CreateCall4(
      def->builder, def->luaV_forlimitF, plimit, ilimit, pstep_ivalue, stopnow);

  // init->tt_ == LUA_TNUMINT && pstep->tt_ == LUA_TNUMINT
  llvm::Value *and1 =
      def->builder->CreateAnd(cmp1, icmp2, "init.and.step.are.integers");

  // Convert result from forlimit() to bool
  llvm::Value *tobool =
      def->builder->CreateICmpNE(forlimit_ret, def->types->kInt[0]);

  // init->tt_ == LUA_TNUMINT && pstep->tt_ == LUA_TNUMINT && forlimit()
  llvm::Value *and2 = def->builder->CreateAnd(and1, tobool, "all.integers");

  // Create if then else branch
  llvm::BasicBlock *then1 = llvm::BasicBlock::Create(def->jitState->context(),
                                                     "if.all.integers", def->f);
  llvm::BasicBlock *else1 =
      llvm::BasicBlock::Create(def->jitState->context(), "if.not.all.integers");
  def->builder->CreateCondBr(and2, then1, else1);
  def->builder->SetInsertPoint(then1);

  //    all values are integers
  //    lua_Integer initv = (stopnow ? 0 : ivalue(init));

  // Get stopnow
  llvm::Instruction *stopnow_val = emit_load_local_int(def, stopnow);

  // Test if stopnow is 0
  llvm::Value *stopnow_is_zero = def->builder->CreateICmpEQ(
      stopnow_val, def->types->kInt[0], "stopnow.is.zero");

  // Setup if then else branch for stopnow
  llvm::BasicBlock *then1_iffalse = llvm::BasicBlock::Create(
      def->jitState->context(), "if.stopnow.iszero", def->f);
  llvm::BasicBlock *then1_iftrue =
      llvm::BasicBlock::Create(def->jitState->context(), "if.stopnow.notzero");
  def->builder->CreateCondBr(stopnow_is_zero, then1_iffalse, then1_iftrue);
  def->builder->SetInsertPoint(then1_iffalse);

  // stopnow is 0
  // Get init->i
  llvm::Instruction *init_ivalue = emit_load_reg_i(def, init);

  // Join after the branch
  def->builder->CreateBr(then1_iftrue);
  def->f->getBasicBlockList().push_back(then1_iftrue);
  def->builder->SetInsertPoint(then1_iftrue);

  // Set initv to 0 if !stopnow else init->i
  auto phi1 = def->builder->CreatePHI(def->types->lua_IntegerT, 2, "initv");
  phi1->addIncoming(init_ivalue, then1_iffalse);
  phi1->addIncoming(def->types->kluaInteger[0], then1);

  //    setivalue(plimit, ilimit);
  llvm::Instruction *ilimit_val = emit_load_local_n(def, ilimit);

  emit_store_reg_i_withtype(def, ilimit_val, plimit);

  //    setivalue(init, initv - ivalue(pstep));
  // we aleady know init is LUA_TNUMINT
  pstep_ivalue = emit_load_reg_i(def, pstep);
  llvm::Value *sub =
      def->builder->CreateSub(phi1, pstep_ivalue, "initv-pstep.i", false, true);

  emit_store_reg_i(def, sub, init);

  // We are done so jump to forloop
  lua_assert(def->jmp_targets[pc].jmp1);
  def->builder->CreateBr(def->jmp_targets[pc].jmp1);

  // NOW the non-integer case

  def->f->getBasicBlockList().push_back(else1);
  def->builder->SetInsertPoint(else1);

  // ************ PLIMIT - Convert plimit to float

  llvm::Instruction *plimit_tt = emit_load_type(def, plimit);
  // Test if already a float
  cmp1 = emit_is_value_of_type(def, plimit_tt, LUA__TNUMFLT, "limit.is.float");
  llvm::BasicBlock *else1_plimit_ifnum = llvm::BasicBlock::Create(
      def->jitState->context(), "if.limit.isfloat", def->f);
  llvm::BasicBlock *else1_plimit_elsenum =
      llvm::BasicBlock::Create(def->jitState->context(), "if.limit.notfloat");
  def->builder->CreateCondBr(cmp1, else1_plimit_ifnum, else1_plimit_elsenum);
  def->builder->SetInsertPoint(else1_plimit_ifnum);

  // Already a float - copy to nlimit
  llvm::Instruction *plimit_nvalue_load = emit_load_reg_n(def, plimit);
  emit_store_local_n(def, plimit_nvalue_load, nlimit);

  // Go to the PSTEP section
  llvm::BasicBlock *else1_pstep =
      llvm::BasicBlock::Create(def->jitState->context(), "if.else.step");
  def->builder->CreateBr(else1_pstep);

  // If plimit was not already a float we need to convert
  def->f->getBasicBlockList().push_back(else1_plimit_elsenum);
  def->builder->SetInsertPoint(else1_plimit_elsenum);
  // Call luaV_tonumber_()
  llvm::Value *plimit_isnum =
      CreateCall2(def->builder, def->luaV_tonumberF, plimit, nlimit);
  llvm::Value *plimit_isnum_bool = def->builder->CreateICmpEQ(
      plimit_isnum, def->types->kInt[0], "limit.float.ok");

  // Did conversion fail?
  llvm::BasicBlock *else1_plimit_tonum_elsenum = llvm::BasicBlock::Create(
      def->jitState->context(), "if.limit.float.failed", def->f);
  def->builder->CreateCondBr(plimit_isnum_bool, else1_plimit_tonum_elsenum,
                             else1_pstep);

  // Conversion failed, so raise error
  def->builder->SetInsertPoint(else1_plimit_tonum_elsenum);
  emit_raise_lua_error(def, "'for' limit must be a number");
  def->builder->CreateBr(else1_pstep);

  // Conversion OK
  // Update plimit
  def->f->getBasicBlockList().push_back(else1_pstep);
  def->builder->SetInsertPoint(else1_pstep);
  llvm::Instruction *nlimit_load = emit_load_local_n(def, nlimit);

  emit_store_reg_n_withtype(def, nlimit_load, plimit);

  // ***********  PSTEP - convert pstep to float
  // Test if already a float
  pstep_tt = emit_load_type(def, pstep);
  cmp1 = emit_is_value_of_type(def, pstep_tt, LUA__TNUMFLT, "step.is.float");
  llvm::BasicBlock *else1_pstep_ifnum = llvm::BasicBlock::Create(
      def->jitState->context(), "if.step.isfloat", def->f);
  llvm::BasicBlock *else1_pstep_elsenum =
      llvm::BasicBlock::Create(def->jitState->context(), "if.step.notfloat");
  def->builder->CreateCondBr(cmp1, else1_pstep_ifnum, else1_pstep_elsenum);
  def->builder->SetInsertPoint(else1_pstep_ifnum);

  // We float then copy to nstep
  llvm::Instruction *pstep_nvalue_load = emit_load_reg_n(def, pstep);
  emit_store_local_n(def, pstep_nvalue_load, nstep);

  // Now go to handle initial value
  llvm::BasicBlock *else1_pinit =
      llvm::BasicBlock::Create(def->jitState->context(), "if.else.init");
  def->builder->CreateBr(else1_pinit);

  // If pstep was not already a float then we need to convert
  def->f->getBasicBlockList().push_back(else1_pstep_elsenum);
  def->builder->SetInsertPoint(else1_pstep_elsenum);

  // call luaV_tonumber_()
  llvm::Value *pstep_isnum =
      CreateCall2(def->builder, def->luaV_tonumberF, pstep, nstep);
  llvm::Value *pstep_isnum_bool = def->builder->CreateICmpEQ(
      pstep_isnum, def->types->kInt[0], "step.float.ok");
  llvm::BasicBlock *else1_pstep_tonum_elsenum = llvm::BasicBlock::Create(
      def->jitState->context(), "if.step.float.failed", def->f);
  def->builder->CreateCondBr(pstep_isnum_bool, else1_pstep_tonum_elsenum,
                             else1_pinit);

  // If conversion failed raise error
  def->builder->SetInsertPoint(else1_pstep_tonum_elsenum);
  emit_raise_lua_error(def, "'for' step must be a number");
  def->builder->CreateBr(else1_pinit);

  // Conversion okay so update pstep
  def->f->getBasicBlockList().push_back(else1_pinit);
  def->builder->SetInsertPoint(else1_pinit);

  llvm::Instruction *nstep_load = emit_load_local_n(def, nstep);

  emit_store_reg_n_withtype(def, nstep_load, pstep);

  // *********** PINIT finally handle initial value

  // Check if it is already a float
  pinit_tt = emit_load_type(def, init);
  cmp1 = emit_is_value_of_type(def, pinit_tt, LUA__TNUMFLT, "init.is.float");
  llvm::BasicBlock *else1_pinit_ifnum = llvm::BasicBlock::Create(
      def->jitState->context(), "if.init.is.float", def->f);
  llvm::BasicBlock *else1_pinit_elsenum =
      llvm::BasicBlock::Create(def->jitState->context(), "if.init.not.float");
  def->builder->CreateCondBr(cmp1, else1_pinit_ifnum, else1_pinit_elsenum);
  def->builder->SetInsertPoint(else1_pinit_ifnum);

  // Already float so copy to ninit
  llvm::Instruction *pinit_nvalue_load = emit_load_reg_n(def, init);
  emit_store_local_n(def, pinit_nvalue_load, ninit);

  // Go to final section
  llvm::BasicBlock *else1_pdone =
      llvm::BasicBlock::Create(def->jitState->context(), "if.else.done");
  def->builder->CreateBr(else1_pdone);

  // Not a float so we need to convert
  def->f->getBasicBlockList().push_back(else1_pinit_elsenum);
  def->builder->SetInsertPoint(else1_pinit_elsenum);

  // Call luaV_tonumber_()
  llvm::Value *pinit_isnum =
      CreateCall2(def->builder, def->luaV_tonumberF, init, ninit);
  llvm::Value *pinit_isnum_bool = def->builder->CreateICmpEQ(
      pinit_isnum, def->types->kInt[0], "init.float.ok");
  llvm::BasicBlock *else1_pinit_tonum_elsenum = llvm::BasicBlock::Create(
      def->jitState->context(), "if.init.float.failed", def->f);
  def->builder->CreateCondBr(pinit_isnum_bool, else1_pinit_tonum_elsenum,
                             else1_pdone);

  // Conversion failed so raise error
  def->builder->SetInsertPoint(else1_pinit_tonum_elsenum);
  emit_raise_lua_error(def, "'for' initial value must be a number");
  def->builder->CreateBr(else1_pdone);

  // Conversion OK so we are nearly done
  def->f->getBasicBlockList().push_back(else1_pdone);
  def->builder->SetInsertPoint(else1_pdone);
  llvm::Instruction *ninit_load = emit_load_local_n(def, ninit);
  nstep_load = emit_load_local_n(def, nstep);

  //    setfltvalue(init, luai_numsub(L, ninit, nstep));
  llvm::Value *init_n =
      def->builder->CreateFSub(ninit_load, nstep_load, "ninit-nstep");

  emit_store_reg_n_withtype(def, init_n, init);

  // Done so jump to forloop
  def->builder->CreateBr(def->jmp_targets[pc].jmp1);
}
Beispiel #14
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);
}