Clean up irgen.h a bit
[hiphop-php.git] / hphp / runtime / vm / jit / vasm-internal-inl.h
blob3c1f4981e2bfb7edbaffae00b7754bb6179ebe87
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/containers.h"
18 #include "hphp/runtime/vm/jit/ir-opcode.h"
19 #include "hphp/runtime/vm/jit/trans-rec.h"
20 #include "hphp/runtime/vm/jit/vasm.h"
21 #include "hphp/runtime/vm/jit/vasm-instr.h"
22 #include "hphp/runtime/vm/jit/vasm-text.h"
23 #include "hphp/runtime/vm/jit/vasm-unit.h"
25 #include "hphp/util/data-block.h"
27 #include <vector>
29 namespace HPHP { namespace jit {
31 struct IRInstruction;
33 ///////////////////////////////////////////////////////////////////////////////
35 namespace vasm_detail {
37 ///////////////////////////////////////////////////////////////////////////////
40 * Nouned verb class used to hide mostly-debug metadata updates from the main
41 * body of vasm_emit().
43 * This is invoked on every Vinstr encountered in order to accumulate mappings
44 * from higher-level representations.
46 struct IRMetadataUpdater {
47 IRMetadataUpdater(const Venv& env, AsmInfo* asm_info);
50 * Update IR mappings for a Vinstr.
52 void register_inst(const Vinstr& inst);
55 * Update IR mappings at the end of a block.
57 void register_block_end();
60 * Update AsmInfo after the Vunit has been fully emitted.
62 void finish(const jit::vector<Vlabel>& labels);
64 private:
65 struct Snippet {
66 const IRInstruction* origin;
67 TcaRange range;
71 * Get HHIR mapping info for the current block in `m_env'.
73 jit::vector<Snippet>& block_info();
75 private:
76 const Venv& m_env;
77 AsmInfo* m_asm_info;
78 const IRInstruction* m_origin{nullptr};
79 jit::vector<jit::vector<jit::vector<Snippet>>> m_area_to_blockinfos;
80 std::vector<TransBCMapping>* m_bcmap{nullptr};
83 ///////////////////////////////////////////////////////////////////////////////
86 * Is `block' an empty catch block?
88 bool is_empty_catch(const Vblock& block);
91 * Register catch blocks for fixups.
93 void register_catch_block(const Venv& env, const Venv::LabelPatch& p);
96 * Emit a service request stub and register a patch point as needed.
98 void emit_svcreq_stub(Venv& env, const Venv::SvcReqPatch& p);
101 * Arch-independent emitters.
103 * Return true if the instruction was supported.
105 template<class Inst> bool emit(Venv& env, const Inst&) { return false; }
106 bool emit(Venv& env, const bindjmp& i);
107 bool emit(Venv& env, const bindjcc& i);
108 bool emit(Venv& env, const bindjcc1st& i);
109 bool emit(Venv& env, const bindaddr& i);
110 bool emit(Venv& env, const fallback& i);
111 bool emit(Venv& env, const fallbackcc& i);
112 bool emit(Venv& env, const retransopt& i);
114 ///////////////////////////////////////////////////////////////////////////////
118 ///////////////////////////////////////////////////////////////////////////////
120 template<class Vemit>
121 void vasm_emit(const Vunit& unit, Vtext& text, CGMeta& fixups,
122 AsmInfo* asm_info) {
123 using namespace vasm_detail;
125 Venv env { unit, text, fixups };
126 env.addrs.resize(unit.blocks.size());
128 auto labels = layoutBlocks(unit, text);
130 IRMetadataUpdater irmu(env, asm_info);
132 auto const area_start = [&] (Vlabel b) {
133 auto area = unit.blocks[b].area_idx;
134 return text.area(area).start;
137 for (int i = 0, n = labels.size(); i < n; ++i) {
138 assertx(checkBlockEnd(unit, labels[i]));
140 auto b = labels[i];
141 auto& block = unit.blocks[b];
143 env.cb = &text.area(block.area_idx).code;
144 env.addrs[b] = env.cb->frontier();
146 { // Compute the next block we will emit into the current area.
147 auto const cur_start = area_start(labels[i]);
148 auto j = i + 1;
149 while (j < labels.size() &&
150 cur_start != area_start(labels[j])) {
151 j++;
153 env.next = j < labels.size() ? labels[j] : Vlabel(unit.blocks.size());
154 env.current = b;
157 // We'll replace exception edges to empty catch blocks with the catch
158 // helper unique stub.
159 if (is_empty_catch(block)) continue;
161 for (auto& inst : block.code) {
162 irmu.register_inst(inst);
164 switch (inst.op) {
165 #define O(name, imms, uses, defs) \
166 case Vinstr::name: \
167 if (emit(env, inst.name##_)) break; \
168 Vemit(env).emit(inst.name##_); \
169 break;
170 VASM_OPCODES
171 #undef O
175 irmu.register_block_end();
178 // Emit service request stubs and register patch points.
179 for (auto& p : env.stubs) emit_svcreq_stub(env, p);
181 // Patch up jump targets and friends.
182 Vemit::patch(env);
184 // Register catch blocks.
185 for (auto& p : env.catches) register_catch_block(env, p);
187 if (unit.padding) Vemit::pad(text.main().code);
189 irmu.finish(labels);
192 ///////////////////////////////////////////////////////////////////////////////