Esempio n. 1
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);
}
Esempio n. 2
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();
    }
  }
}
Esempio n. 3
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);
}