Updating submodules
[hiphop-php.git] / hphp / runtime / vm / jit / ssa-tmp.cpp
blobbe8045b797ec5ab7c37c156db4f29e8a82c3af2e
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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/ssa-tmp.h"
19 #include <sstream>
21 #include "hphp/runtime/vm/jit/ir-instruction.h"
22 #include "hphp/runtime/vm/jit/print.h"
23 #include "hphp/util/low-ptr.h"
25 namespace HPHP::jit {
27 SSATmp::SSATmp(uint32_t opndId, IRInstruction* i, int dstId /* = 0 */)
28 : m_id(opndId)
30 setInstruction(i, dstId);
33 void SSATmp::setInstruction(IRInstruction* inst, int dstId) {
34 m_inst = inst;
35 m_type = outputType(inst, dstId);
38 namespace {
39 int typeNeededWords(Type t) {
40 // Although we say we have zero registers, we always allocate 1 in
41 // reg-alloc.cpp. In practice this doesn't mean much.
42 if (t.subtypeOfAny(TUninit,
43 TInitNull,
44 TNullptr)) {
45 // These don't need a register because their values are static or unused.
46 return 0;
48 if (t.maybe(TNullptr)) {
49 return typeNeededWords(t - TNullptr);
51 if (t <= TPtr) {
52 // PtrTo* may be statically unknown but always need just one
53 // register.
54 return 1;
56 if (t <= TLval) {
57 // If tv_val<> is ever anything other than 1 or more normal pointers, this
58 // will need to change.
59 static_assert(sizeof(tv_lval) % 8 == 0, "");
60 return sizeof(tv_lval) / 8;
62 if (!t.isUnion()) {
63 // Not a union type and not a special case: 1 register.
64 assertx(IMPLIES(t <= TCell, t.isKnownDataType()));
65 return 1;
68 assertx(t <= TCell);
70 // XXX(t4592459): This will return 2 for TNull, even though it only
71 // needs 1 register (one for the type, none for the value). This is to work
72 // around limitations in codegen; see the task for details. It does mean we
73 // will be loading and storing garbage m_data for Null values but that's fine
74 // since m_data is undefined for Null values.
75 return t.needsReg() ? 2 : 1;
79 int SSATmp::numWords() const {
80 return typeNeededWords(type());
83 Variant SSATmp::variantVal() const {
84 auto const dt = type().toDataType();
85 switch (dt) {
86 case KindOfUninit:
87 case KindOfNull:
88 // Upon return both will converted to KindOfNull anyway.
89 return init_null();
90 case KindOfBoolean:
91 return boolVal();
92 case KindOfInt64:
93 return intVal();
94 case KindOfDouble:
95 return dblVal();
96 case KindOfPersistentString:
97 return Variant{strVal(), Variant::PersistentStrInit{}};
98 case KindOfPersistentVec:
99 case KindOfPersistentDict:
100 case KindOfPersistentKeyset:
101 return Variant{arrLikeVal(), dt, Variant::PersistentArrInit{}};
102 case KindOfClass:
103 return Variant{const_cast<Class*>(clsVal())};
104 case KindOfLazyClass:
105 return Variant{lclsVal()};
106 case KindOfFunc:
107 return Variant{funcVal()};
108 case KindOfClsMeth:
109 return Variant{clsmethVal()};
110 case KindOfEnumClassLabel:
111 return Variant{eclVal(), Variant::EnumClassLabelInit{}};
112 case KindOfRClsMeth:
113 case KindOfString:
114 case KindOfVec:
115 case KindOfDict:
116 case KindOfKeyset:
117 case KindOfObject:
118 case KindOfResource:
119 case KindOfRFunc:
120 break;
122 always_assert(false);
125 std::string SSATmp::toString() const {
126 std::ostringstream out;
127 print(out, this);
128 return out.str();