Chromium Code Reviews| Index: src/IceTargetLoweringX86Base.h |
| diff --git a/src/IceTargetLoweringX86Base.h b/src/IceTargetLoweringX86Base.h |
| index 32d7d6bfbe34e1c33a3ef2aa1f3ab1018ff127e2..6bb5e8562cc8fd8cc001f41b230abc83b303a1e0 100644 |
| --- a/src/IceTargetLoweringX86Base.h |
| +++ b/src/IceTargetLoweringX86Base.h |
| @@ -23,6 +23,7 @@ |
| #include <type_traits> |
| #include <unordered_map> |
| +#include <utility> |
| namespace Ice { |
| namespace X86Internal { |
| @@ -31,75 +32,30 @@ template <class MachineTraits> class BoolFolding; |
| template <class Machine> struct MachineTraits {}; |
| -template <class Machine> class TargetX86Base : public Machine { |
| - static_assert(std::is_base_of<::Ice::TargetLowering, Machine>::value, |
| - "Machine template parameter must be a TargetLowering."); |
| - |
| +/// 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.
|
| +/// pattern for generating code, delegating to actual backends target-specific |
| +/// lowerings (e.g., call, ret, and intrinsics.) Backends are expected to |
| +/// implement the following methods (which should be accessible from |
| +/// TargetX86Base): |
| +/// |
| +/// 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
|
| +/// |
| +/// Note: Ideally, we should be able to |
| +/// |
| +/// static_assert(std::is_base_of<TargetX86Base<Machine>, Machine>::value); |
| +/// |
| +/// but that does not work: the compiler does not know that Machine inherits |
| +/// from TargetX86Base at this point in translation. |
| +template <class Machine> class TargetX86Base : public TargetLowering { |
| TargetX86Base() = delete; |
| TargetX86Base(const TargetX86Base &) = delete; |
| TargetX86Base &operator=(const TargetX86Base &) = delete; |
| -protected: |
| - using Machine::H_bitcast_16xi1_i16; |
| - using Machine::H_bitcast_8xi1_i8; |
| - using Machine::H_bitcast_i16_16xi1; |
| - using Machine::H_bitcast_i8_8xi1; |
| - using Machine::H_call_ctpop_i32; |
| - using Machine::H_call_ctpop_i64; |
| - using Machine::H_call_longjmp; |
| - using Machine::H_call_memcpy; |
| - using Machine::H_call_memmove; |
| - using Machine::H_call_memset; |
| - using Machine::H_call_read_tp; |
| - using Machine::H_call_setjmp; |
| - using Machine::H_fptosi_f32_i64; |
| - using Machine::H_fptosi_f64_i64; |
| - using Machine::H_fptoui_4xi32_f32; |
| - using Machine::H_fptoui_f32_i32; |
| - using Machine::H_fptoui_f32_i64; |
| - using Machine::H_fptoui_f64_i32; |
| - using Machine::H_fptoui_f64_i64; |
| - using Machine::H_frem_f32; |
| - using Machine::H_frem_f64; |
| - using Machine::H_sdiv_i64; |
| - using Machine::H_sitofp_i64_f32; |
| - using Machine::H_sitofp_i64_f64; |
| - using Machine::H_srem_i64; |
| - using Machine::H_udiv_i64; |
| - using Machine::H_uitofp_4xi32_4xf32; |
| - using Machine::H_uitofp_i32_f32; |
| - using Machine::H_uitofp_i32_f64; |
| - using Machine::H_uitofp_i64_f32; |
| - using Machine::H_uitofp_i64_f64; |
| - using Machine::H_urem_i64; |
| - |
| - using Machine::alignStackSpillAreas; |
| - using Machine::assignVarStackSlots; |
| - using Machine::inferTwoAddress; |
| - using Machine::makeHelperCall; |
| - using Machine::getVarStackSlotParams; |
| - |
| public: |
| using Traits = MachineTraits<Machine>; |
| using BoolFolding = ::Ice::X86Internal::BoolFolding<Traits>; |
| - using Machine::RegSet_All; |
| - using Machine::RegSet_CalleeSave; |
| - using Machine::RegSet_CallerSave; |
| - using Machine::RegSet_FramePointer; |
| - using Machine::RegSet_None; |
| - using Machine::RegSet_StackPointer; |
| - using Machine::Context; |
| - using Machine::Ctx; |
| - using Machine::Func; |
| - using RegSetMask = typename Machine::RegSetMask; |
| - |
| - using Machine::_bundle_lock; |
| - using Machine::_bundle_unlock; |
| - using Machine::getContext; |
| - using Machine::getStackAdjustment; |
| - using Machine::regAlloc; |
| - using Machine::resetStackAdjustment; |
| + ~TargetX86Base() override = default; |
| static TargetX86Base *create(Cfg *Func) { return new TargetX86Base(Func); } |
| @@ -152,10 +108,9 @@ public: |
| Operand *hiOperand(Operand *Operand); |
| void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| size_t BasicFrameOffset, size_t &InArgsSizeBytes); |
| - typename Traits::Address |
| - stackVarToAsmOperand(const Variable *Var) const final; |
| + typename Traits::Address stackVarToAsmOperand(const Variable *Var) const; |
| - typename Traits::InstructionSet getInstructionSet() const final { |
| + typename Traits::InstructionSet getInstructionSet() const { |
| return InstructionSet; |
| } |
| @@ -613,7 +568,28 @@ protected: |
| bool RandomizationPoolingPaused = false; |
| private: |
| - ~TargetX86Base() override {} |
| + /// dispatchToConcrete is the template voodoo that allows TargetX86Base to |
| + /// invoke methods in Machine (which inherits from TargetX86Base) without |
| + /// having to rely on virtual method calls. There are two overloads, one for |
| + /// non-void types, and one for void types. We need this becase, for non-void |
| + /// types, we need to return the method result, where as for void, we don't. |
| + /// While it is true that the code compiles without the void "version", there |
| + /// used to be a time when compilers would reject such code. |
| + /// |
| + /// This machinery is far from perfect. Note that, in particular, the |
| + /// arguments provided to dispatchToConcrete() need to match the arguments for |
| + /// Method **exactly** (i.e., no argument promotion is performed.) |
| + template <typename Ret, typename... Args> |
| + typename std::enable_if<!std::is_void<Ret>::value, Ret>::type |
| + dispatchToConcrete(Ret (Machine::*Method)(Args...), Args &&... args) { |
| + return (static_cast<Machine *>(this)->*Method)(std::forward<Args>(args)...); |
| + } |
| + |
| + template <typename... Args> |
| + void dispatchToConcrete(void (Machine::*Method)(Args...), Args &&... args) { |
| + (static_cast<Machine *>(this)->*Method)(std::forward<Args>(args)...); |
| + } |
| + |
| BoolFolding FoldingInfo; |
| }; |
| } // end of namespace X86Internal |