OLD | NEW |
---|---|
1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// | 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
11 /// \brief Implements the InstX86Base class and its descendants. | 11 /// \brief Implements the InstX86Base class and its descendants. |
12 /// | 12 /// |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H | 15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H |
16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H | 16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H |
17 | 17 |
18 #include "IceInstX86Base.h" | 18 #include "IceInstX86Base.h" |
19 | 19 |
20 #include "IceAssemblerX86Base.h" | 20 #include "IceAssemblerX86Base.h" |
21 #include "IceCfg.h" | 21 #include "IceCfg.h" |
22 #include "IceCfgNode.h" | 22 #include "IceCfgNode.h" |
23 #include "IceDefs.h" | 23 #include "IceDefs.h" |
24 #include "IceInst.h" | 24 #include "IceInst.h" |
25 #include "IceOperand.h" | 25 #include "IceOperand.h" |
26 #include "IceTargetLowering.h" | 26 #include "IceTargetLowering.h" |
27 #include "IceTargetLoweringX86Base.h" | |
27 | 28 |
28 namespace Ice { | 29 namespace Ice { |
29 | 30 |
30 namespace X86Internal { | 31 namespace X86Internal { |
31 | 32 |
32 template <class Machine> | 33 template <class Machine> |
33 const char *InstX86Base<Machine>::getWidthString(Type Ty) { | 34 const char *InstX86Base<Machine>::getWidthString(Type Ty) { |
34 return Traits::TypeAttributes[Ty].WidthString; | 35 return Traits::TypeAttributes[Ty].WidthString; |
35 } | 36 } |
36 | 37 |
(...skipping 13 matching lines...) Expand all Loading... | |
50 InstArithmetic::OpKind Op, | 51 InstArithmetic::OpKind Op, |
51 Variable *Beacon) | 52 Variable *Beacon) |
52 : InstX86Base<Machine>(Func, InstX86Base<Machine>::FakeRMW, 3, nullptr), | 53 : InstX86Base<Machine>(Func, InstX86Base<Machine>::FakeRMW, 3, nullptr), |
53 Op(Op) { | 54 Op(Op) { |
54 this->addSource(Data); | 55 this->addSource(Data); |
55 this->addSource(Addr); | 56 this->addSource(Addr); |
56 this->addSource(Beacon); | 57 this->addSource(Beacon); |
57 } | 58 } |
58 | 59 |
59 template <class Machine> | 60 template <class Machine> |
61 InstX86GetIP<Machine>::InstX86GetIP(Cfg *Func, Variable *Dest) | |
62 : InstX86Base<Machine>(Func, InstX86Base<Machine>::GetIP, 0, Dest) {} | |
63 | |
64 template <class Machine> | |
60 InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, | 65 InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, |
61 Operand *Source2) | 66 Operand *Source2) |
62 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) { | 67 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) { |
63 this->addSource(Source1); | 68 this->addSource(Source1); |
64 this->addSource(Source2); | 69 this->addSource(Source2); |
65 } | 70 } |
66 | 71 |
67 template <class Machine> | 72 template <class Machine> |
68 InstX86Shld<Machine>::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, | 73 InstX86Shld<Machine>::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, |
69 Operand *Source2) | 74 Operand *Source2) |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 Type Ty = getData()->getType(); | 392 Type Ty = getData()->getType(); |
388 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *"; | 393 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *"; |
389 getAddr()->dump(Func); | 394 getAddr()->dump(Func); |
390 Str << ", "; | 395 Str << ", "; |
391 getData()->dump(Func); | 396 getData()->dump(Func); |
392 Str << ", beacon="; | 397 Str << ", beacon="; |
393 getBeacon()->dump(Func); | 398 getBeacon()->dump(Func); |
394 } | 399 } |
395 | 400 |
396 template <class Machine> | 401 template <class Machine> |
402 void InstX86GetIP<Machine>::emit(const Cfg *Func) const { | |
403 if (!BuildDefs::dump()) | |
404 return; | |
405 Ostream &Str = Func->getContext()->getStrEmit(); | |
406 assert(this->getDest()->hasReg()); | |
407 Str << "\t" | |
408 "addl\t$_GLOBAL_OFFSET_TABLE_, "; | |
409 this->getDest()->emit(Func); | |
410 } | |
411 | |
412 template <class Machine> | |
413 void InstX86GetIP<Machine>::emitIAS(const Cfg *Func) const { | |
414 if (Func->getContext()->getFlags().getOutFileType() == FT_Iasm) { | |
415 // TODO(stichnot): Find a workaround for llvm-mc's inability to handle | |
416 // something like ".long _GLOBAL_OFFSET_TABLE_ + ." . One possibility is to | |
417 // just use hybrid iasm output for this add instruction. | |
418 llvm::report_fatal_error( | |
419 "Iasm support for _GLOBAL_OFFSET_TABLE_ not implemented"); | |
420 } | |
421 typename InstX86Base<Machine>::Traits::Assembler *Asm = | |
422 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); | |
423 assert(this->getDest()->hasReg()); | |
424 typename InstX86Base<Machine>::Traits::GPRRegister Reg = | |
425 InstX86Base<Machine>::Traits::getEncodedGPR(this->getDest()->getRegNum()); | |
426 Constant *GlobalOffsetTable = | |
427 Func->getContext()->getConstantExternSym("_GLOBAL_OFFSET_TABLE_"); | |
428 AssemblerFixup *Fixup = Asm->createFixup( | |
429 InstX86Base<Machine>::Traits::FixupKindGotPC, GlobalOffsetTable); | |
430 intptr_t OrigPos = Asm->getBufferSize(); | |
431 constexpr int32_t TempDisp = 0; | |
432 constexpr int32_t ImmediateWidth = 4; | |
433 // Emit the add instruction once, in a preliminary fashion, to find its total | |
434 // size. | |
435 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
| |
436 const int32_t Disp = Asm->getBufferSize() - OrigPos - ImmediateWidth; | |
437 // Now roll back and emit the add instruction again, this time with the | |
438 // correct displacement. | |
439 Asm->setBufferSize(OrigPos); | |
440 Asm->add(IceType_i32, Reg, Immediate(Disp, Fixup)); | |
441 } | |
442 | |
443 template <class Machine> | |
444 void InstX86GetIP<Machine>::dump(const Cfg *Func) const { | |
445 if (!BuildDefs::dump()) | |
446 return; | |
447 Ostream &Str = Func->getContext()->getStrDump(); | |
448 this->getDest()->dump(Func); | |
449 Str << " = call getIP"; | |
450 } | |
451 | |
452 template <class Machine> | |
397 void InstX86Label<Machine>::emit(const Cfg *Func) const { | 453 void InstX86Label<Machine>::emit(const Cfg *Func) const { |
398 if (!BuildDefs::dump()) | 454 if (!BuildDefs::dump()) |
399 return; | 455 return; |
400 Ostream &Str = Func->getContext()->getStrEmit(); | 456 Ostream &Str = Func->getContext()->getStrEmit(); |
401 Str << getName(Func) << ":"; | 457 Str << getName(Func) << ":"; |
402 } | 458 } |
403 | 459 |
404 template <class Machine> | 460 template <class Machine> |
405 void InstX86Label<Machine>::emitIAS(const Cfg *Func) const { | 461 void InstX86Label<Machine>::emitIAS(const Cfg *Func) const { |
406 typename InstX86Base<Machine>::Traits::Assembler *Asm = | 462 typename InstX86Base<Machine>::Traits::Assembler *Asm = |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); | 751 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); |
696 } | 752 } |
697 } else if (const auto *Mem = llvm::dyn_cast< | 753 } else if (const auto *Mem = llvm::dyn_cast< |
698 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { | 754 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { |
699 Mem->emitSegmentOverride(Asm); | 755 Mem->emitSegmentOverride(Asm); |
700 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); | 756 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); |
701 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 757 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
702 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue())); | 758 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue())); |
703 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | 759 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
704 AssemblerFixup *Fixup = | 760 AssemblerFixup *Fixup = |
705 Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc); | 761 Asm->createFixup(TargetX86Base<Machine>::getRelFixup(), Reloc); |
706 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup)); | 762 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup)); |
707 } else if (const auto *Split = llvm::dyn_cast< | 763 } else if (const auto *Split = llvm::dyn_cast< |
708 typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) { | 764 typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) { |
709 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); | 765 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); |
710 } else { | 766 } else { |
711 llvm_unreachable("Unexpected operand type"); | 767 llvm_unreachable("Unexpected operand type"); |
712 } | 768 } |
713 } | 769 } |
714 | 770 |
715 template <class Machine> | 771 template <class Machine> |
716 void emitIASAddrOpTyGPR( | 772 void emitIASAddrOpTyGPR( |
717 const Cfg *Func, Type Ty, | 773 const Cfg *Func, Type Ty, |
718 const typename InstX86Base<Machine>::Traits::Address &Addr, | 774 const typename InstX86Base<Machine>::Traits::Address &Addr, |
719 const Operand *Src, | 775 const Operand *Src, |
720 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp | 776 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp |
721 &Emitter) { | 777 &Emitter) { |
722 typename InstX86Base<Machine>::Traits::Assembler *Asm = | 778 typename InstX86Base<Machine>::Traits::Assembler *Asm = |
723 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); | 779 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); |
724 // Src can only be Reg or Immediate. | 780 // Src can only be Reg or Immediate. |
725 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { | 781 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
726 assert(SrcVar->hasReg()); | 782 assert(SrcVar->hasReg()); |
727 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = | 783 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = |
728 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()); | 784 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()); |
729 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); | 785 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); |
730 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 786 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
731 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue())); | 787 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue())); |
732 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | 788 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
733 AssemblerFixup *Fixup = | 789 AssemblerFixup *Fixup = |
734 Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc); | 790 Asm->createFixup(TargetX86Base<Machine>::getRelFixup(), Reloc); |
735 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup)); | 791 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup)); |
736 } else { | 792 } else { |
737 llvm_unreachable("Unexpected operand type"); | 793 llvm_unreachable("Unexpected operand type"); |
738 } | 794 } |
739 } | 795 } |
740 | 796 |
741 template <class Machine> | 797 template <class Machine> |
742 void emitIASAsAddrOpTyGPR( | 798 void emitIASAsAddrOpTyGPR( |
743 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, | 799 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, |
744 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp | 800 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp |
(...skipping 2276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3021 return; | 3077 return; |
3022 Ostream &Str = Func->getContext()->getStrDump(); | 3078 Ostream &Str = Func->getContext()->getStrDump(); |
3023 Str << "IACA_END"; | 3079 Str << "IACA_END"; |
3024 } | 3080 } |
3025 | 3081 |
3026 } // end of namespace X86Internal | 3082 } // end of namespace X86Internal |
3027 | 3083 |
3028 } // end of namespace Ice | 3084 } // end of namespace Ice |
3029 | 3085 |
3030 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H | 3086 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H |
OLD | NEW |