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) {
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index 62939ba..d49b329 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -447,7 +447,7 @@
break;
case Instruction::SPARSE_SWITCH:
- genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
+ genSparseSwitch(cUnit, vB, rlSrc[0]);
break;
case Instruction::CMPL_FLOAT:
@@ -878,7 +878,7 @@
bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
{
MIR* mir;
- LIR* labelList = (LIR*) cUnit->blockLabelList;
+ LIR* labelList = cUnit->blockLabelList;
int blockId = bb->id;
cUnit->curBlock = bb;
@@ -992,7 +992,7 @@
/* Set basic block labels */
bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
{
- LIR* labelList = (LIR*) cUnit->blockLabelList;
+ LIR* labelList = cUnit->blockLabelList;
int blockId = bb->id;
cUnit->curBlock = bb;
@@ -1037,7 +1037,7 @@
{
/* Used to hold the labels of each block */
cUnit->blockLabelList =
- (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
+ (LIR*) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
kPreOrderDFSTraversal, false /* Iterative */);
diff --git a/src/compiler/codegen/arm/FP/Thumb2VFP.cc b/src/compiler/codegen/arm/FP/Thumb2VFP.cc
index 1b67ecb..3ea28c9 100644
--- a/src/compiler/codegen/arm/FP/Thumb2VFP.cc
+++ b/src/compiler/codegen/arm/FP/Thumb2VFP.cc
@@ -162,7 +162,7 @@
void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
bool gtBias, bool isDouble)
{
- LIR* labelList = (LIR*)cUnit->blockLabelList;
+ LIR* labelList = cUnit->blockLabelList;
LIR* target = &labelList[bb->taken->id];
RegLocation rlSrc1;
RegLocation rlSrc2;
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 579aa43..d2532b7 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -369,7 +369,7 @@
* cbnz rIdx, lp
*/
void genSparseSwitch(CompilationUnit* cUnit, uint32_t tableOffset,
- RegLocation rlSrc, LIR* labelList)
+ RegLocation rlSrc)
{
const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
if (cUnit->printMe) {
@@ -654,7 +654,7 @@
void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
{
- LIR* labelList = (LIR*)cUnit->blockLabelList;
+ LIR* labelList = cUnit->blockLabelList;
LIR* taken = &labelList[bb->taken->id];
LIR* notTaken = &labelList[bb->fallThrough->id];
RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0);
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index 090c086..7712985 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -64,7 +64,7 @@
*
*/
void genSparseSwitch(CompilationUnit* cUnit, uint32_t tableOffset,
- RegLocation rlSrc, LIR* labelList)
+ RegLocation rlSrc)
{
const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
if (cUnit->printMe) {
diff --git a/src/compiler/codegen/x86/X86/Gen.cc b/src/compiler/codegen/x86/X86/Gen.cc
index f5466ee..b0b6ba8 100644
--- a/src/compiler/codegen/x86/X86/Gen.cc
+++ b/src/compiler/codegen/x86/X86/Gen.cc
@@ -52,7 +52,7 @@
BasicBlock *findBlock(CompilationUnit* cUnit, unsigned int codeOffset,
bool split, bool create, BasicBlock** immedPredBlockP);
void genSparseSwitch(CompilationUnit* cUnit, uint32_t tableOffset,
- RegLocation rlSrc, LIR* labelList)
+ RegLocation rlSrc)
{
const u2* table = cUnit->insns + cUnit->currentDalvikOffset + tableOffset;
if (cUnit->printMe) {
@@ -67,6 +67,7 @@
BasicBlock* case_block = findBlock(cUnit,
cUnit->currentDalvikOffset + targets[i],
false, false, NULL);
+ LIR* labelList = cUnit->blockLabelList;
opCmpImmBranch(cUnit, kCondEq, rlSrc.lowReg, key,
&labelList[case_block->id]);
}