Esempio n. 1
0
llvm::Value* Executor::codegenArrayAt(const Analyzer::BinOper* array_at, const CompilationOptions& co) {
  const auto arr_expr = array_at->get_left_operand();
  const auto idx_expr = array_at->get_right_operand();
  const auto& idx_ti = idx_expr->get_type_info();
  CHECK(idx_ti.is_integer());
  auto idx_lvs = codegen(idx_expr, true, co);
  CHECK_EQ(size_t(1), idx_lvs.size());
  auto idx_lv = idx_lvs.front();
  if (idx_ti.get_logical_size() < 8) {
    idx_lv = cgen_state_->ir_builder_.CreateCast(
        llvm::Instruction::CastOps::SExt, idx_lv, get_int_type(64, cgen_state_->context_));
  }
  const auto& array_ti = arr_expr->get_type_info();
  CHECK(array_ti.is_array());
  const auto& elem_ti = array_ti.get_elem_type();
  const std::string array_at_fname{
      elem_ti.is_fp() ? "array_at_" + std::string(elem_ti.get_type() == kDOUBLE ? "double_checked" : "float_checked")
                      : "array_at_int" + std::to_string(elem_ti.get_logical_size() * 8) + "_t_checked"};
  const auto ret_ty = elem_ti.is_fp() ? (elem_ti.get_type() == kDOUBLE ? llvm::Type::getDoubleTy(cgen_state_->context_)
                                                                       : llvm::Type::getFloatTy(cgen_state_->context_))
                                      : get_int_type(elem_ti.get_logical_size() * 8, cgen_state_->context_);
  const auto arr_lvs = codegen(arr_expr, true, co);
  CHECK_EQ(size_t(1), arr_lvs.size());
  return cgen_state_->emitExternalCall(array_at_fname,
                                       ret_ty,
                                       {arr_lvs.front(),
                                        posArg(arr_expr),
                                        idx_lv,
                                        elem_ti.is_fp() ? static_cast<llvm::Value*>(inlineFpNull(elem_ti))
                                                        : static_cast<llvm::Value*>(inlineIntNull(elem_ti))});
}
Esempio n. 2
0
static struct expr_val cgasm_handle_ptr_cmp(struct cgasm_context *ctx, int tok_tag, struct expr_val lhs, struct expr_val rhs) {
	lhs = cgasm_handle_deref_flag(ctx, lhs);
	rhs = cgasm_handle_deref_flag(ctx, rhs);

	// allow pointer to compare with integer
	if ((lhs.ctype->tag != T_PTR && lhs.ctype->tag != T_INT) || (rhs.ctype->tag != T_PTR && rhs.ctype->tag != T_INT)) {
		panic("pointer required");
	}
	lhs.ctype = get_int_type(); // convert to int type
	rhs.ctype = get_int_type();
	return cgasm_handle_binary_op(ctx, tok_tag, lhs, rhs);
}
Esempio n. 3
0
DexClass* create_merger_class(const DexType* type,
                              const DexType* super_type,
                              const std::vector<DexField*>& merger_fields,
                              const TypeSet& interfaces,
                              bool add_type_tag_field,
                              bool with_default_ctor /* false */) {
  always_assert(type && super_type);
  std::vector<DexField*> fields;

  if (add_type_tag_field) {
    auto type_tag_field = static_cast<DexField*>(DexField::make_field(
        type, DexString::make_string(INTERNAL_TYPE_TAG_FIELD_NAME),
        get_int_type()));
    type_tag_field->make_concrete(ACC_PUBLIC | ACC_FINAL);
    fields.push_back(type_tag_field);
  }

  for (auto f : merger_fields) {
    fields.push_back(f);
  }
  // Put merger class in the same package as super_type.
  auto pkg_name = get_merger_package_name(super_type);
  auto cls = create_class(type, super_type, pkg_name, fields, interfaces,
                          with_default_ctor);
  TRACE(TERA, 3, "  created merger class w/ fields %s \n", SHOW(cls));
  return cls;
}
Esempio n. 4
0
static struct expr_val cgasm_handle_ptr_add(struct cgasm_context *ctx, struct expr_val lhs, struct expr_val rhs) {
	lhs = cgasm_handle_deref_flag(ctx, lhs);
	rhs = cgasm_handle_deref_flag(ctx, rhs);
	assert(lhs.ctype->tag == T_PTR || rhs.ctype->tag == T_PTR);
	if (lhs.ctype->tag == T_PTR && rhs.ctype->tag == T_PTR) {
		panic("add ptr to ptr is not valid");
	}

	if (lhs.ctype->tag != T_PTR) {
		struct expr_val tmp = lhs;
		lhs = rhs;
		rhs = tmp;
	}

