summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/codegen/linkage-location.h
blob: 662a8f8922f167ca296aba7af1438a1221988c02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Copyright 2023 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.

#ifndef V8_CODEGEN_LINKAGE_LOCATION_H_
#define V8_CODEGEN_LINKAGE_LOCATION_H_

#include "src/base/bit-field.h"
#include "src/codegen/machine-type.h"
#include "src/execution/frame-constants.h"

#if !defined(__clang__) && defined(_M_ARM64)
// _M_ARM64 is an MSVC-specific macro that clang-cl emulates.
#define NO_INLINE_FOR_ARM64_MSVC __declspec(noinline)
#else
#define NO_INLINE_FOR_ARM64_MSVC
#endif

namespace v8 {
namespace internal {
template <typename T>
class Signature;

// Describes the location for a parameter or a return value to a call.
class LinkageLocation {
 public:
  bool operator==(const LinkageLocation& other) const {
    return bit_field_ == other.bit_field_ &&
           machine_type_ == other.machine_type_;
  }

  bool operator!=(const LinkageLocation& other) const {
    return !(*this == other);
  }

  static bool IsSameLocation(const LinkageLocation& a,
                             const LinkageLocation& b) {
    // Different MachineTypes may end up at the same physical location. With the
    // sub-type check we make sure that types like {AnyTagged} and
    // {TaggedPointer} which would end up with the same physical location are
    // considered equal here.
    return (a.bit_field_ == b.bit_field_) &&
           (IsSubtype(a.machine_type_.representation(),
                      b.machine_type_.representation()) ||
            IsSubtype(b.machine_type_.representation(),
                      a.machine_type_.representation()));
  }

  static LinkageLocation ForNullRegister(
      int32_t reg, MachineType type = MachineType::None()) {
    return LinkageLocation(REGISTER, reg, type);
  }

  static LinkageLocation ForAnyRegister(
      MachineType type = MachineType::None()) {
    return LinkageLocation(REGISTER, ANY_REGISTER, type);
  }

  static LinkageLocation ForRegister(int32_t reg,
                                     MachineType type = MachineType::None()) {
    DCHECK_LE(0, reg);
    return LinkageLocation(REGISTER, reg, type);
  }

  static LinkageLocation ForCallerFrameSlot(int32_t slot, MachineType type) {
    DCHECK_GT(0, slot);
    return LinkageLocation(STACK_SLOT, slot, type);
  }

  static LinkageLocation ForCalleeFrameSlot(int32_t slot, MachineType type) {
    // TODO(titzer): bailout instead of crashing here.
    DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT);
    return LinkageLocation(STACK_SLOT, slot, type);
  }

  // TODO(ahaas): Extract these TurboFan-specific functions from the
  // LinkageLocation.
  static LinkageLocation ForSavedCallerReturnAddress() {
    return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
                               StandardFrameConstants::kCallerPCOffset) /
                                  kSystemPointerSize,
                              MachineType::Pointer());
  }

  static LinkageLocation ForSavedCallerFramePtr() {
    return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
                               StandardFrameConstants::kCallerFPOffset) /
                                  kSystemPointerSize,
                              MachineType::Pointer());
  }

  static LinkageLocation ForSavedCallerConstantPool() {
    DCHECK(V8_EMBEDDED_CONSTANT_POOL_BOOL);
    return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
                               StandardFrameConstants::kConstantPoolOffset) /
                                  kSystemPointerSize,
                              MachineType::AnyTagged());
  }

  static LinkageLocation ForSavedCallerFunction() {
    return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset -
                               StandardFrameConstants::kFunctionOffset) /
                                  kSystemPointerSize,
                              MachineType::AnyTagged());
  }

  static LinkageLocation ConvertToTailCallerLocation(
      LinkageLocation caller_location, int stack_param_delta) {
    if (!caller_location.IsRegister()) {
      return LinkageLocation(STACK_SLOT,
                             caller_location.GetLocation() + stack_param_delta,
                             caller_location.GetType());
    }
    return caller_location;
  }

  MachineType GetType() const { return machine_type_; }

  int GetSizeInPointers() const {
    return ElementSizeInPointers(GetType().representation());
  }

  int32_t GetLocation() const {
    // We can't use LocationField::decode here because it doesn't work for
    // negative values!
    return static_cast<int32_t>(bit_field_ & LocationField::kMask) >>
           LocationField::kShift;
  }

  bool IsNullRegister() const {
    return IsRegister() && GetLocation() < ANY_REGISTER;
  }
  NO_INLINE_FOR_ARM64_MSVC bool IsRegister() const {
    return TypeField::decode(bit_field_) == REGISTER;
  }
  bool IsAnyRegister() const {
    return IsRegister() && GetLocation() == ANY_REGISTER;
  }
  bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; }
  bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; }

  int32_t AsRegister() const {
    DCHECK(IsRegister());
    return GetLocation();
  }
  int32_t AsCallerFrameSlot() const {
    DCHECK(IsCallerFrameSlot());
    return GetLocation();
  }
  int32_t AsCalleeFrameSlot() const {
    DCHECK(IsCalleeFrameSlot());
    return GetLocation();
  }

 private:
  enum LocationType { REGISTER, STACK_SLOT };

  using TypeField = base::BitField<LocationType, 0, 1>;
  using LocationField = TypeField::Next<int32_t, 31>;

  static constexpr int32_t ANY_REGISTER = -1;
  static constexpr int32_t MAX_STACK_SLOT = 32767;

  LinkageLocation(LocationType type, int32_t location,
                  MachineType machine_type) {
    bit_field_ = TypeField::encode(type) |
                 // {location} can be -1 (ANY_REGISTER).
                 ((static_cast<uint32_t>(location) << LocationField::kShift) &
                  LocationField::kMask);
    machine_type_ = machine_type;
  }

  int32_t bit_field_;
  MachineType machine_type_;
};

using LocationSignature = Signature<LinkageLocation>;

}  // namespace internal
}  // namespace v8
#undef NO_INLINE_FOR_ARM64_MSVC

#endif  // V8_CODEGEN_LINKAGE_LOCATION_H_