code-generator-impl.h 8.28 KB
Newer Older
1 2 3 4
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_
#define V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_
7

8
#include "src/codegen/macro-assembler.h"
9 10
#include "src/compiler/backend/code-generator.h"
#include "src/compiler/backend/instruction.h"
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#include "src/compiler/linkage.h"
#include "src/compiler/opcodes.h"

namespace v8 {
namespace internal {
namespace compiler {

// Converts InstructionOperands from a given instruction to
// architecture-specific
// registers and operands after they have been assigned by the register
// allocator.
class InstructionOperandConverter {
 public:
  InstructionOperandConverter(CodeGenerator* gen, Instruction* instr)
      : gen_(gen), instr_(instr) {}

27 28
  // -- Instruction operand accesses with conversions --------------------------

29
  Register InputRegister(size_t index) const {
30 31 32
    return ToRegister(instr_->InputAt(index));
  }

33 34 35 36
  FloatRegister InputFloatRegister(size_t index) {
    return ToFloatRegister(instr_->InputAt(index));
  }

37
  DoubleRegister InputDoubleRegister(size_t index) {
38 39 40
    return ToDoubleRegister(instr_->InputAt(index));
  }

41 42 43 44
  Simd128Register InputSimd128Register(size_t index) {
    return ToSimd128Register(instr_->InputAt(index));
  }

45
  double InputDouble(size_t index) { return ToDouble(instr_->InputAt(index)); }
46

47 48
  float InputFloat32(size_t index) { return ToFloat32(instr_->InputAt(index)); }

49
  int32_t InputInt32(size_t index) {
50 51 52
    return ToConstant(instr_->InputAt(index)).ToInt32();
  }

53
  uint32_t InputUint32(size_t index) {
54
    return base::bit_cast<uint32_t>(InputInt32(index));
55 56
  }

57 58 59 60
  int64_t InputInt64(size_t index) {
    return ToConstant(instr_->InputAt(index)).ToInt64();
  }

61 62 63
  int8_t InputInt8(size_t index) {
    return static_cast<int8_t>(InputInt32(index));
  }
64

65
  uint8_t InputUint8(size_t index) {
66
    return base::bit_cast<uint8_t>(InputInt8(index));
67 68
  }

69
  int16_t InputInt16(size_t index) {
70 71 72
    return static_cast<int16_t>(InputInt32(index));
  }

73 74 75 76 77 78 79 80
  uint8_t InputInt3(size_t index) {
    return static_cast<uint8_t>(InputInt32(index) & 0x7);
  }

  uint8_t InputInt4(size_t index) {
    return static_cast<uint8_t>(InputInt32(index) & 0xF);
  }

81
  uint8_t InputInt5(size_t index) {
82 83 84
    return static_cast<uint8_t>(InputInt32(index) & 0x1F);
  }

85
  uint8_t InputInt6(size_t index) {
86 87 88
    return static_cast<uint8_t>(InputInt32(index) & 0x3F);
  }

89 90 91 92
  ExternalReference InputExternalReference(size_t index) {
    return ToExternalReference(instr_->InputAt(index));
  }

93
  Handle<CodeT> InputCode(size_t index) {
94
    return ToCode(instr_->InputAt(index));
95 96
  }

97
  Label* InputLabel(size_t index) { return ToLabel(instr_->InputAt(index)); }
98

99
  RpoNumber InputRpo(size_t index) {
100
    return ToRpoNumber(instr_->InputAt(index));
101 102
  }

103
  Register OutputRegister(size_t index = 0) const {
104 105
    return ToRegister(instr_->OutputAt(index));
  }
106

107 108 109
  Register TempRegister(size_t index) {
    return ToRegister(instr_->TempAt(index));
  }
110

111 112 113 114
  FloatRegister OutputFloatRegister() {
    return ToFloatRegister(instr_->Output());
  }

115 116 117 118
  DoubleRegister OutputDoubleRegister() {
    return ToDoubleRegister(instr_->Output());
  }

119 120 121 122
  DoubleRegister TempDoubleRegister(size_t index) {
    return ToDoubleRegister(instr_->TempAt(index));
  }

123 124 125 126
  Simd128Register OutputSimd128Register() {
    return ToSimd128Register(instr_->Output());
  }

127 128 129 130
  Simd128Register TempSimd128Register(size_t index) {
    return ToSimd128Register(instr_->TempAt(index));
  }

131 132 133 134 135 136
  // -- Conversions for operands -----------------------------------------------

