Clean up irgen.h a bit
[hiphop-php.git] / hphp / runtime / vm / jit / extra-data.cpp
blobfc2f06011210d97a913ea52d64daafe2bb7e6f85
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2016 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/extra-data.h"
19 #include "hphp/runtime/vm/jit/ssa-tmp.h"
20 #include "hphp/runtime/vm/jit/abi-x64.h"
21 #include "hphp/util/text-util.h"
23 namespace HPHP { namespace jit {
25 std::string NewStructData::show() const {
26 std::ostringstream os;
27 os << offset.offset << ',';
28 auto delim = "";
29 for (uint32_t i = 0; i < numKeys; i++) {
30 os << delim << "\"" <<
31 escapeStringForCPP(keys[i]->data(), keys[i]->size()) <<
32 "\"";
33 delim = ",";
35 return os.str();
38 //////////////////////////////////////////////////////////////////////
40 namespace {
42 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_hash, hash);
43 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_equals, equals);
44 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_clone, clone);
45 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_show, show);
48 * dispatchExtra translates from runtime values for the Opcode enum
49 * into compile time types. The goal is to call a `targetFunction'
50 * that is overloaded on the extra data type structs.
52 * The purpose of the MAKE_DISPATCHER layer is to weed out Opcode
53 * values that have no associated extra data.
55 * Basically this is doing dynamic dispatch without a vtable in
56 * IRExtraData, instead using the Opcode tag from the associated
57 * instruction to discriminate the runtime type.
59 * Note: functions made with this currently only make sense to call if
60 * it's already known that the opcode has extra data. If you call it
61 * for one that doesn't, you'll get an abort. Generally hasExtra()
62 * should be checked first.
65 #define MAKE_DISPATCHER(name, rettype, targetFunction) \
66 template<bool HasExtra, Opcode opc> struct name { \
67 template<class... Args> \
68 static rettype go(IRExtraData* vp, Args&&...) { not_reached(); } \
69 }; \
70 template<Opcode opc> struct name<true,opc> { \
71 template<class... Args> \
72 static rettype go(IRExtraData* vp, Args&&... args) { \
73 return targetFunction( \
74 static_cast<typename IRExtraDataType<opc>::type*>(vp), \
75 std::forward<Args>(args)... \
76 ); \
77 } \
80 template<
81 class RetType,
82 template<bool, Opcode> class Dispatcher,
83 class... Args
85 RetType dispatchExtra(Opcode opc, IRExtraData* data, Args&&... args) {
86 #define O(opcode, dstinfo, srcinfo, flags) \
87 case opcode: \
88 return Dispatcher< \
89 OpHasExtraData<opcode>::value, \
90 opcode \
91 >::go(data, std::forward<Args>(args)...);
92 switch (opc) { IR_OPCODES default: not_reached(); }
93 #undef O
94 not_reached();
97 template<class T>
98 typename std::enable_if<
99 has_hash<T,size_t () const>::value,
100 size_t
101 >::type hashExtraImpl(T* t) { return t->hash(); }
102 size_t hashExtraImpl(IRExtraData*) {
103 // This probably means we tried to hash an IRInstruction with extra data that
104 // had no hash function.
105 always_assert(!"attempted to hash extra data that didn't "
106 "provide a hash function");
109 template<class T>
110 typename std::enable_if<
111 has_equals<T,bool (T const&) const>::value ||
112 has_equals<T,bool (T) const>::value,
113 bool
114 >::type equalsExtraImpl(T* t, IRExtraData* o) {
115 return t->equals(*static_cast<T*>(o));
117 bool equalsExtraImpl(IRExtraData*, IRExtraData*) {
118 // This probably means we tried to compare IRInstructions with extra data that
119 // had no equals function.
120 always_assert(!"attempted to compare extra data that didn't "
121 "provide an equals function");
124 // Clone using a data-specific clone function.
125 template<class T>
126 typename std::enable_if<
127 has_clone<T,T* (Arena&) const>::value,
129 >::type cloneExtraImpl(T* t, Arena& arena) {
130 return t->clone(arena);
133 // Use the copy constructor if no clone() function was supplied.
134 template<class T>
135 typename std::enable_if<
136 !has_clone<T,T* (Arena&) const>::value,
138 >::type cloneExtraImpl(T* t, Arena& arena) {
139 return new (arena) T(*t);
142 template<class T>
143 std::string showExtraImpl(const T* extra) { return extra->show(); }
145 MAKE_DISPATCHER(HashDispatcher, size_t, hashExtraImpl);
146 MAKE_DISPATCHER(EqualsDispatcher, bool, equalsExtraImpl);
147 MAKE_DISPATCHER(CloneDispatcher, IRExtraData*, cloneExtraImpl);
148 MAKE_DISPATCHER(ShowDispatcher, std::string, showExtraImpl);
152 //////////////////////////////////////////////////////////////////////
154 size_t hashExtra(Opcode opc, const IRExtraData* data) {
155 return dispatchExtra<size_t,HashDispatcher>(
156 opc, const_cast<IRExtraData*>(data));
159 bool equalsExtra(
160 Opcode opc,
161 const IRExtraData* data,
162 const IRExtraData* other
164 return dispatchExtra<bool,EqualsDispatcher>(
165 opc, const_cast<IRExtraData*>(data), const_cast<IRExtraData*>(other));
168 IRExtraData* cloneExtra(Opcode opc, IRExtraData* data, Arena& a) {
169 return dispatchExtra<IRExtraData*,CloneDispatcher>(opc, data, a);
172 std::string showExtra(Opcode opc, const IRExtraData* data) {
173 return dispatchExtra<std::string,ShowDispatcher>(
174 opc, const_cast<IRExtraData*>(data)
178 //////////////////////////////////////////////////////////////////////