Flutter Engine
The Flutter Engine
native_location.h
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
5#ifndef RUNTIME_VM_COMPILER_FFI_NATIVE_LOCATION_H_
6#define RUNTIME_VM_COMPILER_FFI_NATIVE_LOCATION_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#include "platform/assert.h"
15#include "vm/constants.h"
16#include "vm/growable_array.h"
17
18#if !defined(FFI_UNIT_TESTS)
20#endif
21
22namespace dart {
23
24class BaseTextBuffer;
25
26namespace compiler {
27
28namespace ffi {
29
30class NativeRegistersLocation;
31class NativeFpuRegistersLocation;
32class NativeStackLocation;
33class MultipleNativeLocations;
34class PointerToMemoryLocation;
35class BothNativeLocations;
36
37// NativeLocation objects are used in the FFI to describe argument and return
38// value locations in all native ABIs that the FFI supports.
39//
40// NativeLocations contain two NativeTypes.
41// * The payload type.
42// * The container type, equal to or larger than the payload. If the
43// container is larger than the payload, the upper bits are defined by sign
44// or zero extension.
45// Container type is also used to denote an integer container when floating
46// point values are passed in integer registers.
47//
48// NativeLocations can express things that dart::Locations cannot express:
49// * Multiple consecutive registers.
50// * Multiple sizes of FPU registers (e.g. S, D, and Q on Arm32).
51// * Arbitrary byte-size stack locations, at byte-size offsets.
52// (The Location class uses word-size offsets.)
53// * Pointers to a memory location.
54// * Split between multiple registers and stack.
55//
56// NativeLocations cannot express the following dart::Locations:
57// * No PairLocations. Instead, NativeRegistersLocations can have multiple
58// registers, and NativeStackLocations can have arbitrary types.
59// * No ConstantLocations.
60//
61// NativeLocation does not satisfy the invariant of Location: bitwise
62// inequality cannot be used to determine disjointness.
64 public:
65#if !defined(FFI_UNIT_TESTS)
67 static NativeLocation& FromLocation(Zone* zone,
68 Location loc,
69 Representation rep);
71 Location loc,
73 intptr_t index);
74#endif
75
76 // The type of the data at this location.
77 const NativeType& payload_type() const { return payload_type_; }
78
79 // The location container size, possibly larger than data.
80 //
81 // If the container is larger than the data, the remaining bits are _not_
82 // undefined. For example a uint8 inside a uint32 has the upper 24 bits set
83 // to 0. Effectively allowing the value to be read as uint8, uint16 and
84 // uint32.
85 const NativeType& container_type() const { return container_type_; }
86
88 Zone* zone,
89 const NativeType& new_payload_type,
90 const NativeType& new_container_type) const = 0;
91
92#if defined(TARGET_ARCH_ARM)
93 const NativeLocation& WidenToQFpuRegister(Zone* zone) const;
94#endif // defined(TARGET_ARCH_ARM)
95
96 NativeLocation& WidenTo4Bytes(Zone* zone) const;
97 NativeLocation& WidenTo8Bytes(Zone* zone) const;
98
99 virtual bool IsRegisters() const { return false; }
100 virtual bool IsFpuRegisters() const { return false; }
101 virtual bool IsStack() const { return false; }
102 virtual bool IsMultiple() const { return false; }
103 virtual bool IsPointerToMemory() const { return false; }
104 virtual bool IsBoth() const { return false; }
105
106 virtual bool IsExpressibleAsLocation() const { return false; }
107#if !defined(FFI_UNIT_TESTS)
108 virtual Location AsLocation() const {
111 }
112#endif
113
114 virtual void PrintTo(BaseTextBuffer* f) const;
115 const char* ToCString(Zone* zone) const;
116#if !defined(FFI_UNIT_TESTS)
117 const char* ToCString() const;
118#endif
119
122 const NativeStackLocation& AsStack() const;
123 const MultipleNativeLocations& AsMultiple() const;
125 const BothNativeLocations& AsBoth() const;
126
127 // Retrieve one part from this location when it is split into multiple parts.
128 virtual NativeLocation& Split(Zone* zone,
129 intptr_t num_parts,
130 intptr_t index) const {
132 }
133
134 // Return the top of the stack in bytes. Recurses over its constituents when
135 // MultipleNativeLocations.
136 virtual intptr_t StackTopInBytes() const { return 0; }
137
138 // Equality of location, ignores the payload and container native types.
139 virtual bool Equals(const NativeLocation& other) const { UNREACHABLE_THIS(); }
140
141 virtual ~NativeLocation() {}
142
143 protected:
146 : payload_type_(payload_type), container_type_(container_type) {}
147
148 private:
149 const NativeType& payload_type_;
150 // The location container size, possibly larger than data.
151 //
152 // If the container is larger than the data, the remaining bits are _not_
153 // undefined. For example a uint8 inside a uint32 has the upper 24 bits set
154 // to 0. Effectively allowing the value to be read as uint8, uint16 and
155 // uint32.
156 const NativeType& container_type_;
157};
158
160 public:
164 : NativeLocation(payload_type, container_type), regs_(registers) {}
168 Register reg)
170 regs_ = new (zone) ZoneGrowableArray<Register>(zone, 1);
171 regs_->Add(reg);
172 }
176 Register register1,
177 Register register2)
179 regs_ = new (zone) ZoneGrowableArray<Register>(zone, 2);
180 regs_->Add(register1);
181 regs_->Add(register2);
182 }
184
186 Zone* zone,
187 const NativeType& new_payload_type,
188 const NativeType& new_container_type) const {
189 return *new (zone)
190 NativeRegistersLocation(new_payload_type, new_container_type, regs_);
191 }
192
193 virtual bool IsRegisters() const { return true; }
194 virtual bool IsExpressibleAsLocation() const {
195 return num_regs() == 1 || num_regs() == 2;
196 }
197#if !defined(FFI_UNIT_TESTS)
198 virtual Location AsLocation() const;
199#endif
200 intptr_t num_regs() const { return regs_->length(); }
201 Register reg_at(intptr_t index) const { return regs_->At(index); }
202
203 virtual NativeRegistersLocation& Split(Zone* zone,
204 intptr_t num_parts,
205 intptr_t index) const;
206
207 virtual void PrintTo(BaseTextBuffer* f) const;
208
209 virtual bool Equals(const NativeLocation& other) const;
210
211 private:
213
214 DISALLOW_COPY_AND_ASSIGN(NativeRegistersLocation);
215};
216
218 kQuadFpuReg, // 16 bytes
219 kDoubleFpuReg, // 8 bytes, a double
220 kSingleFpuReg // 4 bytes, a float
222
224FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes);
225
227 public:
231 intptr_t fpu_register)
233 fpu_reg_kind_(fpu_reg_kind),
234 fpu_reg_(fpu_register) {}
237 FpuRegister fpu_register)
239 fpu_reg_kind_(kQuadFpuReg),
240 fpu_reg_(fpu_register) {}
241#if defined(TARGET_ARCH_ARM)
244 DRegister fpu_register)
246 fpu_reg_kind_(kDoubleFpuReg),
247 fpu_reg_(fpu_register) {}
249 const NativeType& container_type,
250 SRegister fpu_register)
252 fpu_reg_kind_(kSingleFpuReg),
253 fpu_reg_(fpu_register) {}
254#endif // defined(TARGET_ARCH_ARM)
256
258 Zone* zone,
259 const NativeType& new_payload_type,
260 const NativeType& new_container_type) const {
261 return *new (zone) NativeFpuRegistersLocation(
262 new_payload_type, new_container_type, fpu_reg_kind_, fpu_reg_);
263 }
264 virtual bool IsFpuRegisters() const { return true; }
265 virtual bool IsExpressibleAsLocation() const {
266 return fpu_reg_kind_ == kQuadFpuReg;
267 }
268#if !defined(FFI_UNIT_TESTS)
269 virtual Location AsLocation() const {
272 }
273#endif
274 FpuRegisterKind fpu_reg_kind() const { return fpu_reg_kind_; }
276 ASSERT(fpu_reg_kind_ == kQuadFpuReg);
277 return static_cast<FpuRegister>(fpu_reg_);
278 }
279#if defined(TARGET_ARCH_ARM)
280 DRegister fpu_d_reg() const {
281 ASSERT(fpu_reg_kind_ == kDoubleFpuReg);
282 return static_cast<DRegister>(fpu_reg_);
283 }
284 SRegister fpu_s_reg() const {
285 ASSERT(fpu_reg_kind_ == kSingleFpuReg);
286 return static_cast<SRegister>(fpu_reg_);
287 }
288 DRegister fpu_as_d_reg() const;
289 SRegister fpu_as_s_reg() const;
290
291 bool IsLowestBits() const;
292#endif // defined(TARGET_ARCH_ARM)
293
294 virtual void PrintTo(BaseTextBuffer* f) const;
295
296 virtual bool Equals(const NativeLocation& other) const;
297
298 private:
299 FpuRegisterKind fpu_reg_kind_;
300 intptr_t fpu_reg_;
301 DISALLOW_COPY_AND_ASSIGN(NativeFpuRegistersLocation);
302};
303
305 public:
309 intptr_t offset_in_bytes)
311 base_register_(base_register),
312 offset_in_bytes_(offset_in_bytes) {}
314
316 Zone* zone,
317 const NativeType& new_payload_type,
318 const NativeType& new_container_type) const {
319 return *new (zone) NativeStackLocation(new_payload_type, new_container_type,
320 base_register_, offset_in_bytes_);
321 }
322
323 virtual bool IsStack() const { return true; }
324 virtual bool IsExpressibleAsLocation() const {
325 const intptr_t size = payload_type().SizeInBytes();
326 const intptr_t size_slots = size / compiler::target::kWordSize;
327 return offset_in_bytes_ % compiler::target::kWordSize == 0 &&
329 (size_slots == 1 || size_slots == 2);
330 }
331
332#if !defined(FFI_UNIT_TESTS)
333 virtual Location AsLocation() const;
334
335 // ConstantInstr expects DoubleStackSlot for doubles, even on 64-bit systems.
336 //
337 // So this return a wrong-sized Location on purpose.
340 return Location::DoubleStackSlot(offset_in_words(), base_register_);
341 }
342#endif
343
344 virtual NativeStackLocation& Split(Zone* zone,
345 intptr_t num_parts,
346 intptr_t index) const;
347
348 virtual intptr_t StackTopInBytes() const {
350 }
351
352 virtual void PrintTo(BaseTextBuffer* f) const;
353
354 virtual bool Equals(const NativeLocation& other) const;
355
356 Register base_register() const { return base_register_; }
357 intptr_t offset_in_bytes() const { return offset_in_bytes_; }
358
359 private:
360 intptr_t offset_in_words() const {
361 ASSERT(offset_in_bytes_ % compiler::target::kWordSize == 0);
362 return offset_in_bytes_ / compiler::target::kWordSize;
363 }
364
365 Register base_register_;
366 intptr_t offset_in_bytes_;
367
368 DISALLOW_COPY_AND_ASSIGN(NativeStackLocation);
369};
370
371// The location of a pointer pointing to a compound.
372//
373// For arguments a pointer to a copy of an object. The backing copy of the
374// object typically resides on the stack.
375//
376// For return values a pointer to empty space that should hold the object. This
377// space also typically resides on the stack.
379 public:
381 const NativeCompoundType& object_pointed_to)
382 : NativeLocation(object_pointed_to, object_pointed_to),
383 pointer_location_(pointer_location),
384 pointer_return_location_(pointer_location) {
386 }
389 const NativeCompoundType& object_pointed_to)
390 : NativeLocation(object_pointed_to, object_pointed_to),
391 pointer_location_(pointer_location),
392 pointer_return_location_(pointer_return_location) {
394 }
395
397
398 virtual bool IsPointerToMemory() const { return true; }
399
400 virtual void PrintTo(BaseTextBuffer* f) const;
401
402 virtual bool Equals(const NativeLocation& other) const;
403
405 Zone* zone,
406 const NativeType& new_payload_type,
407 const NativeType& new_container_type) const {
409 }
410
411 virtual intptr_t StackTopInBytes() const {
413 }
414
415 // The location where the pointer is passed to the function.
416 const NativeLocation& pointer_location() const { return pointer_location_; }
417
418 // The location where the pointer is returned from the function.
420 return pointer_return_location_;
421 }
422
423 private:
424 const NativeLocation& pointer_location_;
425 // The return location is only in use for return values, not for arguments.
426 const NativeLocation& pointer_return_location_;
427
428 DISALLOW_COPY_AND_ASSIGN(PointerToMemoryLocation);
429};
430
432
433// A struct broken up over multiple native locations.
435 public:
440
441 virtual bool IsMultiple() const { return true; }
442
443 virtual void PrintTo(BaseTextBuffer* f) const;
444
446 Zone* zone,
447 const NativeType& new_payload_type,
448 const NativeType& new_container_type) const {
450 }
451
452 virtual intptr_t StackTopInBytes() const;
453
454 const NativeLocations& locations() const { return locations_; }
455
456 private:
457 const NativeLocations& locations_;
458 DISALLOW_COPY_AND_ASSIGN(MultipleNativeLocations);
459};
460
461// The location of a value that is in two locations.
462//
463// Should only happen on win_x64 with variadic arguments.
465 public:
467 const NativeLocation& location1)
468 : NativeLocation(location0.payload_type(), location0.container_type()),
469 location0_(location0),
470 location1_(location1) {}
472
473 virtual bool IsBoth() const { return true; }
474
475 virtual void PrintTo(BaseTextBuffer* f) const;
476
478 Zone* zone,
479 const NativeType& new_payload_type,
480 const NativeType& new_container_type) const {
482 }
483
484 virtual intptr_t StackTopInBytes() const {
485 // Only used with registers.
486 return 0;
487 }
488
489 const NativeLocation& location(intptr_t index) const {
490 ASSERT(index == 0 || index == 1);
491 if (index == 0) {
492 return location0_;
493 }
494 return location1_;
495 }
496
497 private:
498 const NativeLocation& location0_;
499 const NativeLocation& location1_;
500 DISALLOW_COPY_AND_ASSIGN(BothNativeLocations);
501};
502
503#if !defined(FFI_UNIT_TESTS)
504// Return a memory operand for stack slot locations.
506 const NativeStackLocation& loc);
507#endif
508
509} // namespace ffi
510
511} // namespace compiler
512
513} // namespace dart
514
515#endif // RUNTIME_VM_COMPILER_FFI_NATIVE_LOCATION_H_
void Add(const T &value)
const T & At(intptr_t index) const
intptr_t length() const
static Location FpuRegisterLocation(FpuRegister reg)
Definition: locations.h:410
static Location DoubleStackSlot(intptr_t stack_index, Register base)
Definition: locations.h:458
BothNativeLocations(const NativeLocation &location0, const NativeLocation &location1)
virtual intptr_t StackTopInBytes() const
const NativeLocation & location(intptr_t index) const
virtual NativeLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const
virtual void PrintTo(BaseTextBuffer *f) const
const NativeLocations & locations() const
virtual NativeLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const
virtual void PrintTo(BaseTextBuffer *f) const
MultipleNativeLocations(const NativeCompoundType &payload_type, const NativeLocations &locations)
virtual NativeFpuRegistersLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const
NativeFpuRegistersLocation(const NativeType &payload_type, const NativeType &container_type, FpuRegisterKind fpu_reg_kind, intptr_t fpu_register)
virtual bool Equals(const NativeLocation &other) const
virtual void PrintTo(BaseTextBuffer *f) const
NativeFpuRegistersLocation(const NativeType &payload_type, const NativeType &container_type, FpuRegister fpu_register)
virtual bool IsPointerToMemory() const
NativeLocation & WidenTo8Bytes(Zone *zone) const
const MultipleNativeLocations & AsMultiple() const
virtual bool IsExpressibleAsLocation() const
virtual intptr_t StackTopInBytes() const
virtual Location AsLocation() 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
NativeLocation(const NativeType &payload_type, const NativeType &container_type)
virtual NativeLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) 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
virtual bool Equals(const NativeLocation &other) const
const NativeFpuRegistersLocation & AsFpuRegisters() const
const NativeType & payload_type() const
NativeRegistersLocation(const NativeType &payload_type, const NativeType &container_type, ZoneGrowableArray< Register > *registers)
virtual bool Equals(const NativeLocation &other) const
NativeRegistersLocation(Zone *zone, const NativeType &payload_type, const NativeType &container_type, Register register1, Register register2)
virtual NativeRegistersLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) const
Register reg_at(intptr_t index) const
virtual void PrintTo(BaseTextBuffer *f) const
NativeRegistersLocation(Zone *zone, const NativeType &payload_type, const NativeType &container_type, Register reg)
virtual NativeRegistersLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const
virtual NativeStackLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) const
virtual intptr_t StackTopInBytes() const
NativeStackLocation(const NativeType &payload_type, const NativeType &container_type, Register base_register, intptr_t offset_in_bytes)
virtual void PrintTo(BaseTextBuffer *f) const
virtual NativeStackLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const
virtual bool Equals(const NativeLocation &other) const
virtual intptr_t SizeInBytes() const =0
PointerToMemoryLocation(const NativeLocation &pointer_location, const NativeLocation &pointer_return_location, const NativeCompoundType &object_pointed_to)
const NativeLocation & pointer_location() const
PointerToMemoryLocation(const NativeLocation &pointer_location, const NativeCompoundType &object_pointed_to)
virtual NativeLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) 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)
compiler::Address NativeLocationToStackSlotAddress(const NativeStackLocation &loc)
enum FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes)
ZoneGrowableArray< const NativeLocation * > NativeLocations
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
Definition: dart_vm.cc:33
Representation
Definition: locations.h:66
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
#define UNREACHABLE_THIS()
Definition: native_type.h:25