	if (!is_integer_type(rhs.ctype)) {
		panic("ptr is only allowed to add with integer type");
	}

	struct type *ptrtype = lhs.ctype;
	struct type *subtype = ptrtype->subtype;

	lhs.ctype = get_int_type(); // convert to int
	struct expr_val res;

	if (subtype->tag != T_VOID && type_get_size(subtype) != 1) {
		rhs = cgasm_handle_binary_op(ctx, TOK_STAR, rhs, int_const_expr_val(type_get_size(subtype)));
	}
	res = cgasm_handle_binary_op(ctx, TOK_ADD, lhs, rhs);

	res = cgasm_handle_deref_flag(ctx, res);

	res.ctype = ptrtype;
	return res;
}
Esempio n. 5
0
std::vector<DexField*> create_merger_fields(
    const DexType* owner, const std::vector<DexField*>& mergeable_fields) {
  std::vector<DexField*> res;
  size_t cnt = 0;
  for (const auto f : mergeable_fields) {
    auto type = f->get_type();
    std::string name;
    if (type == get_byte_type() || type == get_char_type() ||
        type == get_short_type() || type == get_int_type()) {
      type = get_int_type();
      name = "i";
    } else if (type == get_boolean_type()) {
      type = get_boolean_type();
      name = "z";
    } else if (type == get_long_type()) {
      type = get_long_type();
      name = "j";
    } else if (type == get_float_type()) {
      type = get_float_type();
      name = "f";
    } else if (type == get_double_type()) {
      type = get_double_type();
      name = "d";
    } else {
      static DexType* string_type = DexType::make_type("Ljava/lang/String;");
      if (type == string_type) {
        type = string_type;
        name = "s";
      } else {
        char t = type_shorty(type);
        always_assert(t == 'L' || t == '[');
        type = get_object_type();
        name = "l";
      }
    }

    name = name + std::to_string(cnt);
    auto field = static_cast<DexField*>(
        DexField::make_field(owner, DexString::make_string(name), type));
    field->make_concrete(ACC_PUBLIC);
    res.push_back(field);
    cnt++;
  }

  TRACE(TERA, 8, "  created merger fields %d \n", res.size());
  return res;
}
Esempio n. 6
0
void MethodBlock::load_const(Location& loc, int32_t value) {
  always_assert(!loc.is_wide());
  DexInstruction* load = new DexInstruction(OPCODE_CONST_16);
  load->set_dest(reg_num(loc));
  load->set_literal(value);
  loc.type = get_int_type();
  push_instruction(load);
}
Esempio n. 7
0
void MethodBlock::binop_lit8(IROpcode op,
                             const Location& dest,
                             const Location& src,
                             int8_t literal) {
  always_assert(OPCODE_ADD_INT_LIT8 <= op && op <= OPCODE_USHR_INT_LIT8);
  always_assert(dest.type == src.type);
  always_assert(dest.type == get_int_type());
  IRInstruction* insn = new IRInstruction(op);
  insn->set_dest(dest.get_reg());
  insn->set_src(0, src.get_reg());
  insn->set_literal(literal);
  push_instruction(insn);
}
Esempio n. 8
0
static struct expr_val cgasm_handle_ptr_sub(struct cgasm_context *ctx, struct expr_val lhs, struct expr_val rhs) {
	lhs = cgasm_handle_deref_flag(ctx, lhs);
	rhs = cgasm_handle_deref_flag(ctx, rhs);

	if (lhs.ctype->tag == T_PTR && is_integer_type(rhs.ctype)) {
		struct type *oldtype = lhs.ctype;
		struct type *subtype = lhs.ctype->subtype;
		if (subtype->tag != T_VOID && type_get_size(subtype) != 1) {
			panic("non unit ptr");
		}

		lhs.ctype = get_int_type();
		struct expr_val res = cgasm_handle_binary_op(ctx, TOK_SUB, lhs, rhs);
		res = cgasm_handle_deref_flag(ctx, res);
		res.ctype = oldtype;
		return res;
	}

	if (lhs.ctype->tag == T_PTR && rhs.ctype->tag == T_PTR) {
		if (!type_eq(lhs.ctype->subtype, rhs.ctype->subtype)) {
			panic("incompatible pointer types");
		}

		struct type *elem_type = lhs.ctype->subtype;
		lhs.ctype = get_int_type();
		rhs.ctype = get_int_type();
		struct expr_val res = cgasm_handle_binary_op(ctx, TOK_SUB, lhs, rhs);
		int elem_size = type_get_size(elem_type);
		if (elem_type->tag != T_VOID && elem_size != 1) {
			res = cgasm_handle_binary_op(ctx, TOK_DIV, res, int_const_expr_val(elem_size));
		}
		return res;
	}

