Fix spilling bug
[hiphop-php.git] / hphp / runtime / vm / jit / vectortranslator-internal.h
blob9b70297cad4653f8cde84d3ca8d2b36f9440543b
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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 #ifndef incl_HPHP_RUNTIME_VM_TRANSLATOR_HOPT_VECTOR_TRANSLATOR_HELPERS_H_
18 #define incl_HPHP_RUNTIME_VM_TRANSLATOR_HOPT_VECTOR_TRANSLATOR_HELPERS_H_
20 #include "hphp/util/base.h"
21 #include "hphp/runtime/base/types.h"
22 #include "hphp/runtime/base/stats.h"
23 #include "hphp/runtime/vm/jit/translator.h"
24 #include "hphp/runtime/vm/member_operations.h"
26 namespace HPHP { namespace JIT {
28 #define CTX() cns(contextClass())
30 static const MInstrAttr Warn = MIA_warn;
31 static const MInstrAttr Unset = MIA_unset;
32 static const MInstrAttr Reffy = MIA_reffy;
33 static const MInstrAttr Define = MIA_define;
34 static const MInstrAttr None = MIA_none;
35 static const MInstrAttr WarnDefine = MInstrAttr(Warn | Define);
36 static const MInstrAttr DefineReffy = MInstrAttr(Define | Reffy);
37 static const MInstrAttr WarnDefineReffy = MInstrAttr(Warn | Define | Reffy);
38 #define WDU(attrs) (attrs & Warn) != 0, (attrs & Define) != 0, \
39 (attrs & Unset) != 0
40 #define WDRU(attrs) (attrs & Warn) != 0, (attrs & Define) != 0, \
41 (attrs & Reffy) != 0, (attrs & Unset) != 0
43 /* The following bunch of macros and functions are used to build up tables of
44 * helper function pointers and determine which helper should be called based
45 * on a variable number of bool and enum arguments. */
47 template<typename T> constexpr unsigned bitWidth() {
48 static_assert(IncDec_invalid == 4,
49 "IncDecOp enum must fit in 2 bits");
50 static_assert(SetOp_invalid == 11,
51 "SetOpOp enum must fit in 4 bits");
52 return std::is_same<T, bool>::value ? 1
53 : std::is_same<T, KeyType>::value ? 2
54 : std::is_same<T, MInstrAttr>::value ? 4
55 : std::is_same<T, IncDecOp>::value ? 2
56 : std::is_same<T, SetOpOp>::value ? 4
57 : sizeof(T) * CHAR_BIT;
60 // Determines the width in bits of all of its arguments
61 template<typename... T> unsigned multiBitWidth();
62 template<typename T, typename... Args>
63 inline unsigned multiBitWidth(T t, Args... args) {
64 return bitWidth<T>() + multiBitWidth<Args...>(args...);
66 template<>
67 inline unsigned multiBitWidth() {
68 return 0;
71 // Given the same arguments as multiBitWidth, buildBitmask will determine which
72 // index in the table corresponds to the provided parameters.
73 template<unsigned bit>
74 inline unsigned buildBitmask() {
75 static_assert(bit < (sizeof(unsigned) * CHAR_BIT - 1), "Too many bits");
76 return 0;
78 template<unsigned bit = 0, typename T, typename... Args>
79 inline unsigned buildBitmask(T c, Args... args) {
80 unsigned bits = (unsigned)c & ((1u << bitWidth<T>()) - 1);
81 return buildBitmask<bit + bitWidth<T>()>(args...) | bits << bit;
84 // FILL_ROW and BUILD_OPTAB* build up the static table of function pointers
85 #define FILL_ROW(nm, ...) do { \
86 OpFunc* dest = &optab[buildBitmask(__VA_ARGS__)]; \
87 assert(*dest == nullptr); \
88 *dest = (OpFunc)VectorHelpers::nm; \
89 } while (false);
90 #define FILL_ROW_HOT(nm, hot, ...) FILL_ROW(nm, __VA_ARGS__)
92 #define BUILD_OPTAB(...) BUILD_OPTAB_ARG(HELPER_TABLE(FILL_ROW), __VA_ARGS__)
93 #define BUILD_OPTAB_HOT(...) \
94 BUILD_OPTAB_ARG(HELPER_TABLE(FILL_ROW_HOT), __VA_ARGS__)
95 #define BUILD_OPTAB_ARG(FILL_TABLE, ...) \
96 static OpFunc* optab = nullptr; \
97 if (!optab) { \
98 optab = (OpFunc*)calloc(1 << multiBitWidth(__VA_ARGS__), sizeof(OpFunc)); \
99 FILL_TABLE \
101 unsigned idx = buildBitmask(__VA_ARGS__); \
102 OpFunc opFunc = optab[idx]; \
103 assert(opFunc);
105 // The getKeyType family of functions determine the KeyType to be used as a
106 // template argument to helper functions. S, IS, or I at the end of the
107 // function names signals that the caller supports non-literal strings, int, or
108 // both, respectively.
109 static KeyType getKeyType(const SSATmp* key, bool nonLitStr,
110 bool nonLitInt) {
111 auto DEBUG_ONLY keyType = key->type();
112 assert(keyType.notBoxed());
113 assert(keyType.isKnownDataType() || keyType.equals(Type::Cell));
115 if ((key->isConst() || nonLitStr) && key->isString()) {
116 return KeyType::Str;
117 } else if ((key->isConst() || nonLitInt) && key->isA(Type::Int)) {
118 return KeyType::Int;
119 } else {
120 return KeyType::Any;
123 inline static KeyType getKeyType(const SSATmp* key) {
124 return getKeyType(key, false, false);
126 inline static KeyType getKeyTypeS(const SSATmp* key) {
127 return getKeyType(key, true, false);
129 inline static KeyType getKeyTypeIS(const SSATmp* key) {
130 return getKeyType(key, true, true);
133 // keyPtr is used by helper function implementations to convert a
134 // TypedValue passed by value into a TypedValue* suitable for passing
135 // to helpers from member_operations.h, which are prepared to handle
136 // int64 and StringData* keys in their key argument. This should be
137 // cleaned up to use the right types: #2174037
138 template<KeyType kt>
139 static inline TypedValue* keyPtr(TypedValue& key) {
140 if (kt == KeyType::Any) {
141 assert(tvIsPlausible(&key));
142 return &key;
143 } else {
144 return reinterpret_cast<TypedValue*>(key.m_data.num);
150 #endif