Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
dart::FfiCallInstr Class Reference

#include <il.h>

Inheritance diagram for dart::FfiCallInstr:
dart::VariadicDefinition dart::Definition dart::Instruction dart::ZoneAllocated

Public Member Functions

 FfiCallInstr (intptr_t deopt_id, const compiler::ffi::CallMarshaller &marshaller, bool is_leaf, InputsArray &&inputs)
 
intptr_t TargetAddressIndex () const
 
intptr_t CompoundReturnTypedDataIndex () const
 
virtual bool MayThrow () const
 
virtual bool MayCreateUnsafeUntaggedPointer () const
 
virtual bool ComputeCanDeoptimize () const
 
virtual bool ComputeCanDeoptimizeAfterCall () const
 
virtual bool HasUnknownSideEffects () const
 
virtual bool CanCallDart () const
 
virtual Representation RequiredInputRepresentation (intptr_t idx) const
 
virtual Representation representation () const
 
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(FfiCallInstr, VariadicDefinition, FIELD_LIST) private void EmitParamMoves (FlowGraphCompiler *compiler, const Register saved_fp, const Register temp0, const Register temp1)
 
void EmitReturnMoves (FlowGraphCompiler *compiler, const Register temp0, const Register temp1)
 
 DISALLOW_COPY_AND_ASSIGN (FfiCallInstr)
 
- Public Member Functions inherited from dart::VariadicDefinition
 VariadicDefinition (InputsArray &&inputs, intptr_t deopt_id=DeoptId::kNone)
 
 VariadicDefinition (InputsArray &&inputs, const InstructionSource &source, intptr_t deopt_id=DeoptId::kNone)
 
 VariadicDefinition (const intptr_t num_inputs, intptr_t deopt_id=DeoptId::kNone)
 
intptr_t InputCount () const
 
ValueInputAt (intptr_t i) const
 
- Public Member Functions inherited from dart::Definition
 Definition (intptr_t deopt_id=DeoptId::kNone)
 
 Definition (const InstructionSource &source, intptr_t deopt_id=DeoptId::kNone)
 
virtual intptr_t CallCount () const
 
intptr_t temp_index () const
 
void set_temp_index (intptr_t index)
 
void ClearTempIndex ()
 
bool HasTemp () const
 
intptr_t ssa_temp_index () const
 
void set_ssa_temp_index (intptr_t index)
 
bool HasSSATemp () const
 
void ClearSSATempIndex ()
 
intptr_t vreg (intptr_t index) const
 
intptr_t location_count () const
 
bool HasPairRepresentation () const
 
CompileTypeType ()
 
bool HasType () const
 
bool IsInt64Definition ()
 
bool IsInt32Definition ()
 
virtual CompileType ComputeType () const
 
virtual bool RecomputeType ()
 
PRINT_OPERANDS_TO_SUPPORT PRINT_TO_SUPPORT bool UpdateType (CompileType new_type)
 
bool HasUses () const
 
bool HasOnlyUse (Value *use) const
 
bool HasOnlyInputUse (Value *use) const
 
Valueinput_use_list () const
 
void set_input_use_list (Value *head)
 
Valueenv_use_list () const
 
void set_env_use_list (Value *head)
 
ValueListIterable input_uses () const
 
void AddInputUse (Value *value)
 
void AddEnvUse (Value *value)
 
virtual bool MayCreateUnsafeUntaggedPointer () const
 
virtual bool CanReplaceWithConstant () const
 
virtual bool CanEliminate (const BlockEntryInstr *block) const
 
void ReplaceUsesWith (Definition *other)
 
void ReplaceWithResult (Instruction *replacement, Definition *replacement_for_uses, ForwardInstructionIterator *iterator)
 
void ReplaceWith (Definition *other, ForwardInstructionIterator *iterator)
 
Objectconstant_value ()
 
virtual void InferRange (RangeAnalysis *analysis, Range *range)
 
Rangerange () const
 
void set_range (const Range &)
 
virtual DefinitionCanonicalize (FlowGraph *flow_graph)
 
DefinitionReplacement ()
 
void SetReplacement (Definition *other)
 
virtual AliasIdentity Identity () const
 
