Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | Protected Member Functions | List of all members
dart::compiler::ffi::CallMarshaller Class Reference

#include <marshaller.h>

Inheritance diagram for dart::compiler::ffi::CallMarshaller:
dart::compiler::ffi::BaseMarshaller dart::ZoneAllocated

Public Member Functions

 CallMarshaller (Zone *zone, const Function &dart_signature, intptr_t dart_signature_params_start_at, const FunctionType &c_signature, const NativeCallingConvention &native_calling_convention)
 
virtual intptr_t NumDefinitions (intptr_t arg_index) const
 
virtual intptr_t NumReturnDefinitions () const
 
virtual Representation RepInFfiCall (intptr_t def_index_global) const
 
dart::Location LocInFfiCall (intptr_t def_index_global) const
 
bool ReturnsCompound () const
 
intptr_t CompoundReturnSizeInBytes () const
 
intptr_t PassByPointerStackOffset (intptr_t arg_index) const
 
intptr_t RequiredStackSpaceInBytes () const
 
- Public Member Functions inherited from dart::compiler::ffi::BaseMarshaller
intptr_t num_args () const
 
intptr_t NumArgumentDefinitions () const
 
virtual intptr_t NumDefinitions (intptr_t arg_index) const
 
virtual intptr_t NumReturnDefinitions () const =0
 
bool ArgumentIndexIsReturn (intptr_t arg_index) const
 
bool DefinitionIndexIsReturn (intptr_t def_index_global) const
 
intptr_t ArgumentIndex (intptr_t def_index_global) const
 
intptr_t FirstDefinitionIndex (intptr_t arg_index) const
 
intptr_t DefinitionInArgument (intptr_t def_index_global, intptr_t arg_index) const
 
intptr_t DefinitionIndex (intptr_t def_index_in_arg, intptr_t arg_index) const
 
const NativeLocationLocation (intptr_t arg_index) const
 
Representation RepInDart (intptr_t arg_index) const
 
virtual Representation RepInFfiCall (intptr_t def_index_global) const
 
void RepsInFfiCall (intptr_t arg_index, GrowableArray< Representation > *out) const
 
bool RequiresBitCast (intptr_t index) const
 
const NativeTypeSignExtendFrom (intptr_t arg_index) const
 
AbstractTypePtr CType (intptr_t arg_index) const
 
AbstractTypePtr DartType (intptr_t arg_index) const
 
bool IsPointerPointer (intptr_t arg_index) const
 
bool IsTypedDataPointer (intptr_t arg_index) const
 
bool IsCompoundPointer (intptr_t arg_index) const
 
bool IsHandleCType (intptr_t arg_index) const
 
bool IsBool (intptr_t arg_index) const
 
bool IsCompoundCType (intptr_t arg_index) const
 
bool IsVoid (intptr_t arg_index) const
 
bool ContainsHandles () const
 
bool contains_varargs () const
 
const Functiondart_signature () const
 
intptr_t dart_signature_params_start_at () const
 
const FunctionTypec_signature () const
 
StringPtr function_name () const
 
- Public Member Functions inherited from dart::ZoneAllocated
 ZoneAllocated ()
 
void * operator new (size_t size)
 
void * operator new (size_t size, Zone *zone)
 
void operator delete (void *pointer)
 

Static Public Member Functions

static CallMarshallerFromFunction (Zone *zone, const Function &function, intptr_t function_params_start_at, const FunctionType &c_signature, const char **error)
 

Protected Member Functions

 ~CallMarshaller ()
 
- Protected Member Functions inherited from dart::compiler::ffi::BaseMarshaller
bool IsPointerDartType (intptr_t arg_index) const
 
bool IsPointerCType (intptr_t arg_index) const
 
 BaseMarshaller (Zone *zone, const Function &dart_signature, intptr_t dart_signature_params_start_at, const FunctionType &c_signature, const NativeCallingConvention &native_calling_convention)
 
 ~BaseMarshaller ()
 

Additional Inherited Members

- Protected Attributes inherited from dart::compiler::ffi::BaseMarshaller
Zonezone_
 
const Functiondart_signature_
 
const intptr_t dart_signature_params_start_at_
 
const FunctionTypec_signature_
 
const NativeCallingConventionnative_calling_convention_
 

Detailed Description

Definition at line 198 of file marshaller.h.

Constructor & Destructor Documentation

◆ CallMarshaller()

dart::compiler::ffi::CallMarshaller::CallMarshaller ( Zone zone,
const Function dart_signature,
intptr_t  dart_signature_params_start_at,
const FunctionType c_signature,
const NativeCallingConvention native_calling_convention 
)
inline

Definition at line 206 of file marshaller.h.

