v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
instruction-codes.h
Go to the documentation of this file.
1// Copyright 2014 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_INSTRUCTION_CODES_H_
6#define V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
7
8#include <iosfwd>
9
10#if V8_TARGET_ARCH_ARM
12#elif V8_TARGET_ARCH_ARM64
14#elif V8_TARGET_ARCH_IA32
16#elif V8_TARGET_ARCH_MIPS64
18#elif V8_TARGET_ARCH_LOONG64
20#elif V8_TARGET_ARCH_X64
22#elif V8_TARGET_ARCH_PPC64
24#elif V8_TARGET_ARCH_S390X
26#elif V8_TARGET_ARCH_RISCV32 || V8_TARGET_ARCH_RISCV64
28#else
29#define TARGET_ARCH_OPCODE_LIST(V)
30#define TARGET_ADDRESSING_MODE_LIST(V)
31#endif
32#include "src/base/bit-field.h"
35
36namespace v8 {
37namespace internal {
38namespace compiler {
39
40// Modes for ArchStoreWithWriteBarrier below.
48
50 WriteBarrierKind write_barrier_kind) {
51 switch (write_barrier_kind) {
62 case kNoWriteBarrier:
63 // Should not be passed as argument.
64 default:
65 break;
66 }
68}
69
70#define COMMON_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(V) \
71 V(AtomicExchangeInt8) \
72 V(AtomicExchangeUint8) \
73 V(AtomicExchangeInt16) \
74 V(AtomicExchangeUint16) \
75 V(AtomicExchangeWord32) \
76 V(AtomicCompareExchangeInt8) \
77 V(AtomicCompareExchangeUint8) \
78 V(AtomicCompareExchangeInt16) \
79 V(AtomicCompareExchangeUint16) \
80 V(AtomicCompareExchangeWord32) \
81 V(AtomicAddInt8) \
82 V(AtomicAddUint8) \
83 V(AtomicAddInt16) \
84 V(AtomicAddUint16) \
85 V(AtomicAddWord32) \
86 V(AtomicSubInt8) \
87 V(AtomicSubUint8) \
88 V(AtomicSubInt16) \
89 V(AtomicSubUint16) \
90 V(AtomicSubWord32) \
91 V(AtomicAndInt8) \
92 V(AtomicAndUint8) \
93 V(AtomicAndInt16) \
94 V(AtomicAndUint16) \
95 V(AtomicAndWord32) \
96 V(AtomicOrInt8) \
97 V(AtomicOrUint8) \
98 V(AtomicOrInt16) \
99 V(AtomicOrUint16) \
100 V(AtomicOrWord32) \
101 V(AtomicXorInt8) \
102 V(AtomicXorUint8) \
103 V(AtomicXorInt16) \
104 V(AtomicXorUint16) \
105 V(AtomicXorWord32) \
106 V(ArchStoreWithWriteBarrier) \
107 V(ArchAtomicStoreWithWriteBarrier) \
108 V(ArchStoreIndirectWithWriteBarrier) \
109 V(AtomicLoadInt8) \
110 V(AtomicLoadUint8) \
111 V(AtomicLoadInt16) \
112 V(AtomicLoadUint16) \
113 V(AtomicLoadWord32) \
114 V(AtomicStoreWord8) \
115 V(AtomicStoreWord16) \
116 V(AtomicStoreWord32)
117
118// Target-specific opcodes that specify which assembly sequence to emit.
119// Most opcodes specify a single instruction.
120#define COMMON_ARCH_OPCODE_LIST(V) \
121 /* Tail call opcodes are grouped together to make IsTailCall fast */ \
122 /* and Arch call opcodes are grouped together to make */ \
123 /* IsCallWithDescriptorFlags fast */ \
124 V(ArchTailCallCodeObject) \
125 V(ArchTailCallAddress) \
126 IF_WASM(V, ArchTailCallWasm) \
127 IF_WASM(V, ArchTailCallWasmIndirect) \
128 /* Update IsTailCall if further TailCall opcodes are added */ \
129 \
130 V(ArchCallCodeObject) \
131 V(ArchCallJSFunction) \
132 IF_WASM(V, ArchCallWasmFunction) \
133 IF_WASM(V, ArchCallWasmFunctionIndirect) \
134 V(ArchCallBuiltinPointer) \
135 /* Update IsCallWithDescriptorFlags if further Call opcodes are added */ \
136 \
137 V(ArchPrepareCallCFunction) \
138 V(ArchSaveCallerRegisters) \
139 V(ArchRestoreCallerRegisters) \
140 V(ArchCallCFunction) \
141 V(ArchCallCFunctionWithFrameState) \
142 V(ArchPrepareTailCall) \
143 V(ArchJmp) \
144 V(ArchBinarySearchSwitch) \
145 V(ArchTableSwitch) \
146 V(ArchNop) \
147 V(ArchAbortCSADcheck) \
148 V(ArchDebugBreak) \
149 V(ArchComment) \
150 V(ArchThrowTerminator) \
151 V(ArchDeoptimize) \
152 V(ArchRet) \
153 V(ArchFramePointer) \
154 IF_WASM(V, ArchStackPointer) \
155 IF_WASM(V, ArchSetStackPointer) \
156 V(ArchParentFramePointer) \
157 V(ArchTruncateDoubleToI) \
158 V(ArchStackSlot) \
159 V(ArchStackPointerGreaterThan) \
160 V(ArchStackCheckOffset) \
161 V(Ieee754Float64Acos) \
162 V(Ieee754Float64Acosh) \
163 V(Ieee754Float64Asin) \
164 V(Ieee754Float64Asinh) \
165 V(Ieee754Float64Atan) \
166 V(Ieee754Float64Atanh) \
167 V(Ieee754Float64Atan2) \
168 V(Ieee754Float64Cbrt) \
169 V(Ieee754Float64Cos) \
170 V(Ieee754Float64Cosh) \
171 V(Ieee754Float64Exp) \
172 V(Ieee754Float64Expm1) \
173 V(Ieee754Float64Log) \
174 V(Ieee754Float64Log1p) \
175 V(Ieee754Float64Log10) \
176 V(Ieee754Float64Log2) \
177 V(Ieee754Float64Pow) \
178 V(Ieee754Float64Sin) \
179 V(Ieee754Float64Sinh) \
180 V(Ieee754Float64Tan) \
181 V(Ieee754Float64Tanh) \
182 COMMON_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(V)
183
184#define ARCH_OPCODE_LIST(V) \
185 COMMON_ARCH_OPCODE_LIST(V) \
186 TARGET_ARCH_OPCODE_LIST(V)
187
189#define DECLARE_ARCH_OPCODE(Name) k##Name,
191#undef DECLARE_ARCH_OPCODE
192#define COUNT_ARCH_OPCODE(Name) +1
194#undef COUNT_ARCH_OPCODE
196
197V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
198 const ArchOpcode& ao);
199
200// Addressing modes represent the "shape" of inputs to an instruction.
201// Many instructions support multiple addressing modes. Addressing modes
202// are encoded into the InstructionCode of the instruction and tell the
203// code generator after register allocation which assembler method to call.
204#define ADDRESSING_MODE_LIST(V) \
205 V(None) \
206 TARGET_ADDRESSING_MODE_LIST(V)
207
208enum AddressingMode : uint8_t {
209#define DECLARE_ADDRESSING_MODE(Name) kMode_##Name,
211#undef DECLARE_ADDRESSING_MODE
212#define COUNT_ADDRESSING_MODE(Name) +1
214#undef COUNT_ADDRESSING_MODE
216
217V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
218 const AddressingMode& am);
219
220// The mode of the flags continuation (see below).
231
232V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
233 const FlagsMode& fm);
234
235// The condition of flags continuation (see below).
264
267
271
273
274V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
275 const FlagsCondition& fc);
276
282
284
285inline size_t AtomicWidthSize(AtomicWidth width) {
286 switch (width) {
288 return 4;
290 return 8;
291 }
292 UNREACHABLE();
293}
294
295static constexpr int kLazyDeoptOnThrowSentinel = -1;
296
297// The InstructionCode is an opaque, target-specific integer that encodes what
298// code to emit for an instruction in the code generator. It is not interesting
299// to the register allocator, as the inputs and flags on the instructions
300// specify everything of interest.
301using InstructionCode = uint32_t;
302
303// Helpers for encoding / decoding InstructionCode into the fields needed
304// for code generation. We encode the instruction, addressing mode, flags, and
305// other information into a single InstructionCode which is stored as part of
306// the instruction. Some fields in the layout of InstructionCode overlap as
307// follows:
308// ArchOpcodeField
309// AddressingModeField
310// FlagsModeField
311// FlagsConditionField
312// AtomicWidthField | RecordWriteModeField | LaneSizeField
313// AtomicMemoryOrderField | | VectorLengthField
314// AtomicStoreRecordWriteModeField | |
315// AccessModeField
316//
317// or,
318//
319// ArchOpcodeField
320// AddressingModeField
321// FlagsModeField
322// FlagsConditionField
323// DeoptImmedArgsCountField | ParamField | MiscField
324// DeoptFrameStateOffsetField | FPParamField |
325//
326// Notably, AccessModeField can follow any of several sequences of fields.
327
330 "All opcodes must fit in the 9-bit ArchOpcodeField.");
332static_assert(
334 "All addressing modes must fit in the 5-bit AddressingModeField.");
337
338// AtomicWidthField is used for the various Atomic opcodes. Only used on 64bit
339// architectures. All atomic instructions on 32bit architectures are assumed to
340// be 32bit wide.
342// AtomicMemoryOrderField is used for the various Atomic opcodes. This field is
343// not used on all architectures. It is used on architectures where the codegen
344// for kSeqCst and kAcqRel differ only by emitting fences.
348
349// Write modes for writes with barrier.
351
352// LaneSizeField and AccessModeField are helper types to encode/decode a lane
353// size, an access mode, or both inside the overlapping MiscField.
354#ifdef V8_TARGET_ARCH_X64
355enum LaneSize { kL8 = 0, kL16 = 1, kL32 = 2, kL64 = 3 };
356enum VectorLength { kV128 = 0, kV256 = 1, kV512 = 3 };
358using VectorLengthField = LaneSizeField::Next<VectorLength, 2>;
359#else
361#endif // V8_TARGET_ARCH_X64
362
363// Denotes whether the instruction needs to emit an accompanying landing pad for
364// the trap handler.
367
368// Since AccessModeField is defined in terms of atomics, this assert ensures it
369// does not overlap with other fields it is used with.
372#ifdef V8_TARGET_ARCH_X64
374 VectorLengthField::kLastUsedBit);
375#else
378#endif
379
380// TODO(turbofan): {HasMemoryAccessMode} is currently only used to guard
381// decoding (in CodeGenerator and InstructionScheduler). Encoding (in
382// InstructionSelector) is not yet guarded. There are in fact instructions for
383// which InstructionSelector does set a MemoryAccessMode but CodeGenerator
384// doesn't care to consume it (e.g. kArm64LdrDecompressTaggedSigned). This is
385// scary. {HasMemoryAccessMode} does not include these instructions, so they can
386// be easily found by guarding encoding.
387inline bool HasMemoryAccessMode(ArchOpcode opcode) {
388#if defined(TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST)
389 switch (opcode) {
390#define CASE(Name) \
391 case k##Name: \
392 return true;
395#undef CASE
396 default:
397 return false;
398 }
399#else
400 return false;
401#endif
402}
403
406
407// ParamField and FPParamField represent the general purpose and floating point
408// parameter counts of a direct call into C and are given 5 bits each, which
409// allow storing a number up to the current maximum parameter count, which is 20
410// (see kMaxCParameters defined in macro-assembler.h).
413
414// {MiscField} is used for a variety of things, depending on the opcode.
415// TODO(turbofan): There should be an abstraction that ensures safe encoding and
416// decoding. {HasMemoryAccessMode} and its uses are a small step in that
417// direction.
419
420// This static assertion serves as an early warning if we are about to exhaust
421// the available opcode space. If we are about to exhaust it, we should start
422// looking into options to compress some opcodes (see
423// https://crbug.com/v8/12093) before we fully run out of available opcodes.
424// Otherwise we risk being unable to land an important security fix or merge
425// back fixes that add new opcodes.
426// It is OK to temporarily reduce the required slack if we have a tracking bug
427// to reduce the number of used opcodes again.
428static_assert(ArchOpcodeField::kMax - kLastArchOpcode >= 16,
429 "We are running close to the number of available opcodes.");
430
431} // namespace compiler
432} // namespace internal
433} // namespace v8
434
435#endif // V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
static constexpr U kMax
Definition bit-field.h:44
static constexpr int kLastUsedBit
Definition bit-field.h:42
BitField< T2, kShift+kSize, size2, U > Next
Definition bit-field.h:47
static constexpr bool is_valid(T value)
Definition bit-field.h:50
#define TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(V)
#define COUNT_ARCH_OPCODE(Name)
#define COUNT_ADDRESSING_MODE(Name)
#define ARCH_OPCODE_LIST(V)
#define DECLARE_ADDRESSING_MODE(Name)
#define DECLARE_ARCH_OPCODE(Name)
#define COMMON_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(V)
#define ADDRESSING_MODE_LIST(V)
bool HasMemoryAccessMode(ArchOpcode opcode)
FlagsConditionField::Next< int, 8 > LaneSizeField
size_t AtomicWidthSize(AtomicWidth width)
FlagsCondition CommuteFlagsCondition(FlagsCondition condition)
RecordWriteMode WriteBarrierKindToRecordWriteMode(WriteBarrierKind write_barrier_kind)
FlagsCondition NegateFlagsCondition(FlagsCondition condition)
static constexpr int kLazyDeoptOnThrowSentinel
static constexpr FlagsCondition kStackPointerGreaterThanCondition
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
#define V8_EXPORT_PRIVATE
Definition macros.h:460