| Index: src/IceTargetLoweringARM32.cpp
|
| diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
|
| index d260db0e690cbeb7ee073421b491fd4dcb0edc5d..5469db1d5a19abc28989f8da1fa9f8b49b6fe926 100644
|
| --- a/src/IceTargetLoweringARM32.cpp
|
| +++ b/src/IceTargetLoweringARM32.cpp
|
| @@ -161,7 +161,8 @@ TargetARM32Features::TargetARM32Features(const ClFlags &Flags) {
|
| }
|
|
|
| TargetARM32::TargetARM32(Cfg *Func)
|
| - : TargetLowering(Func), CPUFeatures(Func->getContext()->getFlags()) {}
|
| + : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()),
|
| + CPUFeatures(Func->getContext()->getFlags()) {}
|
|
|
| void TargetARM32::staticInit() {
|
| // Limit this size (or do all bitsets need to be the same width)???
|
| @@ -544,8 +545,7 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
|
| return;
|
| }
|
| case Intrinsics::NaClReadTP: {
|
| - if (Ctx->getFlags().getUseSandboxing()) {
|
| - UnimplementedError(Func->getContext()->getFlags());
|
| + if (NeedSandboxing) {
|
| return;
|
| }
|
| static constexpr SizeT MaxArgs = 0;
|
| @@ -1120,6 +1120,10 @@ void TargetARM32::addProlog(CfgNode *Node) {
|
| continue;
|
| }
|
| if (CalleeSaves[i] && RegsUsed[i]) {
|
| + if (NeedSandboxing && i == RegARM32::Reg_r9) {
|
| + // r9 is never updated in sandboxed code.
|
| + continue;
|
| + }
|
| ++NumCallee;
|
| Variable *PhysicalRegister = getPhysicalRegister(i);
|
| PreservedRegsSizeBytes +=
|
| @@ -1173,10 +1177,9 @@ void TargetARM32::addProlog(CfgNode *Node) {
|
| // Use the scratch register if needed to legalize the immediate.
|
| Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes),
|
| Legal_Reg | Legal_Flex, getReservedTmpReg());
|
| - Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
|
| - _sub(SP, SP, SubAmount);
|
| + AutoSandboxer(this).sub_sp(SubAmount);
|
| if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) {
|
| - alignRegisterPow2(SP, FixedAllocaAlignBytes);
|
| + AutoSandboxer(this).align_sp(FixedAllocaAlignBytes);
|
| }
|
| }
|
|
|
| @@ -1270,7 +1273,7 @@ void TargetARM32::addEpilog(CfgNode *Node) {
|
| // use of SP before the assignment of SP=FP keeps previous SP adjustments
|
| // from being dead-code eliminated.
|
| Context.insert(InstFakeUse::create(Func, SP));
|
| - _mov(SP, FP);
|
| + AutoSandboxer(this).reset_sp(FP);
|
| } else {
|
| // add SP, SpillAreaSizeBytes
|
| if (SpillAreaSizeBytes) {
|
| @@ -1278,7 +1281,7 @@ void TargetARM32::addEpilog(CfgNode *Node) {
|
| Operand *AddAmount =
|
| legalize(Ctx->getConstantInt32(SpillAreaSizeBytes),
|
| Legal_Reg | Legal_Flex, getReservedTmpReg());
|
| - _add(SP, SP, AddAmount);
|
| + AutoSandboxer(this).add_sp(AddAmount);
|
| }
|
| }
|
|
|
| @@ -1302,6 +1305,9 @@ void TargetARM32::addEpilog(CfgNode *Node) {
|
| }
|
|
|
| if (CalleeSaves[i] && RegsUsed[i]) {
|
| + if (NeedSandboxing && i == RegARM32::Reg_r9) {
|
| + continue;
|
| + }
|
| GPRsToRestore.push_back(getPhysicalRegister(i));
|
| }
|
| }
|
| @@ -1318,16 +1324,13 @@ void TargetARM32::addEpilog(CfgNode *Node) {
|
| // bundle_unlock
|
| // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to
|
| // restrict to the lower 1GB as well.
|
| - Operand *RetMask =
|
| - legalize(Ctx->getConstantInt32(0xc000000f), Legal_Reg | Legal_Flex);
|
| - Variable *LR = makeReg(IceType_i32, RegARM32::Reg_lr);
|
| + Variable *LR = getPhysicalRegister(RegARM32::Reg_lr);
|
| Variable *RetValue = nullptr;
|
| if (RI->getSrcSize())
|
| RetValue = llvm::cast<Variable>(RI->getSrc(0));
|
| - _bundle_lock();
|
| - _bic(LR, LR, RetMask);
|
| - _ret(LR, RetValue);
|
| - _bundle_unlock();
|
| +
|
| + AutoSandboxer(this).ret(LR, RetValue);
|
| +
|
| RI->setDeleted();
|
| }
|
|
|
| @@ -1378,7 +1381,7 @@ Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister(
|
| OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand(
|
| Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) {
|
| assert(!Base->isRematerializable());
|
| - if (AllowOffsets && Target->isLegalMemOffset(Ty, Offset)) {
|
| + if (Offset == 0 || (AllowOffsets && Target->isLegalMemOffset(Ty, Offset))) {
|
| return OperandARM32Mem::create(
|
| Target->Func, Ty, Base,
|
| llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)),
|
| @@ -1451,8 +1454,9 @@ void TargetARM32::PostLoweringLegalizer::legalizeMov(InstARM32Mov *MovInstr) {
|
| assert(!SrcR->isRematerializable());
|
| const int32_t Offset = Dest->getStackOffset();
|
| // This is a _mov(Mem(), Variable), i.e., a store.
|
| - Target->_str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset),
|
| - MovInstr->getPredicate());
|
| + TargetARM32::AutoSandboxer(Target)
|
| + .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset),
|
| + MovInstr->getPredicate());
|
| // _str() does not have a Dest, so we add a fake-def(Dest).
|
| Target->Context.insert(InstFakeDef::create(Target->Func, Dest));
|
| Legalized = true;
|
| @@ -1476,8 +1480,9 @@ void TargetARM32::PostLoweringLegalizer::legalizeMov(InstARM32Mov *MovInstr) {
|
| if (!Var->hasReg()) {
|
| // This is a _mov(Variable, Mem()), i.e., a load.
|
| const int32_t Offset = Var->getStackOffset();
|
| - Target->_ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset),
|
| - MovInstr->getPredicate());
|
| + TargetARM32::AutoSandboxer(Target)
|
| + .ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset),
|
| + MovInstr->getPredicate());
|
| Legalized = true;
|
| }
|
| }
|
| @@ -1542,7 +1547,15 @@ TargetARM32::PostLoweringLegalizer::legalizeMemOperand(OperandARM32Mem *Mem,
|
| Legalized = true;
|
| }
|
|
|
| - if (!Legalized) {
|
| + if (!Legalized && !Target->NeedSandboxing) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (Target->NeedSandboxing && Base->getRegNum() == RegARM32::Reg_r9) {
|
| + if (Legalized) {
|
| + llvm::report_fatal_error("r9-based mem operand should not need to be "
|
| + "legalized.");
|
| + }
|
| return nullptr;
|
| }
|
|
|
| @@ -1550,6 +1563,7 @@ TargetARM32::PostLoweringLegalizer::legalizeMemOperand(OperandARM32Mem *Mem,
|
| return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets);
|
| }
|
|
|
| + assert(!Target->NeedSandboxing);
|
| assert(MemTraits[Mem->getType()].CanHaveIndex);
|
|
|
| if (Offset != 0) {
|
| @@ -1621,7 +1635,8 @@ void TargetARM32::postLowerLegalization() {
|
| } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) {
|
| if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
|
| llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) {
|
| - _ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate());
|
| + AutoSandboxer(this)
|
| + .ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate());
|
| CurInstr->setDeleted();
|
| }
|
| } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) {
|
| @@ -1629,14 +1644,16 @@ void TargetARM32::postLowerLegalization() {
|
| if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
|
| llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)),
|
| DisallowOffsetsBecauseLdrex)) {
|
| - _ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate());
|
| + AutoSandboxer(this)
|
| + .ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate());
|
| CurInstr->setDeleted();
|
| }
|
| } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) {
|
| + AutoSandboxer Bundle(this);
|
| if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
|
| llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) {
|
| - _str(llvm::cast<Variable>(CurInstr->getSrc(0)), LegalMem,
|
| - StrInstr->getPredicate());
|
| + AutoSandboxer(this).str(llvm::cast<Variable>(CurInstr->getSrc(0)),
|
| + LegalMem, StrInstr->getPredicate());
|
| CurInstr->setDeleted();
|
| }
|
| } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) {
|
| @@ -1644,8 +1661,9 @@ void TargetARM32::postLowerLegalization() {
|
| if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
|
| llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)),
|
| DisallowOffsetsBecauseStrex)) {
|
| - _strex(CurInstr->getDest(), llvm::cast<Variable>(CurInstr->getSrc(0)),
|
| - LegalMem, StrexInstr->getPredicate());
|
| + AutoSandboxer(this).strex(CurInstr->getDest(),
|
| + llvm::cast<Variable>(CurInstr->getSrc(0)),
|
| + LegalMem, StrexInstr->getPredicate());
|
| CurInstr->setDeleted();
|
| }
|
| }
|
| @@ -1803,7 +1821,7 @@ void TargetARM32::lowerAlloca(const InstAlloca *Inst) {
|
|
|
| Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
|
| if (OverAligned) {
|
| - alignRegisterPow2(SP, Alignment);
|
| + AutoSandboxer(this).align_sp(Alignment);
|
| }
|
|
|
| Variable *Dest = Inst->getDest();
|
| @@ -1828,7 +1846,7 @@ void TargetARM32::lowerAlloca(const InstAlloca *Inst) {
|
| // in Dest.
|
| Operand *SubAmountRF =
|
| legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex);
|
| - _sub(SP, SP, SubAmountRF);
|
| + AutoSandboxer(this).sub_sp(SubAmountRF);
|
| } else {
|
| // Non-constant sizes need to be adjusted to the next highest multiple of
|
| // the required alignment at runtime.
|
| @@ -1838,7 +1856,7 @@ void TargetARM32::lowerAlloca(const InstAlloca *Inst) {
|
| Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1));
|
| _add(T, T, AddAmount);
|
| alignRegisterPow2(T, Alignment);
|
| - _sub(SP, SP, T);
|
| + AutoSandboxer(this).sub_sp(T);
|
| }
|
|
|
| // Adds back a few bytes to SP to account for the out args area.
|
| @@ -3249,8 +3267,6 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
|
| break;
|
| }
|
| }
|
| - // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing =
|
| - // Ctx->getFlags().getUseSandboxing();
|
|
|
| // Allow ConstantRelocatable to be left alone as a direct call, but force
|
| // other constants like ConstantInteger32 to be in a register and make it an
|
| @@ -3271,8 +3287,10 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
|
| // the call.
|
| Context.insert(InstFakeUse::create(Func, Reg));
|
| }
|
| - Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget);
|
| - Context.insert(NewCall);
|
| +
|
| + InstARM32Call *NewCall = AutoSandboxer(this, InstBundleLock::Opt_AlignToEnd)
|
| + .bl(ReturnReg, CallTarget);
|
| +
|
| if (ReturnRegHi)
|
| Context.insert(InstFakeDef::create(Func, ReturnRegHi));
|
|
|
| @@ -4612,7 +4630,14 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| llvm::report_fatal_error("memmove should have been prelowered.");
|
| }
|
| case Intrinsics::NaClReadTP: {
|
| - llvm::report_fatal_error("nacl-read-tp should have been prelowered.");
|
| + if (!NeedSandboxing) {
|
| + llvm::report_fatal_error("nacl-read-tp should have been prelowered.");
|
| + }
|
| + Variable *TP = legalizeToReg(OperandARM32Mem::create(
|
| + Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9),
|
| + llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))));
|
| + _mov(Dest, TP);
|
| + return;
|
| }
|
| case Intrinsics::Setjmp: {
|
| llvm::report_fatal_error("setjmp should have been prelowered.");
|
| @@ -4630,9 +4655,8 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
|
| return;
|
| }
|
| case Intrinsics::Stackrestore: {
|
| - Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
|
| - Operand *Val = legalize(Instr->getArg(0), Legal_Reg | Legal_Flex);
|
| - _mov_redefined(SP, Val);
|
| + Variable *Val = legalizeToReg(Instr->getArg(0));
|
| + AutoSandboxer(this).reset_sp(Val);
|
| return;
|
| }
|
| case Intrinsics::Trap:
|
| @@ -4987,8 +5011,9 @@ OperandARM32Mem *TargetARM32::formAddressingMode(Type Ty, Cfg *Func,
|
| (void)MemTraitsSize;
|
| assert(Ty < MemTraitsSize);
|
| auto *TypeTraits = &MemTraits[Ty];
|
| - const bool CanHaveIndex = TypeTraits->CanHaveIndex;
|
| - const bool CanHaveShiftedIndex = TypeTraits->CanHaveShiftedIndex;
|
| + const bool CanHaveIndex = !NeedSandboxing && TypeTraits->CanHaveIndex;
|
| + const bool CanHaveShiftedIndex =
|
| + !NeedSandboxing && TypeTraits->CanHaveShiftedIndex;
|
| const bool CanHaveImm = TypeTraits->CanHaveImm;
|
| const int32_t ValidImmMask = TypeTraits->ValidImmMask;
|
| (void)ValidImmMask;
|
| @@ -5160,6 +5185,7 @@ void TargetARM32::lowerRet(const InstRet *Inst) {
|
| // frame removal instructions. addEpilog is responsible for restoring the
|
| // "lr" register as needed prior to this ret instruction.
|
| _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg);
|
| +
|
| // Add a fake use of sp to make sure sp stays alive for the entire function.
|
| // Otherwise post-call sp adjustments get dead-code eliminated.
|
| // TODO: Are there more places where the fake use should be inserted? E.g.
|
|
|