diff options
Diffstat (limited to 'src/compiler/codegen')
| -rw-r--r-- | src/compiler/codegen/CodegenFactory.cc | 6 | ||||
| -rw-r--r-- | src/compiler/codegen/GenInvoke.cc | 10 | ||||
| -rw-r--r-- | src/compiler/codegen/MethodBitcode.cc | 151 | ||||
| -rw-r--r-- | src/compiler/codegen/MethodCodegenDriver.cc | 4 | ||||
| -rw-r--r-- | src/compiler/codegen/Ralloc.h | 1 | ||||
| -rw-r--r-- | src/compiler/codegen/RallocUtil.cc | 11 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArchFactory.cc | 5 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/ArchFactory.cc | 5 | ||||
| -rw-r--r-- | src/compiler/codegen/x86/ArchFactory.cc | 5 |
9 files changed, 153 insertions, 45 deletions
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc index 71b557c0d8..9d380c7e36 100644 --- a/src/compiler/codegen/CodegenFactory.cc +++ b/src/compiler/codegen/CodegenFactory.cc @@ -292,17 +292,17 @@ void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) /* Utilities to load the current Method* */ void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt) { - loadValueDirectFixed(cUnit, cUnit->regLocation[cUnit->methodSReg], rTgt); + loadValueDirectFixed(cUnit, cUnit->methodLoc, rTgt); } RegLocation loadCurrMethod(CompilationUnit *cUnit) { - return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg); + return loadValue(cUnit, cUnit->methodLoc, kCoreReg); } bool methodStarInReg(CompilationUnit* cUnit) { - return (cUnit->regLocation[cUnit->methodSReg].location == kLocPhysReg); + return (cUnit->methodLoc.location == kLocPhysReg); } diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc index bcc9067fd7..7c2cf1cba3 100644 --- a/src/compiler/codegen/GenInvoke.cc +++ b/src/compiler/codegen/GenInvoke.cc @@ -33,16 +33,18 @@ LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target); * If there are any ins passed in registers that have not been promoted * to a callee-save register, flush them to the frame. Perform intial * assignment of promoted arguments. + * + * argLocs is an array of location records describing the incoming arguments + * with one location record per word of argument. */ -void flushIns(CompilationUnit* cUnit) +void flushIns(CompilationUnit* cUnit, RegLocation* argLocs, RegLocation rlMethod) { /* * Dummy up a RegLocation for the incoming Method* * It will attempt to keep rARG0 live (or copy it to home location * if promoted). */ - RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg]; - RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg]; + RegLocation rlSrc = rlMethod; rlSrc.location = kLocPhysReg; rlSrc.lowReg = rARG0; rlSrc.home = false; @@ -75,7 +77,7 @@ void flushIns(CompilationUnit* cUnit) if (i < numArgRegs) { // If arriving in register bool needFlush = true; - RegLocation* tLoc = &cUnit->regLocation[startVReg + i]; + RegLocation* tLoc = &argLocs[i]; if ((vMap->coreLocation == kLocPhysReg) && !tLoc->fp) { opRegCopy(cUnit, vMap->coreReg, argRegs[i]); needFlush = false; diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index f13a473be5..66823c2313 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -27,6 +27,7 @@ #include <llvm/Type.h> #include <llvm/Instructions.h> #include <llvm/Support/Casting.h> +#include <llvm/Support/InstIterator.h> const char* labelFormat = "L0x%x_%d"; @@ -75,6 +76,50 @@ llvm::Type* llvmTypeFromLocRec(CompilationUnit* cUnit, RegLocation loc) return res; } +/* Create an in-memory RegLocation from an llvm Value. */ +void createLocFromValue(CompilationUnit* cUnit, llvm::Value* val) +{ + // NOTE: llvm takes shortcuts with c_str() - get to std::string firstt + std::string s(val->getName().str()); + const char* valName = s.c_str(); + if (cUnit->printMe) { + LOG(INFO) << "Processing llvm Value " << valName; + } + SafeMap<llvm::Value*, RegLocation>::iterator it = cUnit->locMap.find(val); + DCHECK(it == cUnit->locMap.end()) << " - already defined: " << valName; + int baseSReg = INVALID_SREG; + int subscript = -1; + sscanf(valName, "v%d_%d", &baseSReg, &subscript); + if ((baseSReg == INVALID_SREG) && (!strcmp(valName, "method"))) { + baseSReg = SSA_METHOD_BASEREG; + subscript = 0; + } + if (cUnit->printMe) { + LOG(INFO) << "Base: " << baseSReg << ", Sub: " << subscript; + } + DCHECK_NE(baseSReg, INVALID_SREG); + DCHECK_NE(subscript, -1); + // TODO: redo during C++'ification + RegLocation loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, INVALID_REG, + INVALID_REG, INVALID_SREG, INVALID_SREG}; + llvm::Type* ty = val->getType(); + loc.wide = ((ty == cUnit->irb->getInt64Ty()) || + (ty == cUnit->irb->getDoubleTy())); + loc.defined = true; + if ((ty == cUnit->irb->getFloatTy()) || + (ty == cUnit->irb->getDoubleTy())) { + loc.fp = true; + } else if (ty == cUnit->irb->GetJObjectTy()) { + loc.ref = true; + } else { + loc.core = true; + } + loc.home = false; // Will change during promotion + loc.sRegLow = baseSReg; + loc.origSReg = cUnit->locMap.size(); + cUnit->locMap.Put(val, loc); +} + void initIR(CompilationUnit* cUnit) { cUnit->context = new llvm::LLVMContext(); @@ -1372,19 +1417,25 @@ void oatMethodMIR2Bitcode(CompilationUnit* cUnit) llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction); - // Write bitcode to file - std::string errmsg; + if (cUnit->enableDebug & (1 << kDebugDumpBitcodeFile)) { + // Write bitcode to file + std::string errmsg; + std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file)); + oatReplaceSpecialChars(fname); + // TODO: make configurable + fname = StringPrintf("/tmp/%s.bc", fname.c_str()); - llvm::OwningPtr<llvm::tool_output_file> out_file( - new llvm::tool_output_file("/tmp/foo.bc", errmsg, - llvm::raw_fd_ostream::F_Binary)); + llvm::OwningPtr<llvm::tool_output_file> out_file( + new llvm::tool_output_file(fname.c_str(), errmsg, + llvm::raw_fd_ostream::F_Binary)); - if (!errmsg.empty()) { - LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; - } + if (!errmsg.empty()) { + LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; + } - llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); - out_file->keep(); + llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); + out_file->keep(); + } } RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) { @@ -1575,11 +1626,6 @@ void cvtCall(CompilationUnit* cUnit, llvm::CallInst* callInst, UNIMPLEMENTED(FATAL); } -void setMethodInfo(CompilationUnit* cUnit, llvm::CallInst* callInst) -{ - UNIMPLEMENTED(WARNING) << "Net setMethodInfo"; -} - void cvtCopy(CompilationUnit* cUnit, llvm::CallInst* callInst) { DCHECK(callInst->getNumArgOperands() == 1); @@ -1670,6 +1716,14 @@ void cvtInvoke(CompilationUnit* cUnit, llvm::CallInst* callInst, genInvoke(cUnit, info); } +/* Look up the RegLocation associated with a Value. Must already be defined */ +RegLocation valToLoc(CompilationUnit* cUnit, llvm::Value* val) +{ + SafeMap<llvm::Value*, RegLocation>::iterator it = cUnit->locMap.find(val); + DCHECK(it != cUnit->locMap.end()) << "Missing definition"; + return it->second; +} + bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) { bool isEntry = (bb == &cUnit->func->getEntryBlock()); @@ -1697,7 +1751,19 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) if (isEntry) { cUnit->currentDalvikOffset = 0; - genEntrySequence(cUnit); + RegLocation* argLocs = (RegLocation*) + oatNew(cUnit, sizeof(RegLocation) * cUnit->numIns, true, kAllocMisc); + llvm::Function::arg_iterator it(cUnit->func->arg_begin()); + llvm::Function::arg_iterator it_end(cUnit->func->arg_end()); + for (unsigned i = 0; it != it_end; ++it) { + llvm::Value* val = it; + argLocs[i++] = valToLoc(cUnit, val); + llvm::Type* ty = val->getType(); + if ((ty == cUnit->irb->getInt64Ty()) || (ty == cUnit->irb->getDoubleTy())) { + argLocs[i++].sRegLow = INVALID_SREG; + } + } + genEntrySequence(cUnit, argLocs, cUnit->methodLoc); } // Visit all of the instructions in the block @@ -1779,7 +1845,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) cvtConst(cUnit, callInst); break; case greenland::IntrinsicHelper::MethodInfo: - setMethodInfo(cUnit, callInst); + // Already dealt with - just ignore it here. break; case greenland::IntrinsicHelper::CheckSuspend: genSuspendTest(cUnit, 0 /* optFlags already applied */); @@ -1891,17 +1957,62 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) */ void oatMethodBitcode2LIR(CompilationUnit* cUnit) { - int numBasicBlocks = cUnit->func->getBasicBlockList().size(); + llvm::Function* func = cUnit->func; + 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; int nextLabel = 0; - for (llvm::Function::iterator i = cUnit->func->begin(), - e = cUnit->func->end(); i != e; ++i) { + for (llvm::Function::iterator i = func->begin(), + e = func->end(); i != e; ++i) { cUnit->blockToLabelMap.Put(static_cast<llvm::BasicBlock*>(i), &labelList[nextLabel++]); } + + /* + * Keep honest - clear regLocations, Value => RegLocation, + * promotion map and VmapTables. + */ + cUnit->locMap.clear(); // Start fresh + cUnit->regLocation = NULL; + for (int i = 0; i < cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1; + i++) { + cUnit->promotionMap[i].coreLocation = kLocDalvikFrame; + cUnit->promotionMap[i].fpLocation = kLocDalvikFrame; + } + cUnit->coreSpillMask = 0; + cUnit->numCoreSpills = 0; + cUnit->fpSpillMask = 0; + cUnit->numFPSpills = 0; + cUnit->coreVmapTable.clear(); + cUnit->fpVmapTable.clear(); + oatAdjustSpillMask(cUnit); + cUnit->frameSize = oatComputeFrameSize(cUnit); + + /* + * At this point, we've lost all knowledge of register promotion. + * Rebuild that info from the MethodInfo intrinsic (if it + * exists - not required for correctness). + */ + // TODO: find and recover MethodInfo. + + // Create RegLocations for arguments + llvm::Function::arg_iterator it(cUnit->func->arg_begin()); + llvm::Function::arg_iterator it_end(cUnit->func->arg_end()); + for (; it != it_end; ++it) { + llvm::Value* val = it; + createLocFromValue(cUnit, val); + } + // Create RegLocations for all non-argument defintions + for (llvm::inst_iterator i = llvm::inst_begin(func), + e = llvm::inst_end(func); i != e; ++i) { + llvm::Value* val = &*i; + if (val->hasName() && (val->getName().str().c_str()[0] == 'v')) { + createLocFromValue(cUnit, val); + } + } + // Walk the blocks, generating code. for (llvm::Function::iterator i = cUnit->func->begin(), e = cUnit->func->end(); i != e; ++i) { diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc index aab323b582..7898ddb7be 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -904,7 +904,9 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) LIR* headLIR = NULL; if (bb->blockType == kEntryBlock) { - genEntrySequence(cUnit); + int startVReg = cUnit->numDalvikRegisters - cUnit->numIns; + genEntrySequence(cUnit, &cUnit->regLocation[startVReg], + cUnit->regLocation[cUnit->methodSReg]); } else if (bb->blockType == kExitBlock) { genExitSequence(cUnit); } diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h index 8c3887a944..ec47e22963 100644 --- a/src/compiler/codegen/Ralloc.h +++ b/src/compiler/codegen/Ralloc.h @@ -229,6 +229,7 @@ extern uint32_t oatFPRegMask(void); extern void oatAdjustSpillMask(CompilationUnit* cUnit); void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg); void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc); +int oatComputeFrameSize(CompilationUnit* cUnit); } // namespace art diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc index e2f2cd683b..074fd26ca0 100644 --- a/src/compiler/codegen/RallocUtil.cc +++ b/src/compiler/codegen/RallocUtil.cc @@ -29,17 +29,6 @@ namespace art { -#define SREG(c, s) ((c)->regLocation[(s)].sRegLow) -/* - * Get the "real" sreg number associated with an sReg slot. In general, - * sReg values passed through codegen are the SSA names created by - * dataflow analysis and refer to slot numbers in the cUnit->regLocation - * array. However, renaming is accomplished by simply replacing RegLocation - * entries in the cUnit->reglocation[] array. Therefore, when location - * records for operands are first created, we need to ask the locRecord - * identified by the dataflow pass what it's new name is. - */ - /* * Free all allocated temps in the temp pools. Note that this does * not affect the "liveness" of a temp register, which will stay diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc index c0d91a454a..ba49277a3f 100644 --- a/src/compiler/codegen/arm/ArchFactory.cc +++ b/src/compiler/codegen/arm/ArchFactory.cc @@ -56,7 +56,8 @@ int loadHelper(CompilationUnit* cUnit, int offset) return rLR; } -void genEntrySequence(CompilationUnit* cUnit) +void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, + RegLocation rlMethod) { int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills; /* @@ -101,7 +102,7 @@ void genEntrySequence(CompilationUnit* cUnit) opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4)); } - flushIns(cUnit); + flushIns(cUnit, argLocs, rlMethod); if (cUnit->genDebugger) { // Refresh update debugger callout diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc index bf4c8a6186..4a61efb4a0 100644 --- a/src/compiler/codegen/mips/ArchFactory.cc +++ b/src/compiler/codegen/mips/ArchFactory.cc @@ -144,7 +144,8 @@ void unSpillCoreRegs(CompilationUnit* cUnit) opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize); } -void genEntrySequence(CompilationUnit* cUnit) +void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, + RegLocation rlMethod) { int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills; /* @@ -183,7 +184,7 @@ void genEntrySequence(CompilationUnit* cUnit) opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4)); } - flushIns(cUnit); + flushIns(cUnit, argLocs, rlMethod); if (cUnit->genDebugger) { // Refresh update debugger callout diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc index b3cebdce19..1620044069 100644 --- a/src/compiler/codegen/x86/ArchFactory.cc +++ b/src/compiler/codegen/x86/ArchFactory.cc @@ -163,7 +163,8 @@ void opRegThreadMem(CompilationUnit* cUnit, OpKind op, int rDest, int threadOffs newLIR2(cUnit, opcode, rDest, threadOffset); } -void genEntrySequence(CompilationUnit* cUnit) +void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, + RegLocation rlMethod) { /* * On entry, rARG0, rARG1, rARG2 are live. Let the register @@ -199,7 +200,7 @@ void genEntrySequence(CompilationUnit* cUnit) oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); } - flushIns(cUnit); + flushIns(cUnit, argLocs, rlMethod); if (cUnit->genDebugger) { // Refresh update debugger callout |