Implement array get and array put in optimizing.

Also fix a couple of assembler/disassembler issues.

Change-Id: I705c8572988c1a9c4df3172b304678529636d5f6
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 1f0b361..43e6b83 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -425,6 +425,41 @@
   return true;
 }
 
+void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
+                                     uint32_t dex_offset,
+                                     bool is_put,
+                                     Primitive::Type anticipated_type) {
+  uint8_t source_or_dest_reg = instruction.VRegA_23x();
+  uint8_t array_reg = instruction.VRegB_23x();
+  uint8_t index_reg = instruction.VRegC_23x();
+
+  DCHECK(IsTypeSupported(anticipated_type));
+
+  // We need one temporary for the null check, one for the index, and one for the length.
+  Temporaries temps(graph_, 3);
+
+  HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot);
+  object = new (arena_) HNullCheck(object, dex_offset);
+  current_block_->AddInstruction(object);
+  temps.Add(object);
+
+  HInstruction* length = new (arena_) HArrayLength(object);
+  current_block_->AddInstruction(length);
+  temps.Add(length);
+  HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt);
+  index = new (arena_) HBoundsCheck(index, length, dex_offset);
+  current_block_->AddInstruction(index);
+  temps.Add(index);
+  if (is_put) {
+    HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
+    // TODO: Insert a type check node if the type is Object.
+    current_block_->AddInstruction(new (arena_) HArraySet(object, index, value, dex_offset));
+  } else {
+    current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
+    UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
+  }
+}
+
 bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) {
   if (current_block_ == nullptr) {
     return true;  // Dead code
@@ -697,6 +732,24 @@
       break;
     }
 
+#define ARRAY_XX(kind, anticipated_type)                                          \
+    case Instruction::AGET##kind: {                                               \
+      BuildArrayAccess(instruction, dex_offset, false, anticipated_type);         \
+      break;                                                                      \
+    }                                                                             \
+    case Instruction::APUT##kind: {                                               \
+      BuildArrayAccess(instruction, dex_offset, true, anticipated_type);          \
+      break;                                                                      \
+    }
+
+    ARRAY_XX(, Primitive::kPrimInt);
+    ARRAY_XX(_WIDE, Primitive::kPrimLong);
+    ARRAY_XX(_OBJECT, Primitive::kPrimNot);
+    ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
+    ARRAY_XX(_BYTE, Primitive::kPrimByte);
+    ARRAY_XX(_CHAR, Primitive::kPrimChar);
+    ARRAY_XX(_SHORT, Primitive::kPrimShort);
+
     default:
       return false;
   }