Chromium Code Reviews| Index: src/IceTargetLoweringARM32.cpp |
| diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp |
| index 7eb4e8ad446f540ef10a4f12aa9d8c6cb4a29e33..bd17b84c44ddff195ba2ba721a334a1321c55f48 100644 |
| --- a/src/IceTargetLoweringARM32.cpp |
| +++ b/src/IceTargetLoweringARM32.cpp |
| @@ -265,6 +265,52 @@ uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { |
| return applyStackAlignment(OutArgsSizeBytes); |
| } |
| +void TargetARM32::genTargetHelperCallFor(Inst *Instr) { |
| + switch (Instr->getKind()) { |
| + default: |
| + return; |
| + case Inst::Arithmetic: { |
| + Variable *Dest = Instr->getDest(); |
| + const Type DestTy = Dest->getType(); |
| + if (DestTy == IceType_i64) { |
| + const InstArithmetic::OpKind Op = |
| + llvm::cast<InstArithmetic>(Instr)->getOp(); |
| + Operand *TargetHelper = nullptr; |
| + switch (Op) { |
| + default: |
| + break; |
|
Jim Stichnoth
2015/11/24 22:24:00
maybe just return here?
John
2015/11/25 16:39:56
Done.
|
| + case InstArithmetic::Udiv: |
| + TargetHelper = Ctx->getConstantExternSym(H_udiv_i64); |
| + break; |
| + case InstArithmetic::Sdiv: |
| + TargetHelper = Ctx->getConstantExternSym(H_sdiv_i64); |
| + break; |
| + case InstArithmetic::Urem: |
| + TargetHelper = Ctx->getConstantExternSym(H_urem_i64); |
| + break; |
| + case InstArithmetic::Srem: |
| + TargetHelper = Ctx->getConstantExternSym(H_srem_i64); |
| + break; |
| + } |
| + if (TargetHelper == nullptr) { |
| + return; |
| + } |
| + ARM32Helpers[TargetHelper] = &TargetARM32::DivRem64Helper; |
| + constexpr SizeT MaxArgs = 2; |
| + constexpr bool NoTailCall = false; |
| + constexpr bool IsTargetHelperCall = true; |
| + auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, |
| + NoTailCall, IsTargetHelperCall); |
| + Call->addArg(Instr->getSrc(0)); |
| + Call->addArg(Instr->getSrc(1)); |
| + Context.insert(Call); |
| + Instr->setDeleted(); |
| + } |
| + return; |
| + } |
| + } |
| +} |
| + |
| void TargetARM32::findMaxStackOutArgsSize() { |
| // MinNeededOutArgsBytes should be updated if the Target ever creates a |
| // high-level InstCall that requires more stack bytes. |
| @@ -1642,6 +1688,27 @@ public: |
| }; |
| } // end of anonymous namespace |
| +void TargetARM32::DivRem64Helper(const InstCall *Instr) { |
| + Operand *Src0 = Instr->getArg(0); |
| + Operand *Src1 = Instr->getArg(1); |
| + Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); |
| + Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); |
| + // Check for divide by 0 (ARM normally doesn't trap, but we want it to |
| + // trap for NaCl). Src1Lo and Src1Hi may have already been legalized to a |
| + // register, which will hide a constant source operand. Instead, check |
| + // the not-yet-legalized Src1 to optimize-out a divide by 0 check. |
| + if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) { |
| + if (SrcsLo.getConstantValue() == 0 && SrcsHi.getConstantValue() == 0) { |
| + _trap(); |
| + return; |
| + } |
| + } else { |
| + Operand *Src1Lo = SrcsLo.unswappedSrc1R(this); |
| + Operand *Src1Hi = SrcsHi.unswappedSrc1R(this); |
| + div0Check(IceType_i64, Src1Lo, Src1Hi); |
| + } |
| +} |
| + |
| void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, |
| Variable *Dest, Operand *Src0, |
| Operand *Src1) { |
| @@ -1662,20 +1729,6 @@ void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, |
| case InstArithmetic::Sdiv: |
| case InstArithmetic::Urem: |
| case InstArithmetic::Srem: { |
| - // Check for divide by 0 (ARM normally doesn't trap, but we want it to |
| - // trap for NaCl). Src1Lo and Src1Hi may have already been legalized to a |
| - // register, which will hide a constant source operand. Instead, check |
| - // the not-yet-legalized Src1 to optimize-out a divide by 0 check. |
| - if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) { |
| - if (SrcsLo.getConstantValue() == 0 && SrcsHi.getConstantValue() == 0) { |
| - _trap(); |
| - return; |
| - } |
| - } else { |
| - Operand *Src1Lo = SrcsLo.unswappedSrc1R(this); |
| - Operand *Src1Hi = SrcsHi.unswappedSrc1R(this); |
| - div0Check(IceType_i64, Src1Lo, Src1Hi); |
| - } |
| // Technically, ARM has its own aeabi routines, but we can use the |
| // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses |
| // the more standard __moddi3 for rem. |
| @@ -2682,6 +2735,10 @@ void TargetARM32::lowerBr(const InstBr *Instr) { |
| } |
| void TargetARM32::lowerCall(const InstCall *Instr) { |
| + Operand *CallTarget = Instr->getCallTarget(); |
| + if (Instr->isTargetHelperCall()) { |
| + (this->*ARM32Helpers[CallTarget])(Instr); |
| + } |
| MaybeLeafFunc = false; |
| NeedsStackAlignment = true; |
| @@ -2804,7 +2861,6 @@ void TargetARM32::lowerCall(const InstCall *Instr) { |
| break; |
| } |
| } |
| - Operand *CallTarget = Instr->getCallTarget(); |
| // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = |
| // Ctx->getFlags().getUseSandboxing(); |