Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 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
 
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
 
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
 
SpeculativeMode SpeculativeModeOfInputs () const
 
virtual SpeculativeMode SpeculativeModeOfInput (intptr_t index) const
 
bool WasEliminated () const
 
virtual intptr_t DeoptimizationTarget () const
 
void InsertBefore (Instruction *next)
 
void InsertAfter (Instruction *prev)
 
InstructionAppendInstruction (Instruction *tail)
 
virtual bool AllowsCSE () 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 MayHaveVisibleEffect () 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 6029 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 6031 of file il.h.

6035 : VariadicDefinition(std::move(inputs), deopt_id),
6036 marshaller_(marshaller),
6037 is_leaf_(is_leaf) {
6038#if defined(DEBUG)
6040 // No argument to an FfiCall should be an unsafe untagged pointer,
6041 // including the target address.
6042 for (intptr_t i = 0; i < InputCount(); i++) {
6043 ASSERT(!InputAt(i)->definition()->MayCreateUnsafeUntaggedPointer());
6044 }
6045#endif
6046 }
#define ASSERT_EQUAL(expected, actual)
Definition assert.h:309
static intptr_t InputCountForMarshaller(const compiler::ffi::CallMarshaller &marshaller)
Definition il.h:6097
virtual bool MayCreateUnsafeUntaggedPointer() const
Definition il.h:6066
InputsIterable inputs()
Definition il.h:1027
intptr_t deopt_id() const
Definition il.h:987
VariadicDefinition(InputsArray &&inputs, intptr_t deopt_id=DeoptId::kNone)
Definition il.h:2755
intptr_t InputCount() const
Definition il.h:2776
Value * InputAt(intptr_t i) const
Definition il.h:2777
#define ASSERT(E)

Member Function Documentation

◆ CanCallDart()

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

Reimplemented from dart::Instruction.

Definition at line 6083 of file il.h.

6083{ return false; }

◆ CanExecuteGeneratedCodeInSafepoint()

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

Definition at line 6093 of file il.h.

6093 {
6094 return FLAG_precompiled_mode;
6095 }

◆ CompoundReturnTypedDataIndex()

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

Definition at line 6056 of file il.h.

6056 {
6057 ASSERT(marshaller_.ReturnsCompound());
6058 return marshaller_.NumArgumentDefinitions() + 1;
6059 }

◆ ComputeCanDeoptimize()

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

Implements dart::Instruction.

Definition at line 6075 of file il.h.

6075{ return false; }

◆ ComputeCanDeoptimizeAfterCall()

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

Reimplemented from dart::Instruction.

Definition at line 6076 of file il.h.

6076 {
6077 return !CompilerState::Current().is_aot();
6078 }
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 7421 of file il.cc.

