summaryrefslogtreecommitdiff
path: root/startop/view_compiler/dex_builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'startop/view_compiler/dex_builder.h')
-rw-r--r--startop/view_compiler/dex_builder.h53
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