Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
native_location.cc
Go to the documentation of this file.
1// Copyright (c) 2020, 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
8
9namespace dart {
10
11namespace compiler {
12
13namespace ffi {
14
15#if !defined(FFI_UNIT_TESTS)
17 switch (loc.kind()) {
22 return true;
23 default:
24 break;
25 }
26 if (loc.IsPairLocation()) {
27 return false;
28 }
29 return false;
30}
31
33 Location loc,
34 Representation rep) {
36
37 const NativeType& native_rep = NativeType::FromRepresentation(zone, rep);
38
39 switch (loc.kind()) {
41 return *new (zone)
42 NativeRegistersLocation(zone, native_rep, native_rep, loc.reg());
44 return *new (zone)
45 NativeFpuRegistersLocation(native_rep, native_rep, loc.fpu_reg());
47 return *new (zone)
48 NativeStackLocation(native_rep, native_rep, loc.base_reg(),
49 loc.stack_index() * compiler::target::kWordSize);
51 return *new (zone)
52 NativeStackLocation(native_rep, native_rep, loc.base_reg(),
53 loc.stack_index() * compiler::target::kWordSize);
54 default:
55 break;
56 }
57
59}
60
62 Location pair_loc,
63 Representation pair_rep,
64 intptr_t index) {
65 ASSERT(pair_loc.IsPairLocation());
66 ASSERT(index == 0 || index == 1);
67 const Representation rep = NativeType::FromRepresentation(zone, pair_rep)
68 .Split(zone, index)
70 const Location loc = pair_loc.AsPairLocation()->At(index);
71 return FromLocation(zone, loc, rep);
72}
73#endif
74
77 return static_cast<const NativeRegistersLocation&>(*this);
78}
79
82 return static_cast<const NativeFpuRegistersLocation&>(*this);
83}
84
86 ASSERT(IsStack());
87 return static_cast<const NativeStackLocation&>(*this);
88}
89
92 return static_cast<const MultipleNativeLocations&>(*this);
93}
94
97 return static_cast<const PointerToMemoryLocation&>(*this);
98}
99
101 ASSERT(IsBoth());
102 return static_cast<const BothNativeLocations&>(*this);
103}
104
105#if !defined(FFI_UNIT_TESTS)
108 switch (num_regs()) {
109 case 1:
110 return Location::RegisterLocation(regs_->At(0));
111 case 2:
113 Location::RegisterLocation(regs_->At(1)));
114 }
116}
117
120 if (payload_type().IsInt()) {
121 const intptr_t size = payload_type().SizeInBytes();
122 const intptr_t size_slots = size / compiler::target::kWordSize;
123 switch (size_slots) {
124 case 1:
125 return Location::StackSlot(offset_in_words(), base_register_);
126 case 2:
127 return Location::Pair(
128 Location::StackSlot(offset_in_words(), base_register_),
129 Location::StackSlot(offset_in_words() + 1, base_register_));
130 }
131 } else {
132 ASSERT(payload_type().IsFloat());
133 if (payload_type().AsPrimitive().representation() == kFloat) {
134 return Location::StackSlot(offset_in_words(), base_register_);
135 } else {
136 ASSERT(payload_type().AsPrimitive().representation() == kDouble);
137 return Location::DoubleStackSlot(offset_in_words(), base_register_);
138 }
139 }
141}
142#endif
143
145 intptr_t num_parts,
146 intptr_t index) const {
147 ASSERT(num_parts == 2);
148 ASSERT(num_regs() == num_parts);
149 return *new (zone) NativeRegistersLocation(
150 zone, payload_type().Split(zone, index),
151 container_type().Split(zone, index), reg_at(index));
152}
153
155 intptr_t num_parts,
156 intptr_t index) const {
157 const intptr_t size = payload_type().SizeInBytes();
158
159 if (payload_type().IsPrimitive()) {
160 ASSERT(num_parts == 2);
161 return *new (zone) NativeStackLocation(
162 payload_type().Split(zone, index), container_type().Split(zone, index),
163 base_register_, offset_in_bytes_ + size / num_parts * index);
164 } else {
165 const intptr_t size_rounded_up =
166 Utils::RoundUp(size, compiler::target::kWordSize);
167 ASSERT(size_rounded_up / compiler::target::kWordSize == num_parts);
168
169 // Blocks of compiler::target::kWordSize.
170 return *new (zone) NativeStackLocation(
171 *new (zone) NativePrimitiveType(
172 compiler::target::kWordSize == 8 ? kInt64 : kInt32),
173 *new (zone) NativePrimitiveType(
174 compiler::target::kWordSize == 8 ? kInt64 : kInt32),
175 base_register_, offset_in_bytes_ + compiler::target::kWordSize * index);
176 }
177}
178
180 intptr_t height = 0;
181 for (int i = 0; i < locations_.length(); i++) {
182 height = Utils::Maximum(height, locations_[i]->StackTopInBytes());
183 }
184 return height;
185}
186
191
196
197#if defined(TARGET_ARCH_ARM)
198const NativeLocation& NativeLocation::WidenToQFpuRegister(Zone* zone) const {
199 if (!IsFpuRegisters()) {
200 return *this;
201 }
202 const auto& fpu_loc = AsFpuRegisters();
203 switch (fpu_loc.fpu_reg_kind()) {
204 case kQuadFpuReg:
205 return *this;
206 case kDoubleFpuReg: {
207 return *new (zone) NativeFpuRegistersLocation(
208 payload_type_, container_type_, QRegisterOf(fpu_loc.fpu_d_reg()));
209 }
210 case kSingleFpuReg: {
211 return *new (zone) NativeFpuRegistersLocation(
212 payload_type_, container_type_, QRegisterOf(fpu_loc.fpu_s_reg()));
213 }
214 }
216}
217#endif // defined(TARGET_ARCH_ARM)
218
220 if (!other.IsRegisters()) {
221 return false;
222 }
223 const auto& other_regs = other.AsRegisters();
224 if (other_regs.num_regs() != num_regs()) {
225 return false;
226 }
227 for (intptr_t i = 0; i < num_regs(); i++) {
228 if (other_regs.reg_at(i) != reg_at(i)) {
229 return false;
230 }
231 }
232 return true;
233}
234
236 if (!other.IsFpuRegisters()) {
237 return false;
238 }
239 auto& other_fpu_reg = other.AsFpuRegisters();
240 if (other_fpu_reg.fpu_reg_kind() != fpu_reg_kind()) {
241 return false;
242 }
243 // We can only compare `fpu_reg_` if the kind is the same.
244 // Q5 is not the same register as (nor overlaps) D5.
245 return other_fpu_reg.fpu_reg_ == fpu_reg_;
246}
247
249 if (!other.IsStack()) {
250 return false;
251 }
252 const auto& other_stack = other.AsStack();
253 if (other_stack.base_register_ != base_register_) {
254 return false;
255 }
256 return other_stack.offset_in_bytes_ == offset_in_bytes_;
257}
258
260 if (!other.IsPointerToMemory()) {
261 return false;
262 }
263 const auto& other_pointer = other.AsPointerToMemory();
264 if (!other_pointer.pointer_location_.Equals(pointer_location_)) {
265 return false;
266 }
267 return other_pointer.payload_type().Equals(payload_type());
268}
269
270#if !defined(FFI_UNIT_TESTS)
275#endif
276
278 f->AddString(" ");
279 loc.container_type().PrintTo(f, /*multi_line=*/false, /*verbose=*/false);
280 if (!loc.container_type().Equals(loc.payload_type())) {
281 f->AddString("[");
282 loc.payload_type().PrintTo(f, /*multi_line=*/false, /*verbose=*/false);
283 f->AddString("]");
284 }
285}
286
288 f->AddString("I");
289 PrintRepresentations(f, *this);
290}
291
293 if (num_regs() == 1) {
294 f->Printf("%s", RegisterNames::RegisterAbiName(regs_->At(0)));
295 } else {
296 f->AddString("(");
297 for (intptr_t i = 0; i < num_regs(); i++) {
298 if (i != 0) {
299 f->Printf(", ");
300 }
301 f->Printf("%s", RegisterNames::RegisterAbiName(regs_->At(i)));
302 }
303 f->AddString(")");
304 }
305 PrintRepresentations(f, *this);
306}
307
309 switch (fpu_reg_kind()) {
310 case kQuadFpuReg:
311 f->Printf("%s", RegisterNames::FpuRegisterName(fpu_reg()));
312 break;
313#if defined(TARGET_ARCH_ARM)
314 case kDoubleFpuReg:
315 f->Printf("%s", RegisterNames::FpuDRegisterName(fpu_d_reg()));
316 break;
317 case kSingleFpuReg:
318 f->Printf("%s", RegisterNames::FpuSRegisterName(fpu_s_reg()));
319 break;
320#endif // defined(TARGET_ARCH_ARM)
321 default:
323 }
324
325 PrintRepresentations(f, *this);
326}
327
329 if (base_register_ != SPREG) {
330 f->Printf("S(%s)+%" Pd, RegisterNames::RegisterAbiName(base_register_),
331 offset_in_bytes_);
332 } else {
333 f->Printf("S+%" Pd, offset_in_bytes_);
334 }
335 PrintRepresentations(f, *this);
336}
337
338const char* NativeLocation::ToCString(Zone* zone) const {
339 ZoneTextBuffer textBuffer(zone);
340 PrintTo(&textBuffer);
341 return textBuffer.buffer();
342}
343
345 f->Printf("P(");
348 f->Printf(", ret:");
350 }
351 f->Printf(")");
352 PrintRepresentations(f, *this);
353}
354
356 f->Printf("M(");
357 for (intptr_t i = 0; i < locations_.length(); i++) {
358 if (i != 0) f->Printf(", ");
359 locations_[i]->PrintTo(f);
360 }
361 f->Printf(")");
362 PrintRepresentations(f, *this);
363}
364
366 f->Printf("B(");
367 location0_.PrintTo(f);
368 f->Printf(", ");
369 location1_.PrintTo(f);
370 f->Printf(")");
371}
372
373#if !defined(FFI_UNIT_TESTS)
374const char* NativeLocation::ToCString() const {
375 return ToCString(Thread::Current()->zone());
376}
377#endif
378
380 switch (kind) {
381 case kQuadFpuReg:
382 return 16;
383 case kDoubleFpuReg:
384 return 8;
385 case kSingleFpuReg:
386 return 4;
387 }
388 UNREACHABLE();
389}
390enum FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes) {
391 switch (size_in_bytes) {
392 case 16:
393 return kQuadFpuReg;
394 case 8:
395 return kDoubleFpuReg;
396 case 4:
397 return kSingleFpuReg;
398 }
399 UNREACHABLE();
400}
401
402#if defined(TARGET_ARCH_ARM)
403DRegister NativeFpuRegistersLocation::fpu_as_d_reg() const {
404 switch (fpu_reg_kind_) {
405 case kQuadFpuReg:
406 return EvenDRegisterOf(fpu_reg());
407 case kDoubleFpuReg:
408 return fpu_d_reg();
409 case kSingleFpuReg:
410 return DRegisterOf(fpu_s_reg());
411 }
413}
414
415SRegister NativeFpuRegistersLocation::fpu_as_s_reg() const {
416 switch (fpu_reg_kind_) {
417 case kQuadFpuReg:
419 case kDoubleFpuReg:
420 return EvenSRegisterOf(fpu_d_reg());
421 case kSingleFpuReg:
422 return fpu_s_reg();
423 }
425}
426
427bool NativeFpuRegistersLocation::IsLowestBits() const {
428 switch (fpu_reg_kind()) {
429 case kQuadFpuReg:
430 return true;
431 case kDoubleFpuReg: {
432 return fpu_d_reg() % 2 == 0;
433 }
434 case kSingleFpuReg: {
435 return fpu_s_reg() % 4 == 0;
436 }
437 }
439}
440#endif // defined(TARGET_ARCH_ARM)
441
442} // namespace ffi
443
444} // namespace compiler
445
446} // namespace dart
#define UNREACHABLE()
Definition assert.h:248
const T & At(intptr_t index) const
intptr_t length() const
char * buffer() const
Definition text_buffer.h:35
static Location StackSlot(intptr_t stack_index, Register base)
Definition locations.h:447
static Location Pair(Location first, Location second)
Definition locations.cc:271
Register reg() const
Definition locations.h:404
static Location DoubleStackSlot(intptr_t stack_index, Register base)
Definition locations.h:458
intptr_t stack_index() const
Definition locations.h:485
Kind kind() const
Definition locations.h:523
Register base_reg() const
Definition locations.h:480
static Location RegisterLocation(Register reg)
Definition locations.h:398
PairLocation * AsPairLocation() const
Definition locations.cc:280
bool IsPairLocation() const
Definition locations.h:316
FpuRegister fpu_reg() const
Definition locations.h:416
Location At(intptr_t i) const
Definition locations.h:618
static const char * FpuRegisterName(FpuRegister reg)
Definition constants.h:54
static const char * RegisterAbiName(Register reg)
Definition constants.h:50
static Thread * Current()
Definition thread.h:361
static constexpr T Maximum(T x, T y)
Definition utils.h:26
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition utils.h:105
virtual void PrintTo(BaseTextBuffer *f) const
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool Equals(const NativeLocation &other) const
virtual void PrintTo(BaseTextBuffer *f) const
NativeLocation & WidenTo8Bytes(Zone *zone) const
const MultipleNativeLocations & AsMultiple() const
const NativeType & container_type() const
virtual void PrintTo(BaseTextBuffer *f) const
const NativeRegistersLocation & AsRegisters() const
static bool LocationCanBeExpressed(Location loc, Representation rep)
const PointerToMemoryLocation & AsPointerToMemory() const
static NativeLocation & FromLocation(Zone *zone, Location loc, Representation rep)
const NativeStackLocation & AsStack() const
virtual NativeLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const =0
NativeLocation & WidenTo4Bytes(Zone *zone) const
static NativeLocation & FromPairLocation(Zone *zone, Location loc, Representation rep, intptr_t index)
const BothNativeLocations & AsBoth() const
const NativeFpuRegistersLocation & AsFpuRegisters() const
const NativeType & payload_type() const
virtual Representation AsRepresentation() const
virtual NativePrimitiveType & Split(Zone *zone, intptr_t part) const
virtual bool Equals(const NativeLocation &other) const
virtual NativeRegistersLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) const
virtual void PrintTo(BaseTextBuffer *f) const
virtual NativeStackLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) const
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool Equals(const NativeLocation &other) const
virtual void PrintTo(BaseTextBuffer *f, bool multi_line=false, bool verbose=true) const
virtual intptr_t SizeInBytes() const =0
static NativePrimitiveType & FromRepresentation(Zone *zone, Representation rep)
virtual NativeType & Split(Zone *zone, intptr_t index) const
virtual bool Equals(const NativeType &other) const
const NativeLocation & pointer_location() const
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool Equals(const NativeLocation &other) const
const NativeLocation & pointer_return_location() const
#define ASSERT(E)
intptr_t SizeFromFpuRegisterKind(enum FpuRegisterKind kind)
static void PrintRepresentations(BaseTextBuffer *f, const NativeLocation &loc)
compiler::Address NativeLocationToStackSlotAddress(const NativeStackLocation &loc)
enum FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes)
static DRegister EvenDRegisterOf(QRegister q)
Representation
Definition locations.h:66
static DRegister DRegisterOf(SRegister s)
static QRegister QRegisterOf(DRegister d)
const Register SPREG
static SRegister EvenSRegisterOf(DRegister d)
#define UNREACHABLE_THIS()
Definition native_type.h:25
#define Pd
Definition globals.h:408
int32_t height