Switch to slicer DEX opcode definitions

Removes dependency on art/libdexfile and uses equivalent definitions
from the dexter/slicer library.

Bug: 133140750
Bug: 142948359
Test: m
Test: atest dex-builder-test \
            view-compiler-tests \
            android.view.cts.PrecompiledLayoutTest
Change-Id: I49562ac4867254ecde287b828f76d23cb5132dd0
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index c380d29..7cc233b 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -16,7 +16,6 @@
 
 cc_defaults {
     name: "viewcompiler_defaults",
-    defaults: ["libdexfile_static_defaults"],
     header_libs: [
         "libbase_headers",
     ],
@@ -30,6 +29,7 @@
         "liblog",
         "libutils",
         "libziparchive",
+        "libz",
     ],
     cppflags: ["-std=c++17"],
     target: {
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 48b44d0..50cf5a50 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -16,8 +16,6 @@
 
 #include "dex_builder.h"
 
-#include "dex/descriptors_names.h"
-
 #include <fstream>
 #include <memory>
 
@@ -30,8 +28,6 @@
 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"}; };
 
@@ -43,22 +39,31 @@
 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
 
 std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {
@@ -178,7 +183,7 @@
 }
 
 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>()} {
@@ -219,11 +224,11 @@
 
 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};
 }
@@ -378,26 +383,26 @@
 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:
@@ -410,10 +415,10 @@
   }
 }
 
-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]);
@@ -433,27 +438,27 @@
   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.
@@ -480,8 +485,8 @@
 
     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;
@@ -514,8 +519,8 @@
 
   // 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()));
   }
 
@@ -523,7 +528,7 @@
 }
 
 // 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];
@@ -546,7 +551,7 @@
   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) {
@@ -558,7 +563,7 @@
   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) {
@@ -569,7 +574,7 @@
       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;
@@ -579,7 +584,7 @@
       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: {
@@ -587,7 +592,7 @@
       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());
@@ -599,7 +604,7 @@
       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());
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 3924e77..3ae37ce 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -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"
 
@@ -364,11 +366,11 @@
   // 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);
@@ -377,17 +379,18 @@
   // 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).
@@ -398,13 +401,13 @@
     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));
@@ -412,13 +415,13 @@
     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
 
@@ -433,7 +436,7 @@
     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);