mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 18:49:37 +00:00
[dart2wasm] Represent ffi compounds as actual Dart objects (they are views on the actual memory)
This fixes issues where structs are accessed dynamically or simply accessed in a nullable fashion, e.g. with `MyStruct? foo` dart2wasm does not yet support using structs-by-value as arguments or return values when calling linear-memory wasm functions. dart2wasm also doesn't support structs-by-value created in dart that are backed by WasmGC memory (e.g. arrays). Change-Id: I9b9c60002d2d32db3f235f1cec25fe3b35fcc17b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365140 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Slava Egorov <vegorov@google.com>
This commit is contained in:
parent
60a0cd6e1c
commit
24370b42b0
|
@ -737,7 +737,6 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
|
|||
if (translator.needsConversion(thisLocal!.type, thisType) &&
|
||||
!(cls == translator.objectInfo.cls ||
|
||||
cls == translator.ffiPointerClass ||
|
||||
translator.isFfiCompound(cls) ||
|
||||
translator.isWasmType(cls))) {
|
||||
preciseThisLocal = addLocal(thisType);
|
||||
b.local_get(thisLocal!);
|
||||
|
|
|
@ -182,26 +182,6 @@ class Intrinsifier {
|
|||
return w.NumType.i64;
|
||||
}
|
||||
|
||||
// _Compound._typedDataBase
|
||||
if (cls == translator.ffiCompoundClass && name == '_typedDataBase') {
|
||||
// A compound (subclass of Struct or Union) is represented by its i32
|
||||
// address. The _typedDataBase field contains a Pointer pointing to the
|
||||
// compound, whose representation is the same.
|
||||
// TODO(https://dartbug.com/55083): Implement structs backed by TypedData.
|
||||
codeGen.wrap(receiver, w.NumType.i32);
|
||||
return w.NumType.i32;
|
||||
}
|
||||
|
||||
// _Compound._offsetInBytes
|
||||
if (cls == translator.ffiCompoundClass && name == '_offsetInBytes') {
|
||||
// A compound (subclass of Struct or Union) is represented by its i32
|
||||
// address. The _offsetInBytes field contains is always 0.
|
||||
// This also breaks nested structs, which are currently not used.
|
||||
// TODO(https://dartbug.com/55083): Implement structs backed by TypedData.
|
||||
b.i64_const(0);
|
||||
return w.NumType.i64;
|
||||
}
|
||||
|
||||
// Pointer.address
|
||||
if (cls == translator.ffiPointerClass && name == 'address') {
|
||||
// A Pointer is represented by its i32 address.
|
||||
|
@ -1120,15 +1100,6 @@ class Intrinsifier {
|
|||
return w.RefType.def(arrayType, nullable: false);
|
||||
}
|
||||
|
||||
// _Compound.#fromTypedDataBase
|
||||
if (name == "#fromTypedDataBase") {
|
||||
// A compound (subclass of Struct or Union) is represented by its i32
|
||||
// address. The argument to the #fromTypedDataBase constructor is a
|
||||
// Pointer, whose representation is the same.
|
||||
codeGen.wrap(node.arguments.positional.single, w.NumType.i32);
|
||||
return w.NumType.i32;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -523,8 +523,6 @@ class Translator with KernelNodes {
|
|||
bool isWasmType(Class cls) =>
|
||||
cls == wasmTypesBaseClass || _hasSuperclass(cls, wasmTypesBaseClass);
|
||||
|
||||
bool isFfiCompound(Class cls) => _hasSuperclass(cls, ffiCompoundClass);
|
||||
|
||||
w.StorageType translateStorageType(DartType type) {
|
||||
bool nullable = type.isPotentiallyNullable;
|
||||
if (type is InterfaceType) {
|
||||
|
@ -569,12 +567,6 @@ class Translator with KernelNodes {
|
|||
return w.RefType.def(wasmType, nullable: nullable);
|
||||
}
|
||||
|
||||
// FFI compound?
|
||||
if (isFfiCompound(cls)) {
|
||||
if (nullable) throw "FFI types can't be nullable";
|
||||
return w.NumType.i32;
|
||||
}
|
||||
|
||||
// Other built-in type?
|
||||
w.StorageType? builtin = builtinTypes[cls];
|
||||
if (builtin != null) {
|
||||
|
@ -668,9 +660,6 @@ class Translator with KernelNodes {
|
|||
if (builtin != null && builtin.isPrimitive) {
|
||||
return builtin as w.ValueType;
|
||||
}
|
||||
if (isFfiCompound(cls)) {
|
||||
return w.NumType.i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO(joshualitt): We'd like to use the potential nullability here too,
|
||||
|
|
|
@ -143,12 +143,19 @@ void main() {
|
|||
toggleBool();
|
||||
Expect.equals(boolReturn(789), false);
|
||||
|
||||
final struct_ = getStruct();
|
||||
Expect.equals(struct_.ref.x, 1.0);
|
||||
Expect.equals(struct_.ref.y, 2);
|
||||
clearStruct(struct_);
|
||||
Expect.equals(struct_.ref.x, 0.0);
|
||||
Expect.equals(struct_.ref.y, 0);
|
||||
final Pointer<MyStruct> structPointer = getStruct();
|
||||
final MyStruct struct = structPointer.ref;
|
||||
Expect.equals(struct.x, 1.0);
|
||||
Expect.equals(struct.y, 2);
|
||||
// Structs are Dart objects that are views on top of actual memory (which may
|
||||
// be backed by C memory or typed data). The view objects can be accessed
|
||||
// dynamically.
|
||||
final l = <dynamic>[struct, 1];
|
||||
Expect.equals(l[int.parse('0')].x, 1.0);
|
||||
|
||||
clearStruct(structPointer);
|
||||
Expect.equals(struct.x, 0.0);
|
||||
Expect.equals(struct.y, 0);
|
||||
|
||||
Expect.equals(incrementChar(1), 2);
|
||||
Expect.equals(incrementUnsignedChar(3), 4);
|
||||
|
|
Loading…
Reference in a new issue