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