Chromium Code Reviews| Index: src/IceTargetLoweringX86BaseImpl.h |
| diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
| index a169203e2e036a48eb8bea3245dfae8f91b4b007..3b61a70c4075b0fb58378a9031731288c5dfaa5e 100644 |
| --- a/src/IceTargetLoweringX86BaseImpl.h |
| +++ b/src/IceTargetLoweringX86BaseImpl.h |
| @@ -324,13 +324,19 @@ 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::FK_PcRel; |
| + AbsFixup = Flags.getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; |
| } |
| 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 +405,7 @@ template <class Machine> void TargetX86Base<Machine>::translateO2() { |
| Func->genCode(); |
| if (Func->hasError()) |
| return; |
| + initGotVarIfNeeded(); |
| Func->dump("After x86 codegen"); |
| // Register allocation. This requires instruction renumbering and full |
| @@ -457,6 +464,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 +489,7 @@ template <class Machine> void TargetX86Base<Machine>::translateOm1() { |
| Func->genCode(); |
| if (Func->hasError()) |
| return; |
| + initGotVarIfNeeded(); |
| Func->dump("After initial x8632 codegen"); |
| regAlloc(RAK_InfOnly); |
| @@ -801,7 +812,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(); |
| @@ -827,9 +839,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(); |
| @@ -910,7 +923,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. |
| @@ -950,7 +963,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. |
| @@ -967,6 +980,22 @@ TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, |
| return Traits::getRegisterSet(Include, Exclude); |
| } |
| +template <class Machine> void TargetX86Base<Machine>::initGotVarIfNeeded() { |
| + if (!Func->getContext()->getFlags().getUseNonsfi()) |
| + return; |
| + if (Traits::Is64Bit) { |
| + // Probably no implementation is needed, but error to be safe for now. |
| + llvm::report_fatal_error( |
| + "Need to implement initGotVarIfNeeded() for 64-bit."); |
| + } |
| + // 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 |
| @@ -3998,6 +4027,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)) |
| @@ -4011,6 +4045,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)) |
| @@ -4320,9 +4359,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; |
| @@ -4349,7 +4388,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; |
| @@ -4468,7 +4507,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 ==> |
| @@ -4519,6 +4560,8 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| NewRelocatable = Reloc0; |
| else if (Reloc1) |
| NewRelocatable = Reloc1; |
| + if ((Reloc0 || Reloc1) && BaseOther && GotVar) |
|
John
2016/01/04 21:33:51
add '!= nullptr'? or not. :)
Jim Stichnoth
2016/01/04 23:32:12
hmm, maybe not, since this follows the style of th
|
| + return false; |
| // Compute the updated constant offset. |
| if (Const0) { |
| int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); |
| @@ -4534,6 +4577,10 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| } |
| // Update the computed address parameters once we are sure optimization |
| // is valid. |
| + if ((Reloc0 || Reloc1) && GotVar) { |
| + assert(BaseOther == nullptr); |
| + BaseOther = GotVar; |
| + } |
| Base = NewBase; |
| Offset = NewOffset; |
| Relocatable = NewRelocatable; |
| @@ -4551,7 +4598,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) { |
| @@ -4582,7 +4629,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. |
| @@ -4590,7 +4637,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) { |
| @@ -4619,10 +4666,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 ==> |
| @@ -4633,6 +4681,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; |
| } |
| @@ -4698,7 +4752,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(); |
| @@ -4721,10 +4775,11 @@ 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::SegmentRegisters::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) { |
| @@ -4734,6 +4789,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); |
| @@ -5028,9 +5085,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; |
| + if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
|
John
2016/01/04 21:33:51
These address mode formation helpers are now bette
Jim Stichnoth
2016/01/04 23:32:12
That seems good, but maybe as a follow-on CL? Giv
|
| + Shift)) { |
| Inst->setDeleted(); |
| Constant *OffsetOp = nullptr; |
| if (Relocatable == nullptr) { |
| @@ -5040,6 +5097,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); |
| @@ -5100,15 +5159,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); |
| @@ -5439,8 +5499,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. |
| @@ -5921,7 +6004,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 |
| @@ -5955,6 +6039,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) { |
| @@ -5965,10 +6050,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 |
| @@ -5979,6 +6081,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); |
| @@ -6009,6 +6112,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)) { |
| @@ -6019,13 +6136,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)) |
| @@ -6039,6 +6159,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 |
| @@ -6067,7 +6188,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; |
| } |
| @@ -6135,7 +6257,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)); |
| @@ -6144,6 +6266,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 |
| @@ -6211,7 +6338,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> |
| @@ -6222,7 +6349,7 @@ void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { |
| if (!BuildDefs::dump()) |
| return; |
| Ostream &Str = Ctx->getStrEmit(); |
| - Str << getConstantPrefix() << C->getValue(); |
| + Str << "$" << C->getValue(); |
| } |
| } |
| @@ -6247,6 +6374,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, |
| @@ -6310,9 +6447,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; |
| } |
| @@ -6407,9 +6548,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 |