| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX86Base.h - x86 lowering ----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringX86Base.h - x86 lowering ----*- 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 /// This file declares the TargetLoweringX86 template class, which | 11 /// This file declares the TargetLoweringX86 template class, which |
| 12 /// implements the TargetLowering base interface for the x86 | 12 /// implements the TargetLowering base interface for the x86 |
| 13 /// architecture. | 13 /// architecture. |
| 14 /// | 14 /// |
| 15 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 16 | 16 |
| 17 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H | 17 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| 18 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H | 18 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| 19 | 19 |
| 20 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 21 #include "IceInst.h" | 21 #include "IceInst.h" |
| 22 #include "IceSwitchLowering.h" | 22 #include "IceSwitchLowering.h" |
| 23 #include "IceTargetLowering.h" | 23 #include "IceTargetLowering.h" |
| 24 | 24 |
| 25 #include <type_traits> | 25 #include <type_traits> |
| 26 #include <unordered_map> | 26 #include <unordered_map> |
| 27 #include <utility> |
| 27 | 28 |
| 28 namespace Ice { | 29 namespace Ice { |
| 29 namespace X86Internal { | 30 namespace X86Internal { |
| 30 | 31 |
| 31 template <class MachineTraits> class BoolFolding; | 32 template <class MachineTraits> class BoolFolding; |
| 32 | 33 |
| 33 template <class Machine> struct MachineTraits {}; | 34 template <class Machine> struct MachineTraits {}; |
| 34 | 35 |
| 35 template <class Machine> class TargetX86Base : public Machine { | 36 /// TargetX86Base is a template for all X86 Targets, and it relies on the CRT |
| 36 static_assert(std::is_base_of<::Ice::TargetLowering, Machine>::value, | 37 /// pattern for generating code, delegating to actual backends target-specific |
| 37 "Machine template parameter must be a TargetLowering."); | 38 /// lowerings (e.g., call, ret, and intrinsics.) Backends are expected to |
| 38 | 39 /// implement the following methods (which should be accessible from |
| 40 /// TargetX86Base): |
| 41 /// |
| 42 /// Operand *createNaClReadTPSrcOperand() |
| 43 /// |
| 44 /// Note: Ideally, we should be able to |
| 45 /// |
| 46 /// static_assert(std::is_base_of<TargetX86Base<Machine>, Machine>::value); |
| 47 /// |
| 48 /// but that does not work: the compiler does not know that Machine inherits |
| 49 /// from TargetX86Base at this point in translation. |
| 50 template <class Machine> class TargetX86Base : public TargetLowering { |
| 39 TargetX86Base() = delete; | 51 TargetX86Base() = delete; |
| 40 TargetX86Base(const TargetX86Base &) = delete; | 52 TargetX86Base(const TargetX86Base &) = delete; |
| 41 TargetX86Base &operator=(const TargetX86Base &) = delete; | 53 TargetX86Base &operator=(const TargetX86Base &) = delete; |
| 42 | 54 |
| 43 protected: | |
| 44 using Machine::H_bitcast_16xi1_i16; | |
| 45 using Machine::H_bitcast_8xi1_i8; | |
| 46 using Machine::H_bitcast_i16_16xi1; | |
| 47 using Machine::H_bitcast_i8_8xi1; | |
| 48 using Machine::H_call_ctpop_i32; | |
| 49 using Machine::H_call_ctpop_i64; | |
| 50 using Machine::H_call_longjmp; | |
| 51 using Machine::H_call_memcpy; | |
| 52 using Machine::H_call_memmove; | |
| 53 using Machine::H_call_memset; | |
| 54 using Machine::H_call_read_tp; | |
| 55 using Machine::H_call_setjmp; | |
| 56 using Machine::H_fptosi_f32_i64; | |
| 57 using Machine::H_fptosi_f64_i64; | |
| 58 using Machine::H_fptoui_4xi32_f32; | |
| 59 using Machine::H_fptoui_f32_i32; | |
| 60 using Machine::H_fptoui_f32_i64; | |
| 61 using Machine::H_fptoui_f64_i32; | |
| 62 using Machine::H_fptoui_f64_i64; | |
| 63 using Machine::H_frem_f32; | |
| 64 using Machine::H_frem_f64; | |
| 65 using Machine::H_sdiv_i64; | |
| 66 using Machine::H_sitofp_i64_f32; | |
| 67 using Machine::H_sitofp_i64_f64; | |
| 68 using Machine::H_srem_i64; | |
| 69 using Machine::H_udiv_i64; | |
| 70 using Machine::H_uitofp_4xi32_4xf32; | |
| 71 using Machine::H_uitofp_i32_f32; | |
| 72 using Machine::H_uitofp_i32_f64; | |
| 73 using Machine::H_uitofp_i64_f32; | |
| 74 using Machine::H_uitofp_i64_f64; | |
| 75 using Machine::H_urem_i64; | |
| 76 | |
| 77 using Machine::alignStackSpillAreas; | |
| 78 using Machine::assignVarStackSlots; | |
| 79 using Machine::inferTwoAddress; | |
| 80 using Machine::makeHelperCall; | |
| 81 using Machine::getVarStackSlotParams; | |
| 82 | |
| 83 public: | 55 public: |
| 84 using Traits = MachineTraits<Machine>; | 56 using Traits = MachineTraits<Machine>; |
| 85 using BoolFolding = ::Ice::X86Internal::BoolFolding<Traits>; | 57 using BoolFolding = ::Ice::X86Internal::BoolFolding<Traits>; |
| 86 | 58 |
| 87 using Machine::RegSet_All; | 59 ~TargetX86Base() override = default; |
| 88 using Machine::RegSet_CalleeSave; | |
| 89 using Machine::RegSet_CallerSave; | |
| 90 using Machine::RegSet_FramePointer; | |
| 91 using Machine::RegSet_None; | |
| 92 using Machine::RegSet_StackPointer; | |
| 93 using Machine::Context; | |
| 94 using Machine::Ctx; | |
| 95 using Machine::Func; | |
| 96 using RegSetMask = typename Machine::RegSetMask; | |
| 97 | |
| 98 using Machine::_bundle_lock; | |
| 99 using Machine::_bundle_unlock; | |
| 100 using Machine::_set_dest_nonkillable; | |
| 101 using Machine::getContext; | |
| 102 using Machine::getStackAdjustment; | |
| 103 using Machine::regAlloc; | |
| 104 using Machine::resetStackAdjustment; | |
| 105 | 60 |
| 106 static TargetX86Base *create(Cfg *Func) { return new TargetX86Base(Func); } | 61 static TargetX86Base *create(Cfg *Func) { return new TargetX86Base(Func); } |
| 107 | 62 |
| 108 void translateOm1() override; | 63 void translateOm1() override; |
| 109 void translateO2() override; | 64 void translateO2() override; |
| 110 void doLoadOpt(); | 65 void doLoadOpt(); |
| 111 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; | 66 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; |
| 112 | 67 |
| 113 SizeT getNumRegisters() const override { | 68 SizeT getNumRegisters() const override { |
| 114 return Traits::RegisterSet::Reg_NUM; | 69 return Traits::RegisterSet::Reg_NUM; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 /// Ensure that a 64-bit Variable has been split into 2 32-bit | 104 /// Ensure that a 64-bit Variable has been split into 2 32-bit |
| 150 /// Variables, creating them if necessary. This is needed for all | 105 /// Variables, creating them if necessary. This is needed for all |
| 151 /// I64 operations, and it is needed for pushing F64 arguments for | 106 /// I64 operations, and it is needed for pushing F64 arguments for |
| 152 /// function calls using the 32-bit push instruction (though the | 107 /// function calls using the 32-bit push instruction (though the |
| 153 /// latter could be done by directly writing to the stack). | 108 /// latter could be done by directly writing to the stack). |
| 154 void split64(Variable *Var); | 109 void split64(Variable *Var); |
| 155 Operand *loOperand(Operand *Operand); | 110 Operand *loOperand(Operand *Operand); |
| 156 Operand *hiOperand(Operand *Operand); | 111 Operand *hiOperand(Operand *Operand); |
| 157 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 112 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 158 size_t BasicFrameOffset, size_t &InArgsSizeBytes); | 113 size_t BasicFrameOffset, size_t &InArgsSizeBytes); |
| 159 typename Traits::Address | 114 typename Traits::Address stackVarToAsmOperand(const Variable *Var) const; |
| 160 stackVarToAsmOperand(const Variable *Var) const final; | |
| 161 | 115 |
| 162 typename Traits::InstructionSet getInstructionSet() const final { | 116 typename Traits::InstructionSet getInstructionSet() const { |
| 163 return InstructionSet; | 117 return InstructionSet; |
| 164 } | 118 } |
| 165 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); | 119 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 166 | 120 |
| 167 protected: | 121 protected: |
| 168 explicit TargetX86Base(Cfg *Func); | 122 explicit TargetX86Base(Cfg *Func); |
| 169 | 123 |
| 170 void postLower() override; | 124 void postLower() override; |
| 171 | 125 |
| 172 void lowerAlloca(const InstAlloca *Inst) override; | 126 void lowerAlloca(const InstAlloca *Inst) override; |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 | 575 |
| 622 /// Randomize a given immediate operand | 576 /// Randomize a given immediate operand |
| 623 Operand *randomizeOrPoolImmediate(Constant *Immediate, | 577 Operand *randomizeOrPoolImmediate(Constant *Immediate, |
| 624 int32_t RegNum = Variable::NoRegister); | 578 int32_t RegNum = Variable::NoRegister); |
| 625 typename Traits::X86OperandMem * | 579 typename Traits::X86OperandMem * |
| 626 randomizeOrPoolImmediate(typename Traits::X86OperandMem *MemOperand, | 580 randomizeOrPoolImmediate(typename Traits::X86OperandMem *MemOperand, |
| 627 int32_t RegNum = Variable::NoRegister); | 581 int32_t RegNum = Variable::NoRegister); |
| 628 bool RandomizationPoolingPaused = false; | 582 bool RandomizationPoolingPaused = false; |
| 629 | 583 |
| 630 private: | 584 private: |
| 631 ~TargetX86Base() override {} | 585 /// dispatchToConcrete is the template voodoo that allows TargetX86Base to |
| 586 /// invoke methods in Machine (which inherits from TargetX86Base) without |
| 587 /// having to rely on virtual method calls. There are two overloads, one for |
| 588 /// non-void types, and one for void types. We need this becase, for non-void |
| 589 /// types, we need to return the method result, where as for void, we don't. |
| 590 /// While it is true that the code compiles without the void "version", there |
| 591 /// used to be a time when compilers would reject such code. |
| 592 /// |
| 593 /// This machinery is far from perfect. Note that, in particular, the |
| 594 /// arguments provided to dispatchToConcrete() need to match the arguments for |
| 595 /// Method **exactly** (i.e., no argument promotion is performed.) |
| 596 template <typename Ret, typename... Args> |
| 597 typename std::enable_if<!std::is_void<Ret>::value, Ret>::type |
| 598 dispatchToConcrete(Ret (Machine::*Method)(Args...), Args &&... args) { |
| 599 return (static_cast<Machine *>(this)->*Method)(std::forward<Args>(args)...); |
| 600 } |
| 601 |
| 602 template <typename... Args> |
| 603 void dispatchToConcrete(void (Machine::*Method)(Args...), Args &&... args) { |
| 604 (static_cast<Machine *>(this)->*Method)(std::forward<Args>(args)...); |
| 605 } |
| 606 |
| 632 BoolFolding FoldingInfo; | 607 BoolFolding FoldingInfo; |
| 633 }; | 608 }; |
| 634 } // end of namespace X86Internal | 609 } // end of namespace X86Internal |
| 635 } // end of namespace Ice | 610 } // end of namespace Ice |
| 636 | 611 |
| 637 #include "IceTargetLoweringX86BaseImpl.h" | 612 #include "IceTargetLoweringX86BaseImpl.h" |
| 638 | 613 |
| 639 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H | 614 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| OLD | NEW |