ART: Introduce compiler data type.

Replace most uses of the runtime's Primitive in compiler
with a new class DataType. This prepares for introducing
new types, such as Uint8, that the runtime does not need
to know about.

Test: m test-art-host-gtest
Test: testrunner.py --host
Bug: 23964345
Change-Id: Iec2ad82454eec678fffcd8279a9746b90feb9b0c
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 50ab11b..77b7a22 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -17,6 +17,7 @@
 #include "ssa_builder.h"
 
 #include "bytecode_utils.h"
+#include "data_type-inl.h"
 #include "mirror/class-inl.h"
 #include "nodes.h"
 #include "reference_type_propagation.h"
@@ -37,10 +38,11 @@
       HInstruction* right = equality_instr->InputAt(1);
       HInstruction* int_operand = nullptr;
 
-      if ((left->GetType() == Primitive::kPrimNot) && (right->GetType() == Primitive::kPrimInt)) {
+      if ((left->GetType() == DataType::Type::kReference) &&
+          (right->GetType() == DataType::Type::kInt32)) {
         int_operand = right;
-      } else if ((right->GetType() == Primitive::kPrimNot)
-                 && (left->GetType() == Primitive::kPrimInt)) {
+      } else if ((right->GetType() == DataType::Type::kReference) &&
+                 (left->GetType() == DataType::Type::kInt32)) {
         int_operand = left;
       } else {
         continue;
@@ -122,7 +124,7 @@
 // Find a candidate primitive type for `phi` by merging the type of its inputs.
 // Return false if conflict is identified.
 static bool TypePhiFromInputs(HPhi* phi) {
-  Primitive::Type common_type = phi->GetType();
+  DataType::Type common_type = phi->GetType();
 
   for (HInstruction* input : phi->GetInputs()) {
     if (input->IsPhi() && input->AsPhi()->IsDead()) {
@@ -131,26 +133,29 @@
       return false;
     }
 
-    Primitive::Type input_type = HPhi::ToPhiType(input->GetType());
+    DataType::Type input_type = HPhi::ToPhiType(input->GetType());
     if (common_type == input_type) {
       // No change in type.
-    } else if (Primitive::Is64BitType(common_type) != Primitive::Is64BitType(input_type)) {
+    } else if (DataType::Is64BitType(common_type) != DataType::Is64BitType(input_type)) {
       // Types are of different sizes, e.g. int vs. long. Must be a conflict.
       return false;
-    } else if (Primitive::IsIntegralType(common_type)) {
+    } else if (DataType::IsIntegralType(common_type)) {
       // Previous inputs were integral, this one is not but is of the same size.
       // This does not imply conflict since some bytecode instruction types are
       // ambiguous. TypeInputsOfPhi will either type them or detect a conflict.
-      DCHECK(Primitive::IsFloatingPointType(input_type) || input_type == Primitive::kPrimNot);
+      DCHECK(DataType::IsFloatingPointType(input_type) ||
+             input_type == DataType::Type::kReference);
       common_type = input_type;
-    } else if (Primitive::IsIntegralType(input_type)) {
+    } else if (DataType::IsIntegralType(input_type)) {
       // Input is integral, common type is not. Same as in the previous case, if
       // there is a conflict, it will be detected during TypeInputsOfPhi.
-      DCHECK(Primitive::IsFloatingPointType(common_type) || common_type == Primitive::kPrimNot);
+      DCHECK(DataType::IsFloatingPointType(common_type) ||
+             common_type == DataType::Type::kReference);
     } else {
       // Combining float and reference types. Clearly a conflict.
-      DCHECK((common_type == Primitive::kPrimFloat && input_type == Primitive::kPrimNot) ||
-             (common_type == Primitive::kPrimNot && input_type == Primitive::kPrimFloat));
+      DCHECK(
+          (common_type == DataType::Type::kFloat32 && input_type == DataType::Type::kReference) ||
+          (common_type == DataType::Type::kReference && input_type == DataType::Type::kFloat32));
       return false;
     }
   }
@@ -163,8 +168,8 @@
 
 // Replace inputs of `phi` to match its type. Return false if conflict is identified.
 bool SsaBuilder::TypeInputsOfPhi(HPhi* phi, ArenaVector<HPhi*>* worklist) {
-  Primitive::Type common_type = phi->GetType();
-  if (Primitive::IsIntegralType(common_type)) {
+  DataType::Type common_type = phi->GetType();
+  if (DataType::IsIntegralType(common_type)) {
     // We do not need to retype ambiguous inputs because they are always constructed
     // with the integral type candidate.
     if (kIsDebugBuild) {
@@ -175,14 +180,15 @@
     // Inputs did not need to be replaced, hence no conflict. Report success.
     return true;
   } else {
-    DCHECK(common_type == Primitive::kPrimNot || Primitive::IsFloatingPointType(common_type));
+    DCHECK(common_type == DataType::Type::kReference ||
+           DataType::IsFloatingPointType(common_type));
     HInputsRef inputs = phi->GetInputs();
     for (size_t i = 0; i < inputs.size(); ++i) {
       HInstruction* input = inputs[i];
       if (input->GetType() != common_type) {
         // Input type does not match phi's type. Try to retype the input or
         // generate a suitably typed equivalent.
-        HInstruction* equivalent = (common_type == Primitive::kPrimNot)
+        HInstruction* equivalent = (common_type == DataType::Type::kReference)
             ? GetReferenceTypeEquivalent(input)
             : GetFloatOrDoubleEquivalent(input, common_type);
         if (equivalent == nullptr) {
@@ -209,7 +215,7 @@
 // it was changed by the algorithm or not.
 bool SsaBuilder::UpdatePrimitiveType(HPhi* phi, ArenaVector<HPhi*>* worklist) {
   DCHECK(phi->IsLive());
-  Primitive::Type original_type = phi->GetType();
+  DataType::Type original_type = phi->GetType();
 
   // Try to type the phi in two stages:
   // (1) find a candidate type for the phi by merging types of all its inputs,
@@ -270,8 +276,8 @@
 }
 
 static HArrayGet* FindFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) {
-  Primitive::Type type = aget->GetType();
-  DCHECK(Primitive::IsIntOrLongType(type));
+  DataType::Type type = aget->GetType();
+  DCHECK(DataType::IsIntOrLongType(type));
   HInstruction* next = aget->GetNext();
   if (next != nullptr && next->IsArrayGet()) {
     HArrayGet* next_aget = next->AsArrayGet();
@@ -283,24 +289,25 @@
 }
 
 static HArrayGet* CreateFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) {
-  Primitive::Type type = aget->GetType();
-  DCHECK(Primitive::IsIntOrLongType(type));
+  DataType::Type type = aget->GetType();
+  DCHECK(DataType::IsIntOrLongType(type));
   DCHECK(FindFloatOrDoubleEquivalentOfArrayGet(aget) == nullptr);
 
   HArrayGet* equivalent = new (aget->GetBlock()->GetGraph()->GetArena()) HArrayGet(
       aget->GetArray(),
       aget->GetIndex(),
-      type == Primitive::kPrimInt ? Primitive::kPrimFloat : Primitive::kPrimDouble,
+      type == DataType::Type::kInt32 ? DataType::Type::kFloat32 : DataType::Type::kFloat64,
       aget->GetDexPc());
   aget->GetBlock()->InsertInstructionAfter(equivalent, aget);
   return equivalent;
 }
 
-static Primitive::Type GetPrimitiveArrayComponentType(HInstruction* array)
+static DataType::Type GetPrimitiveArrayComponentType(HInstruction* array)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ReferenceTypeInfo array_type = array->GetReferenceTypeInfo();
   DCHECK(array_type.IsPrimitiveArrayClass());
-  return array_type.GetTypeHandle()->GetComponentType()->GetPrimitiveType();
+  return DataTypeFromPrimitive(
+      array_type.GetTypeHandle()->GetComponentType()->GetPrimitiveType());
 }
 
 bool SsaBuilder::FixAmbiguousArrayOps() {
@@ -325,10 +332,10 @@
       }
 
       HArrayGet* aget_float = FindFloatOrDoubleEquivalentOfArrayGet(aget_int);
-      Primitive::Type array_type = GetPrimitiveArrayComponentType(array);
-      DCHECK_EQ(Primitive::Is64BitType(aget_int->GetType()), Primitive::Is64BitType(array_type));
+      DataType::Type array_type = GetPrimitiveArrayComponentType(array);
+      DCHECK_EQ(DataType::Is64BitType(aget_int->GetType()), DataType::Is64BitType(array_type));
 
-      if (Primitive::IsIntOrLongType(array_type)) {
+      if (DataType::IsIntOrLongType(array_type)) {
         if (aget_float != nullptr) {
           // There is a float/double equivalent. We must replace it and re-run
           // primitive type propagation on all dependent instructions.
@@ -337,7 +344,7 @@
           AddDependentInstructionsToWorklist(aget_int, &worklist);
         }
       } else {
-        DCHECK(Primitive::IsFloatingPointType(array_type));
+        DCHECK(DataType::IsFloatingPointType(array_type));
         if (aget_float == nullptr) {
           // This is a float/double ArrayGet but there were no typed uses which
           // would create the typed equivalent. Create it now.
@@ -365,13 +372,13 @@
       }
 
       HInstruction* value = aset->GetValue();
-      Primitive::Type value_type = value->GetType();
-      Primitive::Type array_type = GetPrimitiveArrayComponentType(array);
-      DCHECK_EQ(Primitive::Is64BitType(value_type), Primitive::Is64BitType(array_type));
+      DataType::Type value_type = value->GetType();
+      DataType::Type array_type = GetPrimitiveArrayComponentType(array);
+      DCHECK_EQ(DataType::Is64BitType(value_type), DataType::Is64BitType(array_type));
 
-      if (Primitive::IsFloatingPointType(array_type)) {
-        if (!Primitive::IsFloatingPointType(value_type)) {
-          DCHECK(Primitive::IsIntegralType(value_type));
+      if (DataType::IsFloatingPointType(array_type)) {
+        if (!DataType::IsFloatingPointType(value_type)) {
+          DCHECK(DataType::IsIntegralType(value_type));
           // Array elements are floating-point but the value has not been replaced
           // with its floating-point equivalent. The replacement must always
           // succeed in code validated by the verifier.
@@ -390,8 +397,8 @@
       } else {
         // Array elements are integral and the value assigned to it initially
         // was integral too. Nothing to do.
-        DCHECK(Primitive::IsIntegralType(array_type));
-        DCHECK(Primitive::IsIntegralType(value_type));
+        DCHECK(DataType::IsIntegralType(array_type));
+        DCHECK(DataType::IsIntegralType(value_type));
       }
     }
   }
@@ -599,7 +606,7 @@
  * floating point registers and core registers), we need to create a copy of the
  * phi with a floating point / reference type.
  */
-HPhi* SsaBuilder::GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, Primitive::Type type) {
+HPhi* SsaBuilder::GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, DataType::Type type) {
   DCHECK(phi->IsLive()) << "Cannot get equivalent of a dead phi since it would create a live one.";
 
   // We place the floating point /reference phi next to this phi.
@@ -637,9 +644,9 @@
 }
 
 HArrayGet* SsaBuilder::GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget) {
-  DCHECK(Primitive::IsIntegralType(aget->GetType()));
+  DCHECK(DataType::IsIntegralType(aget->GetType()));
 
-  if (!Primitive::IsIntOrLongType(aget->GetType())) {
+  if (!DataType::IsIntOrLongType(aget->GetType())) {
     // Cannot type boolean, char, byte, short to float/double.
     return nullptr;
   }
@@ -650,7 +657,7 @@
     // int/long. Requesting a float/double equivalent should lead to a conflict.
     if (kIsDebugBuild) {
       ScopedObjectAccess soa(Thread::Current());
-      DCHECK(Primitive::IsIntOrLongType(GetPrimitiveArrayComponentType(aget->GetArray())));
+      DCHECK(DataType::IsIntOrLongType(GetPrimitiveArrayComponentType(aget->GetArray())));
     }
     return nullptr;
   } else {
@@ -661,7 +668,7 @@
   }
 }
 
-HInstruction* SsaBuilder::GetFloatOrDoubleEquivalent(HInstruction* value, Primitive::Type type) {
+HInstruction* SsaBuilder::GetFloatOrDoubleEquivalent(HInstruction* value, DataType::Type type) {
   if (value->IsArrayGet()) {
     return GetFloatOrDoubleEquivalentOfArrayGet(value->AsArrayGet());
   } else if (value->IsLongConstant()) {
@@ -679,7 +686,7 @@
   if (value->IsIntConstant() && value->AsIntConstant()->GetValue() == 0) {
     return graph_->GetNullConstant();
   } else if (value->IsPhi()) {
-    return GetFloatDoubleOrReferenceEquivalentOfPhi(value->AsPhi(), Primitive::kPrimNot);
+    return GetFloatDoubleOrReferenceEquivalentOfPhi(value->AsPhi(), DataType::Type::kReference);
   } else {
     return nullptr;
   }