Index: src/IceInstX86BaseImpl.h |
diff --git a/src/IceInstX86BaseImpl.h b/src/IceInstX86BaseImpl.h |
index 3b6200194fdca99c532c99e5a883c1fb6d83c29c..244ee65e118ee9bf9ab77d74fd911791c8552c17 100644 |
--- a/src/IceInstX86BaseImpl.h |
+++ b/src/IceInstX86BaseImpl.h |
@@ -24,6 +24,7 @@ |
#include "IceInst.h" |
#include "IceOperand.h" |
#include "IceTargetLowering.h" |
+#include "IceTargetLoweringX86Base.h" |
namespace Ice { |
@@ -57,6 +58,10 @@ InstX86FakeRMW<Machine>::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, |
} |
template <class Machine> |
+InstX86GetIP<Machine>::InstX86GetIP(Cfg *Func, Variable *Dest) |
+ : InstX86Base<Machine>(Func, InstX86Base<Machine>::GetIP, 0, Dest) {} |
+ |
+template <class Machine> |
InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, |
Operand *Source2) |
: InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) { |
@@ -394,6 +399,57 @@ void InstX86FakeRMW<Machine>::dump(const Cfg *Func) const { |
} |
template <class Machine> |
+void InstX86GetIP<Machine>::emit(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ assert(this->getDest()->hasReg()); |
+ Str << "\t" |
+ "addl\t$_GLOBAL_OFFSET_TABLE_, "; |
+ this->getDest()->emit(Func); |
+} |
+ |
+template <class Machine> |
+void InstX86GetIP<Machine>::emitIAS(const Cfg *Func) const { |
+ if (Func->getContext()->getFlags().getOutFileType() == FT_Iasm) { |
+ // TODO(stichnot): Find a workaround for llvm-mc's inability to handle |
+ // something like ".long _GLOBAL_OFFSET_TABLE_ + ." . One possibility is to |
+ // just use hybrid iasm output for this add instruction. |
+ llvm::report_fatal_error( |
+ "Iasm support for _GLOBAL_OFFSET_TABLE_ not implemented"); |
+ } |
+ typename InstX86Base<Machine>::Traits::Assembler *Asm = |
+ Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); |
+ assert(this->getDest()->hasReg()); |
+ typename InstX86Base<Machine>::Traits::GPRRegister Reg = |
+ InstX86Base<Machine>::Traits::getEncodedGPR(this->getDest()->getRegNum()); |
+ Constant *GlobalOffsetTable = |
+ Func->getContext()->getConstantExternSym("_GLOBAL_OFFSET_TABLE_"); |
+ AssemblerFixup *Fixup = Asm->createFixup( |
+ InstX86Base<Machine>::Traits::FixupKindGotPC, GlobalOffsetTable); |
+ intptr_t OrigPos = Asm->getBufferSize(); |
+ constexpr int32_t TempDisp = 0; |
+ constexpr int32_t ImmediateWidth = 4; |
+ // Emit the add instruction once, in a preliminary fashion, to find its total |
+ // size. |
+ Asm->add(IceType_i32, Reg, Immediate(TempDisp, Fixup)); |
John
2015/12/22 15:44:38
I believe the assembler will always emit an addl i
Jim Stichnoth
2015/12/28 07:54:07
Right, but the specific issue here is that adding
|
+ const int32_t Disp = Asm->getBufferSize() - OrigPos - ImmediateWidth; |
+ // Now roll back and emit the add instruction again, this time with the |
+ // correct displacement. |
+ Asm->setBufferSize(OrigPos); |
+ Asm->add(IceType_i32, Reg, Immediate(Disp, Fixup)); |
+} |
+ |
+template <class Machine> |
+void InstX86GetIP<Machine>::dump(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ this->getDest()->dump(Func); |
+ Str << " = call getIP"; |
+} |
+ |
+template <class Machine> |
void InstX86Label<Machine>::emit(const Cfg *Func) const { |
if (!BuildDefs::dump()) |
return; |
@@ -702,7 +758,7 @@ void emitIASRegOpTyGPR( |
(Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue())); |
} else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
AssemblerFixup *Fixup = |
- Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc); |
+ Asm->createFixup(TargetX86Base<Machine>::getRelFixup(), Reloc); |
(Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup)); |
} else if (const auto *Split = llvm::dyn_cast< |
typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) { |
@@ -731,7 +787,7 @@ void emitIASAddrOpTyGPR( |
(Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue())); |
} else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
AssemblerFixup *Fixup = |
- Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc); |
+ Asm->createFixup(TargetX86Base<Machine>::getRelFixup(), Reloc); |
(Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup)); |
} else { |
llvm_unreachable("Unexpected operand type"); |