Separate out more of LLVM build. Move verifier.

Move the verifier to its own directory and break out major components.
Avoid compiling unused files as part of the LLVM build, increase the use
of unimplemented for LLVM.

Change-Id: Icd3b1708363fb70ae99417d06ef8669d60446533
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
new file mode 100644
index 0000000..d06377a
--- /dev/null
+++ b/src/verifier/reg_type_cache.cc
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "reg_type_cache.h"
+
+#include "object_utils.h"
+
+namespace art {
+namespace verifier {
+
+static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
+  switch (prim_type) {
+    case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
+    case Primitive::kPrimByte:    return RegType::kRegTypeByte;
+    case Primitive::kPrimShort:   return RegType::kRegTypeShort;
+    case Primitive::kPrimChar:    return RegType::kRegTypeChar;
+    case Primitive::kPrimInt:     return RegType::kRegTypeInteger;
+    case Primitive::kPrimLong:    return RegType::kRegTypeLongLo;
+    case Primitive::kPrimFloat:   return RegType::kRegTypeFloat;
+    case Primitive::kPrimDouble:  return RegType::kRegTypeDoubleLo;
+    case Primitive::kPrimVoid:
+    default:                      return RegType::kRegTypeUnknown;
+  }
+}
+
+static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) {
+  if (descriptor.length() == 1) {
+    switch (descriptor[0]) {
+      case 'Z': return RegType::kRegTypeBoolean;
+      case 'B': return RegType::kRegTypeByte;
+      case 'S': return RegType::kRegTypeShort;
+      case 'C': return RegType::kRegTypeChar;
+      case 'I': return RegType::kRegTypeInteger;
+      case 'J': return RegType::kRegTypeLongLo;
+      case 'F': return RegType::kRegTypeFloat;
+      case 'D': return RegType::kRegTypeDoubleLo;
+      case 'V':
+      default:  return RegType::kRegTypeUnknown;
+    }
+  } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
+    return RegType::kRegTypeReference;
+  } else {
+    return RegType::kRegTypeUnknown;
+  }
+}
+
+const RegType& RegTypeCache::FromDescriptor(const ClassLoader* loader,
+                                            const char* descriptor) {
+  return From(RegTypeFromDescriptor(descriptor), loader, descriptor);
+}
+
+const RegType& RegTypeCache::From(RegType::Type type, const ClassLoader* loader,
+                                  const char* descriptor) {
+  if (type <= RegType::kRegTypeLastFixedLocation) {
+    // entries should be sized greater than primitive types
+    DCHECK_GT(entries_.size(), static_cast<size_t>(type));
+    RegType* entry = entries_[type];
+    if (entry == NULL) {
+      Class* klass = NULL;
+      if (strlen(descriptor) != 0) {
+        klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
+      }
+      entry = new RegType(type, klass, 0, type);
+      entries_[type] = entry;
+    }
+    return *entry;
+  } else {
+    DCHECK(type == RegType::kRegTypeReference);
+    ClassHelper kh;
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      // check resolved and unresolved references, ignore uninitialized references
+      if (cur_entry->IsReference()) {
+        kh.ChangeClass(cur_entry->GetClass());
+        if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+          return *cur_entry;
+        }
+      } else if (cur_entry->IsUnresolvedReference() &&
+                 cur_entry->GetDescriptor()->Equals(descriptor)) {
+        return *cur_entry;
+      }
+    }
+    Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
+    if (klass != NULL) {
+      // Able to resolve so create resolved register type
+      RegType* entry = new RegType(type, klass, 0, entries_.size());
+      entries_.push_back(entry);
+      return *entry;
+    } else {
+      // TODO: we assume unresolved, but we may be able to do better by validating whether the
+      // descriptor string is valid
+      // Unable to resolve so create unresolved register type
+      DCHECK(Thread::Current()->IsExceptionPending());
+      Thread::Current()->ClearException();
+      if (IsValidDescriptor(descriptor)) {
+        String* string_descriptor =
+            Runtime::Current()->GetInternTable()->InternStrong(descriptor);
+        RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
+                                     entries_.size());
+        entries_.push_back(entry);
+        return *entry;
+      } else {
+        // The descriptor is broken return the unknown type as there's nothing sensible that
+        // could be done at runtime
+        return Unknown();
+      }
+    }
+  }
+}
+
+const RegType& RegTypeCache::FromClass(Class* klass) {
+  if (klass->IsPrimitive()) {
+    RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
+    // entries should be sized greater than primitive types
+    DCHECK_GT(entries_.size(), static_cast<size_t>(type));
+    RegType* entry = entries_[type];
+    if (entry == NULL) {
+      entry = new RegType(type, klass, 0, type);
+      entries_[type] = entry;
+    }
+    return *entry;
+  } else {
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+    entries_.push_back(entry);
+    return *entry;
+  }
+}
+
+const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
+  RegType* entry;
+  if (type.IsUnresolvedTypes()) {
+    String* descriptor = type.GetDescriptor();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUnresolvedAndUninitializedReference() &&
+          cur_entry->GetAllocationPc() == allocation_pc &&
+          cur_entry->GetDescriptor() == descriptor) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
+                        descriptor, allocation_pc, entries_.size());
+  } else {
+    Class* klass = type.GetClass();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUninitializedReference() &&
+          cur_entry->GetAllocationPc() == allocation_pc &&
+          cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUninitializedReference,
+                        klass, allocation_pc, entries_.size());
+  }
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
+  RegType* entry;
+  if (uninit_type.IsUnresolvedTypes()) {
+    String* descriptor = uninit_type.GetDescriptor();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
+  } else {
+    Class* klass = uninit_type.GetClass();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+  }
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::UninitializedThisArgument(Class* klass) {
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+    RegType* cur_entry = entries_[i];
+    if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
+      return *cur_entry;
+    }
+  }
+  RegType* entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0,
+                               entries_.size());
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::FromType(RegType::Type type) {
+  CHECK(type < RegType::kRegTypeReference);
+  switch (type) {
+    case RegType::kRegTypeBoolean:  return From(type, NULL, "Z");
+    case RegType::kRegTypeByte:     return From(type, NULL, "B");
+    case RegType::kRegTypeShort:    return From(type, NULL, "S");
+    case RegType::kRegTypeChar:     return From(type, NULL, "C");
+    case RegType::kRegTypeInteger:  return From(type, NULL, "I");
+    case RegType::kRegTypeFloat:    return From(type, NULL, "F");
+    case RegType::kRegTypeLongLo:
+    case RegType::kRegTypeLongHi:   return From(type, NULL, "J");
+    case RegType::kRegTypeDoubleLo:
+    case RegType::kRegTypeDoubleHi: return From(type, NULL, "D");
+    default:                        return From(type, NULL, "");
+  }
+}
+
+const RegType& RegTypeCache::FromCat1Const(int32_t value) {
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+    RegType* cur_entry = entries_[i];
+    if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
+      return *cur_entry;
+    }
+  }
+  RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::GetComponentType(const RegType& array, const ClassLoader* loader) {
+  CHECK(array.IsArrayTypes());
+  if (array.IsUnresolvedTypes()) {
+    std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
+    std::string component(descriptor.substr(1, descriptor.size() - 1));
+    return FromDescriptor(loader, component.c_str());
+  } else {
+    return FromClass(array.GetClass()->GetComponentType());
+  }
+}
+
+}  // verifier
+}  // art