7424 {
7425 __ Comment("EmitParamMoves");
7426
7427 // Moves for return pointer.
7428 const auto& return_location =
7429 marshaller_.Location(compiler::ffi::kResultIndex);
7430 if (return_location.IsPointerToMemory()) {
7431 __ Comment("return_location.IsPointerToMemory");
7432 const auto& pointer_location =
7433 return_location.AsPointerToMemory().pointer_location();
7434 const auto& pointer_register =
7435 pointer_location.IsRegisters()
7436 ? pointer_location.AsRegisters().reg_at(0)
7437 : temp0;
7438 __ MoveRegister(pointer_register, SPREG);
7439 __ AddImmediate(pointer_register, marshaller_.PassByPointerStackOffset(
7441
7442 if (pointer_location.IsStack()) {
7443 const auto& pointer_stack = pointer_location.AsStack();
7444 __ StoreMemoryValue(pointer_register, pointer_stack.base_register(),
7445 pointer_stack.offset_in_bytes());
7446 }
7447 }
7448
7449 // Moves for arguments.
7450 compiler::ffi::FrameRebase rebase(compiler->zone(), /*old_base=*/FPREG,
7451 /*new_base=*/saved_fp,
7452 /*stack_delta=*/0);
7453 intptr_t def_index = 0;
7454 for (intptr_t arg_index = 0; arg_index < marshaller_.num_args();
7455 arg_index++) {
7456 const intptr_t num_defs = marshaller_.NumDefinitions(arg_index);
7457 const auto& arg_target = marshaller_.Location(arg_index);
7458 __ Comment("arg_index %" Pd " arg_target %s", arg_index,
7459 arg_target.ToCString());
7460
7461 // First deal with moving all individual definitions passed in to the
7462 // FfiCall to the right native location based on calling convention.
7463 for (intptr_t i = 0; i < num_defs; i++) {
7464 if ((arg_target.IsPointerToMemory() ||
7465 marshaller_.IsCompoundPointer(arg_index)) &&
7466 i == 1) {
7467 // The offset_in_bytes is not an argument for C, so don't move it.
7468 // It is used as offset_in_bytes_loc below and moved there if
7469 // necessary.
7470 def_index++;
7471 continue;
7472 }
7473 __ Comment(" def_index %" Pd, def_index);
7474 Location origin = rebase.Rebase(locs()->in(def_index));
7475 const Representation origin_rep = RequiredInputRepresentation(def_index);
7476
7477 // Find the native location where this individual definition should be
7478 // moved to.
7479 const auto& def_target =
7480 arg_target.payload_type().IsPrimitive() ? arg_target
7481 : arg_target.IsMultiple() ? *arg_target.AsMultiple().locations()[i]
7482 : arg_target.IsPointerToMemory()
7483 ? arg_target.AsPointerToMemory().pointer_location()
7484 : /*arg_target.IsStack()*/ arg_target.Split(compiler->zone(),
7485 num_defs, i);
7486
7487 ConstantTemporaryAllocator temp_alloc(temp0);
7488 if (origin.IsConstant()) {
7489 __ Comment("origin.IsConstant()");
7490 ASSERT(!marshaller_.IsHandleCType(arg_index));
7491 ASSERT(!marshaller_.IsTypedDataPointer(arg_index));
7492 ASSERT(!marshaller_.IsCompoundPointer(arg_index));
7493 compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
7494 } else if (origin.IsPairLocation() &&
7495 (origin.AsPairLocation()->At(0).IsConstant() ||
7496 origin.AsPairLocation()->At(1).IsConstant())) {
7497 // Note: half of the pair can be constant.
7498 __ Comment("origin.IsPairLocation() and constant");
7499 ASSERT(!marshaller_.IsHandleCType(arg_index));
7500 ASSERT(!marshaller_.IsTypedDataPointer(arg_index));
7501 ASSERT(!marshaller_.IsCompoundPointer(arg_index));
7502 compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
7503 } else if (marshaller_.IsHandleCType(arg_index)) {
7504 __ Comment("marshaller_.IsHandleCType(arg_index)");
7505 // Handles are passed into FfiCalls as Tagged values on the stack, and
7506 // then we pass pointers to these handles to the native function here.
7507 ASSERT(origin_rep == kTagged);
7508 ASSERT(compiler::target::LocalHandle::ptr_offset() == 0);
7509 ASSERT(compiler::target::LocalHandle::InstanceSize() ==
7510 compiler::target::kWordSize);
7511 ASSERT(num_defs == 1);
7512 ASSERT(origin.IsStackSlot());
7513 if (def_target.IsRegisters()) {
7514 __ AddImmediate(def_target.AsLocation().reg(), origin.base_reg(),
7515 origin.stack_index() * compiler::target::kWordSize);
7516 } else {
7517 ASSERT(def_target.IsStack());
7518 const auto& target_stack = def_target.AsStack();
7519 __ AddImmediate(temp0, origin.base_reg(),
7520 origin.stack_index() * compiler::target::kWordSize);
7521 __ StoreToOffset(temp0, target_stack.base_register(),
7522 target_stack.offset_in_bytes());
7523 }
7524 } else {
7525 __ Comment("def_target %s <- origin %s %s",
7526 def_target.ToCString(compiler->zone()), origin.ToCString(),
7527 RepresentationUtils::ToCString(origin_rep));
7528#ifdef DEBUG
7529 // Stack arguments split are in word-size chunks. These chunks can copy
7530 // too much. However, that doesn't matter in practise because we process
7531 // the stack in order.
7532 // It only matters for the last chunk, it should not overwrite what was
7533 // already on the stack.
7534 if (def_target.IsStack()) {
7535 const auto& def_target_stack = def_target.AsStack();
7536 ASSERT(def_target_stack.offset_in_bytes() +
7537 def_target.payload_type().SizeInBytes() <=
7538 marshaller_.RequiredStackSpaceInBytes());
7539 }
7540#endif
7541 if (marshaller_.IsTypedDataPointer(arg_index) ||
7542 marshaller_.IsCompoundPointer(arg_index)) {
7543 // Unwrap typed data before move to native location.
7544 __ Comment("Load typed data base address");
7545 if (origin.IsStackSlot()) {
7546 compiler->EmitMove(Location::RegisterLocation(temp0), origin,
7547 &temp_alloc);
7548 origin = Location::RegisterLocation(temp0);
7549 }
7550 ASSERT(origin.IsRegister());
7551 __ LoadFromSlot(origin.reg(), origin.reg(), Slot::PointerBase_data());
7552 if (marshaller_.IsCompoundPointer(arg_index)) {
7553 __ Comment("Load offset in bytes");
7554 const intptr_t offset_in_bytes_def_index = def_index + 1;
7555 const Location offset_in_bytes_loc =
7556 rebase.Rebase(locs()->in(offset_in_bytes_def_index));
7557 Register offset_in_bytes_reg = kNoRegister;
7558 if (offset_in_bytes_loc.IsRegister()) {
7559 offset_in_bytes_reg = offset_in_bytes_loc.reg();
7560 } else {
7561 offset_in_bytes_reg = temp1;
7562 NoTemporaryAllocator no_temp;
7563 compiler->EmitMove(
7564 Location::RegisterLocation(offset_in_bytes_reg),
7565 offset_in_bytes_loc, &no_temp);
7566 }
7567 __ AddRegisters(origin.reg(), offset_in_bytes_reg);
7568 }
7569 }
7570 compiler->EmitMoveToNative(def_target, origin, origin_rep, &temp_alloc);
7571 }
7572 def_index++;
7573 }
7574
7575 // Then make sure that any pointers passed through the calling convention
7576 // actually have a copy of the struct.
7577 // Note that the step above has already moved the pointer into the expected
7578 // native location.
7579 if (arg_target.IsPointerToMemory()) {
7580 __ Comment("arg_target.IsPointerToMemory");
7581 NoTemporaryAllocator temp_alloc;
7582 const auto& pointer_loc =
7583 arg_target.AsPointerToMemory().pointer_location();
7584
7585 // TypedData data pointed to in temp.
7586 const auto& dst = compiler::ffi::NativeRegistersLocation(
7587 compiler->zone(), pointer_loc.payload_type(),
7588 pointer_loc.container_type(), temp0);
7589 compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
7590 __ LoadFromSlot(temp0, temp0, Slot::PointerBase_data());
7591
7592 __ Comment("IsPointerToMemory add offset");
7593 const intptr_t offset_in_bytes_def_index =
7594 def_index - 1; // ++'d already.
7595 const Location offset_in_bytes_loc =
7596 rebase.Rebase(locs()->in(offset_in_bytes_def_index));
7597 Register offset_in_bytes_reg = kNoRegister;
7598 if (offset_in_bytes_loc.IsRegister()) {
7599 offset_in_bytes_reg = offset_in_bytes_loc.reg();
7600 } else {
7601 offset_in_bytes_reg = temp1;
7602 NoTemporaryAllocator no_temp;
7603 compiler->EmitMove(Location::RegisterLocation(offset_in_bytes_reg),
7604 offset_in_bytes_loc, &no_temp);
7605 }
7606 __ AddRegisters(temp0, offset_in_bytes_reg);
7607
7608 // Copy chunks. The destination may be rounded up to a multiple of the
7609 // word size, because we do the same rounding when we allocate the space
7610 // on the stack. But source may not be allocated by the VM and end at a
7611 // page boundary.
7612 __ Comment("IsPointerToMemory copy chunks");
7613 const intptr_t sp_offset =
7614 marshaller_.PassByPointerStackOffset(arg_index);
7615 __ UnrolledMemCopy(SPREG, sp_offset, temp0, 0,
7616 arg_target.payload_type().SizeInBytes(), temp1);
7617
7618 // Store the stack address in the argument location.
7619 __ MoveRegister(temp0, SPREG);
7620 __ AddImmediate(temp0, sp_offset);
7621 const auto& src = compiler::ffi::NativeRegistersLocation(
7622 compiler->zone(), pointer_loc.payload_type(),
7623 pointer_loc.container_type(), temp0);
7624 __ Comment("pointer_loc %s <- src %s", pointer_loc.ToCString(),
7625 src.ToCString());
7626 compiler->EmitNativeMove(pointer_loc, src, &temp_alloc);
7627 }
7628 }
7629
7630 __ Comment("EmitParamMovesEnd");
7631}
#define __
virtual Representation RequiredInputRepresentation(intptr_t idx) const
Definition il.cc:7351
LocationSummary * locs()
Definition il.h:1186
static Location RegisterLocation(Register reg)
Definition locations.h:398
const intptr_t kResultIndex
Definition marshaller.h:28
Representation
Definition locations.h:66
@ kNoRegister
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 7633 of file il.cc.

7635 {
7636 const auto& returnLocation =
7637 marshaller_.Location(compiler::ffi::kResultIndex);
7638 if (returnLocation.payload_type().IsVoid()) {
7639 return;
7640 }
7641
7642 __ Comment("EmitReturnMoves");
7643
7644 NoTemporaryAllocator no_temp;
7645 if (returnLocation.IsRegisters() || returnLocation.IsFpuRegisters()) {
7646 const auto& src = returnLocation;
7647 const Location dst_loc = locs()->out(0);
7648 const Representation dst_type = representation();
7649 compiler->EmitMoveFromNative(dst_loc, dst_type, src, &no_temp);
7650 } else if (marshaller_.ReturnsCompound()) {
7651 ASSERT(returnLocation.payload_type().IsCompound());
7652
7653 // Get the typed data pointer which we have pinned to a stack slot.
7654 const Location typed_data_loc = locs()->in(CompoundReturnTypedDataIndex());
7655 if (typed_data_loc.IsStackSlot()) {
7656 ASSERT(typed_data_loc.base_reg() == FPREG);
7657 // If this is a leaf call there is no extra call frame to step through.
7658 if (is_leaf_) {
7659 __ LoadMemoryValue(temp0, FPREG, typed_data_loc.ToStackSlotOffset());
7660 } else {
7661 __ LoadMemoryValue(
7662 temp0, FPREG,
7663 kSavedCallerFpSlotFromFp * compiler::target::kWordSize);
7664 __ LoadMemoryValue(temp0, temp0, typed_data_loc.ToStackSlotOffset());
7665 }
7666 } else {
7667 compiler->EmitMove(Location::RegisterLocation(temp0), typed_data_loc,
7668 &no_temp);
7669 }
7670 __ LoadFromSlot(temp0, temp0, Slot::PointerBase_data());
7671
7672 if (returnLocation.IsPointerToMemory()) {
7673 // Copy blocks from the stack location to TypedData.
7674 // Struct size is rounded up to a multiple of target::kWordSize.
7675 // This is safe because we do the same rounding when we allocate the
7676 // TypedData in IL.
7677 const intptr_t sp_offset =
7678 marshaller_.PassByPointerStackOffset(compiler::ffi::kResultIndex);
7679 __ UnrolledMemCopy(temp0, 0, SPREG, sp_offset,
7680 marshaller_.CompoundReturnSizeInBytes(), temp1);
7681 } else {
7682 ASSERT(returnLocation.IsMultiple());
7683 // Copy to the struct from the native locations.
7684 const auto& multiple =
7685 marshaller_.Location(compiler::ffi::kResultIndex).AsMultiple();
7686
7687 int offset_in_bytes = 0;
7688 for (int i = 0; i < multiple.locations().length(); i++) {
7689 const auto& src = *multiple.locations().At(i);
7690 const auto& dst = compiler::ffi::NativeStackLocation(
7691 src.payload_type(), src.container_type(), temp0, offset_in_bytes);
7692 compiler->EmitNativeMove(dst, src, &no_temp);
7693 offset_in_bytes += src.payload_type().SizeInBytes();
7694 }
7695 }
7696 } else {
7697 UNREACHABLE();
7698 }
7699
7700 __ Comment("EmitReturnMovesEnd");
7701}
#define UNREACHABLE()
Definition assert.h:248
intptr_t CompoundReturnTypedDataIndex() const
Definition il.h:6056
virtual Representation representation() const
Definition il.cc:7946
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 6080 of file il.h.

6080{ return true; }

◆ InputCountForMarshaller()

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

Definition at line 6097 of file il.h.

6098 {
6099 return marshaller.NumArgumentDefinitions() + 1 +
6100 (marshaller.ReturnsCompound() ? 1 : 0);
6101 }

◆ MayCreateUnsafeUntaggedPointer()

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

Reimplemented from dart::Definition.

Definition at line 6066 of file il.h.

6066 {
6067 // The only case where we have an untagged result is when the return
6068 // value is a pointer, which is then stored in a newly allocated FFI
6069 // Pointer object by the generated IL, so the C code must return an
6070 // external (not GC-movable) address to Dart.
6071 return false;
6072 }

◆ MayThrow()

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

Implements dart::Instruction.

Definition at line 6061 of file il.h.

6061 {
6062 // By Dart_PropagateError.
6063 return true;
6064 }

◆ representation()

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

Reimplemented from dart::Instruction.

Definition at line 7946 of file il.cc.

7946 {
7947 if (marshaller_.ReturnsCompound()) {
7948 // Don't care, we're discarding the value.
7949 return kTagged;
7950 }
7951 if (marshaller_.IsHandleCType(compiler::ffi::kResultIndex)) {
7952 // The call returns a Dart_Handle, from which we need to extract the
7953 // tagged pointer using LoadField with an appropriate slot.
7954 return kUntagged;
7955 }
7956 return marshaller_.RepInFfiCall(compiler::ffi::kResultIndex);
7957}

◆ RequiredInputRepresentation()

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

Reimplemented from dart::Instruction.

Definition at line 7351 of file il.cc.

7351 {
7352 if (idx < TargetAddressIndex()) {
7353 // All input handles are passed as tagged values to FfiCallInstr and
7354 // are given stack locations. FfiCallInstr then passes an untagged pointer
7355 // to the handle on the stack (Dart_Handle) to the C function.
7356 if (marshaller_.IsHandleCType(marshaller_.ArgumentIndex(idx))) {
7357 return kTagged;
7358 }
7359 return marshaller_.RepInFfiCall(idx);
7360 } else if (idx == TargetAddressIndex()) {
7361#if defined(DEBUG)
7362 auto const rep =
7364 ASSERT(rep == kUntagged || rep == kUnboxedAddress);
7365#endif
7366 return kNoRepresentation; // Allows kUntagged or kUnboxedAddress.
7367 } else {
7369 return kTagged;
7370 }
7371}
intptr_t TargetAddressIndex() const
Definition il.h:6051
virtual Representation representation() const
Definition il.h:1254
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 6051 of file il.h.

6051 {
6052 return marshaller_.NumArgumentDefinitions();
6053 }

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