virtual void SetIdentity (AliasIdentity identity)
 
DefinitionOriginalDefinition ()
 
virtual ValueRedefinedValue () const
 
DefinitionOriginalDefinitionIgnoreBoxingAndConstraints ()
 
virtual DefinitionAsDefinition ()
 
virtual const DefinitionAsDefinition () const
 
- Public Member Functions inherited from dart::Instruction
 Instruction (const InstructionSource &source, intptr_t deopt_id=DeoptId::kNone)
 
 Instruction (intptr_t deopt_id=DeoptId::kNone)
 
virtual ~Instruction ()
 
virtual Tag tag () const =0
 
virtual intptr_t statistics_tag () const
 
intptr_t deopt_id () const
 
virtual TokenPosition token_pos () const
 
InstructionSource source () const
 
virtual intptr_t InputCount () const =0
 
virtual ValueInputAt (intptr_t i) const =0
 
void SetInputAt (intptr_t i, Value *value)
 
InputsIterable inputs ()
 
void UnuseAllInputs ()
 
virtual intptr_t ArgumentCount () const
 
ValueArgumentValueAt (intptr_t index) const
 
DefinitionArgumentAt (intptr_t index) const
 
virtual void SetMoveArguments (MoveArgumentsArray *move_arguments)
 
virtual MoveArgumentsArrayGetMoveArguments () const
 
virtual void ReplaceInputsWithMoveArguments (MoveArgumentsArray *move_arguments)
 
bool HasMoveArguments () const
 
void RepairArgumentUsesInEnvironment () const
 
virtual bool ComputeCanDeoptimize () const =0
 
virtual bool ComputeCanDeoptimizeAfterCall () const
 
bool CanDeoptimize () const
 
virtual void Accept (InstructionVisitor *visitor)=0
 
Instructionprevious () const
 
void set_previous (Instruction *instr)
 
Instructionnext () const
 
void set_next (Instruction *instr)
 
void LinkTo (Instruction *next)
 
InstructionRemoveFromGraph (bool return_previous=true)
 
virtual intptr_t SuccessorCount () const
 
virtual BlockEntryInstrSuccessorAt (intptr_t index) const
 
SuccessorsIterable successors () const
 
void Goto (JoinEntryInstr *entry)
 
virtual const char * DebugName () const =0
 
void CheckField (const Field &field) const
 
const char * ToCString () const
 
 DECLARE_INSTRUCTION_TYPE_CHECK (BlockEntryWithInitialDefs, BlockEntryWithInitialDefs) template< typename T > T *Cast()
 
template<typename T >
const TCast () const
 
LocationSummarylocs ()
 
bool HasLocs () const
 
virtual LocationSummaryMakeLocationSummary (Zone *zone, bool is_optimizing) const =0
 
void InitializeLocationSummary (Zone *zone, bool optimizing)
 
virtual void EmitNativeCode (FlowGraphCompiler *compiler)
 
Environmentenv () const
 
void SetEnvironment (Environment *deopt_env)
 
void RemoveEnvironment ()
 
void ReplaceInEnvironment (Definition *current, Definition *replacement)
 
virtual intptr_t NumberOfInputsConsumedBeforeCall () const
 
intptr_t GetPassSpecificId (CompilerPass::Id pass) const
 
void SetPassSpecificId (CompilerPass::Id pass, intptr_t id)
 
bool HasPassSpecificId (CompilerPass::Id pass) const
 
bool HasUnmatchedInputRepresentations () const
 
virtual Representation RequiredInputRepresentation (intptr_t idx) const
 
SpeculativeMode SpeculativeModeOfInputs () const
 
virtual SpeculativeMode SpeculativeModeOfInput (intptr_t index) const
 
virtual Representation representation () const
 
bool WasEliminated () const
 
virtual intptr_t DeoptimizationTarget () const
 
virtual InstructionCanonicalize (FlowGraph *flow_graph)
 
void InsertBefore (Instruction *next)
 
void InsertAfter (Instruction *prev)
 
InstructionAppendInstruction (Instruction *tail)
 
virtual bool AllowsCSE () const
 
virtual bool HasUnknownSideEffects () const =0
 
virtual bool CanCallDart () const
 
