Separate DexIr building from constructors.

Move all the construction from DexFile out of the constructors of the
basic IR.

Bug: 29921113
Change-Id: I3f79c104ce7183ddde73f143c047061416009a54
Test: test-art-host-gtest
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 0b31614..0d0b37a 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -30,7 +30,7 @@
 #include <sstream>
 #include <vector>
 
-#include "dex_ir.h"
+#include "dex_ir_builder.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "utils.h"
@@ -501,20 +501,33 @@
   }
   fprintf(out_file_, "annotations_off     : %d (0x%06x)\n",
           annotations_offset, annotations_offset);
-  fprintf(out_file_, "class_data_off      : %d (0x%06x)\n",
-          class_def->GetClassData()->GetOffset(), class_def->GetClassData()->GetOffset());
+  if (class_def->GetClassData() == nullptr) {
+    fprintf(out_file_, "class_data_off      : %d (0x%06x)\n", 0, 0);
+  } else {
+    fprintf(out_file_, "class_data_off      : %d (0x%06x)\n",
+            class_def->GetClassData()->GetOffset(), class_def->GetClassData()->GetOffset());
+  }
 
   // Fields and methods.
   dex_ir::ClassData* class_data = class_def->GetClassData();
-  if (class_data != nullptr) {
-    fprintf(out_file_, "static_fields_size  : %zu\n", class_data->StaticFields().size());
-    fprintf(out_file_, "instance_fields_size: %zu\n", class_data->InstanceFields().size());
-    fprintf(out_file_, "direct_methods_size : %zu\n", class_data->DirectMethods().size());
-    fprintf(out_file_, "virtual_methods_size: %zu\n", class_data->VirtualMethods().size());
+  if (class_data != nullptr && class_data->StaticFields() != nullptr) {
+    fprintf(out_file_, "static_fields_size  : %zu\n", class_data->StaticFields()->size());
   } else {
     fprintf(out_file_, "static_fields_size  : 0\n");
+  }
+  if (class_data != nullptr && class_data->InstanceFields() != nullptr) {
+    fprintf(out_file_, "instance_fields_size: %zu\n", class_data->InstanceFields()->size());
+  } else {
     fprintf(out_file_, "instance_fields_size: 0\n");
+  }
+  if (class_data != nullptr && class_data->DirectMethods() != nullptr) {
+    fprintf(out_file_, "direct_methods_size : %zu\n", class_data->DirectMethods()->size());
+  } else {
     fprintf(out_file_, "direct_methods_size : 0\n");
+  }
+  if (class_data != nullptr && class_data->VirtualMethods() != nullptr) {
+    fprintf(out_file_, "virtual_methods_size: %zu\n", class_data->VirtualMethods()->size());
+  } else {
     fprintf(out_file_, "virtual_methods_size: 0\n");
   }
   fprintf(out_file_, "\n");
@@ -524,12 +537,11 @@
  * Dumps an annotation set item.
  */
 static void DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item) {
-  if (set_item == nullptr || set_item->GetItems().size() == 0) {
+  if (set_item == nullptr || set_item->GetItems()->size() == 0) {
     fputs("  empty-annotation-set\n", out_file_);
     return;
   }
-  for (std::unique_ptr<dex_ir::AnnotationSetItem::AnnotationItem>& annotation :
-       set_item->GetItems()) {
+  for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : *set_item->GetItems()) {
     if (annotation == nullptr) {
       continue;
     }
@@ -561,12 +573,9 @@
   fprintf(out_file_, "Class #%d annotations:\n", idx);
 
   dex_ir::AnnotationSetItem* class_set_item = annotations_directory->GetClassAnnotation();
-  std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::FieldAnnotation>>& fields =
-      annotations_directory->GetFieldAnnotations();
-  std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::MethodAnnotation>>& methods =
-      annotations_directory->GetMethodAnnotations();
-  std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::ParameterAnnotation>>& parameters =
-      annotations_directory->GetParameterAnnotations();
+  dex_ir::FieldAnnotationVector* fields = annotations_directory->GetFieldAnnotations();
+  dex_ir::MethodAnnotationVector* methods = annotations_directory->GetMethodAnnotations();
+  dex_ir::ParameterAnnotationVector* parameters = annotations_directory->GetParameterAnnotations();
 
   // Annotations on the class itself.
   if (class_set_item != nullptr) {
@@ -575,34 +584,40 @@
   }
 
   // Annotations on fields.
-  for (auto& field : fields) {
-    const dex_ir::FieldId* field_id = field->GetFieldId();
-    const uint32_t field_idx = field_id->GetOffset();
-    const char* field_name = field_id->Name()->Data();
-    fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name);
-    DumpAnnotationSetItem(field->GetAnnotationSetItem());
+  if (fields != nullptr) {
+    for (auto& field : *fields) {
+      const dex_ir::FieldId* field_id = field->GetFieldId();
+      const uint32_t field_idx = field_id->GetOffset();
+      const char* field_name = field_id->Name()->Data();
+      fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name);
+      DumpAnnotationSetItem(field->GetAnnotationSetItem());
+    }
   }
 
   // Annotations on methods.
-  for (auto& method : methods) {
-    const dex_ir::MethodId* method_id = method->GetMethodId();
-    const uint32_t method_idx = method_id->GetOffset();
-    const char* method_name = method_id->Name()->Data();
-    fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name);
-    DumpAnnotationSetItem(method->GetAnnotationSetItem());
+  if (methods != nullptr) {
+    for (auto& method : *methods) {
+      const dex_ir::MethodId* method_id = method->GetMethodId();
+      const uint32_t method_idx = method_id->GetOffset();
+      const char* method_name = method_id->Name()->Data();
+      fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name);
+      DumpAnnotationSetItem(method->GetAnnotationSetItem());
+    }
   }
 
   // Annotations on method parameters.
-  for (auto& parameter : parameters) {
-    const dex_ir::MethodId* method_id = parameter->GetMethodId();
-    const uint32_t method_idx = method_id->GetOffset();
-    const char* method_name = method_id->Name()->Data();
-    fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name);
-    uint32_t j = 0;
-    for (auto& annotation : parameter->GetAnnotations()) {
-      fprintf(out_file_, "#%u\n", j);
-      DumpAnnotationSetItem(annotation.get());
-      ++j;
+  if (parameters != nullptr) {
+    for (auto& parameter : *parameters) {
+      const dex_ir::MethodId* method_id = parameter->GetMethodId();
+      const uint32_t method_idx = method_id->GetOffset();
+      const char* method_name = method_id->Name()->Data();
+      fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name);
+      uint32_t j = 0;
+      for (auto& annotation : *parameter->GetAnnotations()) {
+        fprintf(out_file_, "#%u\n", j);
+        DumpAnnotationSetItem(annotation.get());
+        ++j;
+      }
     }
   }
 
@@ -612,7 +627,7 @@
 /*
  * Dumps an interface that a class declares to implement.
  */
-static void DumpInterface(dex_ir::TypeId* type_item, int i) {
+static void DumpInterface(const dex_ir::TypeId* type_item, int i) {
   const char* interface_name = type_item->GetStringId()->Data();
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "    #%d              : '%s'\n", i, interface_name);
@@ -1260,8 +1275,8 @@
   }
   while (it.HasNextVirtualMethod()) {
     DumpCFG(dex_file,
-                it.GetMemberIndex(),
-                it.GetMethodCodeItem());
+            it.GetMemberIndex(),
+            it.GetMethodCodeItem());
     it.Next();
   }
 }
