diff options
Diffstat (limited to 'startop/view_compiler/dex_builder.h')
-rw-r--r-- | startop/view_compiler/dex_builder.h | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h index 31414c82e510..181d1db0082a 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -112,6 +112,7 @@ class Value { static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; } static constexpr Value String(size_t value) { return Value{value, Kind::kString}; } static constexpr Value Label(size_t id) { return Value{id, Kind::kLabel}; } + static constexpr Value Type(size_t id) { return Value{id, Kind::kType}; } bool is_register() const { return kind_ == Kind::kLocalRegister; } bool is_parameter() const { return kind_ == Kind::kParameter; } @@ -119,11 +120,12 @@ class Value { bool is_immediate() const { return kind_ == Kind::kImmediate; } bool is_string() const { return kind_ == Kind::kString; } bool is_label() const { return kind_ == Kind::kLabel; } + bool is_type() const { return kind_ == Kind::kType; } size_t value() const { return value_; } private: - enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel }; + enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel, kType }; const size_t value_; const Kind kind_; @@ -139,7 +141,16 @@ class Instruction { public: // The operation performed by this instruction. These are virtual instructions that do not // correspond exactly to DEX instructions. - enum class Op { kReturn, kReturnObject, kMove, kInvokeVirtual, kBindLabel, kBranchEqz }; + enum class Op { + kReturn, + kReturnObject, + kMove, + kInvokeVirtual, + kInvokeDirect, + kBindLabel, + kBranchEqz, + kNew + }; //////////////////////// // Named Constructors // @@ -160,6 +171,12 @@ class Instruction { Value this_arg, T... args) { return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...}; } + // For direct calls (basically, constructors). + template <typename... T> + static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest, + Value this_arg, T... args) { + return Instruction{Op::kInvokeDirect, method_id, dest, this_arg, args...}; + } /////////////// // Accessors // @@ -189,6 +206,12 @@ class Instruction { // Needed for CHECK_EQ, DCHECK_EQ, etc. std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode); +// Keeps track of information needed to manipulate or call a method. +struct MethodDeclData { + size_t id; + ir::MethodDecl* decl; +}; + // Tools to help build methods and their bodies. class MethodBuilder { public: @@ -216,6 +239,8 @@ class MethodBuilder { // const/4 void BuildConst4(Value target, int value); void BuildConstString(Value target, const std::string& value); + template <typename... T> + void BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args); // TODO: add builders for more instructions @@ -229,8 +254,9 @@ class MethodBuilder { void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeMove(const Instruction& instruction); - void EncodeInvokeVirtual(const Instruction& instruction); + void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); + void EncodeNew(const Instruction& instruction); // Converts a register or parameter to its DEX register number. size_t RegisterValue(const Value& value) const; @@ -270,6 +296,10 @@ class MethodBuilder { }; std::vector<LabelData> labels_; + + // During encoding, keep track of the largest number of arguments needed, so we can use it for our + // outs count + size_t max_args_{0}; }; // A helper to build class definitions. @@ -289,12 +319,6 @@ class ClassBuilder { ir::Class* const class_; }; -// Keeps track of information needed to manipulate or call a method. -struct MethodDeclData { - size_t id; - ir::MethodDecl* decl; -}; - // Builds Dex files from scratch. class DexBuilder { public: @@ -363,6 +387,17 @@ class DexBuilder { std::map<Prototype, ir::Proto*> proto_map_; }; +template <typename... T> +void MethodBuilder::BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args) { + MethodDeclData constructor_data{dex_->GetOrDeclareMethod(type, "<init>", constructor)}; + // allocate the object + ir::Type* type_def = dex_->GetOrAddType(type.descriptor()); + AddInstruction( + Instruction::OpWithArgs(Instruction::Op::kNew, target, Value::Type(type_def->orig_index))); + // call the constructor + AddInstruction(Instruction::InvokeDirect(constructor_data.id, /*dest=*/{}, target, args...)); +}; + } // namespace dex } // namespace startop |