	panic("invalid ptr subtraction");
}
Esempio n. 9
0
	int get_scaled_double(const paramdsc* v, double& rc)
	{
		ISC_INT64 iv;
		int rct = get_int_type(v, iv);
		if (rct < 0)
			rct = get_double_type(v, rc);
		else
		{
			rc = static_cast<double>(iv);
			int scale = v->dsc_scale;
			for (; scale < 0; ++scale)
				rc /= 10;
			for (; scale > 0; --scale)
				rc *= 10;
		}
		return rct;
	}
Esempio n. 10
0
// Returns the type of a unary expression.
//
// The operand of a unary arithmetic expression (-e, +e, and ~e)
// shall have integer type. The result type the expression is `int`.
//
// The operand of the unary logical expression (!e) shall have 
// boolean type. The result type the expression is `bool`.
Type const*
get_type(Unary_op op, Expr const* e)
{
  Type const* z = get_int_type();
  Type const* b = get_bool_type();
  switch (op) {
    case num_neg_op:
    case num_pos_op: 
    case bit_not_op: 
      return expect_type(e, z, z);
    case log_not_op:
      return expect_type(e, b, b);
    default:
      break;
  }
  lingo_unreachable();
}
Esempio n. 11
0
// Returns the type of a binary expression. 
//
// The operands of a binary arithmetic expression (e1 + e2, e1 - e2,
// e1 * e2, e1 / e2, e1 % e2, e1 & e2, e1 | e2, e1 ^ e2, e1 << e2,
// and e1 >> e2) shall have integer type. The result type the 
// expression is `int`.
//
// The operands of a binary relational expression (e1 < e2, e1 > e2,
// e1 <= e2, e1 >= e2, e1 == e2, and e1 != e2) shall have integer or 
// boolean type. The result type the expression is `bool`.
//
// The operands of a binary logical expression (e1 && e2 and e1 || e2) 
// shall have boolean type. The result type the expression is `bool`.
Type const*
get_type(Binary_op op, Expr const* e1, Expr const* e2)
{
  Type const* z = get_int_type();
  Type const* b = get_bool_type();
  switch (op) {
    case num_add_op:
    case num_sub_op:
    case num_mul_op:
    case num_div_op:
    case num_mod_op:
    case bit_and_op:
    case bit_or_op:
    case bit_xor_op:
    case bit_lsh_op:
    case bit_rsh_op:
      // Arithmetic expressions have integer opreands and results.
      return expect_type(e1, e2, z, z);
    
    case rel_eq_op:
    case rel_ne_op:
    case rel_lt_op:
    case rel_gt_op:
    case rel_le_op:
    case rel_ge_op:
      // Relational expressions have any type and the result
      // is bool.
      return b;
    
    case log_and_op:
    case log_or_op:
      // Logical expressions have boolean operands and result.
      return expect_type(e1, e2, b, b);
    default:
      break;
  }
  lingo_unreachable();
}
Esempio n. 12
0
// Returns the canonical type `int8`.
inline int_type& builder::get_int8_type() { return get_int_type(8); }
Esempio n. 13
0
// Returns the canonical type `int64`.
inline int_type& builder::get_int64_type() { return get_int_type(64); }
Esempio n. 14
0
// Returns the canonical type `int32`.
inline int_type& builder::get_int32_type() { return get_int_type(32); }
Esempio n. 15
0
IntConstant* NodeBuilder::int_const(IInteger c)
{
  return create_int_constant(_suif_env, get_int_type(), c);
}
Esempio n. 16
0
VariableSymbol* NodeBuilder::new_int_var(LString name, bool addr_taken)
{
  return new_var(name, get_int_type());
}
Esempio n. 17
0
Executor::GroupColLLVMValue Executor::groupByColumnCodegen(Analyzer::Expr* group_by_col,
                                                           const size_t col_width,
                                                           const CompilationOptions& co,
                                                           const bool translate_null_val,
                                                           const int64_t translated_null_val,
                                                           GroupByAndAggregate::DiamondCodegen& diamond_codegen,
                                                           std::stack<llvm::BasicBlock*>& array_loops,
                                                           const bool thread_mem_shared) {
#ifdef ENABLE_KEY_COMPACTION
  CHECK_GE(col_width, sizeof(int32_t));
#else
  CHECK_EQ(col_width, sizeof(int64_t));
#endif
  auto group_key = codegen(group_by_col, true, co).front();
  auto key_to_cache = group_key;
  if (dynamic_cast<Analyzer::UOper*>(group_by_col) &&
      static_cast<Analyzer::UOper*>(group_by_col)->get_optype() == kUNNEST) {
    auto preheader = cgen_state_->ir_builder_.GetInsertBlock();
    auto array_loop_head = llvm::BasicBlock::Create(
        cgen_state_->context_, "array_loop_head", cgen_state_->row_func_, preheader->getNextNode());
    diamond_codegen.setFalseTarget(array_loop_head);
    const auto ret_ty = get_int_type(32, cgen_state_->context_);
    auto array_idx_ptr = cgen_state_->ir_builder_.CreateAlloca(ret_ty);
    CHECK(array_idx_ptr);
    cgen_state_->ir_builder_.CreateStore(ll_int(int32_t(0)), array_idx_ptr);
    const auto arr_expr = static_cast<Analyzer::UOper*>(group_by_col)->get_operand();
    const auto& array_ti = arr_expr->get_type_info();
    CHECK(array_ti.is_array());
    const auto& elem_ti = array_ti.get_elem_type();
    auto array_len = cgen_state_->emitExternalCall(
        "array_size", ret_ty, {group_key, posArg(arr_expr), ll_int(log2_bytes(elem_ti.get_logical_size()))});
    cgen_state_->ir_builder_.CreateBr(array_loop_head);
    cgen_state_->ir_builder_.SetInsertPoint(array_loop_head);
    CHECK(array_len);
    auto array_idx = cgen_state_->ir_builder_.CreateLoad(array_idx_ptr);
    auto bound_check = cgen_state_->ir_builder_.CreateICmp(llvm::ICmpInst::ICMP_SLT, array_idx, array_len);
    auto array_loop_body = llvm::BasicBlock::Create(cgen_state_->context_, "array_loop_body", cgen_state_->row_func_);
    cgen_state_->ir_builder_.CreateCondBr(
        bound_check, array_loop_body, array_loops.empty() ? diamond_codegen.orig_cond_false_ : array_loops.top());
    cgen_state_->ir_builder_.SetInsertPoint(array_loop_body);
    cgen_state_->ir_builder_.CreateStore(cgen_state_->ir_builder_.CreateAdd(array_idx, ll_int(int32_t(1))),
                                         array_idx_ptr);
    const auto array_at_fname = "array_at_" + numeric_type_name(elem_ti);
    const auto ar_ret_ty = elem_ti.is_fp()
                               ? (elem_ti.get_type() == kDOUBLE ? llvm::Type::getDoubleTy(cgen_state_->context_)
                                                                : llvm::Type::getFloatTy(cgen_state_->context_))
                               : get_int_type(elem_ti.get_logical_size() * 8, cgen_state_->context_);
    group_key = cgen_state_->emitExternalCall(array_at_fname, ar_ret_ty, {group_key, posArg(arr_expr), array_idx});
    if (need_patch_unnest_double(elem_ti, isArchMaxwell(co.device_type_), thread_mem_shared)) {
      key_to_cache = spillDoubleElement(group_key, ar_ret_ty);
    } else {
      key_to_cache = group_key;
    }
    CHECK(array_loop_head);
    array_loops.push(array_loop_head);
  }
  cgen_state_->group_by_expr_cache_.push_back(key_to_cache);
  llvm::Value* orig_group_key{nullptr};
  if (translate_null_val) {
    const std::string translator_func_name(col_width == sizeof(int32_t) ? "translate_null_key_i32_"
                                                                        : "translate_null_key_");
    const auto& ti = group_by_col->get_type_info();
    const auto key_type = get_int_type(ti.get_logical_size() * 8, cgen_state_->context_);
    orig_group_key = group_key;
    group_key =
        cgen_state_->emitCall(translator_func_name + numeric_type_name(ti),
                              {group_key,
                               static_cast<llvm::Value*>(llvm::ConstantInt::get(key_type, inline_int_null_val(ti))),
                               static_cast<llvm::Value*>(llvm::ConstantInt::get(key_type, translated_null_val))});
  }
  group_key = cgen_state_->ir_builder_.CreateBitCast(castToTypeIn(group_key, col_width * 8),
                                                     get_int_type(col_width * 8, cgen_state_->context_));
  if (orig_group_key) {
    orig_group_key = cgen_state_->ir_builder_.CreateBitCast(castToTypeIn(orig_group_key, col_width * 8),
                                                            get_int_type(col_width * 8, cgen_state_->context_));
  }
  return {group_key, orig_group_key};
}
Esempio n. 18
0
// Returns the canonical type `int16`.
inline int_type& builder::get_int16_type() { return get_int_type(16); }
Esempio n. 19
0
Integer_expr&
Builder::get_int(Integer const& n)
{
  return get_integer(get_int_type(), n);
}