@@ -1274,7 +1289,10 @@
  * If "*last_package" is nullptr or does not match the current class' package,
  * the value will be replaced with a newly-allocated string.
  */
-static void DumpClass(dex_ir::Header* header, int idx, char** last_package) {
+static void DumpClass(const DexFile* dex_file,
+                      dex_ir::Header* header,
+                      int idx,
+                      char** last_package) {
   dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
   // Omitting non-public class.
   if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) {
@@ -1290,7 +1308,7 @@
   }
 
   if (options_.show_cfg_) {
-    DumpCFG(&header->GetDexFile(), idx);
+    DumpCFG(dex_file, idx);
     return;
   }
 
@@ -1368,10 +1386,12 @@
   }
 
   // Interfaces.
-  std::vector<dex_ir::TypeId*>* interfaces = class_def->Interfaces();
-  for (uint32_t i = 0; i < interfaces->size(); i++) {
-    DumpInterface((*interfaces)[i], i);
-  }  // for
+  dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
+  if (interfaces != nullptr) {
+    for (uint32_t i = 0; i < interfaces->size(); i++) {
+      DumpInterface((*interfaces)[i], i);
+    }  // for
+  }
 
   // Fields and methods.
   dex_ir::ClassData* class_data = class_def->GetClassData();
@@ -1383,52 +1403,68 @@
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Static fields     -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::FieldItem>>& static_fields = class_data->StaticFields();
-  for (uint32_t i = 0; i < static_fields.size(); i++) {
-    DumpSField(header,
-               static_fields[i]->GetFieldId()->GetOffset(),
-               static_fields[i]->GetAccessFlags(),
-               i,
-               i < static_values_size ? (*static_values)[i].get() : nullptr);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::FieldItemVector* static_fields = class_data->StaticFields();
+    if (static_fields != nullptr) {
+      for (uint32_t i = 0; i < static_fields->size(); i++) {
+        DumpSField(header,
+                   (*static_fields)[i]->GetFieldId()->GetOffset(),
+                   (*static_fields)[i]->GetAccessFlags(),
+                   i,
+                   i < static_values_size ? (*static_values)[i].get() : nullptr);
+      }  // for
+    }
+  }
 
   // Instance fields.
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Instance fields   -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::FieldItem>>& instance_fields = class_data->InstanceFields();
-  for (uint32_t i = 0; i < instance_fields.size(); i++) {
-    DumpIField(header,
-               instance_fields[i]->GetFieldId()->GetOffset(),
-               instance_fields[i]->GetAccessFlags(),
-               i);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::FieldItemVector* instance_fields = class_data->InstanceFields();
+    if (instance_fields != nullptr) {
+      for (uint32_t i = 0; i < instance_fields->size(); i++) {
+        DumpIField(header,
+                   (*instance_fields)[i]->GetFieldId()->GetOffset(),
+                   (*instance_fields)[i]->GetAccessFlags(),
+                   i);
+      }  // for
+    }
+  }
 
   // Direct methods.
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Direct methods    -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::MethodItem>>& direct_methods = class_data->DirectMethods();
-  for (uint32_t i = 0; i < direct_methods.size(); i++) {
-    DumpMethod(header,
-               direct_methods[i]->GetMethodId()->GetOffset(),
-               direct_methods[i]->GetAccessFlags(),
-               direct_methods[i]->GetCodeItem(),
-               i);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::MethodItemVector* direct_methods = class_data->DirectMethods();
+    if (direct_methods != nullptr) {
+      for (uint32_t i = 0; i < direct_methods->size(); i++) {
+        DumpMethod(header,
+                   (*direct_methods)[i]->GetMethodId()->GetOffset(),
+                   (*direct_methods)[i]->GetAccessFlags(),
+                   (*direct_methods)[i]->GetCodeItem(),
+                 i);
+      }  // for
+    }
+  }
 
   // Virtual methods.
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Virtual methods   -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::MethodItem>>& virtual_methods = class_data->VirtualMethods();
-  for (uint32_t i = 0; i < virtual_methods.size(); i++) {
-    DumpMethod(header,
-               virtual_methods[i]->GetMethodId()->GetOffset(),
-               virtual_methods[i]->GetAccessFlags(),
-               virtual_methods[i]->GetCodeItem(),
-               i);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::MethodItemVector* virtual_methods = class_data->VirtualMethods();
+    if (virtual_methods != nullptr) {
+      for (uint32_t i = 0; i < virtual_methods->size(); i++) {
+        DumpMethod(header,
+                   (*virtual_methods)[i]->GetMethodId()->GetOffset(),
+                   (*virtual_methods)[i]->GetAccessFlags(),
+                   (*virtual_methods)[i]->GetCodeItem(),
+                   i);
+      }  // for
+    }
+  }
 
   // End of class.
   if (options_.output_format_ == kOutputPlain) {
@@ -1454,11 +1490,11 @@
     fprintf(out_file_, "Opened '%s', DEX version '%.3s'\n",
             file_name, dex_file->GetHeader().magic_ + 4);
   }
-  dex_ir::Header header(*dex_file);
+  dex_ir::Header* header = dex_ir::DexIrBuilder(*dex_file);
 
   // Headers.
   if (options_.show_file_headers_) {
-    DumpFileHeader(&header);
+    DumpFileHeader(header);
   }
 
   // Open XML context.
@@ -1468,9 +1504,9 @@
 
   // Iterate over all classes.
   char* package = nullptr;
-  const uint32_t class_defs_size = header.ClassDefsSize();
+  const uint32_t class_defs_size = header->ClassDefsSize();
   for (uint32_t i = 0; i < class_defs_size; i++) {
-    DumpClass(&header, i, &package);
+    DumpClass(dex_file, header, i, &package);
   }  // for
 
   // Free the last package allocated.