Enable bitcode verification for debug builds
Turn bitcode function verification on for debug Quick and
Portable builds. Also in this CL, some sanity checking for
the dex2pc table and a temporary workaround for excessive filename
lengths for bitcode file dumps.
Change-Id: I430ed28824b078c03be7826cb13876cdcb8a0fec
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 434320d..593fce5 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -576,6 +576,7 @@
*/
int liveSReg;
#endif
+ std::set<uint32_t> catches;
int* opcodeCount; // Count Dalvik opcodes for tuning
};
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 09bc054..d1259b7 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -700,6 +700,7 @@
false /* creat */,
NULL /* immedPredBlockP */);
catchBlock->catchEntry = true;
+ cUnit->catches.insert(catchBlock->startOffset);
SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
oatNew(cUnit, sizeof(SuccessorBlockInfo), false, kAllocSuccessor);
successorBlockInfo->block = catchBlock;
@@ -840,7 +841,9 @@
}
#if defined(ART_USE_QUICK_COMPILER)
if (cUnit->genBitcode) {
- //cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
+#ifndef NDEBUG
+ cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
+#endif
//cUnit->printMe = true;
//cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
}
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index 22aacc2..ccc2a83 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -764,6 +764,40 @@
return offset;
}
+// Make sure we have a code address for every declared catch entry
+bool verifyCatchEntries(CompilationUnit* cUnit)
+{
+ bool success = true;
+ for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
+ uint32_t dexPc = *it;
+ bool found = false;
+ for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
+ if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
+ success = false;
+ }
+ }
+ // Now, try in the other direction
+ for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
+ uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
+ if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
+ LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
+ success = false;
+ }
+ }
+ if (!success) {
+ LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
+ << cUnit->dex2pcMappingTable.size()/2;
+ }
+ return success;
+}
+
void createMappingTables(CompilationUnit* cUnit)
{
for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
@@ -776,6 +810,7 @@
cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
}
}
+ DCHECK(verifyCatchEntries(cUnit));
cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
cUnit->dex2pcMappingTable.size());
cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index cff4ee5..a9e134f 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -540,10 +540,16 @@
if (index == -1) {
return;
}
+ llvm::Type* ty = newVal->getType();
greenland::IntrinsicHelper::IntrinsicId id =
greenland::IntrinsicHelper::SetShadowFrameEntry;
llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(id);
llvm::Value* tableSlot = cUnit->irb->getInt32(index);
+ // If newVal is a Null pointer, we'll see it here as a const int. Replace
+ if (!ty->isPointerTy()) {
+ // TODO: assert newVal created w/ dex_lang_const_int(0) or dex_lang_const_float(0)
+ newVal = cUnit->irb->GetJNull();
+ }
llvm::Value* args[] = { newVal, tableSlot };
cUnit->irb->CreateCall(func, args);
}
@@ -2112,9 +2118,14 @@
std::string errmsg;
std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
oatReplaceSpecialChars(fname);
- // TODO: make configurable
+ // TODO: make configurable change naming mechanism to avoid fname length issues.
fname = StringPrintf("/sdcard/Bitcode/%s.bc", fname.c_str());
+ if (fname.size() > 240) {
+ LOG(INFO) << "Warning: bitcode filename too long. Truncated.";
+ fname.resize(240);
+ }
+
llvm::OwningPtr<llvm::tool_output_file> out_file(
new llvm::tool_output_file(fname.c_str(), errmsg,
llvm::raw_fd_ostream::F_Binary));