Quick compiler: complete switch support

With this CL, all Dex opcodes are handled.  We pass 79 run-tests,
and fail 12.  Temporarily going single-threaded for the Quick
compiler (llvm's ir-builder dies otherwise - will figure out what I
need to do for multi-threaded operation in a later CL).

Change-Id: I389e94d9a831096d4e7493460729933fb45e649e
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index 71921d0..cf7b6ff 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -172,6 +172,34 @@
   bb->fallThrough = NULL;
 }
 
+void convertSparseSwitch(CompilationUnit* cUnit, BasicBlock* bb,
+                         int32_t tableOffset, RegLocation rlSrc)
+{
+  const Instruction::SparseSwitchPayload* payload =
+      reinterpret_cast<const Instruction::SparseSwitchPayload*>(
+      cUnit->insns + cUnit->currentDalvikOffset + tableOffset);
+
+  const int32_t* keys = payload->GetKeys();
+  const int32_t* targets = payload->GetTargets();
+
+  llvm::Value* value = getLLVMValue(cUnit, rlSrc.origSReg);
+
+  llvm::SwitchInst* sw =
+    cUnit->irb->CreateSwitch(value, getLLVMBlock(cUnit, bb->fallThrough->id),
+                             payload->case_count);
+
+  for (size_t i = 0; i < payload->case_count; ++i) {
+    llvm::BasicBlock* llvmBB =
+        findCaseTarget(cUnit, cUnit->currentDalvikOffset + targets[i]);
+    sw->addCase(cUnit->irb->getInt32(keys[i]), llvmBB);
+  }
+  llvm::MDNode* switchNode =
+      llvm::MDNode::get(*cUnit->context, cUnit->irb->getInt32(tableOffset));
+  sw->setMetadata("SwitchTable", switchNode);
+  bb->taken = NULL;
+  bb->fallThrough = NULL;
+}
+
 void convertSget(CompilationUnit* cUnit, int32_t fieldIndex,
                  greenland::IntrinsicHelper::IntrinsicId id,
                  RegLocation rlDest)
@@ -301,7 +329,7 @@
 void convertThrowVerificationError(CompilationUnit* cUnit, int info1, int info2)
 {
   llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(
-      greenland::IntrinsicHelper::Throw);
+      greenland::IntrinsicHelper::ThrowVerificationError);
   llvm::SmallVector<llvm::Value*, 2> args;
   args.push_back(cUnit->irb->getInt32(info1));
   args.push_back(cUnit->irb->getInt32(info2));
@@ -1537,12 +1565,9 @@
       convertPackedSwitch(cUnit, bb, vB, rlSrc[0]);
       break;
 
-#if 0
-
     case Instruction::SPARSE_SWITCH:
-      genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
+      convertSparseSwitch(cUnit, bb, vB, rlSrc[0]);
       break;
-#endif
 
     default:
       UNIMPLEMENTED(FATAL) << "Unsupported Dex opcode 0x" << std::hex << opcode;
@@ -2609,7 +2634,14 @@
           static_cast<llvm::ConstantInt*>(tableOffsetNode->getOperand(0));
   int32_t tableOffset = tableOffsetValue->getSExtValue();
   RegLocation rlSrc = getLoc(cUnit, testVal);
-  genPackedSwitch(cUnit, tableOffset, rlSrc);
+  const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
+  u2 tableMagic = *table;
+  if (tableMagic == 0x100) {
+    genPackedSwitch(cUnit, tableOffset, rlSrc);
+  } else {
+    DCHECK_EQ(tableMagic, 0x200);
+    genSparseSwitch(cUnit, tableOffset, rlSrc);
+  }
 }
 
 void cvtInvoke(CompilationUnit* cUnit, llvm::CallInst* callInst,
@@ -2859,6 +2891,9 @@
             case greenland::IntrinsicHelper::HLSputDouble:
               cvtSput(cUnit, callInst, true /* wide */, false /* Object */);
               break;
+            case greenland::IntrinsicHelper::HLSputObject:
+              cvtSput(cUnit, callInst, false /* wide */, true /* Object */);
+              break;
             case greenland::IntrinsicHelper::GetException:
               cvtMoveException(cUnit, callInst);
               break;
@@ -3117,8 +3152,8 @@
   int numBasicBlocks = func->getBasicBlockList().size();
   // Allocate a list for LIR basic block labels
   cUnit->blockLabelList =
-    (void*)oatNew(cUnit, sizeof(LIR) * numBasicBlocks, true, kAllocLIR);
-  LIR* labelList = (LIR*)cUnit->blockLabelList;
+    (LIR*)oatNew(cUnit, sizeof(LIR) * numBasicBlocks, true, kAllocLIR);
+  LIR* labelList = cUnit->blockLabelList;
   int nextLabel = 0;
   for (llvm::Function::iterator i = func->begin(),
        e = func->end(); i != e; ++i) {