Replace REQ_RETRANSLATE_OPT with a regular C++ call via ustub
[hiphop-php.git] / hphp / runtime / vm / jit / vasm-instr.cpp
blobfbccb2f681ff6357faf9f1029bcf787f1ec1b4c9
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/vasm-instr.h"
19 namespace HPHP { namespace jit {
20 ///////////////////////////////////////////////////////////////////////////////
22 #define O(name, ...) \
23 static_assert(sizeof(name) <= 48, "vasm struct " #name " is too big");
24 VASM_OPCODES
25 #undef O
26 static_assert(sizeof(Vinstr) <= 64, "Vinstr should be <= 64 bytes");
28 const char* vinst_names[] = {
29 #define O(name, imms, uses, defs) #name,
30 VASM_OPCODES
31 #undef O
34 ///////////////////////////////////////////////////////////////////////////////
36 bool isBlockEnd(const Vinstr& inst) {
37 switch (inst.op) {
38 // service request-y things
39 case Vinstr::bindjmp:
40 case Vinstr::fallback:
41 // control flow
42 case Vinstr::jcc:
43 case Vinstr::jcci:
44 case Vinstr::jmp:
45 case Vinstr::jmps:
46 case Vinstr::jmpr:
47 case Vinstr::jmpm:
48 case Vinstr::jmpi:
49 case Vinstr::phijmp:
50 // terminal calls
51 case Vinstr::tailcallstub:
52 case Vinstr::tailcallstubr:
53 case Vinstr::resumetc:
54 // exception edges
55 case Vinstr::unwind:
56 case Vinstr::vinvoke:
57 case Vinstr::contenter:
58 // terminal
59 case Vinstr::trap:
60 case Vinstr::ret:
61 case Vinstr::stubret:
62 case Vinstr::phpret:
63 case Vinstr::leavetc:
64 case Vinstr::fallthru:
65 return true;
66 default:
67 return false;
71 bool isCall(Vinstr::Opcode op) {
72 switch (op) {
73 case Vinstr::call:
74 case Vinstr::callfaststub:
75 case Vinstr::callm:
76 case Vinstr::callphp:
77 case Vinstr::callphpr:
78 case Vinstr::callphps:
79 case Vinstr::callr:
80 case Vinstr::calls:
81 case Vinstr::callstub:
82 case Vinstr::tailcallstub:
83 case Vinstr::tailcallstubr:
84 case Vinstr::vcall:
85 case Vinstr::vinvoke:
86 return true;
87 default:
88 return false;
92 Width width(Vinstr::Opcode op) {
93 switch (op) {
94 // service requests
95 case Vinstr::bindjmp:
96 case Vinstr::bindjcc:
97 case Vinstr::bindaddr:
98 case Vinstr::fallback:
99 case Vinstr::fallbackcc:
100 // vasm intrinsics
101 case Vinstr::conjure:
102 case Vinstr::conjureuse:
103 case Vinstr::copy:
104 case Vinstr::copy2:
105 case Vinstr::copyargs:
106 case Vinstr::debugtrap:
107 case Vinstr::fallthru:
108 case Vinstr::ldimmb:
109 case Vinstr::ldimmw:
110 case Vinstr::ldimml:
111 case Vinstr::ldimmq:
112 case Vinstr::ldundefq:
113 case Vinstr::movqs:
114 case Vinstr::load:
115 case Vinstr::store:
116 case Vinstr::mcprep:
117 case Vinstr::phidef:
118 case Vinstr::phijmp:
119 case Vinstr::inlinestart:
120 case Vinstr::inlineend:
121 case Vinstr::pushframe:
122 case Vinstr::popframe:
123 case Vinstr::recordstack:
124 case Vinstr::recordbasenativesp:
125 case Vinstr::unrecordbasenativesp:
126 case Vinstr::spill:
127 case Vinstr::spillbi:
128 case Vinstr::spillli:
129 case Vinstr::spillqi:
130 case Vinstr::spillundefq:
131 case Vinstr::reload:
132 case Vinstr::ssaalias:
133 // native function abi
134 case Vinstr::vcall:
135 case Vinstr::vinvoke:
136 case Vinstr::call:
137 case Vinstr::callm:
138 case Vinstr::callr:
139 case Vinstr::calls:
140 case Vinstr::ret:
141 // stub function abi
142 case Vinstr::stublogue:
143 case Vinstr::unstublogue:
144 case Vinstr::stubret:
145 case Vinstr::callstub:
146 case Vinstr::callfaststub:
147 case Vinstr::tailcallstub:
148 case Vinstr::tailcallstubr:
149 case Vinstr::stubunwind:
150 // php function abi
151 case Vinstr::defvmsp:
152 case Vinstr::defvmfp:
153 case Vinstr::pushvmfp:
154 case Vinstr::popvmfp:
155 case Vinstr::syncvmsp:
156 case Vinstr::defvmretdata:
157 case Vinstr::defvmrettype:
158 case Vinstr::syncvmret:
159 case Vinstr::syncvmrettype:
160 case Vinstr::phplogue:
161 case Vinstr::stubtophp:
162 case Vinstr::loadstubret:
163 case Vinstr::phpret:
164 case Vinstr::callphp:
165 case Vinstr::callphpr:
166 case Vinstr::callphps:
167 case Vinstr::contenter:
168 // vm entry abi
169 case Vinstr::resumetc:
170 case Vinstr::inittc:
171 case Vinstr::leavetc:
172 // exception intrinsics
173 case Vinstr::landingpad:
174 case Vinstr::nothrow:
175 case Vinstr::syncpoint:
176 case Vinstr::unwind:
177 // nop and trap
178 case Vinstr::nop:
179 case Vinstr::trap:
180 // restrict/unrestrict new virtuals
181 case Vinstr::vregrestrict:
182 case Vinstr::vregunrestrict:
183 // sign/zero-extending/truncating copies
184 case Vinstr::movsbl:
185 case Vinstr::movswl:
186 case Vinstr::movsbq:
187 case Vinstr::movswq:
188 case Vinstr::movslq:
189 case Vinstr::movzbw:
190 case Vinstr::movzbl:
191 case Vinstr::movzbq:
192 case Vinstr::movzwl:
193 case Vinstr::movzwq:
194 case Vinstr::movzlq:
195 case Vinstr::movtqb:
196 case Vinstr::movtdb:
197 case Vinstr::movtdq:
198 case Vinstr::movtql:
199 case Vinstr::movtqw:
200 // branches
201 case Vinstr::jcc:
202 case Vinstr::jcci:
203 case Vinstr::jmp:
204 case Vinstr::jmps:
205 case Vinstr::jmpr:
206 case Vinstr::jmpm:
207 case Vinstr::jmpi:
208 // push/pop
209 case Vinstr::pop:
210 case Vinstr::popf:
211 case Vinstr::popm:
212 case Vinstr::popp:
213 case Vinstr::poppm:
214 case Vinstr::push:
215 case Vinstr::pushf:
216 case Vinstr::pushm:
217 case Vinstr::pushp:
218 case Vinstr::pushpm:
219 // floating-point conversions
220 case Vinstr::cvttsd2siq:
221 case Vinstr::cvtsi2sd:
222 case Vinstr::cvtsi2sdm:
223 case Vinstr::unpcklpd:
224 // x64 instructions
225 case Vinstr::cqo:
226 case Vinstr::idiv:
227 case Vinstr::sarq:
228 case Vinstr::shlq:
229 case Vinstr::shrq:
230 // arm instructions
231 case Vinstr::fcvtzs:
232 case Vinstr::mrs:
233 case Vinstr::msr:
234 return Width::AnyNF;
236 case Vinstr::andb:
237 case Vinstr::andbi:
238 case Vinstr::andbim:
239 case Vinstr::notb:
240 case Vinstr::orbi:
241 case Vinstr::orbim:
242 case Vinstr::xorb:
243 case Vinstr::xorbi:
244 case Vinstr::cmpb:
245 case Vinstr::cmpbi:
246 case Vinstr::cmpbim:
247 case Vinstr::cmpbm:
248 case Vinstr::testb:
249 case Vinstr::testbi:
250 case Vinstr::testbim:
251 case Vinstr::testbm:
252 case Vinstr::cmovb:
253 case Vinstr::csincb:
254 case Vinstr::setcc:
255 case Vinstr::movb:
256 case Vinstr::loadb:
257 case Vinstr::loadtqb:
258 case Vinstr::storeb:
259 case Vinstr::storebi:
260 return Width::Byte;
262 case Vinstr::addwm:
263 case Vinstr::andw:
264 case Vinstr::andwi:
265 case Vinstr::incw:
266 case Vinstr::incwm:
267 case Vinstr::orwim:
268 case Vinstr::cmovw:
269 case Vinstr::csincw:
270 case Vinstr::cmpw:
271 case Vinstr::cmpwi:
272 case Vinstr::cmpwim:
273 case Vinstr::cmpwm:
274 case Vinstr::testw:
275 case Vinstr::testwi:
276 case Vinstr::testwim:
277 case Vinstr::testwm:
278 case Vinstr::loadw:
279 case Vinstr::movw:
280 case Vinstr::storew:
281 case Vinstr::storewi:
282 case Vinstr::xorw:
283 case Vinstr::xorwi:
284 return Width::Word;
286 case Vinstr::addl:
287 case Vinstr::addli:
288 case Vinstr::addlm:
289 case Vinstr::addlim:
290 case Vinstr::andl:
291 case Vinstr::andli:
292 case Vinstr::decl:
293 case Vinstr::declm:
294 case Vinstr::incl:
295 case Vinstr::inclm:
296 case Vinstr::shlli:
297 case Vinstr::shrli:
298 case Vinstr::subl:
299 case Vinstr::subli:
300 case Vinstr::xorl:
301 case Vinstr::orlim:
302 case Vinstr::cmovl:
303 case Vinstr::csincl:
304 case Vinstr::cmpl:
305 case Vinstr::cmpli:
306 case Vinstr::cmplm:
307 case Vinstr::cmplim:
308 case Vinstr::testl:
309 case Vinstr::testli:
310 case Vinstr::testlim:
311 case Vinstr::testlm:
312 case Vinstr::movl:
313 case Vinstr::loadl:
314 case Vinstr::loadzbl:
315 case Vinstr::loadsbl:
316 case Vinstr::loadtql:
317 case Vinstr::storel:
318 case Vinstr::storeli:
319 case Vinstr::ubfmli:
320 return Width::Long;
322 case Vinstr::addq:
323 case Vinstr::addqi:
324 case Vinstr::addqmr:
325 case Vinstr::addqrm:
326 case Vinstr::addqim:
327 case Vinstr::andq:
328 case Vinstr::andqi:
329 case Vinstr::andqi64:
330 case Vinstr::decq:
331 case Vinstr::decqm:
332 case Vinstr::decqmlock:
333 case Vinstr::incq:
334 case Vinstr::incqm:
335 case Vinstr::imul:
336 case Vinstr::divint:
337 case Vinstr::srem:
338 case Vinstr::neg:
339 case Vinstr::not:
340 case Vinstr::orwi:
341 case Vinstr::orli:
342 case Vinstr::orq:
343 case Vinstr::orqi:
344 case Vinstr::orqim:
345 case Vinstr::sar:
346 case Vinstr::shl:
347 case Vinstr::shr:
348 case Vinstr::sarqi:
349 case Vinstr::shlqi:
350 case Vinstr::shrqi:
351 case Vinstr::subq:
352 case Vinstr::subqi:
353 case Vinstr::xorq:
354 case Vinstr::xorqi:
355 case Vinstr::cmpq:
356 case Vinstr::cmpqi:
357 case Vinstr::cmpqm:
358 case Vinstr::cmpqim:
359 case Vinstr::testq:
360 case Vinstr::testqi:
361 case Vinstr::testqm:
362 case Vinstr::testqim:
363 case Vinstr::cloadq:
364 case Vinstr::cmovq:
365 case Vinstr::csincq:
366 case Vinstr::lea:
367 case Vinstr::leap:
368 case Vinstr::leav:
369 case Vinstr::lead:
370 case Vinstr::loadqp:
371 case Vinstr::loadqd:
372 case Vinstr::loadzbq:
373 case Vinstr::loadzwq:
374 case Vinstr::loadzlq:
375 case Vinstr::loadsbq:
376 case Vinstr::storeqi:
377 case Vinstr::addsd:
378 case Vinstr::subsd:
379 case Vinstr::cmpsd:
380 case Vinstr::ucomisd:
381 case Vinstr::loadsd:
382 case Vinstr::storesd:
383 case Vinstr::absdbl:
384 case Vinstr::divsd:
385 case Vinstr::mulsd:
386 case Vinstr::roundsd:
387 case Vinstr::sqrtsd:
388 case Vinstr::crc32q:
389 return Width::Quad;
391 case Vinstr::loadups:
392 case Vinstr::storeups:
393 return Width::Octa;
395 not_reached();
398 bool instrHasIndirectFixup(const Vinstr& inst) {
399 switch (inst.op) {
400 case Vinstr::vcall:
401 return inst.vcall_.fixup.isIndirect();
402 case Vinstr::vinvoke:
403 return inst.vinvoke_.fixup.isIndirect();
404 case Vinstr::syncpoint:
405 return inst.syncpoint_.fix.isIndirect();
406 case Vinstr::callfaststub:
407 return inst.callfaststub_.fix.isIndirect();
408 default:
409 return false;
411 not_reached();
414 void updateIndirectFixupBySpill(Vinstr& inst, size_t spillSize) {
415 assertx(instrHasIndirectFixup(inst));
416 auto const update = [&](Fixup& f) {
417 assertx(f.isIndirect());
418 f.adjustRipOffset(spillSize);
420 switch (inst.op) {
421 case Vinstr::vcall:
422 update(inst.vcall_.fixup);
423 return;
424 case Vinstr::vinvoke:
425 update(inst.vinvoke_.fixup);
426 return;
427 case Vinstr::syncpoint:
428 update(inst.syncpoint_.fix);
429 return;
430 case Vinstr::callfaststub:
431 update(inst.callfaststub_.fix);
432 return;
433 default:
434 always_assert(false);
436 not_reached();
439 ///////////////////////////////////////////////////////////////////////////////