211 : BaseMarshaller(zone,
215 native_calling_convention) {}
BaseMarshaller(Zone *zone, const Function &dart_signature, intptr_t dart_signature_params_start_at, const FunctionType &c_signature, const NativeCallingConvention &native_calling_convention)
Definition: marshaller.h:176
const Function & dart_signature() const
Definition: marshaller.h:168
const FunctionType & c_signature() const
Definition: marshaller.h:172
intptr_t dart_signature_params_start_at() const
Definition: marshaller.h:169

◆ ~CallMarshaller()

dart::compiler::ffi::CallMarshaller::~CallMarshaller ( )
inlineprotected

Definition at line 240 of file marshaller.h.

240{}

Member Function Documentation

◆ CompoundReturnSizeInBytes()

intptr_t dart::compiler::ffi::CallMarshaller::CompoundReturnSizeInBytes ( ) const

Definition at line 684 of file marshaller.cc.

684 {
686 return Utils::RoundUp(
689}
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
const NativeLocation & Location(intptr_t arg_index) const
Definition: marshaller.h:71
#define ASSERT(E)
static int SizeInBytes(Dart_TypedData_Type type)
Definition: file.cc:1199
const intptr_t kResultIndex
Definition: marshaller.h:28
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274

◆ FromFunction()

CallMarshaller * dart::compiler::ffi::CallMarshaller::FromFunction ( Zone zone,
const Function function,
intptr_t  function_params_start_at,
const FunctionType c_signature,
const char **  error 
)
static

Definition at line 90 of file marshaller.cc.

94 {
95 DEBUG_ASSERT(function.IsNotTemporaryScopedHandle());
96 DEBUG_ASSERT(c_signature.IsNotTemporaryScopedHandle());
97 const auto native_function_signature =
99 if (*error != nullptr) {
100 return nullptr;
101 }
102 const auto& native_calling_convention =
103 NativeCallingConvention::FromSignature(zone, *native_function_signature);
104 return new (zone) CallMarshaller(zone, function, function_params_start_at,
105 c_signature, native_calling_convention);
106}
#define DEBUG_ASSERT(cond)
Definition: assert.h:321
CallMarshaller(Zone *zone, const Function &dart_signature, intptr_t dart_signature_params_start_at, const FunctionType &c_signature, const NativeCallingConvention &native_calling_convention)
Definition: marshaller.h:206
static const NativeCallingConvention & FromSignature(Zone *zone, const NativeFunctionType &signature)
const uint8_t uint32_t uint32_t GError ** error
Dart_NativeFunction function
Definition: fuchsia.cc:51
const NativeFunctionType * NativeFunctionTypeFromFunctionType(Zone *zone, const FunctionType &c_signature, const char **error)
Definition: marshaller.cc:34

◆ LocInFfiCall()

Location dart::compiler::ffi::CallMarshaller::LocInFfiCall ( intptr_t  def_index_global) const

Definition at line 600 of file marshaller.cc.

600 {
601 const intptr_t arg_index = ArgumentIndex(def_index_global);
602 const NativeLocation& loc = this->Location(arg_index);
603
604 if (ArgumentIndexIsReturn(arg_index)) {
605 if (loc.IsRegisters() || loc.IsFpuRegisters()) {
606 return loc.AsLocation();
607 }
609 // No location at all, because we store into TypedData passed to the
610 // FfiCall instruction. But we have to supply a location.
612 }
613
614 // Force all handles to be Stack locations.
615 if (IsHandleCType(arg_index)) {
617 }
618
619 if (loc.IsMultiple()) {
620 const intptr_t def_index_in_arg =
621 def_index_global - FirstDefinitionIndex(arg_index);
622 const auto& def_loc = *(loc.AsMultiple().locations()[def_index_in_arg]);
623 if (def_loc.IsStack()) {
624 // Don't pin stack locations, they need to be moved anyway.
625 return ConvertToAnyLocation(def_loc.AsStack(),
626 RepInFfiCall(def_index_global));
627 }
628
629 if (def_loc.IsFpuRegisters()) {
630 return SelectFpuLocationInIL(zone_, def_loc);
631 }
632
633 return def_loc.AsLocation();
634 }
635
636 if (loc.IsPointerToMemory()) {
637 const intptr_t def_index_in_arg =
638 def_index_global - FirstDefinitionIndex(arg_index);
639 if (def_index_in_arg == kTypedDataBaseIndex) {
640 const auto& pointer_location = loc.AsPointerToMemory().pointer_location();
641 if (pointer_location.IsStack()) {
642 // Don't pin stack locations, they need to be moved anyway.
643 return ConvertToAnyLocation(pointer_location.AsStack(),
644 RepInFfiCall(def_index_global));
645 }
646 return pointer_location.AsLocation();
647 } else {
648 ASSERT_EQUAL(def_index_in_arg, kOffsetInBytesIndex);
649 return Location::Any();
650 }
651 }
652
653 if (IsCompoundPointer(arg_index)) {
654 const intptr_t def_index_in_arg =
655 def_index_global - FirstDefinitionIndex(arg_index);
656 if (def_index_in_arg == kOffsetInBytesIndex) {
657 // The typed data is passed in the location from the calling convention.
658 // The offset in bytes can be passed in any location.
659 return Location::Any();
660 }
661 }
662
663 if (loc.IsStack()) {
664 return ConvertToAnyLocation(loc.AsStack(), RepInFfiCall(def_index_global));
665 }
666
667 if (loc.IsFpuRegisters()) {
668 return SelectFpuLocationInIL(zone_, loc);
669 }
670
671 if (loc.IsBoth()) {
672 const auto& fpu_reg_loc = loc.AsBoth().location(0).AsFpuRegisters();
673 return SelectFpuLocationInIL(zone_, fpu_reg_loc);
674 }
675
676 ASSERT(loc.IsRegisters());
677 return loc.AsLocation();
678}
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
static constexpr Register kReturnReg
static Location RequiresStack()
Definition: locations.h:354
static Location RegisterLocation(Register reg)
Definition: locations.h:398
static Location Any()
Definition: locations.h:352
bool IsCompoundPointer(intptr_t arg_index) const
Definition: marshaller.cc:215
bool ArgumentIndexIsReturn(intptr_t arg_index) const
Definition: marshaller.cc:357
intptr_t FirstDefinitionIndex(intptr_t arg_index) const
Definition: marshaller.cc:385
intptr_t ArgumentIndex(intptr_t def_index_global) const
Definition: marshaller.cc:367
bool IsHandleCType(intptr_t arg_index) const
Definition: marshaller.cc:229
virtual Representation RepInFfiCall(intptr_t def_index_global) const
Definition: marshaller.cc:480
static Location SelectFpuLocationInIL(Zone *zone, const NativeLocation &location)
Definition: marshaller.cc:585
static const intptr_t kOffsetInBytesIndex
Definition: marshaller.cc:478
static const intptr_t kTypedDataBaseIndex
Definition: marshaller.cc:477
static Location ConvertToAnyLocation(const NativeStackLocation &loc, Representation rep_in_ffi_call)
Definition: marshaller.cc:562

◆ NumDefinitions()

intptr_t dart::compiler::ffi::CallMarshaller::NumDefinitions ( intptr_t  arg_index) const
virtual

Reimplemented from dart::compiler::ffi::BaseMarshaller.

Definition at line 293 of file marshaller.cc.

293 {
294 if (!ArgumentIndexIsReturn(arg_index)) {
295 const auto& loc = Location(arg_index);
296 const auto& type = loc.payload_type();
297 if (type.IsCompound() && loc.IsPointerToMemory()) {
298 // For FFI calls, pass in TypedDataBase and offsetInBytes in IL, and copy
299 // contents to stack and pass pointer in right location in MC.
300 return 2;
301 }
302 }
303 return BaseMarshaller::NumDefinitions(arg_index);
304}
GLenum type
virtual intptr_t NumDefinitions(intptr_t arg_index) const
Definition: marshaller.cc:257

◆ NumReturnDefinitions()

intptr_t dart::compiler::ffi::CallMarshaller::NumReturnDefinitions ( ) const
virtual

Implements dart::compiler::ffi::BaseMarshaller.

Definition at line 319 of file marshaller.cc.

319 {
320 // An FFICall is a Definition, and Definitions currently only have one
321 // return value.
322 //
323 // For compound returns, the IL generated by the flow graph builder allocates
324 // a TypedDataBase object that is passed into the FfiCall. The generated
325 // machine code for the FfiCall instruction then fills in the contents.
326 // After the call, the generated IL wraps the TypedDataBase object in a
327 // Compound object with an offset in bytes of 0.
328 return 1;
329}

◆ PassByPointerStackOffset()

intptr_t dart::compiler::ffi::CallMarshaller::PassByPointerStackOffset ( intptr_t  arg_index) const

Definition at line 695 of file marshaller.cc.

695 {
696 ASSERT(arg_index == kResultIndex ||
697 (arg_index >= 0 && arg_index < num_args()) ||
698 arg_index == kAfterLastArgumentIndex);
699
700 intptr_t stack_offset = 0;
701
702 // First the native arguments are on the stack.
703 // This is governed by the native ABI, the rest we can chose freely.
705#if (defined(DART_TARGET_OS_MACOS_IOS) || defined(DART_TARGET_OS_MACOS)) && \
706 defined(TARGET_ARCH_ARM64)
707 // Add extra padding for possibly non stack-aligned word-size writes.
708 // TODO(https://dartbug.com/48806): Re-engineer the moves to not over-
709 // approximate struct sizes on stack.
710 stack_offset += 4;
711#endif
712 stack_offset = Utils::RoundUp(stack_offset, compiler::target::kWordSize);
713 if (arg_index == kResultIndex) {
714 return stack_offset;
715 }
716
717 // Then save space for the result.
718 const auto& result_location = Location(compiler::ffi::kResultIndex);
719 if (result_location.IsPointerToMemory()) {
720 stack_offset += result_location.payload_type().SizeInBytes();
721 stack_offset = Utils::RoundUp(stack_offset, compiler::target::kWordSize);
722 }
723
724 // And finally put the arguments on the stack that are passed by pointer.
725 for (int i = 0; i < num_args(); i++) {
726 if (arg_index == i) {
727 return stack_offset;
728 }
729 const auto& arg_location = Location(i);
730 if (arg_location.IsPointerToMemory()) {
731 stack_offset += arg_location.payload_type().SizeInBytes();
732 stack_offset = Utils::RoundUp(stack_offset, compiler::target::kWordSize);
733 }
734 }
735
736 // The total stack space we need.
737 ASSERT(arg_index == kAfterLastArgumentIndex);
738 return stack_offset;
739}
const NativeCallingConvention & native_calling_convention_
Definition: marshaller.h:195
const intptr_t kAfterLastArgumentIndex
Definition: marshaller.cc:693

◆ RepInFfiCall()

Representation dart::compiler::ffi::CallMarshaller::RepInFfiCall ( intptr_t  def_index_global) const
virtual

Reimplemented from dart::compiler::ffi::BaseMarshaller.

Definition at line 480 of file marshaller.cc.

480 {
481 intptr_t arg_index = ArgumentIndex(def_index_global);
482 if (IsHandleCType(arg_index)) {
483 // For FfiCall arguments, the FfiCall instruction takes a tagged pointer
484 // from the IL. (It then creates a handle on the stack and passes a
485 // pointer to the newly allocated handle to C.)
486 //
487 // For FfiCall returns, FfiCall returns the untagged pointer to the handle
488 // to the IL, which then extracts the ptr field of the handle to retrieve
489 // the tagged pointer.
490 return ArgumentIndexIsReturn(arg_index) ? kUntagged : kTagged;
491 }
492 if (ArgumentIndexIsReturn(arg_index) && ReturnsCompound()) {
493 // The IL creates a TypedData object which is stored on the stack, and the
494 // FfiCall copies the compound value, however it is returned into that
495 // TypedData object. In order to make the return value of the definition
496 // defined, the same TypedData object is returned from the FfiCall.
497 return kTagged;
498 }
499 const auto& location = Location(arg_index);
500 if (location.IsPointerToMemory() || IsCompoundPointer(arg_index) ||
501 IsTypedDataPointer(arg_index)) {
502 // For arguments, the compound data being passed as a pointer is first
503 // collected into a TypedData object by the IL, and that object is what is
504 // passed to the FfiCall instruction. (The machine code generated by
505 // FfiCall handles copying the data into non-GC-moveable memory and
506 // passing a pointer to that memory to the C code.)
507 const intptr_t def_index_in_arg =
508 def_index_global - FirstDefinitionIndex(arg_index);
509 if (def_index_in_arg == kTypedDataBaseIndex) {
510 // The TypedDataBase object is managed by the GC, so the payload address
511 // cannot be eagerly extracted in the IL, as that would create an
512 // unsafe untagged address as an input to a GC-triggering instruction.
513 return kTagged;
514 } else {
515 ASSERT_EQUAL(def_index_in_arg, kOffsetInBytesIndex);
516 ASSERT(!IsTypedDataPointer(arg_index));
517 return kUnboxedUword;
518 }
519 }
520 return BaseMarshaller::RepInFfiCall(def_index_global);
521}
virtual Representation RepInFfiCall(intptr_t def_index_global) const
Definition: marshaller.cc:444
bool IsTypedDataPointer(intptr_t arg_index) const
Definition: marshaller.cc:180
static constexpr Representation kUnboxedUword
Definition: locations.h:171

◆ RequiredStackSpaceInBytes()

intptr_t dart::compiler::ffi::CallMarshaller::RequiredStackSpaceInBytes ( ) const

Definition at line 741 of file marshaller.cc.

741 {
743}
intptr_t PassByPointerStackOffset(intptr_t arg_index) const
Definition: marshaller.cc:695

◆ ReturnsCompound()

bool dart::compiler::ffi::CallMarshaller::ReturnsCompound ( ) const

Definition at line 680 of file marshaller.cc.

680 {
682}
bool IsCompoundCType(intptr_t arg_index) const
Definition: marshaller.cc:240

The documentation for this class was generated from the following files: