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; }
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()); }
// 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()); }
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())); }
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; }
// 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"); }
// 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"); }
// 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"); }
// 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"); }