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_MARSHALLER_H_
6#define RUNTIME_VM_COMPILER_FFI_MARSHALLER_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/globals.h>
13
14#include "vm/compiler/backend/locations.h"
15#include "vm/compiler/ffi/callback.h"
16#include "vm/compiler/ffi/native_calling_convention.h"
17#include "vm/compiler/ffi/native_location.h"
18#include "vm/compiler/ffi/native_type.h"
19#include "vm/object.h"
20
21namespace dart {
22
23namespace compiler {
24
25namespace ffi {
26
27// Provides the mapping from the native calling convention to the Dart calling
28// convention.
29//
30// This class is set up in a query-able way so that it's underlying logic can
31// be extended to support more native ABI features and calling conventions.
32//
33// TODO(36730): Add a way to query arguments that are broken into multiple
34// parts.
35class BaseMarshaller : public NativeCallingConvention {
36 public:
37 // Unboxed representation on how the value is passed or received from regular
38 // Dart code.
39 Representation RepInDart(intptr_t arg_index) const {
40 return Location(arg_index).payload_type().AsRepresentationOverApprox(zone_);
41 }
42
43 // Representation on how the value is passed to or recieved from the FfiCall
44 // instruction or StaticCall, NativeParameter, and NativeReturn instructions.
45 Representation RepInFfiCall(intptr_t arg_index) const {
46 if (Location(arg_index).container_type().IsInt() &&
47 Location(arg_index).payload_type().IsFloat()) {
48 return Location(arg_index).container_type().AsRepresentationOverApprox(
49 zone_);
50 }
51 return Location(arg_index).payload_type().AsRepresentationOverApprox(zone_);
52 }
53
54 // Bitcasting floats to ints, only required in SoftFP.
55 bool RequiresBitCast(intptr_t index) const {
56 return Location(index).payload_type().IsFloat() &&
57 Location(index).container_type().IsInt();
58 }
59
60 // 8 or 16 bit int value to sign extend from.
61 const NativeType& SignExtendFrom(intptr_t arg_index) const {
62 return Location(arg_index).payload_type();
63 }
64
65 // Requires boxing or unboxing.
66 bool IsPointer(intptr_t arg_index) const {
67 return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
68 kFfiPointerCid;
69 }
70 bool IsHandle(intptr_t arg_index) const {
71 return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
72 kFfiHandleCid;
73 }
74
75 // Treated as a null constant in Dart.
76 bool IsVoid(intptr_t arg_index) const {
77 return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
78 kFfiVoidCid;
79 }
80
81 bool ContainsHandles() const;
82
83 StringPtr function_name() const { return dart_signature_.name(); }
84
85 protected:
86 BaseMarshaller(Zone* zone, const Function& dart_signature)
87 : NativeCallingConvention(
88 zone,
89 Function::ZoneHandle(zone, dart_signature.FfiCSignature())),
90 dart_signature_(dart_signature) {
91 ASSERT(dart_signature_.IsZoneHandle());
92 }
93
94 private:
95 // Contains the function pointer as argument #0.
96 // The Dart signature is used for the function and argument names.
97 const Function& dart_signature_;
98};
99
100class CallMarshaller : public BaseMarshaller {
101 public:
102 CallMarshaller(Zone* zone, const Function& dart_signature)
103 : BaseMarshaller(zone, dart_signature) {}
104
105 dart::Location LocInFfiCall(intptr_t arg_index) const;
106};
107
108class CallbackMarshaller : public BaseMarshaller {
109 public:
110 CallbackMarshaller(Zone* zone, const Function& dart_signature);
111
112 // All parameters are saved on stack to do safe-point transition.
113 const NativeLocation& NativeLocationOfNativeParameter(
114 intptr_t arg_index) const {
115 if (arg_index == kResultIndex) {
116 // No moving around of result.
117 return Location(arg_index);
118 }
119 return *callback_locs_.At(arg_index);
120 }
121
122 // All parameters are saved on stack to do safe-point transition.
123 dart::Location LocationOfNativeParameter(intptr_t arg_index) const {
124 return NativeLocationOfNativeParameter(arg_index).AsLocation();
125 }
126
127 protected:
128 const NativeLocations& callback_locs_;
129};
130
131} // namespace ffi
132
133} // namespace compiler
134
135} // namespace dart
136
137#endif // RUNTIME_VM_COMPILER_FFI_MARSHALLER_H_
138