virtual bool CanTriggerGC () const
 
virtual BlockEntryInstrGetBlock ()
 
virtual intptr_t inlining_id () const
 
virtual void set_inlining_id (intptr_t value)
 
virtual bool has_inlining_id () const
 
virtual uword Hash () const
 
bool Equals (const Instruction &other) const
 
virtual bool AttributesEqual (const Instruction &other) const
 
void InheritDeoptTarget (Zone *zone, Instruction *other)
 
bool NeedsEnvironment () const
 
virtual bool CanBecomeDeoptimizationTarget () const
 
void InheritDeoptTargetAfter (FlowGraph *flow_graph, Definition *call, Definition *result)
 
virtual bool MayThrow () const =0
 
virtual bool MayHaveVisibleEffect () const
 
virtual bool CanEliminate (const BlockEntryInstr *block) const
 
bool CanEliminate ()
 
bool IsDominatedBy (Instruction *dom)
 
void ClearEnv ()
 
void Unsupported (FlowGraphCompiler *compiler)
 
virtual bool UseSharedSlowPathStub (bool is_optimizing) const
 
Location::Kind RegisterKindForResult () 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 bool CanExecuteGeneratedCodeInSafepoint ()
 
static intptr_t InputCountForMarshaller (const compiler::ffi::CallMarshaller &marshaller)
 
- Static Public Member Functions inherited from dart::Definition
static bool IsArrayLength (Definition *def)
 
- Static Public Member Functions inherited from dart::Instruction
static const ICDataGetICData (const ZoneGrowableArray< const ICData * > &ic_data_array, intptr_t deopt_id, bool is_static_call)
 
static LocationSummaryMakeCallSummary (Zone *zone, const Instruction *instr, LocationSummary *locs=nullptr)
 
static bool SlowPathSharingSupported (bool is_optimizing)
 

Additional Inherited Members

- Public Types inherited from dart::Instruction
enum  Tag { FOR_EACH_INSTRUCTION =(DECLARE_TAG) kNumInstructions }
 
enum  SpeculativeMode { kGuardInputs , kNotSpeculative }
 
using InputsIterable = InstructionIndexedPropertyIterable< InputsTrait >
 
using SuccessorsIterable = InstructionIndexedPropertyIterable< SuccessorsTrait >
 
- Static Public Attributes inherited from dart::Definition
static constexpr intptr_t kReplacementMarker = -2
 
- Static Public Attributes inherited from dart::Instruction
static const intptr_t kInstructionAttrs [kNumInstructions]
 
- Protected Member Functions inherited from dart::Definition
void set_type (CompileType *type)
 
- Protected Member Functions inherited from dart::Instruction
intptr_t GetDeoptId () const
 
virtual void CopyDeoptIdFrom (const Instruction &instr)
 
void WriteExtraWithoutInputs (FlowGraphSerializer *s)
 
void ReadExtraWithoutInputs (FlowGraphDeserializer *d)
 
- Protected Attributes inherited from dart::VariadicDefinition
InputsArray inputs_
 
- Protected Attributes inherited from dart::Definition
Rangerange_ = nullptr
 

Detailed Description

Definition at line 6078 of file il.h.

Constructor & Destructor Documentation

◆ FfiCallInstr()

dart::FfiCallInstr::FfiCallInstr ( intptr_t  deopt_id,
const compiler::ffi::CallMarshaller marshaller,
bool  is_leaf,
InputsArray &&  inputs 
)
inline

Definition at line 6080 of file il.h.

6084 : VariadicDefinition(std::move(inputs), deopt_id),
6085 marshaller_(marshaller),
6086 is_leaf_(is_leaf) {
6087#if defined(DEBUG)
6089 // No argument to an FfiCall should be an unsafe untagged pointer,
6090 // including the target address.
6091 for (intptr_t i = 0; i < InputCount(); i++) {
6092 ASSERT(!InputAt(i)->definition()->MayCreateUnsafeUntaggedPointer());
6093 }
6094#endif
6095 }
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
static intptr_t InputCountForMarshaller(const compiler::ffi::CallMarshaller &marshaller)
Definition: il.h:6146
virtual bool MayCreateUnsafeUntaggedPointer() const
Definition: il.h:6115
InputsIterable inputs()
Definition: il.h:1033
intptr_t deopt_id() const
Definition: il.h:993
VariadicDefinition(InputsArray &&inputs, intptr_t deopt_id=DeoptId::kNone)
Definition: il.h:2773
intptr_t InputCount() const
Definition: il.h:2794
Value * InputAt(intptr_t i) const
Definition: il.h:2795
#define ASSERT(E)

