Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dart_calling_conventions.cc
Go to the documentation of this file.
1// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
7#include <array>
8
10#include "vm/object.h"
11
12namespace dart {
13
14namespace compiler {
15
16namespace {
17template <typename R, size_t N>
18class SimpleAllocator {
19 public:
20 explicit SimpleAllocator(const R (&regs)[N]) : regs_(regs) {
21 // C++ does not allow zero length arrays - so we use an array with a single
22 // kNoRegister element as a replacement.
23 if (N == 1 && regs_[0] == -1) {
24 next_ = N;
25 }
26 }
27
28 R Allocate() { return next_ < N ? regs_[next_++] : static_cast<R>(-1); }
29
30 std::pair<R, R> AllocatePair() {
31 if ((next_ + 2) <= N) {
32 const auto lo = Allocate();
33 const auto hi = Allocate();
34 return {lo, hi};
35 }
36 return {static_cast<R>(-1), static_cast<R>(-1)};
37 }
38
39 private:
40 const R (&regs_)[N];
41 size_t next_ = 0;
42};
43
44template <typename R, size_t N>
45SimpleAllocator(const R (&)[N]) -> SimpleAllocator<R, N>;
46
47} // namespace
48
50 Zone* zone,
51 const Function& target,
52 intptr_t argc,
53 std::function<Representation(intptr_t)> argument_rep,
54 bool should_assign_stack_locations,
55 ParameterInfoArray* parameter_info) {
56 SimpleAllocator cpu_allocator(DartCallingConvention::kCpuRegistersForArgs);
57 SimpleAllocator fpu_allocator(DartCallingConvention::kFpuRegistersForArgs);
58
59 if (parameter_info != nullptr) {
60 parameter_info->TruncateTo(0);
61 parameter_info->EnsureLength(argc, {});
62 }
63
64 const intptr_t max_arguments_in_registers =
65 !target.IsNull() ? target.MaxNumberOfParametersInRegisters(zone) : 0;
66
67 // First allocate all register parameters and compute the size of
68 // parameters on the stack.
69 intptr_t stack_parameters_size_in_words = 0;
70 for (intptr_t i = 0; i < argc; ++i) {
71 auto rep = argument_rep(i);
72
73 Location location;
74 if (i < max_arguments_in_registers) {
75 switch (rep) {
76 case kUnboxedInt64:
77#if defined(TARGET_ARCH_IS_32_BIT)
78 if (auto [lo_reg, hi_reg] = cpu_allocator.AllocatePair();
79 hi_reg != kNoRegister) {
82#else
83 if (auto reg = cpu_allocator.Allocate(); reg != kNoRegister) {
84 location = Location::RegisterLocation(reg);
85#endif
86 }
87 break;
88
89 case kUnboxedDouble:
90 if (auto reg = fpu_allocator.Allocate(); reg != kNoFpuRegister) {
91 location = Location::FpuRegisterLocation(reg);
92 }
93 break;
94
95 case kTagged:
96 if (auto reg = cpu_allocator.Allocate(); reg != kNoRegister) {
97 location = Location::RegisterLocation(reg);
98 }
99 break;
100
101 default:
102 UNREACHABLE();
103 break;
104 }
105 }
106
107 if (location.IsInvalid()) {
108 intptr_t size_in_words;
109 switch (rep) {
110 case kUnboxedInt64:
111 size_in_words = compiler::target::kIntSpillFactor;
112 break;
113
114 case kUnboxedDouble:
115 size_in_words = compiler::target::kDoubleSpillFactor;
116 break;
117
118 case kTagged:
119 size_in_words = 1;
120 break;
121
122 default:
123 UNREACHABLE();
124 break;
125 }
126 stack_parameters_size_in_words += size_in_words;
127 }
128
129 if (parameter_info != nullptr) {
130 (*parameter_info)[i] = {location, rep};
131 }
132 }
133
134 if (parameter_info == nullptr || !should_assign_stack_locations) {
135 return stack_parameters_size_in_words;
136 }
137
138 // Now that we allocated all register parameters, allocate all other
139 // parameters to the stack.
140 const intptr_t offset_to_last_parameter_slot_from_fp =
141 (compiler::target::frame_layout.param_end_from_fp + 1);
142 intptr_t offset_in_words_from_fp = offset_to_last_parameter_slot_from_fp;
143 for (intptr_t i = argc - 1; i >= 0; --i) {
144 auto& [location, representation] = (*parameter_info)[i];
145 if (!location.IsInvalid()) {
146 continue; // Already allocated to a register.
147 }
148
149 switch (representation) {
150 case kUnboxedInt64:
151 if (compiler::target::kIntSpillFactor == 1) {
152 location = Location::StackSlot(offset_in_words_from_fp, FPREG);
153 } else {
154 ASSERT(compiler::target::kIntSpillFactor == 2);
155 location = Location::Pair(
156 Location::StackSlot(offset_in_words_from_fp, FPREG),
157 Location::StackSlot(offset_in_words_from_fp + 1, FPREG));
158 }
159 offset_in_words_from_fp += compiler::target::kIntSpillFactor;
160 break;
161
162 case kUnboxedDouble:
163 location = Location::DoubleStackSlot(offset_in_words_from_fp, FPREG);
164 offset_in_words_from_fp += compiler::target::kDoubleSpillFactor;
165 break;
166
167 case kTagged:
168 location = Location::StackSlot(offset_in_words_from_fp, FPREG);
169 offset_in_words_from_fp += 1;
170 break;
171
172 default:
173 UNREACHABLE();
174 break;
175 }
176 }
177
179 (offset_in_words_from_fp - offset_to_last_parameter_slot_from_fp) ==
180 stack_parameters_size_in_words);
181
182 return stack_parameters_size_in_words;
183}
184
185} // namespace compiler
186
187} // namespace dart
#define UNREACHABLE()
Definition assert.h:248
#define RELEASE_ASSERT(cond)
Definition assert.h:327
void TruncateTo(intptr_t length)
void EnsureLength(intptr_t new_length, const T &default_value)
static Location StackSlot(intptr_t stack_index, Register base)
Definition locations.h:447
bool IsInvalid() const
Definition locations.h:289
static Location Pair(Location first, Location second)
Definition locations.cc:271
static Location FpuRegisterLocation(FpuRegister reg)
Definition locations.h:410
static Location DoubleStackSlot(intptr_t stack_index, Register base)
Definition locations.h:458
static Location RegisterLocation(Register reg)
Definition locations.h:398
#define ASSERT(E)
uint32_t * target
#define R(r)
intptr_t ComputeCallingConvention(Zone *zone, const Function &target, intptr_t argc, std::function< Representation(intptr_t)> argument_rep, bool should_assign_stack_locations, ParameterInfoArray *parameter_info)
const FpuRegister kNoFpuRegister
static void * Allocate(uword size, Zone *zone)
Definition allocation.cc:14
Representation
Definition locations.h:66
@ kNoRegister
const Register FPREG
static constexpr Register kCpuRegistersForArgs[]
static constexpr FpuRegister kFpuRegistersForArgs[]