Complete compiler portion of exception handling

Will still need much testing once the runtime portions are in place.

Change-Id: I90fc7c1fd89bfae89dfd19a6e422024b6b5454ec
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 89911fe..0db63f9 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -445,8 +445,7 @@
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
         loadBaseIndexed(cUnit, rlObj.lowReg, r0, rlResult.lowReg, 0, size);
         oatGenMemBarrier(cUnit, kSY);
         storeValue(cUnit, rlDest, rlResult);
@@ -459,8 +458,7 @@
         int fieldOffset = fieldPtr->GetOffset().Int32Value();
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
         loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
                      size, rlObj.sRegLow);
         if (isVolatile) {
@@ -481,8 +479,7 @@
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlSrc = loadValue(cUnit, rlSrc, regClass);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
         oatGenMemBarrier(cUnit, kSY);
         storeBaseIndexed(cUnit, rlObj.lowReg, r0, rlSrc.lowReg, 0, size);
     } else {
@@ -494,8 +491,7 @@
         int fieldOffset = fieldPtr->GetOffset().Int32Value();
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlSrc = loadValue(cUnit, rlSrc, regClass);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                    NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
 
         if (isVolatile) {
             oatGenMemBarrier(cUnit, kSY);
@@ -519,8 +515,7 @@
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
         opRegReg(cUnit, kOpAdd, r0, rlObj.lowReg);
         loadPair(cUnit, r0, rlResult.lowReg, rlResult.highReg);
         oatGenMemBarrier(cUnit, kSY);
@@ -537,8 +532,7 @@
 
         assert(rlDest.wide);
 
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
         opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
         rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
 
@@ -563,8 +557,7 @@
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
         opRegReg(cUnit, kOpAdd, r0, rlObj.lowReg);
         oatGenMemBarrier(cUnit, kSY);
         storePair(cUnit, r0, rlSrc.lowReg, rlSrc.highReg);
@@ -579,8 +572,7 @@
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
         int regPtr;
         rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
-        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
-                     NULL);/* null object? */
+        genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
         regPtr = oatAllocTemp(cUnit);
         opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
 
@@ -919,7 +911,7 @@
     assert(art::Monitor::kLwShapeThin == 0);
     loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
     oatLockCallTemps(cUnit);  // Prepare for explicit register usage
-    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
+    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir);
     loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3);
     newLIR3(cUnit, kThumb2Ldrex, r2, r1,
             Object::MonitorOffset().Int32Value() >> 2); // Get object->lock
@@ -970,7 +962,7 @@
     oatFlushAllRegs(cUnit);
     loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
     oatLockCallTemps(cUnit);  // Prepare for explicit register usage
-    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
+    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir);
     loadWordDisp(cUnit, r1, Object::MonitorOffset().Int32Value(), r2); // Get lock
     loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3);
     // Is lock unheld on lock or held by us (==threadId) on unlock?
@@ -1241,14 +1233,6 @@
     return branch;
 }
 
-/* Generate a unconditional branch to go to the interpreter */
-static inline ArmLIR* genTrap(CompilationUnit* cUnit, int dOffset,
-                                  ArmLIR* pcrLabel)
-{
-    ArmLIR* branch = opNone(cUnit, kOpUncondBr);
-    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
-}
-
 /*
  * Generate array store
  *
@@ -1269,8 +1253,7 @@
     ArmLIR*  pcrLabel = NULL;
 
     if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
-        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, r1,
-                                mir->offset, NULL);
+        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, r1, mir);
     }
     loadWordDisp(cUnit, rSELF,
                  OFFSETOF_MEMBER(Thread, pCanPutArrayElementFromCode), rLR);
@@ -1302,8 +1285,8 @@
         loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
         /* regPtr -> array data */
         opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
-        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
-                       pcrLabel);
+        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir,
+                       kArmThrowArrayBounds);
         oatFreeTemp(cUnit, regLen);
     } else {
         /* regPtr -> array data */
@@ -1334,8 +1317,7 @@
     ArmLIR*  pcrLabel = NULL;
 
     if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
-        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow,
-                                rlArray.lowReg, mir->offset, NULL);
+        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
     }
 
     regPtr = oatAllocTemp(cUnit);
@@ -1346,8 +1328,8 @@
         loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
         /* regPtr -> array data */
         opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
-        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
-                       pcrLabel);
+        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir,
+                       kArmThrowArrayBounds);
         oatFreeTemp(cUnit, regLen);
     } else {
         /* regPtr -> array data */
@@ -1409,8 +1391,7 @@
     ArmLIR*  pcrLabel = NULL;
 
     if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
-        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg,
-                                mir->offset, NULL);
+        pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
     }
 
     if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
@@ -1420,8 +1401,8 @@
         loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
         /* regPtr -> array data */
         opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
-        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
-                       pcrLabel);
+        genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir,
+                       kArmThrowArrayBounds);
         oatFreeTemp(cUnit, regLen);
     } else {
         /* regPtr -> array data */
@@ -1429,7 +1410,7 @@
     }
     /* at this point, regPtr points to array, 2 live temps */
     if ((size == kLong) || (size == kDouble)) {
-        //TODO: need specific wide routine that can handle fp regs
+        //TUNING: specific wide routine that can handle fp regs
         if (scale) {
             int rNewIndex = oatAllocTemp(cUnit);
             opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
@@ -1693,7 +1674,7 @@
         loadWordDisp(cUnit, rSELF, funcOffset, rLR);
         loadValueDirectFixed(cUnit, rlSrc1, r0);
         if (checkZero) {
-            genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
+            genImmedCheck(cUnit, kArmCondEq, r1, 0, mir, kArmThrowDivZero);
         }
         opReg(cUnit, kOpBlx, rLR);
         oatClobberCallRegs(cUnit);
@@ -1844,7 +1825,7 @@
     } else {
         // Reverse subtract: (src << (shift + 1)) - src.
         assert(powerOfTwoMinusOne);
-        // TODO: rsb dst, src, src lsl#lowestSetBit(lit + 1)
+        // TUNING: rsb dst, src, src lsl#lowestSetBit(lit + 1)
         int tReg = oatAllocTemp(cUnit);
         opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
         opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
@@ -1925,8 +1906,7 @@
         case OP_REM_INT_LIT8:
         case OP_REM_INT_LIT16:
             if (lit == 0) {
-                UNIMPLEMENTED(FATAL);
-                // FIXME: generate an explicit throw here
+                genImmedCheck(cUnit, kArmCondAl, 0, 0, mir, kArmThrowDivZero);
                 return false;
             }
             if (handleEasyDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit)) {