diff options
Diffstat (limited to 'src/compiler/codegen/MethodBitcode.cc')
| -rw-r--r-- | src/compiler/codegen/MethodBitcode.cc | 316 | 
1 files changed, 247 insertions, 69 deletions
| diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index 3b6b087e8d..f13a473be5 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -28,7 +28,7 @@  #include <llvm/Instructions.h>  #include <llvm/Support/Casting.h> -const char* labelFormat = "L0x%x_d"; +const char* labelFormat = "L0x%x_%d";  namespace art {  extern const RegLocation badLoc; @@ -193,6 +193,8 @@ void convertCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,    condValue->setName(StringPrintf("t%d", cUnit->tempName++));    cUnit->irb->CreateCondBr(condValue, getLLVMBlock(cUnit, bb->taken->id),                             getLLVMBlock(cUnit, bb->fallThrough->id)); +  // Don't redo the fallthrough branch in the BB driver +  bb->fallThrough = NULL;  }  void convertCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, @@ -212,6 +214,8 @@ void convertCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb,    condValue->setName(StringPrintf("t%d", cUnit->tempName++));    cUnit->irb->CreateCondBr(condValue, getLLVMBlock(cUnit, bb->taken->id),                             getLLVMBlock(cUnit, bb->fallThrough->id)); +  // Don't redo the fallthrough branch in the BB driver +  bb->fallThrough = NULL;  }  llvm::Value* genDivModOp(CompilationUnit* cUnit, bool isDiv, bool isLong, @@ -314,6 +318,70 @@ void convertArithOpLit(CompilationUnit* cUnit, OpKind op, RegLocation rlDest,    defineValue(cUnit, res, rlDest.origSReg);  } +void convertInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, +                   InvokeType invokeType, bool isRange) +{ +  CallInfo* info = oatNewCallInfo(cUnit, bb, mir, invokeType, isRange); +  llvm::SmallVector<llvm::Value*, 10> args; +  // Insert the invokeType +  args.push_back(cUnit->irb->getInt32(static_cast<int>(invokeType))); +  // Insert the method_idx +  args.push_back(cUnit->irb->getInt32(info->index)); +  // Insert the optimization flags +  args.push_back(cUnit->irb->getInt32(info->optFlags)); +  // Now, insert the actual arguments +  if (cUnit->printMe) { +    LOG(INFO) << "Building Invoke info"; +  } +  for (int i = 0; i < info->numArgWords;) { +    if (cUnit->printMe) { +      oatDumpRegLoc(info->args[i]); +    } +    llvm::Value* val = getLLVMValue(cUnit, info->args[i].origSReg); +    args.push_back(val); +    i += info->args[i].wide ? 2 : 1; +  } +  /* +   * Choose the invoke return type based on actual usage.  Note: may +   * be different than shorty.  For example, if a function return value +   * is not used, we'll treat this as a void invoke. +   */ +  greenland::IntrinsicHelper::IntrinsicId id; +  if (info->result.location == kLocInvalid) { +    id = greenland::IntrinsicHelper::HLInvokeVoid; +  } else { +    if (info->result.wide) { +      if (info->result.fp) { +        id = greenland::IntrinsicHelper::HLInvokeDouble; +      } else { +        id = greenland::IntrinsicHelper::HLInvokeFloat; +      } +    } else if (info->result.ref) { +        id = greenland::IntrinsicHelper::HLInvokeObj; +    } else if (info->result.fp) { +        id = greenland::IntrinsicHelper::HLInvokeFloat; +    } else { +        id = greenland::IntrinsicHelper::HLInvokeInt; +    } +  } +  llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id); +  llvm::Value* res = cUnit->irb->CreateCall(intr, args); +  if (info->result.location != kLocInvalid) { +    defineValue(cUnit, res, info->result.origSReg); +  } +} + +void convertConstString(CompilationUnit* cUnit, BasicBlock* bb, +                        uint32_t string_idx, RegLocation rlDest) +{ +  greenland::IntrinsicHelper::IntrinsicId id; +  id = greenland::IntrinsicHelper::ConstString; +  llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(id); +  llvm::Value* index = cUnit->irb->getInt32(string_idx); +  llvm::Value* res = cUnit->irb->CreateCall(intr, index); +  defineValue(cUnit, res, rlDest.origSReg); +} +  /*   * Target-independent code generation.  Use only high-level   * load/store utilities here, or target-dependent genXX() handlers @@ -327,6 +395,9 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,    RegLocation rlDest = badLoc;    RegLocation rlResult = badLoc;    Instruction::Code opcode = mir->dalvikInsn.opcode; +  uint32_t vB = mir->dalvikInsn.vB; +  uint32_t vC = mir->dalvikInsn.vC; +    bool objectDefinition = false;    /* Prep Src and Dest locations */ @@ -398,7 +469,7 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,      case Instruction::CONST:      case Instruction::CONST_4:      case Instruction::CONST_16: { -        llvm::Constant* immValue = cUnit->irb->GetJInt(mir->dalvikInsn.vB); +        llvm::Constant* immValue = cUnit->irb->GetJInt(vB);          llvm::Value* res = emitConst(cUnit, immValue, rlDest);          defineValue(cUnit, res, rlDest.origSReg);        } @@ -406,14 +477,14 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,      case Instruction::CONST_WIDE_16:      case Instruction::CONST_WIDE_32: { -        llvm::Constant* immValue = cUnit->irb->GetJLong(mir->dalvikInsn.vB); +        llvm::Constant* immValue = cUnit->irb->GetJLong(vB);          llvm::Value* res = emitConst(cUnit, immValue, rlDest);          defineValue(cUnit, res, rlDest.origSReg);        }        break;      case Instruction::CONST_HIGH16: { -        llvm::Constant* immValue = cUnit->irb->GetJInt(mir->dalvikInsn.vB << 16); +        llvm::Constant* immValue = cUnit->irb->GetJInt(vB << 16);          llvm::Value* res = emitConst(cUnit, immValue, rlDest);          defineValue(cUnit, res, rlDest.origSReg);        } @@ -426,7 +497,7 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,          defineValue(cUnit, res, rlDest.origSReg);      }      case Instruction::CONST_WIDE_HIGH16: { -        int64_t imm = static_cast<int64_t>(mir->dalvikInsn.vB) << 48; +        int64_t imm = static_cast<int64_t>(vB) << 48;          llvm::Constant* immValue = cUnit->irb->GetJLong(imm);          llvm::Value* res = emitConst(cUnit, immValue, rlDest);          defineValue(cUnit, res, rlDest.origSReg); @@ -570,44 +641,44 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,      case Instruction::ADD_INT_LIT16:      case Instruction::ADD_INT_LIT8: -      convertArithOpLit(cUnit, kOpAdd, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpAdd, rlDest, rlSrc[0], vC);        break;      case Instruction::RSUB_INT:      case Instruction::RSUB_INT_LIT8: -      convertArithOpLit(cUnit, kOpRsub, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpRsub, rlDest, rlSrc[0], vC);        break;      case Instruction::MUL_INT_LIT16:      case Instruction::MUL_INT_LIT8: -      convertArithOpLit(cUnit, kOpMul, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpMul, rlDest, rlSrc[0], vC);        break;      case Instruction::DIV_INT_LIT16:      case Instruction::DIV_INT_LIT8: -      convertArithOpLit(cUnit, kOpDiv, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpDiv, rlDest, rlSrc[0], vC);        break;      case Instruction::REM_INT_LIT16:      case Instruction::REM_INT_LIT8: -      convertArithOpLit(cUnit, kOpRem, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpRem, rlDest, rlSrc[0], vC);        break;      case Instruction::AND_INT_LIT16:      case Instruction::AND_INT_LIT8: -      convertArithOpLit(cUnit, kOpAnd, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpAnd, rlDest, rlSrc[0], vC);        break;      case Instruction::OR_INT_LIT16:      case Instruction::OR_INT_LIT8: -      convertArithOpLit(cUnit, kOpOr, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpOr, rlDest, rlSrc[0], vC);        break;      case Instruction::XOR_INT_LIT16:      case Instruction::XOR_INT_LIT8: -      convertArithOpLit(cUnit, kOpXor, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpXor, rlDest, rlSrc[0], vC);        break;      case Instruction::SHL_INT_LIT8: -      convertArithOpLit(cUnit, kOpLsl, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpLsl, rlDest, rlSrc[0], vC);        break;      case Instruction::SHR_INT_LIT8: -      convertArithOpLit(cUnit, kOpLsr, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpLsr, rlDest, rlSrc[0], vC);        break;      case Instruction::USHR_INT_LIT8: -      convertArithOpLit(cUnit, kOpAsr, rlDest, rlSrc[0], mir->dalvikInsn.vC); +      convertArithOpLit(cUnit, kOpAsr, rlDest, rlSrc[0], vC);        break;      case Instruction::ADD_FLOAT: @@ -645,6 +716,47 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,        convertFPArithOp(cUnit, kOpRem, rlDest, rlSrc[0], rlSrc[1]);        break; +    case Instruction::INVOKE_STATIC: +      convertInvoke(cUnit, bb, mir, kStatic, false /*range*/); +      break; +    case Instruction::INVOKE_STATIC_RANGE: +      convertInvoke(cUnit, bb, mir, kStatic, true /*range*/); +      break; + +    case Instruction::INVOKE_DIRECT: +      convertInvoke(cUnit, bb,  mir, kDirect, false /*range*/); +      break; +    case Instruction::INVOKE_DIRECT_RANGE: +      convertInvoke(cUnit, bb, mir, kDirect, true /*range*/); +      break; + +    case Instruction::INVOKE_VIRTUAL: +      convertInvoke(cUnit, bb, mir, kVirtual, false /*range*/); +      break; +    case Instruction::INVOKE_VIRTUAL_RANGE: +      convertInvoke(cUnit, bb, mir, kVirtual, true /*range*/); +      break; + +    case Instruction::INVOKE_SUPER: +      convertInvoke(cUnit, bb, mir, kSuper, false /*range*/); +      break; +    case Instruction::INVOKE_SUPER_RANGE: +      convertInvoke(cUnit, bb, mir, kSuper, true /*range*/); +      break; + +    case Instruction::INVOKE_INTERFACE: +      convertInvoke(cUnit, bb, mir, kInterface, false /*range*/); +      break; +    case Instruction::INVOKE_INTERFACE_RANGE: +      convertInvoke(cUnit, bb, mir, kInterface, true /*range*/); +      break; + +    case Instruction::CONST_STRING: +    case Instruction::CONST_STRING_JUMBO: +      convertConstString(cUnit, bb, vB, rlDest); +      break; + +  #if 0      case Instruction::MOVE_EXCEPTION: { @@ -715,11 +827,6 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,        storeValue(cUnit, rlDest, rlResult);        break; -    case Instruction::CONST_STRING: -    case Instruction::CONST_STRING_JUMBO: -      genConstString(cUnit, mir, rlDest, rlSrc[0]); -      break; -      case Instruction::CONST_CLASS:        genConstClass(cUnit, mir, rlDest, rlSrc[0]);        break; @@ -884,41 +991,6 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb,        genSput(cUnit, mir, rlSrc[0], true, false);        break; -    case Instruction::INVOKE_STATIC_RANGE: -      genInvoke(cUnit, bb, mir, kStatic, true /*range*/); -      break; -    case Instruction::INVOKE_STATIC: -      genInvoke(cUnit, bb, mir, kStatic, false /*range*/); -      break; - -    case Instruction::INVOKE_DIRECT: -      genInvoke(cUnit, bb,  mir, kDirect, false /*range*/); -      break; -    case Instruction::INVOKE_DIRECT_RANGE: -      genInvoke(cUnit, bb, mir, kDirect, true /*range*/); -      break; - -    case Instruction::INVOKE_VIRTUAL: -      genInvoke(cUnit, bb, mir, kVirtual, false /*range*/); -      break; -    case Instruction::INVOKE_VIRTUAL_RANGE: -      genInvoke(cUnit, bb, mir, kVirtual, true /*range*/); -      break; - -    case Instruction::INVOKE_SUPER: -      genInvoke(cUnit, bb, mir, kSuper, false /*range*/); -      break; -    case Instruction::INVOKE_SUPER_RANGE: -      genInvoke(cUnit, bb, mir, kSuper, true /*range*/); -      break; - -    case Instruction::INVOKE_INTERFACE: -      genInvoke(cUnit, bb, mir, kInterface, false /*range*/); -      break; -    case Instruction::INVOKE_INTERFACE_RANGE: -      genInvoke(cUnit, bb, mir, kInterface, true /*range*/); -      break; -      case Instruction::NEG_INT:      case Instruction::NOT_INT:        res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]); @@ -1114,6 +1186,15 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)       * path, it will need to be regenereated.       */      return false; +  } else if (bb->blockType == kExceptionHandling) { +    /* +     * Because we're deferring null checking, delete the associated empty +     * exception block. +     * TODO: add new block type for exception blocks that we generate +     * greenland code for. +     */ +    llvmBB->eraseFromParent(); +    return false;    }    for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) { @@ -1144,7 +1225,7 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb)      }    } -  if ((bb->taken == NULL) && (bb->fallThrough != NULL) && !bb->hasReturn) { +  if ((bb->fallThrough != NULL) && !bb->hasReturn) {      cUnit->irb->CreateBr(getLLVMBlock(cUnit, bb->fallThrough->id));    } @@ -1291,21 +1372,19 @@ void oatMethodMIR2Bitcode(CompilationUnit* cUnit)    llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction); -    // Write bitcode to file -    std::string errmsg; +  // Write bitcode to file +  std::string errmsg; -    llvm::OwningPtr<llvm::tool_output_file> out_file( +  llvm::OwningPtr<llvm::tool_output_file> out_file(        new llvm::tool_output_file("/tmp/foo.bc", errmsg,                                   llvm::raw_fd_ostream::F_Binary)); -    if (!errmsg.empty()) { -      LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; -    } - -    llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); -    out_file->keep(); - +  if (!errmsg.empty()) { +    LOG(ERROR) << "Failed to create bitcode output file: " << errmsg; +  } +  llvm::WriteBitcodeToFile(cUnit->module, out_file->os()); +  out_file->keep();  }  RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) { @@ -1438,6 +1517,7 @@ ConditionCode getCond(llvm::ICmpInst::Predicate llvmCond)    ConditionCode res = kCondAl;    switch(llvmCond) {      case llvm::ICmpInst::ICMP_NE: res = kCondNe; break; +    case llvm::ICmpInst::ICMP_EQ: res = kCondEq; break;      case llvm::ICmpInst::ICMP_SGT: res = kCondGt; break;      default: LOG(FATAL) << "Unexpected llvm condition";    } @@ -1531,6 +1611,65 @@ void cvtConst(CompilationUnit* cUnit, llvm::CallInst* callInst)    }  } +void cvtConstString(CompilationUnit* cUnit, llvm::CallInst* callInst) +{ +  DCHECK(callInst->getNumArgOperands() == 1); +  llvm::ConstantInt* stringIdxVal = +      llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); +  uint32_t stringIdx = stringIdxVal->getZExtValue(); +  RegLocation rlDest = getLoc(cUnit, callInst); +  genConstString(cUnit, stringIdx, rlDest); +} + +void cvtInvoke(CompilationUnit* cUnit, llvm::CallInst* callInst, +               greenland::JType jtype) +{ +  CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true, +                                         kAllocMisc); +  if (jtype == greenland::kVoid) { +    info->result.location = kLocInvalid; +  } else { +    info->result = getLoc(cUnit, callInst); +  } +  llvm::ConstantInt* invokeTypeVal = +      llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(0)); +  llvm::ConstantInt* methodIndexVal = +      llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(1)); +  llvm::ConstantInt* optFlagsVal = +      llvm::dyn_cast<llvm::ConstantInt>(callInst->getArgOperand(2)); +  info->type = static_cast<InvokeType>(invokeTypeVal->getZExtValue()); +  info->index = methodIndexVal->getZExtValue(); +  info->optFlags = optFlagsVal->getZExtValue(); +  info->offset = cUnit->currentDalvikOffset; + +  // FIXME - rework such that we no longer need isRange +  info->isRange = false; + +  // Count the argument words, and then build argument array. +  info->numArgWords = 0; +  for (unsigned int i = 3; i < callInst->getNumArgOperands(); i++) { +    RegLocation tLoc = getLoc(cUnit, callInst->getArgOperand(i)); +    info->numArgWords += tLoc.wide ? 2 : 1; +  } +  info->args = (info->numArgWords == 0) ? NULL : (RegLocation*) +      oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc); +  // Now, fill in the location records, synthesizing high loc of wide vals +  for (int i = 3, next = 0; next < info->numArgWords;) { +    info->args[next] = getLoc(cUnit, callInst->getArgOperand(i)); +    if (cUnit->printMe) { +      oatDumpRegLoc(info->args[next]); +    } +    if (info->args[next].wide) { +      next++; +      // TODO: Might make sense to mark this as an invalid loc +      info->args[next].origSReg = info->args[next-1].origSReg+1; +      info->args[next].sRegLow = info->args[next-1].sRegLow+1; +    } +    next++; +  } +  genInvoke(cUnit, info); +} +  bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)  {    bool isEntry = (bb == &cUnit->func->getEntryBlock()); @@ -1554,8 +1693,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)    //TODO: restore oat incoming liveness optimization    oatClobberAllRegs(cUnit); -  //LIR* headLIR = NULL; - +  LIR* headLIR = NULL;    if (isEntry) {      cUnit->currentDalvikOffset = 0; @@ -1575,6 +1713,32 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)        cUnit->currentDalvikOffset = dexOffsetValue->getZExtValue();      } +    oatResetRegPool(cUnit); +    if (cUnit->disableOpt & (1 << kTrackLiveTemps)) { +      oatClobberAllRegs(cUnit); +    } + +    if (cUnit->disableOpt & (1 << kSuppressLoads)) { +      oatResetDefTracking(cUnit); +    } + +#ifndef NDEBUG +    /* Reset temp tracking sanity check */ +    cUnit->liveSReg = INVALID_SREG; +#endif + +    LIR* boundaryLIR; +    const char* instStr = "boundary"; +    boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, +                          (intptr_t) instStr); +    cUnit->boundaryMap.Overwrite(cUnit->currentDalvikOffset, boundaryLIR); + +    /* Remember the first LIR for thisl block*/ +    if (headLIR == NULL) { +      headLIR = boundaryLIR; +      headLIR->defMask = ENCODE_ALL; +    } +      switch(opcode) {        case llvm::Instruction::ICmp: { @@ -1597,6 +1761,7 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)            switch (id) {              case greenland::IntrinsicHelper::AllocaShadowFrame:              case greenland::IntrinsicHelper::SetShadowFrameEntry: +            case greenland::IntrinsicHelper::PopShadowFrame:                // Ignore shadow frame stuff for quick compiler                break;              case greenland::IntrinsicHelper::CopyInt: @@ -1619,6 +1784,15 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)              case greenland::IntrinsicHelper::CheckSuspend:                genSuspendTest(cUnit, 0 /* optFlags already applied */);                break; +            case greenland::IntrinsicHelper::HLInvokeInt: +              cvtInvoke(cUnit, callInst, greenland::kInt); +              break; +            case greenland::IntrinsicHelper::HLInvokeVoid: +              cvtInvoke(cUnit, callInst, greenland::kVoid); +              break; +            case greenland::IntrinsicHelper::ConstString: +              cvtConstString(cUnit, callInst); +              break;              case greenland::IntrinsicHelper::UnknownId:                cvtCall(cUnit, callInst, callee);                break; @@ -1694,6 +1868,10 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)          LOG(FATAL) << "Unknown llvm opcode: " << opcode; break;      }    } + +  if (headLIR != NULL) { +    oatApplyLocalOptimizations(cUnit, headLIR, cUnit->lastLIRInsn); +  }    return false;  } |