Various llvm backend bugfixes
[hiphop-php.git] / hphp / runtime / vm / jit / local-effects.cpp
blob6464eaaa499e1825ddf64af93ebd07ce4cf001b0
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/vm/jit/local-effects.h"
18 #include "hphp/runtime/vm/jit/ir-instruction.h"
19 #include "hphp/runtime/vm/jit/frame-state.h"
20 #include "hphp/runtime/vm/jit/analysis.h"
21 #include "hphp/runtime/vm/jit/minstr-effects.h"
23 namespace HPHP { namespace jit {
25 //////////////////////////////////////////////////////////////////////
27 void local_effects(const FrameStateMgr& frameState,
28 const IRInstruction* inst,
29 LocalStateHook& hook) {
30 auto killIterLocals = [&](const std::initializer_list<uint32_t>& ids) {
31 for (auto id : ids) {
32 hook.setLocalValue(id, nullptr);
36 switch (inst->op()) {
37 case CallBuiltin:
38 if (inst->extra<CallBuiltin>()->destroyLocals) hook.clearLocals();
39 break;
41 case Call:
42 case CallArray:
43 case ContEnter:
45 auto const callDestroysLocals =
46 (inst->is(CallArray) && inst->extra<CallArray>()->destroyLocals) ||
47 (inst->is(Call) && inst->extra<Call>()->destroyLocals);
48 hook.killLocalsForCall(callDestroysLocals);
50 break;
52 case StRef:
53 hook.updateLocalRefPredictions(inst->src(0), inst->src(1));
54 break;
56 case StLocNT:
57 case StLoc:
58 hook.setLocalValue(inst->extra<LocalId>()->locId, inst->src(1));
59 break;
61 case LdLoc:
62 hook.setLocalValue(inst->extra<LdLoc>()->locId, inst->dst());
63 break;
65 case StLocPseudoMain:
66 hook.predictLocalType(inst->extra<LocalId>()->locId,
67 inst->src(1)->type());
68 break;
70 case AssertLoc:
71 case GuardLoc:
72 case CheckLoc: {
73 auto id = inst->extra<LocalId>()->locId;
74 if (inst->marker().func()->isPseudoMain()) {
75 hook.predictLocalType(id, inst->typeParam());
76 } else {
77 hook.refineLocalType(id,
78 inst->typeParam(),
79 TypeSource::makeGuard(inst));
81 break;
84 case HintLocInner:
85 hook.setBoxedLocalPrediction(inst->extra<HintLocInner>()->locId,
86 inst->typeParam());
87 break;
89 case CheckType:
90 case AssertType:
91 hook.refineLocalValues(inst->src(0), inst->dst());
92 break;
94 case IterInitK:
95 case WIterInitK:
96 // kill the locals to which this instruction stores iter's key and value
97 killIterLocals({inst->extra<IterData>()->keyId,
98 inst->extra<IterData>()->valId});
99 break;
101 case IterInit:
102 case WIterInit:
103 // kill the local to which this instruction stores iter's value
104 killIterLocals({inst->extra<IterData>()->valId});
105 break;
107 case IterNextK:
108 case WIterNextK:
109 // kill the locals to which this instruction stores iter's key and value
110 killIterLocals({inst->extra<IterData>()->keyId,
111 inst->extra<IterData>()->valId});
112 break;
114 case IterNext:
115 case WIterNext:
116 // kill the local to which this instruction stores iter's value
117 killIterLocals({inst->extra<IterData>()->valId});
118 break;
120 case InterpOne:
121 case InterpOneCF: {
122 auto const& id = *inst->extra<InterpOneData>();
123 assert(!id.smashesAllLocals || id.nChangedLocals == 0);
124 if (id.smashesAllLocals || inst->marker().func()->isPseudoMain()) {
125 hook.clearLocals();
126 } else {
127 auto it = id.changedLocals;
128 auto const end = it + id.nChangedLocals;
129 for (; it != end; ++it) {
130 auto& loc = *it;
131 // If changing the inner type of a boxed local, also drop the
132 // information about inner types for any other boxed locals.
133 if (loc.type.isBoxed()) hook.dropLocalRefsInnerTypes();
134 hook.setLocalType(loc.id, loc.type);
137 break;
139 default:
140 break;
143 if (MInstrEffects::supported(inst)) {
144 MInstrEffects::get(inst, frameState, hook);
148 //////////////////////////////////////////////////////////////////////