Index: src/IceTargetLoweringX86BaseImpl.h |
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h |
index 04d9cdc00d08f884ecb4204804ed2cf07f8e024f..5127768437978d0623cfa2e52d4ea0e0767bfee5 100644 |
--- a/src/IceTargetLoweringX86BaseImpl.h |
+++ b/src/IceTargetLoweringX86BaseImpl.h |
@@ -323,13 +323,19 @@ TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) |
} |
} |
-template <typename TraitsType> void TargetX86Base<TraitsType>::staticInit() { |
+template <typename TraitsType> |
+void TargetX86Base<TraitsType>::staticInit(const ClFlags &Flags) { |
Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); |
+ PcRelFixup = Traits::FK_PcRel; |
+ AbsFixup = Flags.getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; |
} |
template <typename TraitsType> void TargetX86Base<TraitsType>::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"); |
@@ -398,6 +404,7 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { |
Func->genCode(); |
if (Func->hasError()) |
return; |
+ initGotVarIfNeeded(); |
Func->dump("After x86 codegen"); |
// Register allocation. This requires instruction renumbering and full |
@@ -456,6 +463,9 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { |
template <typename TraitsType> void TargetX86Base<TraitsType>::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. |
@@ -478,6 +488,7 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() { |
Func->genCode(); |
if (Func->hasError()) |
return; |
+ initGotVarIfNeeded(); |
Func->dump("After initial x8632 codegen"); |
regAlloc(RAK_InfOnly); |
@@ -803,7 +814,8 @@ void TargetX86Base<TraitsType>::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(); |
@@ -829,9 +841,10 @@ template <typename TraitsType> |
typename TargetX86Base<TraitsType>::X86Address |
TargetX86Base<TraitsType>::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<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->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<TraitsType>::hiOperand(Operand *Operand) { |
} |
auto *MemOperand = 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. |
@@ -968,6 +981,23 @@ TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include, |
} |
template <typename TraitsType> |
+void TargetX86Base<TraitsType>::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<typename Traits::Insts::GetIP>(GotVar); |
+} |
+ |
+template <typename TraitsType> |
void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Inst) { |
// Conservatively require the stack to be aligned. Some stack adjustment |
// operations implemented below assume that the stack is aligned before the |
@@ -3984,6 +4014,11 @@ void TargetX86Base<TraitsType>::lowerCountZeros(bool Cttz, Type Ty, |
template <typename TraitsType> |
void TargetX86Base<TraitsType>::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 = X86OperandMem::create(Func, Ty, Base, Offset); |
if (isVectorType(Ty)) |
@@ -3997,6 +4032,11 @@ void TargetX86Base<TraitsType>::typedLoad(Type Ty, Variable *Dest, |
template <typename TraitsType> |
void TargetX86Base<TraitsType>::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 = X86OperandMem::create(Func, Ty, Base, Offset); |
if (isVectorType(Ty)) |
@@ -4306,9 +4346,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; |
@@ -4335,7 +4375,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; |
@@ -4454,7 +4494,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 ==> |
@@ -4505,6 +4547,8 @@ inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
NewRelocatable = Reloc0; |
else if (Reloc1) |
NewRelocatable = Reloc1; |
+ if ((Reloc0 || Reloc1) && BaseOther && GotVar) |
+ return false; |
// Compute the updated constant offset. |
if (Const0) { |
int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); |
@@ -4520,6 +4564,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; |
@@ -4537,7 +4585,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) { |
@@ -4568,7 +4616,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. |
@@ -4576,7 +4624,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) { |
@@ -4605,10 +4653,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 ==> |
@@ -4619,6 +4668,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; |
} |
@@ -4683,10 +4738,9 @@ void TargetX86Base<TraitsType>::doMockBoundsCheck(Operand *Opnd) { |
template <typename TraitsType> |
void TargetX86Base<TraitsType>::lowerLoad(const InstLoad *Load) { |
// A Load instruction can be treated the same as an Assign instruction, after |
- // the source operand is transformed into an X86OperandMem operand. |
- // Note that the address mode optimization already creates an |
- // X86OperandMem operand, so it doesn't need another level of |
- // transformation. |
+ // the source operand is transformed into an X86OperandMem operand. Note that |
+ // the address mode optimization already creates an X86OperandMem operand, so |
+ // it doesn't need another level of transformation. |
Variable *DestLoad = Load->getDest(); |
Type Ty = DestLoad->getType(); |
Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); |
@@ -4708,9 +4762,10 @@ void TargetX86Base<TraitsType>::doAddressOptLoad() { |
// computeAddressOpt only works at the level of Variables and Constants, not |
// other X86OperandMem, so there should be no mention of segment |
// registers there either. |
- const SegmentRegisters SegmentReg = X86OperandMem::DefaultSegment; |
+ constexpr auto SegmentReg = 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) { |
@@ -4720,6 +4775,8 @@ void TargetX86Base<TraitsType>::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 = X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Index, |
Shift, SegmentReg); |
Context.insert<InstLoad>(Dest, Addr); |
@@ -5011,8 +5068,9 @@ void TargetX86Base<TraitsType>::doAddressOptStore() { |
// computeAddressOpt only works at the level of Variables and Constants, not |
// other X86OperandMem, so there should be no mention of segment |
// registers there either. |
- const SegmentRegisters SegmentReg = X86OperandMem::DefaultSegment; |
- if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { |
+ constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment; |
+ if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
+ Shift)) { |
Inst->setDeleted(); |
Constant *OffsetOp = nullptr; |
if (Relocatable == nullptr) { |
@@ -5022,6 +5080,8 @@ void TargetX86Base<TraitsType>::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 = X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Index, |
Shift, SegmentReg); |
auto *NewStore = Context.insert<InstStore>(Data, Addr); |
@@ -5083,15 +5143,16 @@ void TargetX86Base<TraitsType>::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 = X86OperandMem::SegmentRegisters::DefaultSegment; |
auto *TargetInMemory = 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); |
@@ -5417,8 +5478,31 @@ void TargetX86Base<TraitsType>::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 <typename TraitsType> void TargetX86Base<TraitsType>::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. |
@@ -5901,7 +5985,8 @@ Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, int32_t RegNum) { |
template <typename TraitsType> |
Operand *TargetX86Base<TraitsType>::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 |
@@ -5935,6 +6020,7 @@ Operand *TargetX86Base<TraitsType>::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) { |
@@ -5945,9 +6031,27 @@ Operand *TargetX86Base<TraitsType>::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 = X86OperandMem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex, |
- Mem->getShift(), Mem->getSegmentRegister()); |
+ Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, |
+ Mem->getShift(), Mem->getSegmentRegister(), |
+ NeedPIC); |
} |
// For all Memory Operands, we do randomization/pooling here |
@@ -5958,6 +6062,7 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
} |
return From; |
} |
+ |
if (auto *Const = llvm::dyn_cast<Constant>(From)) { |
if (llvm::isa<ConstantUndef>(Const)) { |
From = legalizeUndef(Const, RegNum); |
@@ -5988,6 +6093,20 @@ Operand *TargetX86Base<TraitsType>::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)) { |
@@ -5998,13 +6117,16 @@ Operand *TargetX86Base<TraitsType>::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 = X86OperandMem::create(Func, Ty, Base, Offset); |
+ auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset); |
+ if (UseNonsfi) |
+ Mem->setIsPIC(); |
+ From = Mem; |
} |
bool NeedsReg = false; |
if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
@@ -6018,6 +6140,7 @@ Operand *TargetX86Base<TraitsType>::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 |
@@ -6046,7 +6169,8 @@ Operand *TargetX86Base<TraitsType>::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; |
} |
@@ -6116,7 +6240,7 @@ TargetX86Base<TraitsType>::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)); |
@@ -6125,6 +6249,11 @@ 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 |
+ // 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 = X86OperandMem::create(Func, Ty, Base, Offset); |
} |
// Do legalization, which contains randomization/pooling or do |
@@ -6192,7 +6321,7 @@ void TargetX86Base<TraitsType>::emit(const ConstantInteger32 *C) const { |
if (!BuildDefs::dump()) |
return; |
Ostream &Str = Ctx->getStrEmit(); |
- Str << getConstantPrefix() << C->getValue(); |
+ Str << "$" << C->getValue(); |
} |
template <typename TraitsType> |
@@ -6203,7 +6332,7 @@ void TargetX86Base<TraitsType>::emit(const ConstantInteger64 *C) const { |
if (!BuildDefs::dump()) |
return; |
Ostream &Str = Ctx->getStrEmit(); |
- Str << getConstantPrefix() << C->getValue(); |
+ Str << "$" << C->getValue(); |
} |
} |
@@ -6228,6 +6357,16 @@ void TargetX86Base<TraitsType>::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 <typename TraitsType> |
Operand * |
@@ -6292,8 +6431,12 @@ TargetX86Base<TraitsType>::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; |
X86OperandMem *MemOperand = |
- X86OperandMem::create(Func, Immediate->getType(), nullptr, Symbol); |
+ X86OperandMem::create(Func, Immediate->getType(), Base, Symbol); |
+ if (UseNonsfi) |
+ MemOperand->setIsPIC(); |
_mov(Reg, MemOperand); |
return Reg; |
} |
@@ -6385,8 +6528,12 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, |
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(), 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 |