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/codegen/macro-assembler.h" 9 #include "src/compiler/backend/code-generator.h" 10 #include "src/compiler/backend/instruction.h" 11 #include "src/compiler/linkage.h" 12 #include "src/compiler/opcodes.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: InstructionOperandConverter(CodeGenerator * gen,Instruction * instr)24 InstructionOperandConverter(CodeGenerator* gen, Instruction* instr) 25 : gen_(gen), instr_(instr) {} 26 27 // -- Instruction operand accesses with conversions -------------------------- 28 InputRegister(size_t index)29 Register InputRegister(size_t index) const { 30 return ToRegister(instr_->InputAt(index)); 31 } 32 InputFloatRegister(size_t index)33 FloatRegister InputFloatRegister(size_t index) { 34 return ToFloatRegister(instr_->InputAt(index)); 35 } 36 InputDoubleRegister(size_t index)37 DoubleRegister InputDoubleRegister(size_t index) { 38 return ToDoubleRegister(instr_->InputAt(index)); 39 } 40 InputSimd128Register(size_t index)41 Simd128Register InputSimd128Register(size_t index) { 42 return ToSimd128Register(instr_->InputAt(index)); 43 } 44 InputDouble(size_t index)45 double InputDouble(size_t index) { return ToDouble(instr_->InputAt(index)); } 46 InputFloat32(size_t index)47 float InputFloat32(size_t index) { return ToFloat32(instr_->InputAt(index)); } 48 InputInt32(size_t index)49 int32_t InputInt32(size_t index) { 50 return ToConstant(instr_->InputAt(index)).ToInt32(); 51 } 52 InputUint32(size_t index)53 uint32_t InputUint32(size_t index) { 54 return bit_cast<uint32_t>(InputInt32(index)); 55 } 56 InputInt64(size_t index)57 int64_t InputInt64(size_t index) { 58 return ToConstant(instr_->InputAt(index)).ToInt64(); 59 } 60 InputInt8(size_t index)61 int8_t InputInt8(size_t index) { 62 return static_cast<int8_t>(InputInt32(index)); 63 } 64 InputUint8(size_t index)65 uint8_t InputUint8(size_t index) { 66 return bit_cast<uint8_t>(InputInt8(index)); 67 } 68 InputInt16(size_t index)69 int16_t InputInt16(size_t index) { 70 return static_cast<int16_t>(InputInt32(index)); 71 } 72 InputInt3(size_t index)73 uint8_t InputInt3(size_t index) { 74 return static_cast<uint8_t>(InputInt32(index) & 0x7); 75 } 76 InputInt4(size_t index)77 uint8_t InputInt4(size_t index) { 78 return static_cast<uint8_t>(InputInt32(index) & 0xF); 79 } 80 InputInt5(size_t index)81 uint8_t InputInt5(size_t index) { 82 return static_cast<uint8_t>(InputInt32(index) & 0x1F); 83 } 84 InputInt6(size_t index)85 uint8_t InputInt6(size_t index) { 86 return static_cast<uint8_t>(InputInt32(index) & 0x3F); 87 } 88 InputExternalReference(size_t index)89 ExternalReference InputExternalReference(size_t index) { 90 return ToExternalReference(instr_->InputAt(index)); 91 } 92 InputCode(size_t index)93 Handle<CodeT> InputCode(size_t index) { 94 return ToCode(instr_->InputAt(index)); 95 } 96 InputLabel(size_t index)97 Label* InputLabel(size_t index) { return ToLabel(instr_->InputAt(index)); } 98 InputRpo(size_t index)99 RpoNumber InputRpo(size_t index) { 100 return ToRpoNumber(instr_->InputAt(index)); 101 } 102 103 Register OutputRegister(size_t index = 0) const { 104 return ToRegister(instr_->OutputAt(index)); 105 } 106 TempRegister(size_t index)107 Register TempRegister(size_t index) { 108 return ToRegister(instr_->TempAt(index)); 109 } 110 OutputFloatRegister()111 FloatRegister OutputFloatRegister() { 112 return ToFloatRegister(instr_->Output()); 113 } 114 OutputDoubleRegister()115 DoubleRegister OutputDoubleRegister() { 116 return ToDoubleRegister(instr_->Output()); 117 } 118 OutputSimd128Register()119 Simd128Register OutputSimd128Register() { 120 return ToSimd128Register(instr_->Output()); 121 } 122 TempSimd128Register(size_t index)123 Simd128Register TempSimd128Register(size_t index) { 124 return ToSimd128Register(instr_->TempAt(index)); 125 } 126 127 // -- Conversions for operands ----------------------------------------------- 128 ToLabel(InstructionOperand * op)129 Label* ToLabel(InstructionOperand* op) { 130 return gen_->GetLabel(ToRpoNumber(op)); 131 } 132 ToRpoNumber(InstructionOperand * op)133 RpoNumber ToRpoNumber(InstructionOperand* op) { 134 return ToConstant(op).ToRpoNumber(); 135 } 136 ToRegister(InstructionOperand * op)137 Register ToRegister(InstructionOperand* op) const { 138 return LocationOperand::cast(op)->GetRegister(); 139 } 140 ToFloatRegister(InstructionOperand * op)141 FloatRegister ToFloatRegister(InstructionOperand* op) { 142 return LocationOperand::cast(op)->GetFloatRegister(); 143 } 144 ToDoubleRegister(InstructionOperand * op)145 DoubleRegister ToDoubleRegister(InstructionOperand* op) { 146 return LocationOperand::cast(op)->GetDoubleRegister(); 147 } 148 ToSimd128Register(InstructionOperand * op)149 Simd128Register ToSimd128Register(InstructionOperand* op) { 150 return LocationOperand::cast(op)->GetSimd128Register(); 151 } 152 ToConstant(InstructionOperand * op)153 Constant ToConstant(InstructionOperand* op) const { 154 if (op->IsImmediate()) { 155 return gen_->instructions()->GetImmediate(ImmediateOperand::cast(op)); 156 } 157 return gen_->instructions()->GetConstant( 158 ConstantOperand::cast(op)->virtual_register()); 159 } 160 ToDouble(InstructionOperand * op)161 double ToDouble(InstructionOperand* op) { 162 return ToConstant(op).ToFloat64().value(); 163 } 164 ToFloat32(InstructionOperand * op)165 float ToFloat32(InstructionOperand* op) { return ToConstant(op).ToFloat32(); } 166 ToExternalReference(InstructionOperand * op)167 ExternalReference ToExternalReference(InstructionOperand* op) { 168 return ToConstant(op).ToExternalReference(); 169 } 170 ToCode(InstructionOperand * op)171 Handle<CodeT> ToCode(InstructionOperand* op) { 172 return ToConstant(op).ToCode(); 173 } 174 frame()175 const Frame* frame() const { return gen_->frame(); } frame_access_state()176 FrameAccessState* frame_access_state() const { 177 return gen_->frame_access_state(); 178 } isolate()179 Isolate* isolate() const { return gen_->isolate(); } linkage()180 Linkage* linkage() const { return gen_->linkage(); } 181 182 protected: 183 CodeGenerator* gen_; 184 Instruction* instr_; 185 }; 186 187 // Deoptimization exit. 188 class DeoptimizationExit : public ZoneObject { 189 public: DeoptimizationExit(SourcePosition pos,BytecodeOffset bailout_id,int translation_id,int pc_offset,DeoptimizeKind kind,DeoptimizeReason reason,NodeId node_id)190 explicit DeoptimizationExit(SourcePosition pos, BytecodeOffset bailout_id, 191 int translation_id, int pc_offset, 192 DeoptimizeKind kind, DeoptimizeReason reason, 193 NodeId node_id) 194 : deoptimization_id_(kNoDeoptIndex), 195 pos_(pos), 196 bailout_id_(bailout_id), 197 translation_id_(translation_id), 198 pc_offset_(pc_offset), 199 kind_(kind), 200 reason_(reason), 201 node_id_(node_id), 202 immediate_args_(nullptr), 203 emitted_(false) {} 204 has_deoptimization_id()205 bool has_deoptimization_id() const { 206 return deoptimization_id_ != kNoDeoptIndex; 207 } deoptimization_id()208 int deoptimization_id() const { 209 DCHECK(has_deoptimization_id()); 210 return deoptimization_id_; 211 } set_deoptimization_id(int deoptimization_id)212 void set_deoptimization_id(int deoptimization_id) { 213 deoptimization_id_ = deoptimization_id; 214 } pos()215 SourcePosition pos() const { return pos_; } 216 // The label for the deoptimization call. label()217 Label* label() { return &label_; } 218 // The label after the deoptimization check, which will resume execution. continue_label()219 Label* continue_label() { return &continue_label_; } bailout_id()220 BytecodeOffset bailout_id() const { return bailout_id_; } translation_id()221 int translation_id() const { return translation_id_; } pc_offset()222 int pc_offset() const { return pc_offset_; } kind()223 DeoptimizeKind kind() const { return kind_; } reason()224 DeoptimizeReason reason() const { return reason_; } node_id()225 NodeId node_id() const { return node_id_; } immediate_args()226 const ZoneVector<ImmediateOperand*>* immediate_args() const { 227 return immediate_args_; 228 } set_immediate_args(ZoneVector<ImmediateOperand * > * immediate_args)229 void set_immediate_args(ZoneVector<ImmediateOperand*>* immediate_args) { 230 immediate_args_ = immediate_args; 231 } 232 // Returns whether the deopt exit has already been emitted. Most deopt exits 233 // are emitted contiguously at the end of the code, but unconditional deopt 234 // exits (kArchDeoptimize) may be inlined where they are encountered. emitted()235 bool emitted() const { return emitted_; } set_emitted()236 void set_emitted() { emitted_ = true; } 237 238 private: 239 static const int kNoDeoptIndex = kMaxInt16 + 1; 240 int deoptimization_id_; 241 const SourcePosition pos_; 242 Label label_; 243 Label continue_label_; 244 const BytecodeOffset bailout_id_; 245 const int translation_id_; 246 const int pc_offset_; 247 const DeoptimizeKind kind_; 248 const DeoptimizeReason reason_; 249 const NodeId node_id_; 250 ZoneVector<ImmediateOperand*>* immediate_args_; 251 bool emitted_; 252 }; 253 254 // Generator for out-of-line code that is emitted after the main code is done. 255 class OutOfLineCode : public ZoneObject { 256 public: 257 explicit OutOfLineCode(CodeGenerator* gen); 258 virtual ~OutOfLineCode(); 259 260 virtual void Generate() = 0; 261 entry()262 Label* entry() { return &entry_; } exit()263 Label* exit() { return &exit_; } frame()264 const Frame* frame() const { return frame_; } tasm()265 TurboAssembler* tasm() { return tasm_; } next()266 OutOfLineCode* next() const { return next_; } 267 268 private: 269 Label entry_; 270 Label exit_; 271 const Frame* const frame_; 272 TurboAssembler* const tasm_; 273 OutOfLineCode* const next_; 274 }; 275 276 } // namespace compiler 277 } // namespace internal 278 } // namespace v8 279 280 #endif // V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_ 281