diff options
author | 2012-06-26 16:27:56 -0700 | |
---|---|---|
committer | 2012-06-26 19:15:57 -0700 | |
commit | 32412961b1c912faba30cdecd3560ab05e463807 (patch) | |
tree | 8d7656dfd7394865442d0374dc7f3fcd5cd4972f | |
parent | 4f1181fe061d3529f72e1237e7662bf9bc73c6e2 (diff) |
Quick compiler exception support
Handle MOVE_RESULT, THROW and THROW_VERIFICATION_ERROR. Enable
runtests 007 and 014 to pass. Minor munging of the tests to make
them easier to selectively compile with the Quick compiler.
Change-Id: I756def54d81771b144e8ebc213cd90077e23758b
-rw-r--r-- | src/compiler/Frontend.cc | 4 | ||||
-rw-r--r-- | src/compiler/codegen/MethodBitcode.cc | 109 | ||||
-rw-r--r-- | src/greenland/intrinsic_func_list.def | 14 | ||||
-rw-r--r-- | test/005-args/src/Main.java | 5 | ||||
-rw-r--r-- | test/007-exceptions/expected.txt | 11 | ||||
-rw-r--r-- | test/007-exceptions/src/Main.java | 5 | ||||
-rw-r--r-- | test/014-math3/src/Main.java | 5 |
7 files changed, 135 insertions, 18 deletions
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index 34798f92b1..9e4b85787c 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -761,8 +761,12 @@ CompiledMethod* oatCompileMethod(Compiler& compiler, if ((PrettyMethod(method_idx, dex_file).find("fibonacci") != std::string::npos) || (PrettyMethod(method_idx, dex_file).find("HelloWorld") != std::string::npos) || (PrettyMethod(method_idx, dex_file).find("count10_006") != std::string::npos) + || (PrettyMethod(method_idx, dex_file).find("exceptions_007") != std::string::npos) + || (PrettyMethod(method_idx, dex_file).find("catchAndRethrow") != std::string::npos) + || (PrettyMethod(method_idx, dex_file).find("throwNullPointerException") != std::string::npos) || (PrettyMethod(method_idx, dex_file).find("math_012") != std::string::npos) || (PrettyMethod(method_idx, dex_file).find("math_013") != std::string::npos) + || (PrettyMethod(method_idx, dex_file).find("math_014") != std::string::npos) || (PrettyMethod(method_idx, dex_file).find("float_017") != std::string::npos) ) { cUnit->genBitcode = true; diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index 1c4fdf4640..cf990ec79a 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -203,6 +203,34 @@ llvm::Value* emitCopy(CompilationUnit* cUnit, llvm::ArrayRef<llvm::Value*> src, return cUnit->irb->CreateCall(intr, src); } +void convertMoveException(CompilationUnit* cUnit, RegLocation rlDest) +{ + llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction( + greenland::IntrinsicHelper::GetException); + llvm::Value* res = cUnit->irb->CreateCall(func); + defineValue(cUnit, res, rlDest.origSReg); +} + +void convertThrow(CompilationUnit* cUnit, RegLocation rlSrc) +{ + llvm::Value* src = getLLVMValue(cUnit, rlSrc.origSReg); + llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction( + greenland::IntrinsicHelper::Throw); + cUnit->irb->CreateCall(func, src); + cUnit->irb->CreateUnreachable(); +} + +void convertThrowVerificationError(CompilationUnit* cUnit, int info1, int info2) +{ + llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction( + greenland::IntrinsicHelper::Throw); + llvm::SmallVector<llvm::Value*, 2> args; + args.push_back(cUnit->irb->getInt32(info1)); + args.push_back(cUnit->irb->getInt32(info2)); + cUnit->irb->CreateCall(func, args); + cUnit->irb->CreateUnreachable(); +} + void emitSuspendCheck(CompilationUnit* cUnit) { greenland::IntrinsicHelper::IntrinsicId id = @@ -474,6 +502,7 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, RegLocation rlDest = badLoc; RegLocation rlResult = badLoc; Instruction::Code opcode = mir->dalvikInsn.opcode; + uint32_t vA = mir->dalvikInsn.vA; uint32_t vB = mir->dalvikInsn.vB; uint32_t vC = mir->dalvikInsn.vC; @@ -855,6 +884,17 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, convertNewInstance(cUnit, bb, vB, rlDest); break; + case Instruction::MOVE_EXCEPTION: + convertMoveException(cUnit, rlDest); + break; + + case Instruction::THROW: + convertThrow(cUnit, rlSrc[0]); + break; + + case Instruction::THROW_VERIFICATION_ERROR: + convertThrowVerificationError(cUnit, vA, vB); + break; #if 0 @@ -1136,6 +1176,7 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, #endif default: + UNIMPLEMENTED(FATAL) << "Unsupported Dex opcode 0x" << std::hex << opcode; res = true; } if (objectDefinition) { @@ -1494,13 +1535,7 @@ RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) { SafeMap<llvm::Value*, RegLocation>::iterator it = cUnit->locMap.find(val); if (it == cUnit->locMap.end()) { std::string valName = val->getName().str(); - DCHECK(!valName.empty()); - if (valName[0] == 'v') { - int baseSReg = INVALID_SREG; - sscanf(valName.c_str(), "v%d_", &baseSReg); - res = cUnit->regLocation[baseSReg]; - cUnit->locMap.Put(val, res); - } else { + if (valName.empty()) { UNIMPLEMENTED(WARNING) << "Need to handle unnamed llvm temps"; memset(&res, 0, sizeof(res)); res.location = kLocPhysReg; @@ -1509,6 +1544,12 @@ RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) { res.sRegLow = INVALID_SREG; res.origSReg = INVALID_SREG; cUnit->locMap.Put(val, res); + } else { + DCHECK_EQ(valName[0], 'v'); + int baseSReg = INVALID_SREG; + sscanf(valName.c_str(), "v%d_", &baseSReg); + res = cUnit->regLocation[baseSReg]; + cUnit->locMap.Put(val, res); } } else { res = it->second; @@ -1773,7 +1814,7 @@ void cvtConstString(CompilationUnit* cUnit, llvm::CallInst* callInst) void cvtNewInstance(CompilationUnit* cUnit, llvm::CallInst* callInst) { - DCHECK(callInst->getNumArgOperands() == 1); + DCHECK_EQ(callInst->getNumArgOperands(), 1U); llvm::ConstantInt* typeIdxVal = llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); uint32_t typeIdx = typeIdxVal->getZExtValue(); @@ -1781,10 +1822,47 @@ void cvtNewInstance(CompilationUnit* cUnit, llvm::CallInst* callInst) genNewInstance(cUnit, typeIdx, rlDest); } +void cvtThrowVerificationError(CompilationUnit* cUnit, llvm::CallInst* callInst) +{ + DCHECK_EQ(callInst->getNumArgOperands(), 2U); + llvm::ConstantInt* info1 = + llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); + llvm::ConstantInt* info2 = + llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(1)); + genThrowVerificationError(cUnit, info1->getZExtValue(), info2->getZExtValue()); +} + +void cvtThrow(CompilationUnit* cUnit, llvm::CallInst* callInst) +{ + DCHECK_EQ(callInst->getNumArgOperands(), 1U); + llvm::Value* src = callInst->getArgOperand(0); + RegLocation rlSrc = getLoc(cUnit, src); + genThrow(cUnit, rlSrc); +} + +void cvtMoveException(CompilationUnit* cUnit, llvm::CallInst* callInst) +{ + DCHECK_EQ(callInst->getNumArgOperands(), 0U); + int exOffset = Thread::ExceptionOffset().Int32Value(); + RegLocation rlDest = getLoc(cUnit, callInst); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); +#if defined(TARGET_X86) + newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset); + newLIR2(cUnit, kX86Mov32TI, exOffset, 0); +#else + int resetReg = oatAllocTemp(cUnit); + loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg); + loadConstant(cUnit, resetReg, 0); + storeWordDisp(cUnit, rSELF, exOffset, resetReg); + oatFreeTemp(cUnit, resetReg); +#endif + storeValue(cUnit, rlDest, rlResult); +} + void cvtSget(CompilationUnit* cUnit, llvm::CallInst* callInst, bool isWide, bool isObject) { - DCHECK(callInst->getNumArgOperands() == 1); + DCHECK_EQ(callInst->getNumArgOperands(), 1U); llvm::ConstantInt* typeIdxVal = llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); uint32_t typeIdx = typeIdxVal->getZExtValue(); @@ -2001,6 +2079,15 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) case greenland::IntrinsicHelper::SgetObj: cvtSget(cUnit, callInst, false /* wide */, true /* Object */); break; + case greenland::IntrinsicHelper::GetException: + cvtMoveException(cUnit, callInst); + break; + case greenland::IntrinsicHelper::Throw: + cvtThrow(cUnit, callInst); + break; + case greenland::IntrinsicHelper::ThrowVerificationError: + cvtThrow(cUnit, callInst); + break; case greenland::IntrinsicHelper::UnknownId: cvtCall(cUnit, callInst, callee); break; @@ -2031,6 +2118,9 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) case llvm::Instruction::FDiv: cvtBinFPOp(cUnit, kOpDiv, inst); break; case llvm::Instruction::FRem: cvtBinFPOp(cUnit, kOpRem, inst); break; + case llvm::Instruction::Unreachable: + break; // FIXME: can we really ignore these? + case llvm::Instruction::Invoke: case llvm::Instruction::Trunc: case llvm::Instruction::ZExt: @@ -2051,7 +2141,6 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) case llvm::Instruction::URem: case llvm::Instruction::UDiv: case llvm::Instruction::Resume: - case llvm::Instruction::Unreachable: case llvm::Instruction::Alloca: case llvm::Instruction::GetElementPtr: case llvm::Instruction::Fence: diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def index 70f5512bcb..e2a5557fb3 100644 --- a/src/greenland/intrinsic_func_list.def +++ b/src/greenland/intrinsic_func_list.def @@ -108,6 +108,20 @@ _EVAL_DEF_INTRINSICS_FUNC(ThrowIndexOutOfBounds, kVoidTy, _EXPAND_ARG2(kInt32Ty, kInt32Ty)) +// void dex_lang_throw(exception_object) +_EVAL_DEF_INTRINSICS_FUNC(Throw, + dex_lang_throw, + kAttrNoThrow, + kVoidTy, + _EXPAND_ARG1(kJavaObjectTy)) + +// void dex_lang_throw_verification_error(int info1, int info2) +_EVAL_DEF_INTRINSICS_FUNC(ThrowVerificationError, + dex_lang_throw_verification_error, + kAttrNoThrow, + kVoidTy, + _EXPAND_ARG2(kInt32Ty, kInt32Ty)) + //---------------------------------------------------------------------------- // ConstString //---------------------------------------------------------------------------- diff --git a/test/005-args/src/Main.java b/test/005-args/src/Main.java index 1240ec5e8e..8abb63c1ba 100644 --- a/test/005-args/src/Main.java +++ b/test/005-args/src/Main.java @@ -18,8 +18,11 @@ * Test passing arguments of various sizes */ public class Main { - public static void main (String args[]) { + public static void args_005() { new ArgsTest() .argTest(123, 'q', 3.343434, 0x1122334455667788L, 0.12345f); } + public static void main (String args[]) { + args_005(); + } } diff --git a/test/007-exceptions/expected.txt b/test/007-exceptions/expected.txt index 982c777e03..ef6eaff59a 100644 --- a/test/007-exceptions/expected.txt +++ b/test/007-exceptions/expected.txt @@ -1,8 +1,9 @@ Got an NPE: second throw java.lang.NullPointerException: second throw - at Main.catchAndRethrow(Main.java:36) - at Main.main(Main.java:23) + at Main.catchAndRethrow(Main.java:39) + at Main.exceptions_007(Main.java:23) + at Main.main(Main.java:31) Caused by: java.lang.NullPointerException: first throw - at Main.throwNullPointerException(Main.java:43) - at Main.catchAndRethrow(Main.java:33) - ... 1 more + at Main.throwNullPointerException(Main.java:46) + at Main.catchAndRethrow(Main.java:36) + ... 2 more diff --git a/test/007-exceptions/src/Main.java b/test/007-exceptions/src/Main.java index c7da2153d0..1f76f12460 100644 --- a/test/007-exceptions/src/Main.java +++ b/test/007-exceptions/src/Main.java @@ -18,7 +18,7 @@ * Exceptions across method calls */ public class Main { - public static void main (String args[]) { + public static void exceptions_007() { try { catchAndRethrow(); } catch (NullPointerException npe) { @@ -27,6 +27,9 @@ public class Main { npe.printStackTrace(); } } + public static void main (String args[]) { + exceptions_007(); + } private static void catchAndRethrow() { try { diff --git a/test/014-math3/src/Main.java b/test/014-math3/src/Main.java index f55b17a947..07e5be3183 100644 --- a/test/014-math3/src/Main.java +++ b/test/014-math3/src/Main.java @@ -18,7 +18,7 @@ * Test math exceptions */ public class Main { - public static void main(String args[]) { + public static void math_014() { int expectedThrows = 2; int i; long j; @@ -54,4 +54,7 @@ public class Main { else System.out.println("testMath3 success"); } + public static void main(String args[]) { + math_014(); + } } |