Chromium Code Reviews| Index: src/IceTargetLoweringX86BaseImpl.h |
| diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
| index d251e6a2756c66ed28d189e7e588ac38c7ed0771..be0494317888ef7112bdaccf2f5f281e20ac9252 100644 |
| --- a/src/IceTargetLoweringX86BaseImpl.h |
| +++ b/src/IceTargetLoweringX86BaseImpl.h |
| @@ -324,13 +324,20 @@ TargetX86Base<Machine>::TargetX86Base(Cfg *Func) |
| } |
| } |
| -template <class Machine> void TargetX86Base<Machine>::staticInit() { |
| +template <class Machine> |
| +void TargetX86Base<Machine>::staticInit(const ClFlags &Flags) { |
| Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); |
| + PcRelFixup = Traits::FixupKindPcRel; |
| + RelFixup = |
| + Flags.getUseNonsfi() ? Traits::FixupKindGotoff : Traits::FixupKindAbs; |
| } |
| template <class Machine> void TargetX86Base<Machine>::translateO2() { |
| TimerMarker T(TimerStack::TT_O2, Func); |
| + if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { |
| + GotVar = Func->makeVariable(IceType_i32); |
| + } |
| genTargetHelperCalls(); |
| Func->dump("After target helper call insertion"); |
| @@ -399,6 +406,7 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
| Func->genCode(); |
| if (Func->hasError()) |
| return; |
| + initGotVar(); |
| Func->dump("After x86 codegen"); |
| // Register allocation. This requires instruction renumbering and full |
| @@ -457,6 +465,9 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
| template <class Machine> void TargetX86Base<Machine>::translateOm1() { |
| TimerMarker T(TimerStack::TT_Om1, Func); |
| + if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { |
| + GotVar = Func->makeVariable(IceType_i32); |
| + } |
| genTargetHelperCalls(); |
| // Do not merge Alloca instructions, and lay out the stack. |
| @@ -479,6 +490,7 @@ template <class Machine> void TargetX86Base<Machine>::translateOm1() { |
| Func->genCode(); |
| if (Func->hasError()) |
| return; |
| + initGotVar(); |
|
John
2015/12/22 15:44:38
My first thought here was "a if (SFI) is missing."
Jim Stichnoth
2015/12/28 07:54:07
Done - renamed to initGotVarIfNeeded().
|
| Func->dump("After initial x8632 codegen"); |
| regAlloc(RAK_InfOnly); |
| @@ -804,7 +816,8 @@ void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { |
| return; |
| } |
| if (Var->mustHaveReg()) { |
| - llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| + llvm::report_fatal_error( |
| + "Infinite-weight Variable has no register assigned"); |
| } |
| const int32_t Offset = Var->getStackOffset(); |
| int32_t BaseRegNum = Var->getBaseRegNum(); |
| @@ -830,9 +843,10 @@ template <class Machine> |
| typename TargetX86Base<Machine>::Traits::Address |
| TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { |
| if (Var->hasReg()) |
| - llvm_unreachable("Stack Variable has a register assigned"); |
| + llvm::report_fatal_error("Stack Variable has a register assigned"); |
| if (Var->mustHaveReg()) { |
| - llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| + llvm::report_fatal_error( |
| + "Infinite-weight Variable has no register assigned"); |
| } |
| int32_t Offset = Var->getStackOffset(); |
| int32_t BaseRegNum = Var->getBaseRegNum(); |
| @@ -913,7 +927,7 @@ TargetX86Base<Machine>::loOperand(Operand *Operand) { |
| if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
| auto *MemOperand = Traits::X86OperandMem::create( |
| Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
| - Mem->getShift(), Mem->getSegmentRegister()); |
| + Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
| // 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. |
| @@ -953,7 +967,7 @@ TargetX86Base<Machine>::hiOperand(Operand *Operand) { |
| } |
| auto *MemOperand = Traits::X86OperandMem::create( |
| Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
| - Mem->getShift(), Mem->getSegmentRegister()); |
| + Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
| // 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. |
| @@ -970,6 +984,21 @@ TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, |
| return Traits::getRegisterSet(Include, Exclude); |
| } |
| +template <class Machine> void TargetX86Base<Machine>::initGotVar() { |
| + if (Traits::Is64Bit) { |
| + // Probably no implementation is needed, but error to be safe for now. |
| + llvm::report_fatal_error("Need to implement initGotVar() for 64-bit."); |
| + } |
| + if (!Func->getContext()->getFlags().getUseNonsfi()) |
| + return; |
| + // Insert the GotVar assignment as the very first lowered instruction. Later, |
| + // it will be moved into the right place - after the stack frame is set up but |
| + // before in-args are copied into registers. |
| + Context.init(Func->getEntryNode()); |
| + Context.setInsertPoint(Context.getCur()); |
| + Context.insert(InstX86GetIP<Machine>::create(Func, GotVar)); |
| +} |
| + |
| template <class Machine> |
| void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { |
| // Conservatively require the stack to be aligned. Some stack adjustment |
| @@ -3975,6 +4004,11 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, |
| template <class Machine> |
| void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, |
| Constant *Offset) { |
| + // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to |
| + // legalize Mem properly. |
| + if (Offset) |
| + assert(!llvm::isa<ConstantRelocatable>(Offset)); |
| + |
| auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
| if (isVectorType(Ty)) |
| @@ -3988,6 +4022,11 @@ void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, |
| template <class Machine> |
| void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value, |
| Variable *Base, Constant *Offset) { |
| + // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to |
| + // legalize Mem properly. |
| + if (Offset) |
| + assert(!llvm::isa<ConstantRelocatable>(Offset)); |
| + |
| auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
| if (isVectorType(Ty)) |
| @@ -4291,9 +4330,9 @@ inline void dumpAddressOpt(const Cfg *Func, |
| << ", Relocatable=" << Relocatable << "\n"; |
| } |
| -inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var, |
| - ConstantRelocatable *&Relocatable, int32_t &Offset, |
| - const Inst *&Reason) { |
| +inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar, |
| + Variable *&Var, ConstantRelocatable *&Relocatable, |
| + int32_t &Offset, const Inst *&Reason) { |
| // Var originates from Var=SrcVar ==> set Var:=SrcVar |
| if (Var == nullptr) |
| return false; |
| @@ -4320,7 +4359,7 @@ inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var, |
| return true; |
| } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { |
| if (Relocatable == nullptr) { |
| - Var = nullptr; |
| + Var = GotVar; |
| Relocatable = AddReloc; |
| Reason = VarAssign; |
| return true; |
| @@ -4439,7 +4478,9 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, |
| return false; |
| } |
| -inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| +inline bool matchOffsetBase(const VariablesMetadata *VMetadata, |
| + Variable *GotVar, Variable *&Base, |
| + Variable *&BaseOther, |
| ConstantRelocatable *&Relocatable, int32_t &Offset, |
| const Inst *&Reason) { |
| // Base is Base=Var+Const || Base is Base=Const+Var ==> |
| @@ -4490,6 +4531,8 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| NewRelocatable = Reloc0; |
| else if (Reloc1) |
| NewRelocatable = Reloc1; |
| + if (NewRelocatable && BaseOther && GotVar) |
| + return false; |
| // Compute the updated constant offset. |
| if (Const0) { |
| int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); |
| @@ -4505,6 +4548,10 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| } |
| // Update the computed address parameters once we are sure optimization |
| // is valid. |
| + if (NewRelocatable && GotVar) { |
| + assert(BaseOther == nullptr); |
| + BaseOther = GotVar; |
| + } |
| Base = NewBase; |
| Offset = NewOffset; |
| Relocatable = NewRelocatable; |
| @@ -4522,7 +4569,7 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| // Base is a Variable, |
| // Index == nullptr, |
| // Shift == 0 |
| -inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, |
| +inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, |
| ConstantRelocatable *&Relocatable, |
| int32_t &Offset, Variable *&Base, |
| Variable *&Index, uint16_t &Shift) { |
| @@ -4553,7 +4600,7 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, |
| Reason = nullptr; |
| } |
| // Update Base and Index to follow through assignments to definitions. |
| - if (matchAssign(VMetadata, Base, Relocatable, Offset, Reason)) { |
| + if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) { |
| // Assignments of Base from a Relocatable or ConstantInt32 can result |
| // in Base becoming nullptr. To avoid code duplication in this loop we |
| // prefer that Base be non-nullptr if possible. |
| @@ -4561,7 +4608,7 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, |
| std::swap(Base, Index); |
| continue; |
| } |
| - if (matchAssign(VMetadata, Index, Relocatable, Offset, Reason)) |
| + if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason)) |
| continue; |
| if (!MockBounds) { |
| @@ -4590,10 +4637,11 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, |
| // Update Offset to reflect additions/subtractions with constants and |
| // relocatables. |
| // TODO: consider overflow issues with respect to Offset. |
| - if (matchOffsetBase(VMetadata, Base, Relocatable, Offset, Reason)) |
| + if (matchOffsetBase(VMetadata, GotVar, Base, Index, Relocatable, Offset, |
| + Reason)) |
| continue; |
| - if (Shift == 0 && |
| - matchOffsetBase(VMetadata, Index, Relocatable, Offset, Reason)) |
| + if (Shift == 0 && matchOffsetBase(VMetadata, GotVar, Index, Base, |
| + Relocatable, Offset, Reason)) |
| continue; |
| // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. |
| // Index is Index=Var+Const ==> |
| @@ -4604,6 +4652,12 @@ inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, |
| // set Index=Var, Offset-=(Const<<Shift) |
| break; |
| } while (Reason); |
| + // Undo any addition of GotVar. It will be added back when the mem operand is |
| + // legalized. |
| + if (Base == GotVar) |
| + Base = nullptr; |
| + if (Index == GotVar) |
| + Index = nullptr; |
| return AddressWasOptimized; |
| } |
| @@ -4669,7 +4723,7 @@ template <class Machine> |
| void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { |
| // A Load instruction can be treated the same as an Assign instruction, after |
| // the source operand is transformed into an Traits::X86OperandMem operand. |
| - // Note that the address mode optimization already creates an |
| + // Note that the address mode optimization already creates a |
| // Traits::X86OperandMem operand, so it doesn't need another level of |
| // transformation. |
| Variable *DestLoad = Load->getDest(); |
| @@ -4692,10 +4746,10 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { |
| // computeAddressOpt only works at the level of Variables and Constants, not |
| // other Traits::X86OperandMem, so there should be no mention of segment |
| // registers there either. |
| - const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = |
| - Traits::X86OperandMem::DefaultSegment; |
| + constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment; |
| auto *Base = llvm::dyn_cast<Variable>(Addr); |
| - if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { |
| + if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
| + Shift)) { |
| Inst->setDeleted(); |
| Constant *OffsetOp = nullptr; |
| if (Relocatable == nullptr) { |
| @@ -4705,6 +4759,8 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { |
| Relocatable->getName(), |
| Relocatable->getSuppressMangling()); |
| } |
| + // The new mem operand is created without IsPIC being set, because |
| + // computeAddressOpt() doesn't include GotVar in its final result. |
| Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, |
| Index, Shift, SegmentReg); |
| Context.insert<InstLoad>(Dest, Addr); |
| @@ -4999,9 +5055,9 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() { |
| // computeAddressOpt only works at the level of Variables and Constants, not |
| // other Traits::X86OperandMem, so there should be no mention of segment |
| // registers there either. |
| - const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = |
| - Traits::X86OperandMem::DefaultSegment; |
| - if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { |
| + constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment; |
|
John
2015/12/22 15:44:38
I personally like this idiom, but this is an "unsa
Jim Stichnoth
2015/12/28 07:54:07
OK, I modified it such that the fully written out
|
| + if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
| + Shift)) { |
| Inst->setDeleted(); |
| Constant *OffsetOp = nullptr; |
| if (Relocatable == nullptr) { |
| @@ -5011,6 +5067,8 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() { |
| Relocatable->getName(), |
| Relocatable->getSuppressMangling()); |
| } |
| + // The new mem operand is created without IsPIC being set, because |
| + // computeAddressOpt() doesn't include GotVar in its final result. |
| Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, |
| Index, Shift, SegmentReg); |
| auto *NewStore = Context.insert<InstStore>(Data, Addr); |
| @@ -5071,15 +5129,16 @@ void TargetX86Base<Machine>::lowerCaseCluster(const CaseCluster &Case, |
| constexpr RelocOffsetT RelocOffset = 0; |
| constexpr bool SuppressMangling = true; |
| + const bool IsPIC = Ctx->getFlags().getUseNonsfi(); |
| IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| - Constant *Base = Ctx->getConstantSym( |
| + Variable *Base = IsPIC ? legalizeToReg(GotVar) : nullptr; |
| + Constant *Offset = Ctx->getConstantSym( |
| RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), |
| SuppressMangling); |
| - Constant *Offset = nullptr; |
| uint16_t Shift = typeWidthInBytesLog2(getPointerType()); |
| - // TODO(ascull): remove need for legalize by allowing null base in memop |
| + constexpr auto Segment = Traits::X86OperandMem::DefaultSegment; |
| auto *TargetInMemory = Traits::X86OperandMem::create( |
| - Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift); |
| + Func, getPointerType(), Base, Offset, Index, Shift, Segment, IsPIC); |
| Variable *Target = nullptr; |
| _mov(Target, TargetInMemory); |
| lowerIndirectJump(Target); |
| @@ -5410,8 +5469,31 @@ void TargetX86Base<Machine>::lowerOther(const Inst *Instr) { |
| /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
| /// integrity of liveness analysis. Undef values are also turned into zeroes, |
| -/// since loOperand() and hiOperand() don't expect Undef input. |
| +/// since loOperand() and hiOperand() don't expect Undef input. Also, in |
| +/// Non-SFI mode, add a FakeUse(GotVar) for every pooled constant operand. |
| template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { |
| + if (Ctx->getFlags().getUseNonsfi()) { |
| + assert(GotVar); |
| + CfgNode *Node = Context.getNode(); |
| + uint32_t GotVarUseCount = 0; |
| + for (Inst &I : Node->getPhis()) { |
| + auto *Phi = llvm::dyn_cast<InstPhi>(&I); |
| + if (Phi->isDeleted()) |
| + continue; |
| + for (SizeT I = 0; I < Phi->getSrcSize(); ++I) { |
| + Operand *Src = Phi->getSrc(I); |
| + // TODO(stichnot): This over-counts for +0.0, and under-counts for other |
| + // kinds of pooling. |
| + if (llvm::isa<ConstantRelocatable>(Src) || |
| + llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) { |
| + ++GotVarUseCount; |
| + } |
| + } |
| + } |
| + if (GotVarUseCount) { |
| + Node->getInsts().push_front(InstFakeUse::create(Func, GotVar)); |
| + } |
| + } |
| if (Traits::Is64Bit) { |
| // On x86-64 we don't need to prelower phis -- the architecture can handle |
| // 64-bit integer natively. |
| @@ -5892,7 +5974,8 @@ Variable *TargetX86Base<Machine>::copyToReg(Operand *Src, int32_t RegNum) { |
| template <class Machine> |
| Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| int32_t RegNum) { |
| - Type Ty = From->getType(); |
| + const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); |
| + const Type Ty = From->getType(); |
| // Assert that a physical register is allowed. To date, all calls to |
| // legalize() allow a physical register. If a physical register needs to be |
| // explicitly disallowed, then new code will need to be written to force a |
| @@ -5926,6 +6009,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| // Base and Index components are in physical registers. |
| Variable *Base = Mem->getBase(); |
| Variable *Index = Mem->getIndex(); |
| + Constant *Offset = Mem->getOffset(); |
| Variable *RegBase = nullptr; |
| Variable *RegIndex = nullptr; |
| if (Base) { |
| @@ -5936,10 +6020,27 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| 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 && |
| + llvm::isa<ConstantRelocatable>(Offset)) { |
| + assert(!(Allowed & Legal_AddrAbs)); |
| + NeedPIC = true; |
| + if (RegBase == nullptr) { |
| + RegBase = legalizeToReg(GotVar); |
| + } else if (RegIndex == nullptr) { |
| + RegIndex = legalizeToReg(GotVar); |
| + } else { |
| + llvm::report_fatal_error( |
| + "Either Base or Index must be unused in Non-SFI mode"); |
| + } |
| + } |
| if (Base != RegBase || Index != RegIndex) { |
| - Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Mem->getOffset(), |
| - RegIndex, Mem->getShift(), |
| - Mem->getSegmentRegister()); |
| + Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, |
| + Mem->getShift(), |
| + Mem->getSegmentRegister(), NeedPIC); |
| } |
| // For all Memory Operands, we do randomization/pooling here |
| @@ -5950,6 +6051,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| } |
| return From; |
| } |
| + |
| if (auto *Const = llvm::dyn_cast<Constant>(From)) { |
| if (llvm::isa<ConstantUndef>(Const)) { |
| From = legalizeUndef(Const, RegNum); |
| @@ -5978,6 +6080,20 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| } |
| } |
| + // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not |
| + // specified, and UseNonsfi is indicated, we need to add GotVar. |
| + if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) { |
| + if (UseNonsfi && !(Allowed & Legal_AddrAbs)) { |
| + assert(Ty == IceType_i32); |
| + Variable *RegBase = legalizeToReg(GotVar); |
| + Variable *NewVar = makeReg(Ty, RegNum); |
| + auto *Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, CR); |
| + Mem->setIsPIC(); |
| + _lea(NewVar, Mem); |
| + From = NewVar; |
| + } |
| + } |
| + |
| // Convert a scalar floating point constant into an explicit memory |
| // operand. |
| if (isScalarFloatingType(Ty)) { |
| @@ -5988,13 +6104,16 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| if (Utils::isPositiveZero(ConstDouble->getValue())) |
| return makeZeroedRegister(Ty, RegNum); |
| } |
| - Variable *Base = nullptr; |
| + Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
| std::string Buffer; |
| llvm::raw_string_ostream StrBuf(Buffer); |
| llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); |
| llvm::cast<Constant>(From)->setShouldBePooled(true); |
| Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| - From = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
| + auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
| + if (UseNonsfi) |
| + Mem->setIsPIC(); |
| + From = Mem; |
| } |
| bool NeedsReg = false; |
| if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
| @@ -6008,6 +6127,7 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| } |
| return From; |
| } |
| + |
| if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
| // Check if the variable is guaranteed a physical register. This can happen |
| // either when the variable is pre-colored or when it is assigned infinite |
| @@ -6036,7 +6156,8 @@ Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
| } |
| return From; |
| } |
| - llvm_unreachable("Unhandled operand kind in legalize()"); |
| + |
| + llvm::report_fatal_error("Unhandled operand kind in legalize()"); |
| return From; |
| } |
| @@ -6104,7 +6225,7 @@ TargetX86Base<Machine>::formMemoryOperand(Operand *Opnd, Type Ty, |
| // offset, we will work on the whole memory operand later as one entity |
| // later, this save one instruction. By turning blinding and pooling off, |
| // we guarantee legalize(Offset) will return a Constant*. |
| - { |
| + if (!llvm::isa<ConstantRelocatable>(Offset)) { |
| BoolFlagSaver B(RandomizationPoolingPaused, true); |
| Offset = llvm::cast<Constant>(legalize(Offset)); |
| @@ -6113,6 +6234,11 @@ TargetX86Base<Machine>::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 |
| + // 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 |
| + // assert that PIC legalization has been applied. |
| Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
| } |
| // Do legalization, which contains randomization/pooling or do |
| @@ -6181,7 +6307,7 @@ void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const { |
| if (!BuildDefs::dump()) |
| return; |
| Ostream &Str = Ctx->getStrEmit(); |
| - Str << getConstantPrefix() << C->getValue(); |
| + Str << "$" << C->getValue(); |
| } |
| template <class Machine> |
| @@ -6192,7 +6318,7 @@ void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { |
| if (!BuildDefs::dump()) |
| return; |
| Ostream &Str = Ctx->getStrEmit(); |
| - Str << getConstantPrefix() << C->getValue(); |
| + Str << "$" << C->getValue(); |
| } |
| } |
| @@ -6217,6 +6343,16 @@ void TargetX86Base<Machine>::emit(const ConstantUndef *) const { |
| llvm::report_fatal_error("undef value encountered by emitter."); |
| } |
| +template <class Machine> |
| +void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const { |
| + if (!BuildDefs::dump()) |
| + return; |
| + assert(!Ctx->getFlags().getUseNonsfi()); |
| + Ostream &Str = Ctx->getStrEmit(); |
| + Str << "$"; |
| + emitWithoutPrefix(C); |
| +} |
| + |
| /// Randomize or pool an Immediate. |
| template <class Machine> |
| Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
| @@ -6280,9 +6416,13 @@ Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
| 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; |
| typename Traits::X86OperandMem *MemOperand = |
| - Traits::X86OperandMem::create(Func, Immediate->getType(), nullptr, |
| + Traits::X86OperandMem::create(Func, Immediate->getType(), Base, |
| Symbol); |
| + if (UseNonsfi) |
| + MemOperand->setIsPIC(); |
| _mov(Reg, MemOperand); |
| return Reg; |
| } |
| @@ -6377,9 +6517,13 @@ TargetX86Base<Machine>::randomizeOrPoolImmediate( |
| 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; |
| typename Traits::X86OperandMem *SymbolOperand = |
| Traits::X86OperandMem::create( |
| - Func, MemOperand->getOffset()->getType(), nullptr, Symbol); |
| + 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 |