Chromium Code Reviews| Index: src/IceTargetLoweringX86BaseImpl.h |
| diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
| index 2b94df0799dbd9ce97815b48218d29b857f5733a..390cdba884f4aada5734661f5e8e3f842ed3e303 100644 |
| --- a/src/IceTargetLoweringX86BaseImpl.h |
| +++ b/src/IceTargetLoweringX86BaseImpl.h |
| @@ -308,7 +308,7 @@ void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) { |
| template <typename TraitsType> |
| TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) |
| - : TargetLowering(Func) { |
| + : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()) { |
| static_assert( |
| (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == |
| (TargetInstructionSet::X86InstructionSet_End - |
| @@ -325,7 +325,8 @@ TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) |
| template <typename TraitsType> |
| void TargetX86Base<TraitsType>::staticInit(const ClFlags &Flags) { |
| - Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); |
| + Traits::initRegisterSet(Flags, &TypeToRegisterSet, &RegisterAliases, |
| + &ScratchRegs); |
| PcRelFixup = Traits::FK_PcRel; |
| AbsFixup = Flags.getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; |
| } |
| @@ -336,6 +337,11 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { |
| if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { |
| GotVar = Func->makeVariable(IceType_i32); |
| } |
| + |
| + if (NeedSandboxing) { |
| + initSandbox(); |
| + } |
| + |
| genTargetHelperCalls(); |
| Func->dump("After target helper call insertion"); |
| @@ -456,8 +462,9 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { |
| Func->doNopInsertion(); |
| // Mark nodes that require sandbox alignment |
| - if (Ctx->getFlags().getUseSandboxing()) |
| + if (NeedSandboxing) { |
| Func->markNodesForSandboxing(); |
| + } |
| } |
| template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() { |
| @@ -466,6 +473,11 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() { |
| if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { |
| GotVar = Func->makeVariable(IceType_i32); |
| } |
| + |
| + if (NeedSandboxing) { |
| + initSandbox(); |
| + } |
| + |
| genTargetHelperCalls(); |
| // Do not merge Alloca instructions, and lay out the stack. |
| @@ -508,7 +520,7 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() { |
| Func->doNopInsertion(); |
| // Mark nodes that require sandbox alignment |
| - if (Ctx->getFlags().getUseSandboxing()) |
| + if (NeedSandboxing) |
| Func->markNodesForSandboxing(); |
| } |
| @@ -810,7 +822,11 @@ void TargetX86Base<TraitsType>::emitVariable(const Variable *Var) const { |
| return; |
| Ostream &Str = Ctx->getStrEmit(); |
| if (Var->hasReg()) { |
| - Str << "%" << getRegName(Var->getRegNum(), Var->getType()); |
| + const bool Is64BitSandboxing = Traits::Is64Bit && NeedSandboxing; |
| + const Type VarType = (Var->isRematerializable() && Is64BitSandboxing) |
| + ? IceType_i64 |
| + : Var->getType(); |
| + Str << "%" << getRegName(Var->getRegNum(), VarType); |
| return; |
| } |
| if (Var->mustHaveReg()) { |
| @@ -923,7 +939,7 @@ TargetX86Base<TraitsType>::loOperand(Operand *Operand) { |
| if (auto *Mem = llvm::dyn_cast<X86OperandMem>(Operand)) { |
| auto *MemOperand = X86OperandMem::create( |
| Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
| - Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
| + Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsRebased()); |
| // Test if we should randomize or pool the offset, if so randomize it or |
| // pool it then create mem operand with the blinded/pooled constant. |
| // Otherwise, return the mem operand as ordinary mem operand. |
| @@ -963,7 +979,7 @@ TargetX86Base<TraitsType>::hiOperand(Operand *Operand) { |
| } |
| auto *MemOperand = X86OperandMem::create( |
| Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
| - Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
| + Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsRebased()); |
| // Test if the Offset is an eligible i32 constants for randomization and |
| // pooling. Blind/pool it if it is. Otherwise return as oridinary mem |
| // operand. |
| @@ -977,7 +993,7 @@ template <typename TraitsType> |
| llvm::SmallBitVector |
| TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include, |
| RegSetMask Exclude) const { |
| - return Traits::getRegisterSet(Include, Exclude); |
| + return Traits::getRegisterSet(Ctx->getFlags(), Include, Exclude); |
| } |
| template <typename TraitsType> |
| @@ -1037,35 +1053,38 @@ void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Inst) { |
| llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| const uint32_t Value = |
| Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); |
| - if (!UseFramePointer) { |
| + if (UseFramePointer) { |
| + _sub_sp(Ctx->getConstantInt32(Value)); |
| + } else { |
| // If we don't need a Frame Pointer, this alloca has a known offset to the |
| // stack pointer. We don't need adjust the stack pointer, nor assign any |
| // value to Dest, as Dest is rematerializable. |
| assert(Dest->isRematerializable()); |
| FixedAllocaSizeBytes += Value; |
| Context.insert<InstFakeDef>(Dest); |
| - } else { |
| - _sub(esp, Ctx->getConstantInt32(Value)); |
| } |
| } else { |
| // Non-constant sizes need to be adjusted to the next highest multiple of |
| // the required alignment at runtime. |
| - Variable *T = makeReg(Traits::WordType); |
| - if (Traits::Is64Bit && TotalSize->getType() != IceType_i64) { |
| + Variable *T = nullptr; |
| + if (Traits::Is64Bit && TotalSize->getType() != IceType_i64 && |
| + !NeedSandboxing) { |
| + T = makeReg(IceType_i64); |
| _movzx(T, TotalSize); |
| } else { |
| + T = makeReg(IceType_i32); |
| _mov(T, TotalSize); |
| } |
| _add(T, Ctx->getConstantInt32(Alignment - 1)); |
| _and(T, Ctx->getConstantInt32(-Alignment)); |
| - _sub(esp, T); |
| + _sub_sp(T); |
| } |
| // Add enough to the returned address to account for the out args area. |
| uint32_t OutArgsSize = maxOutArgsSizeBytes(); |
| if (OutArgsSize > 0) { |
| Variable *T = makeReg(IceType_i32); |
| auto *CalculateOperand = X86OperandMem::create( |
| - Func, IceType_i32, esp, Ctx->getConstantInt(IceType_i32, OutArgsSize)); |
| + Func, IceType_void, esp, Ctx->getConstantInt(IceType_i32, OutArgsSize)); |
| _lea(T, CalculateOperand); |
| _mov(Dest, T); |
| } else { |
| @@ -1086,8 +1105,8 @@ bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0, |
| if (Ctx->getFlags().getOptLevel() < Opt_1) |
| return false; |
| Type Ty = Dest->getType(); |
| - Variable *T = nullptr; |
| if (Src1 == -1) { |
| + Variable *T = nullptr; |
| _mov(T, Src0); |
| _neg(T); |
| _mov(Dest, T); |
| @@ -1098,6 +1117,7 @@ bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0, |
| return true; |
| } |
| if (Src1 == 1) { |
| + Variable *T = nullptr; |
| _mov(T, Src0); |
| _mov(Dest, T); |
| return true; |
| @@ -1136,14 +1156,20 @@ bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0, |
| } |
| } |
| // Lea optimization only works for i16 and i32 types, not i8. |
| - if (Ty != IceType_i16 && Ty != IceType_i32 && (Count3 || Count5 || Count9)) |
| + if (Ty != IceType_i32 && !(Traits::Is64Bit && Ty == IceType_i64) && |
| + (Count3 || Count5 || Count9)) |
| return false; |
| // Limit the number of lea/shl operations for a single multiply, to a |
| // somewhat arbitrary choice of 3. |
| constexpr uint32_t MaxOpsForOptimizedMul = 3; |
| if (CountOps > MaxOpsForOptimizedMul) |
| return false; |
| - _mov(T, Src0); |
| + Variable *T = makeReg(Traits::WordType); |
| + if (typeWidthInBytes(Src0->getType()) < typeWidthInBytes(T->getType())) { |
| + _movzx(T, Src0); |
| + } else { |
| + _mov(T, Src0); |
| + } |
| Constant *Zero = Ctx->getConstantZero(IceType_i32); |
| for (uint32_t i = 0; i < Count9; ++i) { |
| constexpr uint16_t Shift = 3; // log2(9-1) |
| @@ -3543,7 +3569,7 @@ void TargetX86Base<TraitsType>::lowerIntrinsicCall( |
| return; |
| } |
| case Intrinsics::NaClReadTP: { |
| - if (Ctx->getFlags().getUseSandboxing()) { |
| + if (NeedSandboxing) { |
| Operand *Src = |
| dispatchToConcrete(&ConcreteTarget::createNaClReadTPSrcOperand); |
| Variable *Dest = Instr->getDest(); |
| @@ -3571,20 +3597,26 @@ void TargetX86Base<TraitsType>::lowerIntrinsicCall( |
| return; |
| } |
| case Intrinsics::Stacksave: { |
| - Variable *esp = |
| - Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType); |
| + if (!Traits::Is64Bit || !NeedSandboxing) { |
| + Variable *esp = Func->getTarget()->getPhysicalRegister(getStackReg(), |
| + Traits::WordType); |
| + Variable *Dest = Instr->getDest(); |
| + _mov(Dest, esp); |
| + return; |
| + } |
| + Variable *esp = Func->getTarget()->getPhysicalRegister( |
| + Traits::RegisterSet::Reg_esp, IceType_i32); |
| Variable *Dest = Instr->getDest(); |
| _mov(Dest, esp); |
| + |
| return; |
| } |
| case Intrinsics::Stackrestore: { |
| Operand *Src = Instr->getArg(0); |
| - const Type SrcTy = Src->getType(); |
| - Variable *esp = Func->getTarget()->getPhysicalRegister( |
| - Traits::getGprForType(SrcTy, getStackReg()), SrcTy); |
| - _redefined(_mov(esp, Src)); |
| + _mov_sp(Src); |
| return; |
| } |
| + |
| case Intrinsics::Trap: |
| _ud2(); |
| return; |
| @@ -4293,25 +4325,6 @@ void TargetX86Base<TraitsType>::lowerMemset(Operand *Dest, Operand *Val, |
| lowerCall(Call); |
| } |
| -template <typename TraitsType> |
| -void TargetX86Base<TraitsType>::lowerIndirectJump(Variable *JumpTarget) { |
| - const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
| - if (Traits::Is64Bit) { |
| - Variable *T = makeReg(IceType_i64); |
| - _movzx(T, JumpTarget); |
| - JumpTarget = T; |
| - } |
| - if (NeedSandboxing) { |
| - _bundle_lock(); |
| - const SizeT BundleSize = |
| - 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
| - _and(JumpTarget, Ctx->getConstantInt32(~(BundleSize - 1))); |
| - } |
| - _jmp(JumpTarget); |
| - if (NeedSandboxing) |
| - _bundle_unlock(); |
| -} |
| - |
| inline bool isAdd(const Inst *Inst) { |
| if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { |
| return (Arith->getOp() == InstArithmetic::Add); |
| @@ -4551,13 +4564,15 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, |
| return false; |
| // Compute the updated constant offset. |
| if (Const0) { |
| - int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); |
| + const int32_t MoreOffset = |
| + IsAdd ? Const0->getValue() : -Const0->getValue(); |
| if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) |
| return false; |
| NewOffset += MoreOffset; |
| } |
| if (Const1) { |
| - int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); |
| + const int32_t MoreOffset = |
| + IsAdd ? Const1->getValue() : -Const1->getValue(); |
| if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) |
| return false; |
| NewOffset += MoreOffset; |
| @@ -4586,6 +4601,7 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, |
| // Index == nullptr, |
| // Shift == 0 |
| inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, |
| + bool ReserveSlot, |
| ConstantRelocatable *&Relocatable, |
| int32_t &Offset, Variable *&Base, |
| Variable *&Index, uint16_t &Shift) { |
| @@ -4610,6 +4626,7 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, |
| const VariablesMetadata *VMetadata = Func->getVMetadata(); |
| const Inst *Reason = nullptr; |
| do { |
| + assert(!ReserveSlot || Base == nullptr || Index == nullptr); |
| if (Reason) { |
| dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); |
| AddressWasOptimized = true; |
| @@ -4631,7 +4648,8 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, |
| // Transition from: |
| // <Relocatable + Offset>(Base) to |
| // <Relocatable + Offset>(Base, Index) |
| - if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) |
| + if (!ReserveSlot && |
| + matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) |
| continue; |
| // Recognize multiply/shift and update Shift amount. |
| // Index becomes Index=Var<<Const && Const+Shift<=3 ==> |
| @@ -4764,8 +4782,9 @@ void TargetX86Base<TraitsType>::doAddressOptLoad() { |
| // registers there either. |
| constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment; |
| auto *Base = llvm::dyn_cast<Variable>(Addr); |
| - if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
| - Shift)) { |
| + const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing; |
| + if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset, |
| + Base, Index, Shift)) { |
| Inst->setDeleted(); |
| Constant *OffsetOp = nullptr; |
| if (Relocatable == nullptr) { |
| @@ -4775,7 +4794,7 @@ void TargetX86Base<TraitsType>::doAddressOptLoad() { |
| Relocatable->getName(), |
| Relocatable->getSuppressMangling()); |
| } |
| - // The new mem operand is created without IsPIC being set, because |
| + // The new mem operand is created without IsRebased being set, because |
| // computeAddressOpt() doesn't include GotVar in its final result. |
| Addr = X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Index, |
| Shift, SegmentReg); |
| @@ -5069,8 +5088,9 @@ void TargetX86Base<TraitsType>::doAddressOptStore() { |
| // other X86OperandMem, so there should be no mention of segment |
| // registers there either. |
| constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment; |
| - if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
| - Shift)) { |
| + const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing; |
| + if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset, |
| + Base, Index, Shift)) { |
| Inst->setDeleted(); |
| Constant *OffsetOp = nullptr; |
| if (Relocatable == nullptr) { |
| @@ -5080,7 +5100,7 @@ void TargetX86Base<TraitsType>::doAddressOptStore() { |
| Relocatable->getName(), |
| Relocatable->getSuppressMangling()); |
| } |
| - // The new mem operand is created without IsPIC being set, because |
| + // The new mem operand is created without IsRebased being set, because |
| // computeAddressOpt() doesn't include GotVar in its final result. |
| Addr = X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Index, |
| Shift, SegmentReg); |
| @@ -5134,8 +5154,9 @@ void TargetX86Base<TraitsType>::lowerCaseCluster(const CaseCluster &Case, |
| // Make sure the index is a register of the same width as the base |
| Variable *Index; |
| - if (RangeIndex->getType() != getPointerType()) { |
| - Index = makeReg(getPointerType()); |
| + const Type PointerType = getPointerType(); |
| + if (RangeIndex->getType() != PointerType) { |
| + Index = makeReg(PointerType); |
| _movzx(Index, RangeIndex); |
| } else { |
| Index = legalizeToReg(RangeIndex); |
| @@ -5143,18 +5164,24 @@ void TargetX86Base<TraitsType>::lowerCaseCluster(const CaseCluster &Case, |
| constexpr RelocOffsetT RelocOffset = 0; |
| constexpr bool SuppressMangling = true; |
| - const bool IsPIC = Ctx->getFlags().getUseNonsfi(); |
| + const bool IsRebased = Ctx->getFlags().getUseNonsfi(); |
| IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| - Variable *Base = IsPIC ? legalizeToReg(GotVar) : nullptr; |
| + Variable *Base = IsRebased ? legalizeToReg(GotVar) : nullptr; |
| Constant *Offset = Ctx->getConstantSym( |
| RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), |
| SuppressMangling); |
| - uint16_t Shift = typeWidthInBytesLog2(getPointerType()); |
| + uint16_t Shift = typeWidthInBytesLog2(PointerType); |
| constexpr auto Segment = X86OperandMem::SegmentRegisters::DefaultSegment; |
| - auto *TargetInMemory = X86OperandMem::create( |
| - Func, getPointerType(), Base, Offset, Index, Shift, Segment, IsPIC); |
| + |
| Variable *Target = nullptr; |
| + if (Traits::Is64Bit && NeedSandboxing) { |
| + assert(Base == nullptr); |
| + assert(Index != nullptr && Index->getType() == IceType_i32); |
| + } |
| + auto *TargetInMemory = X86OperandMem::create( |
| + Func, PointerType, Base, Offset, Index, Shift, Segment, IsRebased); |
| _mov(Target, TargetInMemory); |
| + |
| lowerIndirectJump(Target); |
| if (DefaultTarget == nullptr) |
| @@ -6023,22 +6050,25 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
| Constant *Offset = Mem->getOffset(); |
| Variable *RegBase = nullptr; |
| Variable *RegIndex = nullptr; |
| + uint16_t Shift = Mem->getShift(); |
| if (Base) { |
| RegBase = llvm::cast<Variable>( |
| legalize(Base, Legal_Reg | Legal_Rematerializable)); |
| } |
| if (Index) { |
| + // TODO(jpp): perhaps we should only allow Legal_Reg if |
| + // Base->isRematerializable. |
| RegIndex = llvm::cast<Variable>( |
| legalize(Index, Legal_Reg | Legal_Rematerializable)); |
| } |
| // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we |
| // replace either Base or Index with a legalized GotVar. At emission time, |
| // the ConstantRelocatable will be emitted with the @GOTOFF relocation. |
| - bool NeedPIC = false; |
| - if (UseNonsfi && !Mem->getIsPIC() && Offset && |
| + bool IsRebased = false; |
| + if (UseNonsfi && !Mem->getIsRebased() && Offset && |
| llvm::isa<ConstantRelocatable>(Offset)) { |
| assert(!(Allowed & Legal_AddrAbs)); |
| - NeedPIC = true; |
| + IsRebased = true; |
| if (RegBase == nullptr) { |
| RegBase = legalizeToReg(GotVar); |
| } else if (RegIndex == nullptr) { |
| @@ -6049,9 +6079,8 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
| } |
| } |
| if (Base != RegBase || Index != RegIndex) { |
| - Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, |
| - Mem->getShift(), Mem->getSegmentRegister(), |
| - NeedPIC); |
| + Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, Shift, |
| + Mem->getSegmentRegister(), IsRebased); |
| } |
| // For all Memory Operands, we do randomization/pooling here |
| @@ -6100,8 +6129,9 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
| assert(Ty == IceType_i32); |
| Variable *RegBase = legalizeToReg(GotVar); |
| Variable *NewVar = makeReg(Ty, RegNum); |
| - auto *Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, CR); |
| - Mem->setIsPIC(); |
| + static constexpr bool IsRebased = true; |
| + auto *Mem = |
| + Traits::X86OperandMem::create(Func, Ty, RegBase, CR, IsRebased); |
| _lea(NewVar, Mem); |
| From = NewVar; |
| } |
| @@ -6123,9 +6153,8 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
| llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); |
| llvm::cast<Constant>(From)->setShouldBePooled(true); |
| Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| - auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset); |
| - if (UseNonsfi) |
| - Mem->setIsPIC(); |
| + const bool IsRebased = Base != nullptr; |
| + auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset, IsRebased); |
| From = Mem; |
| } |
| bool NeedsReg = false; |
| @@ -6249,7 +6278,8 @@ TargetX86Base<TraitsType>::formMemoryOperand(Operand *Opnd, Type Ty, |
| assert(llvm::isa<ConstantInteger32>(Offset) || |
| llvm::isa<ConstantRelocatable>(Offset)); |
| } |
| - // Not completely sure whether it's OK to leave IsPIC unset when creating |
| + // Not completely sure whether it's OK to leave IsRebased unset when |
|
Jim Stichnoth
2016/01/14 00:09:52
reflow
John
2016/01/14 23:18:25
Done.
|
| + // creating |
| // the mem operand. If DoLegalize is true, it will definitely be applied |
| // during the legalize() call, but perhaps not during the |
| // randomizeOrPoolImmediate() call. In any case, the emit routines will |
| @@ -6379,71 +6409,80 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate, |
| // Immediates randomization/pooling off or paused |
| return Immediate; |
| } |
| - if (Immediate->shouldBeRandomizedOrPooled(Ctx)) { |
| - Ctx->statsUpdateRPImms(); |
| - if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == |
| - RPI_Randomize) { |
| - // blind the constant |
| - // FROM: |
| - // imm |
| - // TO: |
| - // insert: mov imm+cookie, Reg |
| - // insert: lea -cookie[Reg], Reg |
| - // => Reg |
| - // If we have already assigned a phy register, we must come from |
| - // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the |
| - // assigned register as this assignment is that start of its use-def |
| - // chain. So we add RegNum argument here. Note we use 'lea' instruction |
| - // instead of 'xor' to avoid affecting the flags. |
| - Variable *Reg = makeReg(IceType_i32, RegNum); |
| - auto *Integer = llvm::cast<ConstantInteger32>(Immediate); |
| - uint32_t Value = Integer->getValue(); |
| - uint32_t Cookie = Func->getConstantBlindingCookie(); |
| - _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); |
| - Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); |
| - _lea(Reg, |
| - X86OperandMem::create(Func, IceType_i32, Reg, Offset, nullptr, 0)); |
| - if (Immediate->getType() != IceType_i32) { |
| - Variable *TruncReg = makeReg(Immediate->getType(), RegNum); |
| - _mov(TruncReg, Reg); |
| - return TruncReg; |
| - } |
| - return Reg; |
| - } |
| - if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { |
| - // pool the constant |
| - // FROM: |
| - // imm |
| - // TO: |
| - // insert: mov $label, Reg |
| - // => Reg |
| - assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool); |
| - Immediate->setShouldBePooled(true); |
| - // if we have already assigned a phy register, we must come from |
| - // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the |
| - // assigned register as this assignment is that start of its use-def |
| - // chain. So we add RegNum argument here. |
| - Variable *Reg = makeReg(Immediate->getType(), RegNum); |
| - IceString Label; |
| - llvm::raw_string_ostream Label_stream(Label); |
| - Immediate->emitPoolLabel(Label_stream, Ctx); |
| - constexpr RelocOffsetT Offset = 0; |
| - constexpr bool SuppressMangling = true; |
| - Constant *Symbol = |
| - Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); |
| - const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
| - Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
| - X86OperandMem *MemOperand = |
| - X86OperandMem::create(Func, Immediate->getType(), Base, Symbol); |
| - if (UseNonsfi) |
| - MemOperand->setIsPIC(); |
| - _mov(Reg, MemOperand); |
| + |
| + if (Traits::Is64Bit && NeedSandboxing) { |
| + // Immediate randomization/pooling is currently disabled for x86-64 |
| + // sandboxing for it could generate invalid memory operands. |
| + assert(false && |
| + "Constant pooling/randomization is disabled for x8664 sandbox."); |
| + return Immediate; |
| + } |
| + |
| + if (!Immediate->shouldBeRandomizedOrPooled(Ctx)) { |
| + // the constant Immediate is not eligible for blinding/pooling |
| + return Immediate; |
| + } |
| + Ctx->statsUpdateRPImms(); |
| + switch (Ctx->getFlags().getRandomizeAndPoolImmediatesOption()) { |
| + default: |
| + llvm::report_fatal_error("Unsupported -randomize-pool-immediates option"); |
| + case RPI_Randomize: { |
| + // blind the constant |
| + // FROM: |
| + // imm |
| + // TO: |
| + // insert: mov imm+cookie, Reg |
| + // insert: lea -cookie[Reg], Reg |
| + // => Reg |
| + // If we have already assigned a phy register, we must come from |
| + // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the |
| + // assigned register as this assignment is that start of its use-def |
| + // chain. So we add RegNum argument here. Note we use 'lea' instruction |
| + // instead of 'xor' to avoid affecting the flags. |
| + Variable *Reg = makeReg(IceType_i32, RegNum); |
| + auto *Integer = llvm::cast<ConstantInteger32>(Immediate); |
| + uint32_t Value = Integer->getValue(); |
| + uint32_t Cookie = Func->getConstantBlindingCookie(); |
| + _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); |
| + Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); |
| + _lea(Reg, X86OperandMem::create(Func, IceType_i32, Reg, Offset)); |
| + if (Immediate->getType() == IceType_i32) { |
| return Reg; |
| } |
| - assert("Unsupported -randomize-pool-immediates option" && false); |
| + Variable *TruncReg = makeReg(Immediate->getType(), RegNum); |
| + _mov(TruncReg, Reg); |
| + return TruncReg; |
| + } |
| + case RPI_Pool: { |
| + // pool the constant |
| + // FROM: |
| + // imm |
| + // TO: |
| + // insert: mov $label, Reg |
| + // => Reg |
| + assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool); |
| + Immediate->setShouldBePooled(true); |
| + // if we have already assigned a phy register, we must come from |
| + // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the |
| + // assigned register as this assignment is that start of its use-def |
| + // chain. So we add RegNum argument here. |
| + Variable *Reg = makeReg(Immediate->getType(), RegNum); |
| + IceString Label; |
| + llvm::raw_string_ostream Label_stream(Label); |
| + Immediate->emitPoolLabel(Label_stream, Ctx); |
| + constexpr RelocOffsetT Offset = 0; |
| + constexpr bool SuppressMangling = true; |
| + Constant *Symbol = |
| + Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); |
| + const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
| + Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
| + const bool IsRebased = Base != nullptr; |
| + X86OperandMem *MemOperand = X86OperandMem::create( |
| + Func, Immediate->getType(), Base, Symbol, IsRebased); |
| + _mov(Reg, MemOperand); |
| + return Reg; |
| + } |
| } |
| - // the constant Immediate is not eligible for blinding/pooling |
| - return Immediate; |
| } |
| template <typename TraitsType> |
| @@ -6457,107 +6496,116 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, |
| return MemOperand; |
| } |
| + if (Traits::Is64Bit && NeedSandboxing) { |
| + // Immediate randomization/pooling is currently disabled for x86-64 |
| + // sandboxing for it could generate invalid memory operands. |
| + assert(false && |
| + "Constant pooling/randomization is disabled for x8664 sandbox."); |
| + return MemOperand; |
| + } |
| + |
| // If this memory operand is already a randomized one, we do not randomize it |
| // again. |
| if (MemOperand->getRandomized()) |
| return MemOperand; |
| - if (auto *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset())) { |
| - if (C->shouldBeRandomizedOrPooled(Ctx)) { |
| - // The offset of this mem operand should be blinded or pooled |
| - Ctx->statsUpdateRPImms(); |
| - if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == |
| - RPI_Randomize) { |
| - // blind the constant offset |
| - // FROM: |
| - // offset[base, index, shift] |
| - // TO: |
| - // insert: lea offset+cookie[base], RegTemp |
| - // => -cookie[RegTemp, index, shift] |
| - uint32_t Value = |
| - llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset()) |
| - ->getValue(); |
| - uint32_t Cookie = Func->getConstantBlindingCookie(); |
| - Constant *Mask1 = Ctx->getConstantInt( |
| - MemOperand->getOffset()->getType(), Cookie + Value); |
| - Constant *Mask2 = |
| - Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie); |
| - |
| - X86OperandMem *TempMemOperand = X86OperandMem::create( |
| - Func, MemOperand->getType(), MemOperand->getBase(), Mask1); |
| - // If we have already assigned a physical register, we must come from |
| - // advancedPhiLowering()=>lowerAssign(). In this case we should reuse |
| - // the assigned register as this assignment is that start of its |
| - // use-def chain. So we add RegNum argument here. |
| - Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); |
| - _lea(RegTemp, TempMemOperand); |
| - |
| - X86OperandMem *NewMemOperand = X86OperandMem::create( |
| - Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(), |
| - MemOperand->getShift(), MemOperand->getSegmentRegister()); |
| - |
| - // Label this memory operand as randomized, so we won't randomize it |
| - // again in case we call legalize() multiple times on this memory |
| - // operand. |
| - NewMemOperand->setRandomized(true); |
| - return NewMemOperand; |
| - } |
| - if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { |
| - // pool the constant offset |
| - // FROM: |
| - // offset[base, index, shift] |
| - // TO: |
| - // insert: mov $label, RegTemp |
| - // insert: lea [base, RegTemp], RegTemp |
| - // =>[RegTemp, index, shift] |
| - assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == |
| - RPI_Pool); |
| - // Memory operand should never exist as source operands in phi lowering |
| - // assignments, so there is no need to reuse any registers here. For |
| - // phi lowering, we should not ask for new physical registers in |
| - // general. However, if we do meet Memory Operand during phi lowering, |
| - // we should not blind or pool the immediates for now. |
| - if (RegNum != Variable::NoRegister) |
| - return MemOperand; |
| - Variable *RegTemp = makeReg(IceType_i32); |
| - IceString Label; |
| - llvm::raw_string_ostream Label_stream(Label); |
| - MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); |
| - MemOperand->getOffset()->setShouldBePooled(true); |
| - constexpr RelocOffsetT SymOffset = 0; |
| - constexpr bool SuppressMangling = true; |
| - Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), |
| - SuppressMangling); |
| - const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
| - Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
| - X86OperandMem *SymbolOperand = X86OperandMem::create( |
| - Func, MemOperand->getOffset()->getType(), Base, Symbol); |
| - if (UseNonsfi) |
| - SymbolOperand->setIsPIC(); |
| - _mov(RegTemp, SymbolOperand); |
| - // If we have a base variable here, we should add the lea instruction |
| - // to add the value of the base variable to RegTemp. If there is no |
| - // base variable, we won't need this lea instruction. |
| - if (MemOperand->getBase()) { |
| - X86OperandMem *CalculateOperand = X86OperandMem::create( |
| - Func, MemOperand->getType(), MemOperand->getBase(), nullptr, |
| - RegTemp, 0, MemOperand->getSegmentRegister()); |
| - _lea(RegTemp, CalculateOperand); |
| - } |
| - X86OperandMem *NewMemOperand = X86OperandMem::create( |
| - Func, MemOperand->getType(), RegTemp, nullptr, |
| - MemOperand->getIndex(), MemOperand->getShift(), |
| - MemOperand->getSegmentRegister()); |
| - return NewMemOperand; |
| - } |
| - assert("Unsupported -randomize-pool-immediates option" && false); |
| - } |
| + auto *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset()); |
| + |
| + if (C == nullptr) { |
| + return MemOperand; |
| } |
| - // the offset is not eligible for blinding or pooling, return the original |
| - // mem operand |
| - return MemOperand; |
| -} |
| + if (!C->shouldBeRandomizedOrPooled(Ctx)) { |
| + return MemOperand; |
| + } |
| + |
| + // The offset of this mem operand should be blinded or pooled |
| + Ctx->statsUpdateRPImms(); |
| + switch (Ctx->getFlags().getRandomizeAndPoolImmediatesOption()) { |
| + default: |
| + llvm::report_fatal_error("Unsupported -randomize-pool-immediates option"); |
| + case RPI_Randomize: { |
| + // blind the constant offset |
| + // FROM: |
| + // offset[base, index, shift] |
| + // TO: |
| + // insert: lea offset+cookie[base], RegTemp |
| + // => -cookie[RegTemp, index, shift] |
| + uint32_t Value = |
| + llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset())->getValue(); |
| + uint32_t Cookie = Func->getConstantBlindingCookie(); |
| + Constant *Mask1 = |
| + Ctx->getConstantInt(MemOperand->getOffset()->getType(), Cookie + Value); |
| + Constant *Mask2 = |
| + Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie); |
| + |
| + X86OperandMem *TempMemOperand = X86OperandMem::create( |
| + Func, MemOperand->getType(), MemOperand->getBase(), Mask1); |
| + // If we have already assigned a physical register, we must come from |
| + // advancedPhiLowering()=>lowerAssign(). In this case we should reuse |
| + // the assigned register as this assignment is that start of its |
| + // use-def chain. So we add RegNum argument here. |
| + Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); |
| + _lea(RegTemp, TempMemOperand); |
| + |
| + X86OperandMem *NewMemOperand = X86OperandMem::create( |
| + Func, MemOperand->getType(), RegTemp, Mask2, MemOperand->getIndex(), |
| + MemOperand->getShift(), MemOperand->getSegmentRegister(), |
| + MemOperand->getIsRebased()); |
| + |
| + // Label this memory operand as randomized, so we won't randomize it |
| + // again in case we call legalize() multiple times on this memory |
| + // operand. |
| + NewMemOperand->setRandomized(true); |
| + return NewMemOperand; |
| + } |
| + case RPI_Pool: { |
| + // pool the constant offset |
| + // FROM: |
| + // offset[base, index, shift] |
| + // TO: |
| + // insert: mov $label, RegTemp |
| + // insert: lea [base, RegTemp], RegTemp |
| + // =>[RegTemp, index, shift] |
| + |
| + // Memory operand should never exist as source operands in phi lowering |
| + // assignments, so there is no need to reuse any registers here. For |
| + // phi lowering, we should not ask for new physical registers in |
| + // general. However, if we do meet Memory Operand during phi lowering, |
| + // we should not blind or pool the immediates for now. |
| + if (RegNum != Variable::NoRegister) |
| + return MemOperand; |
| + Variable *RegTemp = makeReg(IceType_i32); |
| + IceString Label; |
| + llvm::raw_string_ostream Label_stream(Label); |
| + MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); |
| + MemOperand->getOffset()->setShouldBePooled(true); |
| + constexpr RelocOffsetT SymOffset = 0; |
| + constexpr bool SuppressMangling = true; |
| + Constant *Symbol = |
| + Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling); |
| + const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
| + Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
| + const bool IsRebased = Base != nullptr; |
| + X86OperandMem *SymbolOperand = X86OperandMem::create( |
| + Func, MemOperand->getOffset()->getType(), Base, Symbol, IsRebased); |
| + _mov(RegTemp, SymbolOperand); |
| + // If we have a base variable here, we should add the lea instruction |
| + // to add the value of the base variable to RegTemp. If there is no |
| + // base variable, we won't need this lea instruction. |
| + if (MemOperand->getBase()) { |
| + X86OperandMem *CalculateOperand = X86OperandMem::create( |
| + Func, MemOperand->getType(), MemOperand->getBase(), nullptr, RegTemp, |
| + 0, MemOperand->getSegmentRegister()); |
| + _lea(RegTemp, CalculateOperand); |
| + } |
| + X86OperandMem *NewMemOperand = X86OperandMem::create( |
| + Func, MemOperand->getType(), RegTemp, nullptr, MemOperand->getIndex(), |
| + MemOperand->getShift(), MemOperand->getSegmentRegister()); |
| + return NewMemOperand; |
| + } |
| + } |
| +} |
| } // end of namespace X86NAMESPACE |
| } // end of namespace Ice |