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