Member Function Documentation

◆ CanCallDart()

virtual bool dart::FfiCallInstr::CanCallDart ( ) const
inlinevirtual

Reimplemented from dart::Instruction.

Definition at line 6132 of file il.h.

6132{ return false; }

◆ CanExecuteGeneratedCodeInSafepoint()

static bool dart::FfiCallInstr::CanExecuteGeneratedCodeInSafepoint ( )
inlinestatic

Definition at line 6142 of file il.h.

6142 {
6143 return FLAG_precompiled_mode;
6144 }

◆ CompoundReturnTypedDataIndex()

intptr_t dart::FfiCallInstr::CompoundReturnTypedDataIndex ( ) const
inline

Definition at line 6105 of file il.h.

6105 {
6106 ASSERT(marshaller_.ReturnsCompound());
6107 return marshaller_.NumArgumentDefinitions() + 1;
6108 }

◆ ComputeCanDeoptimize()

virtual bool dart::FfiCallInstr::ComputeCanDeoptimize ( ) const
inlinevirtual

Implements dart::Instruction.

Definition at line 6124 of file il.h.

6124{ return false; }

◆ ComputeCanDeoptimizeAfterCall()

virtual bool dart::FfiCallInstr::ComputeCanDeoptimizeAfterCall ( ) const
inlinevirtual

Reimplemented from dart::Instruction.

Definition at line 6125 of file il.h.

6125 {
6126 return !CompilerState::Current().is_aot();
6127 }
bool is_aot() const
static CompilerState & Current()

◆ DISALLOW_COPY_AND_ASSIGN()

dart::FfiCallInstr::DISALLOW_COPY_AND_ASSIGN ( FfiCallInstr  )

◆ EmitParamMoves()

void dart::FfiCallInstr::EmitParamMoves ( FlowGraphCompiler compiler,
const Register  saved_fp,
const Register  temp0,
const Register  temp1 
)

Definition at line 7478 of file il.cc.

