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 |