Loading startop/view_compiler/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ cc_defaults { name: "viewcompiler_defaults", defaults: ["libdexfile_static_defaults"], header_libs: [ "libbase_headers", ], Loading @@ -30,6 +29,7 @@ cc_defaults { "liblog", "libutils", "libziparchive", "libz", ], cppflags: ["-std=c++17"], target: { Loading startop/view_compiler/dex_builder.cc +49 −44 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ #include "dex_builder.h" #include "dex/descriptors_names.h" #include <fstream> #include <memory> Loading @@ -30,8 +28,6 @@ using std::string; using ::dex::kAccPublic; using Op = Instruction::Op; using Opcode = ::art::Instruction::Code; const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; }; const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; }; Loading @@ -43,20 +39,29 @@ constexpr uint8_t kDexFileMagic[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x38, 0x00 constexpr size_t kMaxEncodedStringLength{5}; // Converts invoke-* to invoke-*/range constexpr Opcode InvokeToInvokeRange(Opcode opcode) { constexpr ::dex::Opcode InvokeToInvokeRange(::dex::Opcode opcode) { switch (opcode) { case ::art::Instruction::INVOKE_VIRTUAL: return ::art::Instruction::INVOKE_VIRTUAL_RANGE; case ::art::Instruction::INVOKE_DIRECT: return ::art::Instruction::INVOKE_DIRECT_RANGE; case ::art::Instruction::INVOKE_STATIC: return ::art::Instruction::INVOKE_STATIC_RANGE; case ::art::Instruction::INVOKE_INTERFACE: return ::art::Instruction::INVOKE_INTERFACE_RANGE; case ::dex::Opcode::OP_INVOKE_VIRTUAL: return ::dex::Opcode::OP_INVOKE_VIRTUAL_RANGE; case ::dex::Opcode::OP_INVOKE_DIRECT: return ::dex::Opcode::OP_INVOKE_DIRECT_RANGE; case ::dex::Opcode::OP_INVOKE_STATIC: return ::dex::Opcode::OP_INVOKE_STATIC_RANGE; case ::dex::Opcode::OP_INVOKE_INTERFACE: return ::dex::Opcode::OP_INVOKE_INTERFACE_RANGE; default: LOG(FATAL) << opcode << " is not a recognized invoke opcode."; UNREACHABLE(); __builtin_unreachable(); } } std::string DotToDescriptor(const char* class_name) { std::string descriptor(class_name); std::replace(descriptor.begin(), descriptor.end(), '.', '/'); if (descriptor.length() > 0 && descriptor[0] != '[') { descriptor = "L" + descriptor + ";"; } return descriptor; } } // namespace Loading Loading @@ -178,7 +183,7 @@ void WriteTestDexFile(const string& filename) { } TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) { return TypeDescriptor{art::DotToDescriptor(name.c_str())}; return TypeDescriptor{DotToDescriptor(name.c_str())}; } DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} { Loading Loading @@ -219,11 +224,11 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) { ClassBuilder DexBuilder::MakeClass(const std::string& name) { auto* class_def = Alloc<ir::Class>(); ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str())); ir::Type* type_def = GetOrAddType(DotToDescriptor(name.c_str())); type_def->class_def = class_def; class_def->type = type_def; class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object")); class_def->super_class = GetOrAddType(DotToDescriptor("java.lang.Object")); class_def->access_flags = kAccPublic; return ClassBuilder{this, name, class_def}; } Loading Loading @@ -378,26 +383,26 @@ void MethodBuilder::EncodeInstructions() { void MethodBuilder::EncodeInstruction(const Instruction& instruction) { switch (instruction.opcode()) { case Instruction::Op::kReturn: return EncodeReturn(instruction, ::art::Instruction::RETURN); return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN); case Instruction::Op::kReturnObject: return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT); return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN_OBJECT); case Instruction::Op::kMove: case Instruction::Op::kMoveObject: return EncodeMove(instruction); case Instruction::Op::kInvokeVirtual: return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_VIRTUAL); case Instruction::Op::kInvokeDirect: return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_DIRECT); case Instruction::Op::kInvokeStatic: return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_STATIC); case Instruction::Op::kInvokeInterface: return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_INTERFACE); case Instruction::Op::kBindLabel: return BindLabel(instruction.args()[0]); case Instruction::Op::kBranchEqz: return EncodeBranch(art::Instruction::IF_EQZ, instruction); return EncodeBranch(::dex::Opcode::OP_IF_EQZ, instruction); case Instruction::Op::kBranchNEqz: return EncodeBranch(art::Instruction::IF_NEZ, instruction); return EncodeBranch(::dex::Opcode::OP_IF_NEZ, instruction); case Instruction::Op::kNew: return EncodeNew(instruction); case Instruction::Op::kCheckCast: Loading @@ -410,10 +415,10 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) { } } void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) { void MethodBuilder::EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode) { CHECK(!instruction.dest().has_value()); if (instruction.args().size() == 0) { Encode10x(art::Instruction::RETURN_VOID); Encode10x(::dex::Opcode::OP_RETURN_VOID); } else { CHECK_EQ(1, instruction.args().size()); size_t source = RegisterValue(instruction.args()[0]); Loading @@ -433,27 +438,27 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) { if (source.is_immediate()) { // TODO: support more registers CHECK_LT(RegisterValue(*instruction.dest()), 16); Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value()); Encode11n(::dex::Opcode::OP_CONST_4, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_string()) { constexpr size_t kMaxRegisters = 256; CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters); CHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value()); Encode21c(::dex::Opcode::OP_CONST_STRING, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_variable()) { // For the moment, we only use this when we need to reshuffle registers for // an invoke instruction, meaning we are too big for the 4-bit version. // We'll err on the side of caution and always generate the 16-bit form of // the instruction. Opcode opcode = instruction.opcode() == Instruction::Op::kMove ? ::art::Instruction::MOVE_16 : ::art::Instruction::MOVE_OBJECT_16; auto opcode = instruction.opcode() == Instruction::Op::kMove ? ::dex::Opcode::OP_MOVE_16 : ::dex::Opcode::OP_MOVE_OBJECT_16; Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source)); } else { UNIMPLEMENTED(FATAL); } } void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) { void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode) { constexpr size_t kMaxArgs = 5; // Currently, we only support up to 5 arguments. Loading @@ -480,8 +485,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct for (size_t i = 0; i < instruction.args().size(); ++i) { Instruction::Op move_op; if (opcode == ::art::Instruction::INVOKE_VIRTUAL || opcode == ::art::Instruction::INVOKE_DIRECT) { if (opcode == ::dex::Opcode::OP_INVOKE_VIRTUAL || opcode == ::dex::Opcode::OP_INVOKE_DIRECT) { // In this case, there is an implicit `this` argument, which is always an object. if (i == 0) { move_op = Instruction::Op::kMoveObject; Loading Loading @@ -514,8 +519,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct // If there is a return value, add a move-result instruction if (instruction.dest().has_value()) { Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT : art::Instruction::MOVE_RESULT, Encode11x(instruction.result_is_object() ? ::dex::Opcode::OP_MOVE_RESULT_OBJECT : ::dex::Opcode::OP_MOVE_RESULT, RegisterValue(*instruction.dest())); } Loading @@ -523,7 +528,7 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct } // Encodes a conditional branch that tests a single argument. void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) { void MethodBuilder::EncodeBranch(::dex::Opcode op, const Instruction& instruction) { const auto& args = instruction.args(); const auto& test_value = args[0]; const auto& branch_target = args[1]; Loading @@ -546,7 +551,7 @@ void MethodBuilder::EncodeNew(const Instruction& instruction) { const Value& type = instruction.args()[0]; CHECK_LT(RegisterValue(*instruction.dest()), 256); CHECK(type.is_type()); Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); Encode21c(::dex::Opcode::OP_NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); } void MethodBuilder::EncodeCast(const Instruction& instruction) { Loading @@ -558,7 +563,7 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) { const Value& type = instruction.args()[0]; CHECK_LT(RegisterValue(*instruction.dest()), 256); CHECK(type.is_type()); Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); Encode21c(::dex::Opcode::OP_CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); } void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { Loading @@ -569,7 +574,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(instruction.dest()->is_variable()); CHECK_EQ(0, instruction.args().size()); Encode21c(::art::Instruction::SGET, Encode21c(::dex::Opcode::OP_SGET, RegisterValue(*instruction.dest()), instruction.index_argument()); break; Loading @@ -579,7 +584,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK_EQ(1, args.size()); CHECK(args[0].is_variable()); Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument()); Encode21c(::dex::Opcode::OP_SPUT, RegisterValue(args[0]), instruction.index_argument()); break; } case Instruction::Op::kGetInstanceField: { Loading @@ -587,7 +592,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(instruction.dest()->is_variable()); CHECK_EQ(1, instruction.args().size()); Encode22c(::art::Instruction::IGET, Encode22c(::dex::Opcode::OP_IGET, RegisterValue(*instruction.dest()), RegisterValue(args[0]), instruction.index_argument()); Loading @@ -599,7 +604,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(args[0].is_variable()); CHECK(args[1].is_variable()); Encode22c(::art::Instruction::IPUT, Encode22c(::dex::Opcode::OP_IPUT, RegisterValue(args[1]), RegisterValue(args[0]), instruction.index_argument()); Loading startop/view_compiler/dex_builder.h +16 −13 Original line number Diff line number Diff line Loading @@ -24,7 +24,9 @@ #include <unordered_map> #include <vector> #include "dex/dex_instruction.h" #include "android-base/logging.h" #include "slicer/dex_bytecode.h" #include "slicer/dex_ir.h" #include "slicer/writer.h" Loading Loading @@ -364,11 +366,11 @@ class MethodBuilder { // Encodes a return instruction. For instructions with no return value, the opcode field is // ignored. Otherwise, this specifies which return instruction will be used (return, // return-object, etc.) void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode); void EncodeMove(const Instruction& instruction); void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); void EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode); void EncodeBranch(::dex::Opcode op, const Instruction& instruction); void EncodeNew(const Instruction& instruction); void EncodeCast(const Instruction& instruction); void EncodeFieldOp(const Instruction& instruction); Loading @@ -377,17 +379,18 @@ class MethodBuilder { // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of // formats. inline void Encode10x(art::Instruction::Code opcode) { inline void Encode10x(::dex::Opcode opcode) { // 00|op buffer_.push_back(opcode); static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode)); buffer_.push_back(static_cast<uint8_t>(opcode)); } inline void Encode11x(art::Instruction::Code opcode, uint8_t a) { inline void Encode11x(::dex::Opcode opcode, uint8_t a) { // aa|op buffer_.push_back((a << 8) | opcode); } inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) { inline void Encode11n(::dex::Opcode opcode, uint8_t a, int8_t b) { // b|a|op // Make sure the fields are in bounds (4 bits for a, 4 bits for b). Loading @@ -398,13 +401,13 @@ class MethodBuilder { buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode); } inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) { inline void Encode21c(::dex::Opcode opcode, uint8_t a, uint16_t b) { // aa|op|bbbb buffer_.push_back((a << 8) | opcode); buffer_.push_back(b); } inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) { inline void Encode22c(::dex::Opcode opcode, uint8_t a, uint8_t b, uint16_t c) { // b|a|op|bbbb CHECK(IsShortRegister(a)); CHECK(IsShortRegister(b)); Loading @@ -412,13 +415,13 @@ class MethodBuilder { buffer_.push_back(c); } inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) { inline void Encode32x(::dex::Opcode opcode, uint16_t a, uint16_t b) { buffer_.push_back(opcode); buffer_.push_back(a); buffer_.push_back(b); } inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d, inline void Encode35c(::dex::Opcode opcode, size_t a, uint16_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f, uint8_t g) { // a|g|op|bbbb|f|e|d|c Loading @@ -433,7 +436,7 @@ class MethodBuilder { buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c); } inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) { inline void Encode3rc(::dex::Opcode opcode, size_t a, uint16_t b, uint16_t c) { CHECK_LE(a, 255); buffer_.push_back((a << 8) | opcode); buffer_.push_back(b); Loading Loading
startop/view_compiler/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ cc_defaults { name: "viewcompiler_defaults", defaults: ["libdexfile_static_defaults"], header_libs: [ "libbase_headers", ], Loading @@ -30,6 +29,7 @@ cc_defaults { "liblog", "libutils", "libziparchive", "libz", ], cppflags: ["-std=c++17"], target: { Loading
startop/view_compiler/dex_builder.cc +49 −44 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ #include "dex_builder.h" #include "dex/descriptors_names.h" #include <fstream> #include <memory> Loading @@ -30,8 +28,6 @@ using std::string; using ::dex::kAccPublic; using Op = Instruction::Op; using Opcode = ::art::Instruction::Code; const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; }; const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; }; Loading @@ -43,20 +39,29 @@ constexpr uint8_t kDexFileMagic[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x38, 0x00 constexpr size_t kMaxEncodedStringLength{5}; // Converts invoke-* to invoke-*/range constexpr Opcode InvokeToInvokeRange(Opcode opcode) { constexpr ::dex::Opcode InvokeToInvokeRange(::dex::Opcode opcode) { switch (opcode) { case ::art::Instruction::INVOKE_VIRTUAL: return ::art::Instruction::INVOKE_VIRTUAL_RANGE; case ::art::Instruction::INVOKE_DIRECT: return ::art::Instruction::INVOKE_DIRECT_RANGE; case ::art::Instruction::INVOKE_STATIC: return ::art::Instruction::INVOKE_STATIC_RANGE; case ::art::Instruction::INVOKE_INTERFACE: return ::art::Instruction::INVOKE_INTERFACE_RANGE; case ::dex::Opcode::OP_INVOKE_VIRTUAL: return ::dex::Opcode::OP_INVOKE_VIRTUAL_RANGE; case ::dex::Opcode::OP_INVOKE_DIRECT: return ::dex::Opcode::OP_INVOKE_DIRECT_RANGE; case ::dex::Opcode::OP_INVOKE_STATIC: return ::dex::Opcode::OP_INVOKE_STATIC_RANGE; case ::dex::Opcode::OP_INVOKE_INTERFACE: return ::dex::Opcode::OP_INVOKE_INTERFACE_RANGE; default: LOG(FATAL) << opcode << " is not a recognized invoke opcode."; UNREACHABLE(); __builtin_unreachable(); } } std::string DotToDescriptor(const char* class_name) { std::string descriptor(class_name); std::replace(descriptor.begin(), descriptor.end(), '.', '/'); if (descriptor.length() > 0 && descriptor[0] != '[') { descriptor = "L" + descriptor + ";"; } return descriptor; } } // namespace Loading Loading @@ -178,7 +183,7 @@ void WriteTestDexFile(const string& filename) { } TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) { return TypeDescriptor{art::DotToDescriptor(name.c_str())}; return TypeDescriptor{DotToDescriptor(name.c_str())}; } DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} { Loading Loading @@ -219,11 +224,11 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) { ClassBuilder DexBuilder::MakeClass(const std::string& name) { auto* class_def = Alloc<ir::Class>(); ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str())); ir::Type* type_def = GetOrAddType(DotToDescriptor(name.c_str())); type_def->class_def = class_def; class_def->type = type_def; class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object")); class_def->super_class = GetOrAddType(DotToDescriptor("java.lang.Object")); class_def->access_flags = kAccPublic; return ClassBuilder{this, name, class_def}; } Loading Loading @@ -378,26 +383,26 @@ void MethodBuilder::EncodeInstructions() { void MethodBuilder::EncodeInstruction(const Instruction& instruction) { switch (instruction.opcode()) { case Instruction::Op::kReturn: return EncodeReturn(instruction, ::art::Instruction::RETURN); return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN); case Instruction::Op::kReturnObject: return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT); return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN_OBJECT); case Instruction::Op::kMove: case Instruction::Op::kMoveObject: return EncodeMove(instruction); case Instruction::Op::kInvokeVirtual: return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_VIRTUAL); case Instruction::Op::kInvokeDirect: return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_DIRECT); case Instruction::Op::kInvokeStatic: return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_STATIC); case Instruction::Op::kInvokeInterface: return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE); return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_INTERFACE); case Instruction::Op::kBindLabel: return BindLabel(instruction.args()[0]); case Instruction::Op::kBranchEqz: return EncodeBranch(art::Instruction::IF_EQZ, instruction); return EncodeBranch(::dex::Opcode::OP_IF_EQZ, instruction); case Instruction::Op::kBranchNEqz: return EncodeBranch(art::Instruction::IF_NEZ, instruction); return EncodeBranch(::dex::Opcode::OP_IF_NEZ, instruction); case Instruction::Op::kNew: return EncodeNew(instruction); case Instruction::Op::kCheckCast: Loading @@ -410,10 +415,10 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) { } } void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) { void MethodBuilder::EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode) { CHECK(!instruction.dest().has_value()); if (instruction.args().size() == 0) { Encode10x(art::Instruction::RETURN_VOID); Encode10x(::dex::Opcode::OP_RETURN_VOID); } else { CHECK_EQ(1, instruction.args().size()); size_t source = RegisterValue(instruction.args()[0]); Loading @@ -433,27 +438,27 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) { if (source.is_immediate()) { // TODO: support more registers CHECK_LT(RegisterValue(*instruction.dest()), 16); Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value()); Encode11n(::dex::Opcode::OP_CONST_4, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_string()) { constexpr size_t kMaxRegisters = 256; CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters); CHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value()); Encode21c(::dex::Opcode::OP_CONST_STRING, RegisterValue(*instruction.dest()), source.value()); } else if (source.is_variable()) { // For the moment, we only use this when we need to reshuffle registers for // an invoke instruction, meaning we are too big for the 4-bit version. // We'll err on the side of caution and always generate the 16-bit form of // the instruction. Opcode opcode = instruction.opcode() == Instruction::Op::kMove ? ::art::Instruction::MOVE_16 : ::art::Instruction::MOVE_OBJECT_16; auto opcode = instruction.opcode() == Instruction::Op::kMove ? ::dex::Opcode::OP_MOVE_16 : ::dex::Opcode::OP_MOVE_OBJECT_16; Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source)); } else { UNIMPLEMENTED(FATAL); } } void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) { void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode) { constexpr size_t kMaxArgs = 5; // Currently, we only support up to 5 arguments. Loading @@ -480,8 +485,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct for (size_t i = 0; i < instruction.args().size(); ++i) { Instruction::Op move_op; if (opcode == ::art::Instruction::INVOKE_VIRTUAL || opcode == ::art::Instruction::INVOKE_DIRECT) { if (opcode == ::dex::Opcode::OP_INVOKE_VIRTUAL || opcode == ::dex::Opcode::OP_INVOKE_DIRECT) { // In this case, there is an implicit `this` argument, which is always an object. if (i == 0) { move_op = Instruction::Op::kMoveObject; Loading Loading @@ -514,8 +519,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct // If there is a return value, add a move-result instruction if (instruction.dest().has_value()) { Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT : art::Instruction::MOVE_RESULT, Encode11x(instruction.result_is_object() ? ::dex::Opcode::OP_MOVE_RESULT_OBJECT : ::dex::Opcode::OP_MOVE_RESULT, RegisterValue(*instruction.dest())); } Loading @@ -523,7 +528,7 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct } // Encodes a conditional branch that tests a single argument. void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) { void MethodBuilder::EncodeBranch(::dex::Opcode op, const Instruction& instruction) { const auto& args = instruction.args(); const auto& test_value = args[0]; const auto& branch_target = args[1]; Loading @@ -546,7 +551,7 @@ void MethodBuilder::EncodeNew(const Instruction& instruction) { const Value& type = instruction.args()[0]; CHECK_LT(RegisterValue(*instruction.dest()), 256); CHECK(type.is_type()); Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); Encode21c(::dex::Opcode::OP_NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value()); } void MethodBuilder::EncodeCast(const Instruction& instruction) { Loading @@ -558,7 +563,7 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) { const Value& type = instruction.args()[0]; CHECK_LT(RegisterValue(*instruction.dest()), 256); CHECK(type.is_type()); Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); Encode21c(::dex::Opcode::OP_CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); } void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { Loading @@ -569,7 +574,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(instruction.dest()->is_variable()); CHECK_EQ(0, instruction.args().size()); Encode21c(::art::Instruction::SGET, Encode21c(::dex::Opcode::OP_SGET, RegisterValue(*instruction.dest()), instruction.index_argument()); break; Loading @@ -579,7 +584,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK_EQ(1, args.size()); CHECK(args[0].is_variable()); Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument()); Encode21c(::dex::Opcode::OP_SPUT, RegisterValue(args[0]), instruction.index_argument()); break; } case Instruction::Op::kGetInstanceField: { Loading @@ -587,7 +592,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(instruction.dest()->is_variable()); CHECK_EQ(1, instruction.args().size()); Encode22c(::art::Instruction::IGET, Encode22c(::dex::Opcode::OP_IGET, RegisterValue(*instruction.dest()), RegisterValue(args[0]), instruction.index_argument()); Loading @@ -599,7 +604,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) { CHECK(args[0].is_variable()); CHECK(args[1].is_variable()); Encode22c(::art::Instruction::IPUT, Encode22c(::dex::Opcode::OP_IPUT, RegisterValue(args[1]), RegisterValue(args[0]), instruction.index_argument()); Loading
startop/view_compiler/dex_builder.h +16 −13 Original line number Diff line number Diff line Loading @@ -24,7 +24,9 @@ #include <unordered_map> #include <vector> #include "dex/dex_instruction.h" #include "android-base/logging.h" #include "slicer/dex_bytecode.h" #include "slicer/dex_ir.h" #include "slicer/writer.h" Loading Loading @@ -364,11 +366,11 @@ class MethodBuilder { // Encodes a return instruction. For instructions with no return value, the opcode field is // ignored. Otherwise, this specifies which return instruction will be used (return, // return-object, etc.) void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode); void EncodeMove(const Instruction& instruction); void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode); void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); void EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode); void EncodeBranch(::dex::Opcode op, const Instruction& instruction); void EncodeNew(const Instruction& instruction); void EncodeCast(const Instruction& instruction); void EncodeFieldOp(const Instruction& instruction); Loading @@ -377,17 +379,18 @@ class MethodBuilder { // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of // formats. inline void Encode10x(art::Instruction::Code opcode) { inline void Encode10x(::dex::Opcode opcode) { // 00|op buffer_.push_back(opcode); static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode)); buffer_.push_back(static_cast<uint8_t>(opcode)); } inline void Encode11x(art::Instruction::Code opcode, uint8_t a) { inline void Encode11x(::dex::Opcode opcode, uint8_t a) { // aa|op buffer_.push_back((a << 8) | opcode); } inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) { inline void Encode11n(::dex::Opcode opcode, uint8_t a, int8_t b) { // b|a|op // Make sure the fields are in bounds (4 bits for a, 4 bits for b). Loading @@ -398,13 +401,13 @@ class MethodBuilder { buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode); } inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) { inline void Encode21c(::dex::Opcode opcode, uint8_t a, uint16_t b) { // aa|op|bbbb buffer_.push_back((a << 8) | opcode); buffer_.push_back(b); } inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) { inline void Encode22c(::dex::Opcode opcode, uint8_t a, uint8_t b, uint16_t c) { // b|a|op|bbbb CHECK(IsShortRegister(a)); CHECK(IsShortRegister(b)); Loading @@ -412,13 +415,13 @@ class MethodBuilder { buffer_.push_back(c); } inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) { inline void Encode32x(::dex::Opcode opcode, uint16_t a, uint16_t b) { buffer_.push_back(opcode); buffer_.push_back(a); buffer_.push_back(b); } inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d, inline void Encode35c(::dex::Opcode opcode, size_t a, uint16_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f, uint8_t g) { // a|g|op|bbbb|f|e|d|c Loading @@ -433,7 +436,7 @@ class MethodBuilder { buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c); } inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) { inline void Encode3rc(::dex::Opcode opcode, size_t a, uint16_t b, uint16_t c) { CHECK_LE(a, 255); buffer_.push_back((a << 8) | opcode); buffer_.push_back(b); Loading