7481 {
7482 __ Comment("EmitParamMoves");
7483
7484 // Moves for return pointer.
7485 const auto& return_location =
7486 marshaller_.Location(compiler::ffi::kResultIndex);
7487 if (return_location.IsPointerToMemory()) {
7488 __ Comment("return_location.IsPointerToMemory");
7489 const auto& pointer_location =
7490 return_location.AsPointerToMemory().pointer_location();
7491 const auto& pointer_register =
7492 pointer_location.IsRegisters()
7493 ? pointer_location.AsRegisters().reg_at(0)
7494 : temp0;
7495 __ MoveRegister(pointer_register, SPREG);
7496 __ AddImmediate(pointer_register, marshaller_.PassByPointerStackOffset(
7498
7499 if (pointer_location.IsStack()) {
7500 const auto& pointer_stack = pointer_location.AsStack();
7501 __ StoreMemoryValue(pointer_register, pointer_stack.base_register(),
7502 pointer_stack.offset_in_bytes());
7503 }
7504 }
7505
7506 // Moves for arguments.
7507 compiler::ffi::FrameRebase rebase(compiler->zone(), /*old_base=*/FPREG,
7508 /*new_base=*/saved_fp,
7509 /*stack_delta=*/0);
7510 intptr_t def_index = 0;
7511 for (intptr_t arg_index = 0; arg_index < marshaller_.num_args();
7512 arg_index++) {
7513 const intptr_t num_defs = marshaller_.NumDefinitions(arg_index);
7514 const auto& arg_target = marshaller_.Location(arg_index);
7515 __ Comment("arg_index %" Pd " arg_target %s", arg_index,
7516 arg_target.ToCString());
7517
7518 // First deal with moving all individual definitions passed in to the
7519 // FfiCall to the right native location based on calling convention.
7520 for (intptr_t i = 0; i < num_defs; i++) {
7521 if ((arg_target.IsPointerToMemory() ||
7522 marshaller_.IsCompoundPointer(arg_index)) &&
7523 i == 1) {
7524 // The offset_in_bytes is not an argument for C, so don't move it.
7525 // It is used as offset_in_bytes_loc below and moved there if
7526 // necessary.
7527 def_index++;
7528 continue;
7529 }
7530 __ Comment(" def_index %" Pd, def_index);
7531 Location origin = rebase.Rebase(locs()->in(def_index));
7532 const Representation origin_rep = RequiredInputRepresentation(def_index);
7533
7534 // Find the native location where this individual definition should be
7535 // moved to.
7536 const auto& def_target =
7537 arg_target.payload_type().IsPrimitive() ? arg_target
7538 : arg_target.IsMultiple() ? *arg_target.AsMultiple().locations()[i]
7539 : arg_target.IsPointerToMemory()
7540 ? arg_target.AsPointerToMemory().pointer_location()
7541 : /*arg_target.IsStack()*/ arg_target.Split(compiler->zone(),
7542 num_defs, i);
7543
7544 ConstantTemporaryAllocator temp_alloc(temp0);
7545 if (origin.IsConstant()) {
7546 __ Comment("origin.IsConstant()");
7547 ASSERT(!marshaller_.IsHandleCType(arg_index));
7548 ASSERT(!marshaller_.IsTypedDataPointer(arg_index));
7549 ASSERT(!marshaller_.IsCompoundPointer(arg_index));
7550 compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
7551 } else if (origin.IsPairLocation() &&
7552 (origin.AsPairLocation()->At(0).IsConstant() ||
7553 origin.AsPairLocation()->At(1).IsConstant())) {
7554 // Note: half of the pair can be constant.
7555 __ Comment("origin.IsPairLocation() and constant");
7556 ASSERT(!marshaller_.IsHandleCType(arg_index));
7557 ASSERT(!marshaller_.IsTypedDataPointer(arg_index));
7558 ASSERT(!marshaller_.IsCompoundPointer(arg_index));
7559 compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
7560 } else if (marshaller_.IsHandleCType(arg_index)) {
7561 __ Comment("marshaller_.IsHandleCType(arg_index)");
7562 // Handles are passed into FfiCalls as Tagged values on the stack, and
7563 // then we pass pointers to these handles to the native function here.
7564 ASSERT(origin_rep == kTagged);
7568 ASSERT(num_defs == 1);
7569 ASSERT(origin.IsStackSlot());
7570 if (def_target.IsRegisters()) {
7571 __ AddImmediate(def_target.AsLocation().reg(), origin.base_reg(),
7572 origin.stack_index() * compiler::target::kWordSize);
7573 } else {
7574 ASSERT(def_target.IsStack());
7575 const auto& target_stack = def_target.AsStack();
7576 __ AddImmediate(temp0, origin.base_reg(),
7577 origin.stack_index() * compiler::target::kWordSize);
7578 __ StoreToOffset(temp0, target_stack.base_register(),
7579 target_stack.offset_in_bytes());
7580 }
7581 } else {
7582 __ Comment("def_target %s <- origin %s %s",
7583 def_target.ToCString(compiler->zone()), origin.ToCString(),
7584 RepresentationUtils::ToCString(origin_rep));
7585#ifdef DEBUG
7586 // Stack arguments split are in word-size chunks. These chunks can copy
7587 // too much. However, that doesn't matter in practise because we process
7588 // the stack in order.
7589 // It only matters for the last chunk, it should not overwrite what was
7590 // already on the stack.
7591 if (def_target.IsStack()) {
7592 const auto& def_target_stack = def_target.AsStack();
7593 ASSERT(def_target_stack.offset_in_bytes() +
7594 def_target.payload_type().SizeInBytes() <=
7595 marshaller_.RequiredStackSpaceInBytes());
7596 }
7597#endif
7598 if (marshaller_.IsTypedDataPointer(arg_index) ||
7599 marshaller_.IsCompoundPointer(arg_index)) {
7600 // Unwrap typed data before move to native location.
7601 __ Comment("Load typed data base address");
7602 if (origin.IsStackSlot()) {
7603 compiler->EmitMove(Location::RegisterLocation(temp0), origin,
7604 &temp_alloc);
7605 origin = Location::RegisterLocation(temp0);
7606 }
7607 ASSERT(origin.IsRegister());
7608 __ LoadFromSlot(origin.reg(), origin.reg(), Slot::PointerBase_data());
7609 if (marshaller_.IsCompoundPointer(arg_index)) {
7610 __ Comment("Load offset in bytes");
7611 const intptr_t offset_in_bytes_def_index = def_index + 1;
7612 const Location offset_in_bytes_loc =
7613 rebase.Rebase(locs()->in(offset_in_bytes_def_index));
7614 Register offset_in_bytes_reg = kNoRegister;
7615 if (offset_in_bytes_loc.IsRegister()) {
7616 offset_in_bytes_reg = offset_in_bytes_loc.reg();
7617 } else {
7618 offset_in_bytes_reg = temp1;
7619 NoTemporaryAllocator no_temp;
7620 compiler->EmitMove(
7621 Location::RegisterLocation(offset_in_bytes_reg),
7622 offset_in_bytes_loc, &no_temp);
7623 }
7624 __ AddRegisters(origin.reg(), offset_in_bytes_reg);
7625 }
7626 }
7627 compiler->EmitMoveToNative(def_target, origin, origin_rep, &temp_alloc);
7628 }
7629 def_index++;
7630 }
7631
7632 // Then make sure that any pointers passed through the calling convention
7633 // actually have a copy of the struct.
7634 // Note that the step above has already moved the pointer into the expected
7635 // native location.
7636 if (arg_target.IsPointerToMemory()) {
7637 __ Comment("arg_target.IsPointerToMemory");
7638 NoTemporaryAllocator temp_alloc;
7639 const auto& pointer_loc =
7640 arg_target.AsPointerToMemory().pointer_location();
7641
7642 // TypedData data pointed to in temp.
7643 const auto& dst = compiler::ffi::NativeRegistersLocation(
7644 compiler->zone(), pointer_loc.payload_type(),
7645 pointer_loc.container_type(), temp0);
7646 compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
7647 __ LoadFromSlot(temp0, temp0, Slot::PointerBase_data());
7648
7649 __ Comment("IsPointerToMemory add offset");
7650 const intptr_t offset_in_bytes_def_index =
7651 def_index - 1; // ++'d already.
7652 const Location offset_in_bytes_loc =
7653 rebase.Rebase(locs()->in(offset_in_bytes_def_index));
7654 Register offset_in_bytes_reg = kNoRegister;
7655 if (offset_in_bytes_loc.IsRegister()) {
7656 offset_in_bytes_reg = offset_in_bytes_loc.reg();
7657 } else {
7658 offset_in_bytes_reg = temp1;
7659 NoTemporaryAllocator no_temp;
7660 compiler->EmitMove(Location::RegisterLocation(offset_in_bytes_reg),
7661 offset_in_bytes_loc, &no_temp);
7662 }
7663 __ AddRegisters(temp0, offset_in_bytes_reg);
7664
7665 // Copy chunks. The destination may be rounded up to a multiple of the
7666 // word size, because we do the same rounding when we allocate the space
7667 // on the stack. But source may not be allocated by the VM and end at a
7668 // page boundary.
7669 __ Comment("IsPointerToMemory copy chunks");
7670 const intptr_t sp_offset =
7671 marshaller_.PassByPointerStackOffset(arg_index);
7672 __ UnrolledMemCopy(SPREG, sp_offset, temp0, 0,
7673 arg_target.payload_type().SizeInBytes(), temp1);
7674
7675 // Store the stack address in the argument location.
7676 __ MoveRegister(temp0, SPREG);
7677 __ AddImmediate(temp0, sp_offset);
7678 const auto& src = compiler::ffi::NativeRegistersLocation(
7679 compiler->zone(), pointer_loc.payload_type(),
7680 pointer_loc.container_type(), temp0);
7681 __ Comment("pointer_loc %s <- src %s", pointer_loc.ToCString(),
7682 src.ToCString());
7683 compiler->EmitNativeMove(pointer_loc, src, &temp_alloc);
7684 }
7685 }
7686
7687 __ Comment("EmitParamMovesEnd");
7688}
virtual Representation RequiredInputRepresentation(intptr_t idx) const
Definition: il.cc:7408
LocationSummary * locs()
Definition: il.h:1192
static Location RegisterLocation(Register reg)
Definition: locations.h:398
#define __
Definition: il.cc:4271
const intptr_t kResultIndex
Definition: marshaller.h:28
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
Representation
Definition: locations.h:66
@ kNoRegister
Definition: constants_arm.h:99
const Register FPREG
const Register SPREG
dst
Definition: cp.py:12
#define Pd
Definition: globals.h:408
static const char * ToCString(Representation rep)
Definition: locations.cc:129

◆ EmitReturnMoves()

void dart::FfiCallInstr::EmitReturnMoves ( FlowGraphCompiler compiler,
const Register  temp0,
const Register  temp1 
)

Definition at line 7690 of file il.cc.

7692 {
7693 const auto& returnLocation =
7694 marshaller_.Location(compiler::ffi::kResultIndex);
7695 if (returnLocation.payload_type().IsVoid()) {
7696 return;
7697 }
7698
7699 __ Comment("EmitReturnMoves");
7700
7701 NoTemporaryAllocator no_temp;
7702 if (returnLocation.IsRegisters() || returnLocation.IsFpuRegisters()) {
7703 const auto& src = returnLocation;
7704 const Location dst_loc = locs()->out(0);
7705 const Representation dst_type = representation();
7706 compiler->EmitMoveFromNative(dst_loc, dst_type, src, &no_temp);
7707 } else if (marshaller_.ReturnsCompound()) {
7708 ASSERT(returnLocation.payload_type().IsCompound());
7709
7710 // Get the typed data pointer which we have pinned to a stack slot.
7711 const Location typed_data_loc = locs()->in(CompoundReturnTypedDataIndex());
7712 if (typed_data_loc.IsStackSlot()) {
7713 ASSERT(typed_data_loc.base_reg() == FPREG);
7714 // If this is a leaf call there is no extra call frame to step through.
7715 if (is_leaf_) {
7716 __ LoadMemoryValue(temp0, FPREG, typed_data_loc.ToStackSlotOffset());
7717 } else {
7718 __ LoadMemoryValue(
7719 temp0, FPREG,
7721 __ LoadMemoryValue(temp0, temp0, typed_data_loc.ToStackSlotOffset());
7722 }
7723 } else {
7724 compiler->EmitMove(Location::RegisterLocation(temp0), typed_data_loc,
7725 &no_temp);
7726 }
7727 __ LoadFromSlot(temp0, temp0, Slot::PointerBase_data());
7728
7729 if (returnLocation.IsPointerToMemory()) {
7730 // Copy blocks from the stack location to TypedData.
7731 // Struct size is rounded up to a multiple of target::kWordSize.
7732 // This is safe because we do the same rounding when we allocate the
7733 // TypedData in IL.
7734 const intptr_t sp_offset =
7735 marshaller_.PassByPointerStackOffset(compiler::ffi::kResultIndex);
7736 __ UnrolledMemCopy(temp0, 0, SPREG, sp_offset,
7737 marshaller_.CompoundReturnSizeInBytes(), temp1);
7738 } else {
7739 ASSERT(returnLocation.IsMultiple());
7740 // Copy to the struct from the native locations.
7741 const auto& multiple =
7742 marshaller_.Location(compiler::ffi::kResultIndex).AsMultiple();
7743
7744 int offset_in_bytes = 0;
7745 for (int i = 0; i < multiple.locations().length(); i++) {
7746 const auto& src = *multiple.locations().At(i);
7747 const auto& dst = compiler::ffi::NativeStackLocation(
7748 src.payload_type(), src.container_type(), temp0, offset_in_bytes);
7749 compiler->EmitNativeMove(dst, src, &no_temp);
7750 offset_in_bytes += src.payload_type().SizeInBytes();
7751 }
7752 }
7753 } else {
7754 UNREACHABLE();
7755 }
7756
7757 __ Comment("EmitReturnMovesEnd");
7758}
#define UNREACHABLE()
Definition: assert.h:248
intptr_t CompoundReturnTypedDataIndex() const
Definition: il.h:6105
virtual Representation representation() const
Definition: il.cc:8095
Location out(intptr_t index) const
Definition: locations.h:903
Location in(intptr_t index) const
Definition: locations.h:866
size_t length
static constexpr int kSavedCallerFpSlotFromFp

◆ HasUnknownSideEffects()

virtual bool dart::FfiCallInstr::HasUnknownSideEffects ( ) const
inlinevirtual

Implements dart::Instruction.

Definition at line 6129 of file il.h.

6129{ return true; }

◆ InputCountForMarshaller()

static intptr_t dart::FfiCallInstr::InputCountForMarshaller ( const compiler::ffi::CallMarshaller marshaller)
inlinestatic

Definition at line 6146 of file il.h.

6147 {
6148 return marshaller.NumArgumentDefinitions() + 1 +
6149 (marshaller.ReturnsCompound() ? 1 : 0);
6150 }

◆ MayCreateUnsafeUntaggedPointer()

virtual bool dart::FfiCallInstr::MayCreateUnsafeUntaggedPointer ( ) const
inlinevirtual

Reimplemented from dart::Definition.

Definition at line 6115 of file il.h.

6115 {
6116 // The only case where we have an untagged result is when the return
6117 // value is a pointer, which is then stored in a newly allocated FFI
6118 // Pointer object by the generated IL, so the C code must return an
6119 // external (not GC-movable) address to Dart.
6120 return false;
6121 }

◆ MayThrow()

virtual bool dart::FfiCallInstr::MayThrow ( ) const
inlinevirtual

Implements dart::Instruction.

Definition at line 6110 of file il.h.

6110 {
6111 // By Dart_PropagateError.
6112 return true;
6113 }

◆ representation()

Representation dart::FfiCallInstr::representation ( ) const
virtual

Reimplemented from dart::Instruction.

Definition at line 8095 of file il.cc.

8095 {
8096 if (marshaller_.ReturnsCompound()) {
8097 // Don't care, we're discarding the value.
8098 return kTagged;
8099 }
8100 if (marshaller_.IsHandleCType(compiler::ffi::kResultIndex)) {
8101 // The call returns a Dart_Handle, from which we need to extract the
8102 // tagged pointer using LoadField with an appropriate slot.
8103 return kUntagged;
8104 }
8105 return marshaller_.RepInFfiCall(compiler::ffi::kResultIndex);
8106}

◆ RequiredInputRepresentation()

Representation dart::FfiCallInstr::RequiredInputRepresentation ( intptr_t  idx) const
virtual

Reimplemented from dart::Instruction.

Definition at line 7408 of file il.cc.

7408 {
7409 if (idx < TargetAddressIndex()) {
7410 // All input handles are passed as tagged values to FfiCallInstr and
7411 // are given stack locations. FfiCallInstr then passes an untagged pointer
7412 // to the handle on the stack (Dart_Handle) to the C function.
7413 if (marshaller_.IsHandleCType(marshaller_.ArgumentIndex(idx))) {
7414 return kTagged;
7415 }
7416 return marshaller_.RepInFfiCall(idx);
7417 } else if (idx == TargetAddressIndex()) {
7418#if defined(DEBUG)
7419 auto const rep =
7421 ASSERT(rep == kUntagged || rep == kUnboxedAddress);
7422#endif
7423 return kNoRepresentation; // Allows kUntagged or kUnboxedAddress.
7424 } else {
7426 return kTagged;
7427 }
7428}
intptr_t TargetAddressIndex() const
Definition: il.h:6100
virtual Representation representation() const
Definition: il.h:1260
Definition * definition() const
Definition: il.h:103
static constexpr Representation kUnboxedAddress
Definition: locations.h:182

◆ TargetAddressIndex()

intptr_t dart::FfiCallInstr::TargetAddressIndex ( ) const
inline

Definition at line 6100 of file il.h.

6100 {
6101 return marshaller_.NumArgumentDefinitions();
6102 }

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