  Label* ToLabel(InstructionOperand* op) {
    return gen_->GetLabel(ToRpoNumber(op));
  }

137
  RpoNumber ToRpoNumber(InstructionOperand* op) {
138 139
    return ToConstant(op).ToRpoNumber();
  }
140

141
  Register ToRegister(InstructionOperand* op) const {
142
    return LocationOperand::cast(op)->GetRegister();
143 144
  }

145 146 147 148
  FloatRegister ToFloatRegister(InstructionOperand* op) {
    return LocationOperand::cast(op)->GetFloatRegister();
  }

149
  DoubleRegister ToDoubleRegister(InstructionOperand* op) {
150
    return LocationOperand::cast(op)->GetDoubleRegister();
151 152
  }

153 154
  Simd128Register ToSimd128Register(InstructionOperand* op) {
    return LocationOperand::cast(op)->GetSimd128Register();
155 156
  }

157
  Constant ToConstant(InstructionOperand* op) const {
158
    if (op->IsImmediate()) {
159
      return gen_->instructions()->GetImmediate(ImmediateOperand::cast(op));
160
    }
161
    return gen_->instructions()->GetConstant(
162
        ConstantOperand::cast(op)->virtual_register());
163 164
  }

165 166 167
  double ToDouble(InstructionOperand* op) {
    return ToConstant(op).ToFloat64().value();
  }
168

169 170
  float ToFloat32(InstructionOperand* op) { return ToConstant(op).ToFloat32(); }

171 172 173 174
  ExternalReference ToExternalReference(InstructionOperand* op) {
    return ToConstant(op).ToExternalReference();
  }

175
  Handle<CodeT> ToCode(InstructionOperand* op) {
176
    return ToConstant(op).ToCode();
177 178
  }

179
  const Frame* frame() const { return gen_->frame(); }
180 181 182
  FrameAccessState* frame_access_state() const {
    return gen_->frame_access_state();
  }
183 184 185 186 187 188 189 190
  Isolate* isolate() const { return gen_->isolate(); }
  Linkage* linkage() const { return gen_->linkage(); }

 protected:
  CodeGenerator* gen_;
  Instruction* instr_;
};

191
// Deoptimization exit.
192 193
class DeoptimizationExit : public ZoneObject {
 public:
194
  explicit DeoptimizationExit(SourcePosition pos, BytecodeOffset bailout_id,
195
                              int translation_id, int pc_offset,
196 197
                              DeoptimizeKind kind, DeoptimizeReason reason,
                              NodeId node_id)
198 199 200 201 202 203 204
      : deoptimization_id_(kNoDeoptIndex),
        pos_(pos),
        bailout_id_(bailout_id),
        translation_id_(translation_id),
        pc_offset_(pc_offset),
        kind_(kind),
        reason_(reason),
205
        node_id_(node_id),
206
        immediate_args_(nullptr),
207 208 209 210 211 212 213 214 215 216 217 218
        emitted_(false) {}

  bool has_deoptimization_id() const {
    return deoptimization_id_ != kNoDeoptIndex;
  }
  int deoptimization_id() const {
    DCHECK(has_deoptimization_id());
    return deoptimization_id_;
  }
  void set_deoptimization_id(int deoptimization_id) {
    deoptimization_id_ = deoptimization_id;
  }
219
  SourcePosition pos() const { return pos_; }
220
  // The label for the deoptimization call.
221
  Label* label() { return &label_; }
222 223
  // The label after the deoptimization check, which will resume execution.
  Label* continue_label() { return &continue_label_; }
224
  BytecodeOffset bailout_id() const { return bailout_id_; }
225 226 227 228
  int translation_id() const { return translation_id_; }
  int pc_offset() const { return pc_offset_; }
  DeoptimizeKind kind() const { return kind_; }
  DeoptimizeReason reason() const { return reason_; }
229
  NodeId node_id() const { return node_id_; }
230 231 232 233 234 235
  const ZoneVector<ImmediateOperand*>* immediate_args() const {
    return immediate_args_;
  }
  void set_immediate_args(ZoneVector<ImmediateOperand*>* immediate_args) {
    immediate_args_ = immediate_args;
  }
236 237 238 239 240
  // Returns whether the deopt exit has already been emitted. Most deopt exits
  // are emitted contiguously at the end of the code, but unconditional deopt
  // exits (kArchDeoptimize) may be inlined where they are encountered.
  bool emitted() const { return emitted_; }
  void set_emitted() { emitted_ = true; }
241 242

 private:
243 244 245
  static const int kNoDeoptIndex = kMaxInt16 + 1;
  int deoptimization_id_;
  const SourcePosition pos_;
246
  Label label_;
247
  Label continue_label_;
248
  const BytecodeOffset bailout_id_;
249 250 251 252
  const int translation_id_;
  const int pc_offset_;
  const DeoptimizeKind kind_;
  const DeoptimizeReason reason_;
253
  const NodeId node_id_;
254
  ZoneVector<ImmediateOperand*>* immediate_args_;
255
  bool emitted_;
256
};
257

258 259 260 261 262 263 264 265 266 267
// Generator for out-of-line code that is emitted after the main code is done.
class OutOfLineCode : public ZoneObject {
 public:
  explicit OutOfLineCode(CodeGenerator* gen);
  virtual ~OutOfLineCode();

  virtual void Generate() = 0;

  Label* entry() { return &entry_; }
  Label* exit() { return &exit_; }
268
  const Frame* frame() const { return frame_; }
269
  TurboAssembler* tasm() { return tasm_; }
270 271 272 273 274
  OutOfLineCode* next() const { return next_; }

 private:
  Label entry_;
  Label exit_;
275
  const Frame* const frame_;
276
  TurboAssembler* const tasm_;
277 278 279
  OutOfLineCode* const next_;
};

280 281 282 283
}  // namespace compiler
}  // namespace internal
}  // namespace v8

284
#endif  // V8_COMPILER_BACKEND_CODE_GENERATOR_IMPL_H_