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<Code> 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<Code> 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,BailoutId bailout_id,int translation_id,int pc_offset,DeoptimizeKind kind,DeoptimizeReason reason)190 explicit DeoptimizationExit(SourcePosition pos, BailoutId bailout_id, 191 int translation_id, int pc_offset, 192 DeoptimizeKind kind, DeoptimizeReason reason) 193 : deoptimization_id_(kNoDeoptIndex), 194 pos_(pos), 195 bailout_id_(bailout_id), 196 translation_id_(translation_id), 197 pc_offset_(pc_offset), 198 kind_(kind), 199 reason_(reason), 200 emitted_(false) {} 201 has_deoptimization_id()202 bool has_deoptimization_id() const { 203 return deoptimization_id_ != kNoDeoptIndex; 204 } deoptimization_id()205 int deoptimization_id() const { 206 DCHECK(has_deoptimization_id()); 207 return deoptimization_id_; 208 } set_deoptimization_id(int deoptimization_id)209 void set_deoptimization_id(int deoptimization_id) { 210 deoptimization_id_ = deoptimization_id; 211 } pos()212 SourcePosition pos() const { return pos_; } label()213 Label* label() { return &label_; } bailout_id()214 BailoutId bailout_id() const { return bailout_id_; } translation_id()215 int translation_id() const { return translation_id_; } pc_offset()216 int pc_offset() const { return pc_offset_; } kind()217 DeoptimizeKind kind() const { return kind_; } reason()218 DeoptimizeReason reason() const { return reason_; } 219 // Returns whether the deopt exit has already been emitted. Most deopt exits 220 // are emitted contiguously at the end of the code, but unconditional deopt 221 // exits (kArchDeoptimize) may be inlined where they are encountered. emitted()222 bool emitted() const { return emitted_; } set_emitted()223 void set_emitted() { emitted_ = true; } 224 225 private: 226 static const int kNoDeoptIndex = kMaxInt16 + 1; 227 int deoptimization_id_; 228 const SourcePosition pos_; 229 Label label_; 230 const BailoutId bailout_id_; 231 const int translation_id_; 232 const int pc_offset_; 233 const DeoptimizeKind kind_; 234 const DeoptimizeReason reason_; 235 bool emitted_; 236 }; 237 238 // Generator for out-of-line code that is emitted after the main code is done. 239 class OutOfLineCode : public ZoneObject { 240 public: 241 explicit OutOfLineCode(CodeGenerator* gen); 242 virtual ~OutOfLineCode(); 243 244 virtual void Generate() = 0; 245 entry()246 Label* entry() { return &entry_; } exit()247 Label* exit() { return &exit_; } frame()248 const Frame* frame() const { return frame_; } tasm()249 TurboAssembler* tasm() { return tasm_; } next()250 OutOfLineCode* next() const { return next_; } 251 252 private: 253 Label entry_; 254 Label exit_; 255 const Frame* const frame_; 256 TurboAssembler* const tasm_; 257 OutOfLineCode* const next_; 258 }; 259 260 } // namespace compiler 261 } // namespace internal 262 } // namespace v8 263 264 #endif // V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_ 265