Exemple #1
0
Expr*
Parser::on_bool(Token tok)
{
  Type const* t = get_boolean_type();
  int v = tok.boolean_symbol()->value();
  return init<Literal_expr>(tok.location(), t, v);
}
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;
}
Exemple #3
0
void
Elaborator::elaborate(While_stmt* s)
{
  Expr* c = require_converted(*this, s->first, get_boolean_type());
  if (!c)
    throw Type_error({}, "loop condition does not have type 'bool'");
  elaborate(s->body());
}
Exemple #4
0
// The condition must must be a boolean expression.
void
Elaborator::elaborate(If_else_stmt* s)
{
  Expr* c = require_converted(*this, s->first, get_boolean_type());
  if (!c)
    throw Type_error({}, "if condition does not have type 'bool'");
  elaborate(s->true_branch());
  elaborate(s->false_branch());
}
Exemple #5
0
void MethodBlock::instance_of(Location& obj, Location& dst, DexType* type) {
  always_assert(obj.is_ref());
  always_assert(dst.type == get_boolean_type());
  IRInstruction* insn = new IRInstruction(OPCODE_INSTANCE_OF);
  insn->set_src(0, obj.get_reg());
  insn->set_type(type);
  push_instruction(insn);
  push_instruction(
      (new IRInstruction(IOPCODE_MOVE_RESULT_PSEUDO))->set_dest(dst.get_reg()));
}
Exemple #6
0
Expr*
Elaborator::elaborate(Literal_expr* e)
{
  if (is<Boolean_sym>(e->symbol()))
    e->type(get_boolean_type());
  else if (is<Integer_sym>(e->symbol()))
    e->type(get_integer_type());
  else
    throw std::runtime_error("untyped literal");
  return e;
}
Exemple #7
0
// Return the value corresponding to a literal expression.
llvm::Value*
Generator::gen(Literal_expr const* e)
{
  // TODO: Write better type queries.
  //
  // TODO: Write a better interface for values.
  Value v = evaluate(e);
  if (e->type() == get_boolean_type())
    return build.getInt1(v.get_integer());
  if (e->type() == get_integer_type())
    return build.getInt32(v.get_integer());
  else
    throw std::runtime_error("cannot generate function literal");
}
Exemple #8
0
// Parse a primary type.
//
//    primary-type -> 'bool'
//                  | 'int'
//                  | 'char'
//                  | id-type
//                  | function-type
//
//    function-type -> '(' type-list ')' '->' type
//
//    type-list -> type | type-list ',' type
Type const*
Parser::primary_type()
{
  // id-type
  if (Token tok = match_if(identifier_tok))
    return on_id_type(tok);

  // bool
  if (match_if(bool_kw))
    return get_boolean_type();

  // char
  if (match_if(char_kw))
    return get_character_type();

  // int
  else if (match_if(int_kw))
    return get_integer_type();

  // function-type
  else if (match_if(lparen_tok)) {
    Type_seq ts;
    while (true) {
      ts.push_back(type());
      if (match_if(comma_tok))
        continue;
      else
        break;
    }
    match(rparen_tok);
    match(arrow_tok);
    Type const* t = type();
    return on_function_type(ts, t);
  }

  // error
  //
  // TODO: Make this a little less vague.
  else
    error("invalid type");
}
Exemple #9
0
// Return the value corresponding to a literal expression.
llvm::Value*
Generator::gen(Literal_expr const* e)
{
  // TODO: Write better type queries.
  //
  // TODO: Write a better interface for values.
  Value v = evaluate(e);
  Type const* t = e->type();
  if (t == get_boolean_type())
    return build.getInt1(v.get_integer());
  if (t == get_character_type())
    return build.getInt8(v.get_integer());
  if (t == get_integer_type())
    return build.getInt32(v.get_integer());

  // FIXME: How should we generate array literals? Are
  // these global constants or are they local alloca
  // objects. Does it depend on context?

  // A string literal produces a new global string constant.
  // and returns a pointer to an array of N characters.
  if (is_string(t)) {
    Array_value a = v.get_array();
    String s = a.get_string();

    // FIXME: This does not unify equivalent strings.
    // Maybe we needt maintain a mapping in order to
    // avoid redunancies.
    auto iter = strings.find(s);
    if (iter == strings.end()) {
      llvm::Value* v = build.CreateGlobalString(s);
      iter = strings.emplace(s, v).first;
    }
    return iter->second;
  }

  else
    throw std::runtime_error("cannot generate function literal");
}
Exemple #10
0
// Parse a primary type.
//
//    primary-type -> 'bool'
//                  | 'int'
//                  | 'char'
//                  | id-type
//                  | function-type
//
//    function-type -> '(' type-list ')' '->' type
//
//    type-list -> type | type-list ',' type
Type const*
Parser::primary_type()
{
  // id-type
  if (Token tok = match_if(identifier_tok))
    return on_id_type(tok);

  // bool
  else if (match_if(bool_kw))
    return get_boolean_type();

  // char
  else if (match_if(char_kw))
    return get_character_type();

  // int
  else if (match_if(int_kw))
    return get_integer_type();

  // uint
  else if (match_if(uint_kw))
    return get_integer_type(false);

  // short
  else if (match_if(short_kw))
    return get_integer_type(16);

  // ushort
  else if (match_if(ushort_kw))
    return get_integer_type(false, 16);

  // long
  else if (match_if(long_kw))
    return get_integer_type(64);

  // ulong
  else if (match_if(ulong_kw))
    return get_integer_type(false, 64);

  // int16
  else if (match_if(int16_kw))
    return get_integer_type(16);

  // uint16
  else if (match_if(uint16_kw))
    return get_integer_type(false, 16);

  // int32
  else if (match_if(int32_kw))
    return get_integer_type();

  // uint32
  else if (match_if(uint32_kw))
    return get_integer_type(false);

  // int64
  else if (match_if(int64_kw))
    return get_integer_type(64);

  // uint64
  else if (match_if(uint64_kw))
    return get_integer_type(false, 64);

  // float
  else if (match_if(float_kw))
      return get_float_type();

  // double
  else if (match_if(double_kw))
      return get_double_type();

  // function-type
  else if (match_if(lparen_tok)) {
    Type_seq ts;
    while (true) {
      ts.push_back(type());
      if (match_if(comma_tok))
        continue;
      else
        break;
    }
    match(rparen_tok);
    match(arrow_tok);
    Type const* t = type();
    return on_function_type(ts, t);
  }

  // error
  //
  // TODO: Make this a little less vague.
  else
    error("invalid type");
}