1 | // Copyright 2013 the V8 project authors. All rights reserved. |
---|---|
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_ |
6 | #define V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_ |
7 | |
8 | #include "src/compiler/backend/code-generator.h" |
9 | #include "src/compiler/backend/instruction.h" |
10 | #include "src/compiler/linkage.h" |
11 | #include "src/compiler/opcodes.h" |
12 | #include "src/macro-assembler.h" |
13 | |
14 | namespace v8 { |
15 | namespace internal { |
16 | namespace compiler { |
17 | |
18 | // Converts InstructionOperands from a given instruction to |
19 | // architecture-specific |
20 | // registers and operands after they have been assigned by the register |
21 | // allocator. |
22 | class InstructionOperandConverter { |
23 | public: |
24 | InstructionOperandConverter(CodeGenerator* gen, Instruction* instr) |
25 | : gen_(gen), instr_(instr) {} |
26 | |
27 | // -- Instruction operand accesses with conversions -------------------------- |
28 | |
29 | Register InputRegister(size_t index) { |
30 | return ToRegister(instr_->InputAt(index)); |
31 | } |
32 | |
33 | FloatRegister InputFloatRegister(size_t index) { |
34 | return ToFloatRegister(instr_->InputAt(index)); |
35 | } |
36 | |
37 | DoubleRegister InputDoubleRegister(size_t index) { |
38 | return ToDoubleRegister(instr_->InputAt(index)); |
39 | } |
40 | |
41 | Simd128Register InputSimd128Register(size_t index) { |
42 | return ToSimd128Register(instr_->InputAt(index)); |
43 | } |
44 | |
45 | double InputDouble(size_t index) { return ToDouble(instr_->InputAt(index)); } |
46 | |
47 | float InputFloat32(size_t index) { return ToFloat32(instr_->InputAt(index)); } |
48 | |
49 | int32_t InputInt32(size_t index) { |
50 | return ToConstant(instr_->InputAt(index)).ToInt32(); |
51 | } |
52 | |
53 | uint32_t InputUint32(size_t index) { |
54 | return bit_cast<uint32_t>(InputInt32(index)); |
55 | } |
56 | |
57 | int64_t InputInt64(size_t index) { |
58 | return ToConstant(instr_->InputAt(index)).ToInt64(); |
59 | } |
60 | |
61 | int8_t InputInt8(size_t index) { |
62 | return static_cast<int8_t>(InputInt32(index)); |
63 | } |
64 | |
65 | int16_t InputInt16(size_t index) { |
66 | return static_cast<int16_t>(InputInt32(index)); |
67 | } |
68 | |
69 | uint8_t InputInt3(size_t index) { |
70 | return static_cast<uint8_t>(InputInt32(index) & 0x7); |
71 | } |
72 | |
73 | uint8_t InputInt4(size_t index) { |
74 | return static_cast<uint8_t>(InputInt32(index) & 0xF); |
75 | } |
76 | |
77 | uint8_t InputInt5(size_t index) { |
78 | return static_cast<uint8_t>(InputInt32(index) & 0x1F); |
79 | } |
80 | |
81 | uint8_t InputInt6(size_t index) { |
82 | return static_cast<uint8_t>(InputInt32(index) & 0x3F); |
83 | } |
84 | |
85 | ExternalReference InputExternalReference(size_t index) { |
86 | return ToExternalReference(instr_->InputAt(index)); |
87 | } |
88 | |
89 | Handle<Code> InputCode(size_t index) { |
90 | return ToCode(instr_->InputAt(index)); |
91 | } |
92 | |
93 | Label* InputLabel(size_t index) { return ToLabel(instr_->InputAt(index)); } |
94 | |
95 | RpoNumber InputRpo(size_t index) { |
96 | return ToRpoNumber(instr_->InputAt(index)); |
97 | } |
98 | |
99 | Register OutputRegister(size_t index = 0) { |
100 | return ToRegister(instr_->OutputAt(index)); |
101 | } |
102 | |
103 | Register TempRegister(size_t index) { |
104 | return ToRegister(instr_->TempAt(index)); |
105 | } |
106 | |
107 | FloatRegister OutputFloatRegister() { |
108 | return ToFloatRegister(instr_->Output()); |
109 | } |
110 | |
111 | DoubleRegister OutputDoubleRegister() { |
112 | return ToDoubleRegister(instr_->Output()); |
113 | } |
114 | |
115 | Simd128Register OutputSimd128Register() { |
116 | return ToSimd128Register(instr_->Output()); |
117 | } |
118 | |
119 | // -- Conversions for operands ----------------------------------------------- |
120 | |
121 | Label* ToLabel(InstructionOperand* op) { |
122 | return gen_->GetLabel(ToRpoNumber(op)); |
123 | } |
124 | |
125 | RpoNumber ToRpoNumber(InstructionOperand* op) { |
126 | return ToConstant(op).ToRpoNumber(); |
127 | } |
128 | |
129 | Register ToRegister(InstructionOperand* op) { |
130 | return LocationOperand::cast(op)->GetRegister(); |
131 | } |
132 | |
133 | FloatRegister ToFloatRegister(InstructionOperand* op) { |
134 | return LocationOperand::cast(op)->GetFloatRegister(); |
135 | } |
136 | |
137 | DoubleRegister ToDoubleRegister(InstructionOperand* op) { |
138 | return LocationOperand::cast(op)->GetDoubleRegister(); |
139 | } |
140 | |
141 | Simd128Register ToSimd128Register(InstructionOperand* op) { |
142 | return LocationOperand::cast(op)->GetSimd128Register(); |
143 | } |
144 | |
145 | Constant ToConstant(InstructionOperand* op) { |
146 | if (op->IsImmediate()) { |
147 | return gen_->instructions()->GetImmediate(ImmediateOperand::cast(op)); |
148 | } |
149 | return gen_->instructions()->GetConstant( |
150 | ConstantOperand::cast(op)->virtual_register()); |
151 | } |
152 | |
153 | double ToDouble(InstructionOperand* op) { |
154 | return ToConstant(op).ToFloat64().value(); |
155 | } |
156 | |
157 | float ToFloat32(InstructionOperand* op) { return ToConstant(op).ToFloat32(); } |
158 | |
159 | ExternalReference ToExternalReference(InstructionOperand* op) { |
160 | return ToConstant(op).ToExternalReference(); |
161 | } |
162 | |
163 | Handle<Code> ToCode(InstructionOperand* op) { |
164 | return ToConstant(op).ToCode(); |
165 | } |
166 | |
167 | const Frame* frame() const { return gen_->frame(); } |
168 | FrameAccessState* frame_access_state() const { |
169 | return gen_->frame_access_state(); |
170 | } |
171 | Isolate* isolate() const { return gen_->isolate(); } |
172 | Linkage* linkage() const { return gen_->linkage(); } |
173 | |
174 | protected: |
175 | CodeGenerator* gen_; |
176 | Instruction* instr_; |
177 | }; |
178 | |
179 | // Eager deoptimization exit. |
180 | class DeoptimizationExit : public ZoneObject { |
181 | public: |
182 | explicit DeoptimizationExit(int deoptimization_id, SourcePosition pos) |
183 | : deoptimization_id_(deoptimization_id), pos_(pos) {} |
184 | |
185 | int deoptimization_id() const { return deoptimization_id_; } |
186 | Label* label() { return &label_; } |
187 | SourcePosition pos() const { return pos_; } |
188 | |
189 | private: |
190 | int const deoptimization_id_; |
191 | Label label_; |
192 | SourcePosition const pos_; |
193 | }; |
194 | |
195 | // Generator for out-of-line code that is emitted after the main code is done. |
196 | class OutOfLineCode : public ZoneObject { |
197 | public: |
198 | explicit OutOfLineCode(CodeGenerator* gen); |
199 | virtual ~OutOfLineCode(); |
200 | |
201 | virtual void Generate() = 0; |
202 | |
203 | Label* entry() { return &entry_; } |
204 | Label* exit() { return &exit_; } |
205 | const Frame* frame() const { return frame_; } |
206 | TurboAssembler* tasm() { return tasm_; } |
207 | OutOfLineCode* next() const { return next_; } |
208 | |
209 | private: |
210 | Label entry_; |
211 | Label exit_; |
212 | const Frame* const frame_; |
213 | TurboAssembler* const tasm_; |
214 | OutOfLineCode* const next_; |
215 | }; |
216 | |
217 | inline bool HasCallDescriptorFlag(Instruction* instr, |
218 | CallDescriptor::Flag flag) { |
219 | return MiscField::decode(instr->opcode()) & flag; |
220 | } |
221 | |
222 | } // namespace compiler |
223 | } // namespace internal |
224 | } // namespace v8 |
225 | |
226 | #endif // V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_ |
227 |