mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
[vm/ffi] Make elementAt
an extension method
The CFE rewrite for structs, unions, and abi-specific integers is now done on the extension methods. The other native types are implemented in the extension methods directly. TEST=test/ffi Closes: https://github.com/dart-lang/sdk/issues/50714 Change-Id: I578325733e3cd66200e80949d47ff12a13115b99 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/276102 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
parent
3d3fdc7b46
commit
2435f0b398
6 changed files with 162 additions and 122 deletions
|
@ -113,7 +113,7 @@ const Map<NativeType, int> nativeTypeSizes = <NativeType, int>{
|
|||
NativeType.kBool: 1,
|
||||
};
|
||||
|
||||
/// Load, store, and elementAt are rewired to their static type for these types.
|
||||
/// Load and store are rewired to their static type for these types.
|
||||
const List<NativeType> optimizedTypes = [
|
||||
NativeType.kBool,
|
||||
NativeType.kInt8,
|
||||
|
@ -201,16 +201,19 @@ class FfiTransformer extends Transformer {
|
|||
final Procedure allocatorAllocateMethod;
|
||||
final Procedure castMethod;
|
||||
final Procedure offsetByMethod;
|
||||
final Procedure elementAtMethod;
|
||||
final Procedure addressGetter;
|
||||
final Procedure structPointerGetRef;
|
||||
final Procedure structPointerSetRef;
|
||||
final Procedure structPointerGetElemAt;
|
||||
final Procedure structPointerSetElemAt;
|
||||
final Procedure structPointerElementAt;
|
||||
final Procedure structPointerElementAtTearoff;
|
||||
final Procedure unionPointerGetRef;
|
||||
final Procedure unionPointerSetRef;
|
||||
final Procedure unionPointerGetElemAt;
|
||||
final Procedure unionPointerSetElemAt;
|
||||
final Procedure unionPointerElementAt;
|
||||
final Procedure unionPointerElementAtTearoff;
|
||||
final Procedure structArrayElemAt;
|
||||
final Procedure unionArrayElemAt;
|
||||
final Procedure arrayArrayElemAt;
|
||||
|
@ -219,6 +222,8 @@ class FfiTransformer extends Transformer {
|
|||
final Procedure abiSpecificIntegerPointerSetValue;
|
||||
final Procedure abiSpecificIntegerPointerElemAt;
|
||||
final Procedure abiSpecificIntegerPointerSetElemAt;
|
||||
final Procedure abiSpecificIntegerPointerElementAt;
|
||||
final Procedure abiSpecificIntegerPointerElementAtTearoff;
|
||||
final Procedure abiSpecificIntegerArrayElemAt;
|
||||
final Procedure abiSpecificIntegerArraySetElemAt;
|
||||
final Procedure asFunctionMethod;
|
||||
|
@ -246,7 +251,6 @@ class FfiTransformer extends Transformer {
|
|||
final Map<NativeType, Procedure> loadUnalignedMethods;
|
||||
final Map<NativeType, Procedure> storeMethods;
|
||||
final Map<NativeType, Procedure> storeUnalignedMethods;
|
||||
final Map<NativeType, Procedure> elementAtMethods;
|
||||
final Procedure loadAbiSpecificIntMethod;
|
||||
final Procedure loadAbiSpecificIntAtIndexMethod;
|
||||
final Procedure storeAbiSpecificIntMethod;
|
||||
|
@ -363,8 +367,6 @@ class FfiTransformer extends Transformer {
|
|||
index.getProcedure('dart:ffi', 'Allocator', 'allocate'),
|
||||
castMethod = index.getProcedure('dart:ffi', 'Pointer', 'cast'),
|
||||
offsetByMethod = index.getProcedure('dart:ffi', 'Pointer', '_offsetBy'),
|
||||
elementAtMethod =
|
||||
index.getProcedure('dart:ffi', 'Pointer', 'elementAt'),
|
||||
addressGetter =
|
||||
index.getProcedure('dart:ffi', 'Pointer', 'get:address'),
|
||||
compoundTypedDataBaseField =
|
||||
|
@ -397,6 +399,10 @@ class FfiTransformer extends Transformer {
|
|||
index.getProcedure('dart:ffi', 'StructPointer', '[]'),
|
||||
structPointerSetElemAt =
|
||||
index.getProcedure('dart:ffi', 'StructPointer', '[]='),
|
||||
structPointerElementAt =
|
||||
index.getProcedure('dart:ffi', 'StructPointer', 'elementAt'),
|
||||
structPointerElementAtTearoff = index.getProcedure('dart:ffi',
|
||||
'StructPointer', LibraryIndex.tearoffPrefix + 'elementAt'),
|
||||
unionPointerGetRef =
|
||||
index.getProcedure('dart:ffi', 'UnionPointer', 'get:ref'),
|
||||
unionPointerSetRef =
|
||||
|
@ -405,6 +411,10 @@ class FfiTransformer extends Transformer {
|
|||
index.getProcedure('dart:ffi', 'UnionPointer', '[]'),
|
||||
unionPointerSetElemAt =
|
||||
index.getProcedure('dart:ffi', 'UnionPointer', '[]='),
|
||||
unionPointerElementAt =
|
||||
index.getProcedure('dart:ffi', 'UnionPointer', 'elementAt'),
|
||||
unionPointerElementAtTearoff = index.getProcedure('dart:ffi',
|
||||
'UnionPointer', LibraryIndex.tearoffPrefix + 'elementAt'),
|
||||
structArrayElemAt = index.getProcedure('dart:ffi', 'StructArray', '[]'),
|
||||
unionArrayElemAt = index.getProcedure('dart:ffi', 'UnionArray', '[]'),
|
||||
arrayArrayElemAt = index.getProcedure('dart:ffi', 'ArrayArray', '[]'),
|
||||
|
@ -418,6 +428,12 @@ class FfiTransformer extends Transformer {
|
|||
index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '[]'),
|
||||
abiSpecificIntegerPointerSetElemAt =
|
||||
index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '[]='),
|
||||
abiSpecificIntegerPointerElementAt = index.getProcedure(
|
||||
'dart:ffi', 'AbiSpecificIntegerPointer', 'elementAt'),
|
||||
abiSpecificIntegerPointerElementAtTearoff = index.getProcedure(
|
||||
'dart:ffi',
|
||||
'AbiSpecificIntegerPointer',
|
||||
LibraryIndex.tearoffPrefix + 'elementAt'),
|
||||
abiSpecificIntegerArrayElemAt =
|
||||
index.getProcedure('dart:ffi', 'AbiSpecificIntegerArray', '[]'),
|
||||
abiSpecificIntegerArraySetElemAt =
|
||||
|
@ -462,10 +478,6 @@ class FfiTransformer extends Transformer {
|
|||
return index.getTopLevelProcedure(
|
||||
'dart:ffi', "_store${name}Unaligned");
|
||||
}),
|
||||
elementAtMethods = Map.fromIterable(optimizedTypes, value: (t) {
|
||||
final name = nativeTypeClassNames[t];
|
||||
return index.getTopLevelProcedure('dart:ffi', "_elementAt$name");
|
||||
}),
|
||||
loadAbiSpecificIntMethod =
|
||||
index.getTopLevelProcedure('dart:ffi', "_loadAbiSpecificInt"),
|
||||
loadAbiSpecificIntAtIndexMethod = index.getTopLevelProcedure(
|
||||
|
|
|
@ -123,7 +123,10 @@ mixin _FfiUseSiteTransformer on FfiTransformer {
|
|||
node.isExtensionMember &&
|
||||
(node == allocationTearoff ||
|
||||
node == asFunctionTearoff ||
|
||||
node == lookupFunctionTearoff));
|
||||
node == lookupFunctionTearoff ||
|
||||
node == abiSpecificIntegerPointerElementAtTearoff ||
|
||||
node == structPointerElementAtTearoff ||
|
||||
node == unionPointerElementAtTearoff));
|
||||
final result = super.visitProcedure(node);
|
||||
_inFfiTearoff = false;
|
||||
return result;
|
||||
|
@ -201,6 +204,28 @@ mixin _FfiUseSiteTransformer on FfiTransformer {
|
|||
ensureNativeTypeValid(nativeType, node, allowCompounds: true);
|
||||
|
||||
return _replaceSetRef(node);
|
||||
} else if (target == abiSpecificIntegerPointerElementAt ||
|
||||
target == structPointerElementAt ||
|
||||
target == unionPointerElementAt) {
|
||||
final pointer = node.arguments.positional[0];
|
||||
final index = node.arguments.positional[1];
|
||||
final pointerType =
|
||||
pointer.getStaticType(staticTypeContext!) as InterfaceType;
|
||||
ensureNativeTypeValid(pointerType, pointer,
|
||||
allowCompounds: true, allowInlineArray: true);
|
||||
final DartType nativeType = node.arguments.types[0];
|
||||
|
||||
ensureNativeTypeValid(nativeType, node, allowCompounds: true);
|
||||
|
||||
Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
|
||||
if (inlineSizeOf != null) {
|
||||
// Generates `receiver.offsetBy(inlineSizeOfExpression)`.
|
||||
return InstanceInvocation(InstanceAccessKind.Instance, pointer,
|
||||
offsetByMethod.name, Arguments([multiply(index, inlineSizeOf)]),
|
||||
interfaceTarget: offsetByMethod,
|
||||
functionType: Substitution.fromInterfaceType(pointerType)
|
||||
.substituteType(offsetByMethod.getterType) as FunctionType);
|
||||
}
|
||||
} else if (target == structArrayElemAt || target == unionArrayElemAt) {
|
||||
final DartType nativeType = node.arguments.types[0];
|
||||
|
||||
|
@ -704,60 +729,6 @@ mixin _FfiUseSiteTransformer on FfiTransformer {
|
|||
..fileOffset = node.fileOffset);
|
||||
}
|
||||
|
||||
@override
|
||||
visitInstanceInvocation(InstanceInvocation node) {
|
||||
final modifiedExpression = _visitInstanceInvocation(node);
|
||||
if (node == modifiedExpression) {
|
||||
return super.visitInstanceInvocation(node);
|
||||
}
|
||||
// We've just created this node. We're likely not going to need to transform
|
||||
// this node itself. Visit its sub expressions.
|
||||
return super.defaultExpression(modifiedExpression);
|
||||
}
|
||||
|
||||
/// Replaces nodes if they match. Does not invoke any super visit.
|
||||
Expression _visitInstanceInvocation(InstanceInvocation node) {
|
||||
if (_inFfiTearoff) {
|
||||
return node;
|
||||
}
|
||||
final Member target = node.interfaceTarget;
|
||||
try {
|
||||
if (target == elementAtMethod) {
|
||||
final DartType pointerType =
|
||||
node.receiver.getStaticType(staticTypeContext!);
|
||||
final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
|
||||
|
||||
ensureNativeTypeValid(nativeType, node, allowCompounds: true);
|
||||
|
||||
Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
|
||||
if (inlineSizeOf != null) {
|
||||
// Generates `receiver.offsetBy(inlineSizeOfExpression)`.
|
||||
return InstanceInvocation(
|
||||
InstanceAccessKind.Instance,
|
||||
node.receiver,
|
||||
offsetByMethod.name,
|
||||
Arguments(
|
||||
[multiply(node.arguments.positional.single, inlineSizeOf)]),
|
||||
interfaceTarget: offsetByMethod,
|
||||
functionType:
|
||||
Substitution.fromInterfaceType(pointerType as InterfaceType)
|
||||
.substituteType(offsetByMethod.getterType)
|
||||
as FunctionType);
|
||||
}
|
||||
}
|
||||
} on FfiStaticTypeError {
|
||||
// It's OK to swallow the exception because the diagnostics issued will
|
||||
// cause compilation to fail. By continuing, we can report more
|
||||
// diagnostics before compilation ends.
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
DartType? _pointerTypeGetTypeArg(DartType pointerType) {
|
||||
return pointerType is InterfaceType ? pointerType.typeArguments[0] : null;
|
||||
}
|
||||
|
||||
void _ensureIsStaticFunction(Expression node) {
|
||||
if ((node is StaticGet && node.target is Procedure) ||
|
||||
(node is ConstantExpression &&
|
||||
|
|
|
@ -192,6 +192,9 @@ $platform$truncate$alignment external $dartType operator [](int index);
|
|||
/// The $property at `address + ${sizeTimes}index`.
|
||||
$platform$truncate$alignment external void operator []=(int index, $dartType value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<$nativeType> elementAt(int index);
|
||||
|
||||
$asTypedList
|
||||
}
|
||||
|
||||
|
@ -237,7 +240,7 @@ void generatePatchExtension(
|
|||
if (container == "Pointer") {
|
||||
buffer.write("""
|
||||
extension ${nativeType}Pointer on Pointer<$nativeType> {
|
||||
@patch
|
||||
@patch
|
||||
$dartType get value => _load$nativeType(this, 0);
|
||||
|
||||
@patch
|
||||
|
@ -249,6 +252,9 @@ extension ${nativeType}Pointer on Pointer<$nativeType> {
|
|||
@patch
|
||||
operator []=(int index, $dartType value) => _store$nativeType(this, ${sizeTimes}index, value);
|
||||
|
||||
@patch
|
||||
Pointer<$nativeType> elementAt(int index) => Pointer.fromAddress(address + ${sizeTimes}index);
|
||||
|
||||
$asTypedList
|
||||
}
|
||||
|
||||
|
@ -329,9 +335,12 @@ class Config {
|
|||
final int elementSize;
|
||||
final Version? since;
|
||||
const Config(
|
||||
this.nativeType, this.dartType, this.typedListType, this.elementSize,
|
||||
{Version? since})
|
||||
: since = since;
|
||||
this.nativeType,
|
||||
this.dartType,
|
||||
this.typedListType,
|
||||
this.elementSize, {
|
||||
Version? since,
|
||||
}) : since = since;
|
||||
}
|
||||
|
||||
const String kDoNotEmit = "donotemit";
|
||||
|
|
|
@ -176,14 +176,6 @@ class Pointer<T extends NativeType> {
|
|||
@pragma("vm:external-name", "Ffi_address")
|
||||
external int get address;
|
||||
|
||||
// For statically known types, this is rewritten.
|
||||
@patch
|
||||
Pointer<T> elementAt(int index) {
|
||||
// This case should have been rewritten in pre-processing.
|
||||
// Only dynamic invocations are not rewritten in pre-processing.
|
||||
throw UnsupportedError("Pointer.elementAt cannot be called dynamically.");
|
||||
}
|
||||
|
||||
@patch
|
||||
Pointer<T> _offsetBy(int offsetInBytes) =>
|
||||
Pointer.fromAddress(address + offsetInBytes);
|
||||
|
@ -447,43 +439,6 @@ bool _loadBool(Object typedDataBase, int offsetInBytes) =>
|
|||
void _storeBool(Object typedDataBase, int offsetInBytes, bool value) =>
|
||||
_storeUint8(typedDataBase, offsetInBytes, value ? 1 : 0);
|
||||
|
||||
Pointer<Bool> _elementAtBool(Pointer<Bool> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 1 * index);
|
||||
|
||||
Pointer<Int8> _elementAtInt8(Pointer<Int8> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 1 * index);
|
||||
|
||||
Pointer<Int16> _elementAtInt16(Pointer<Int16> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 2 * index);
|
||||
|
||||
Pointer<Int32> _elementAtInt32(Pointer<Int32> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 4 * index);
|
||||
|
||||
Pointer<Int64> _elementAtInt64(Pointer<Int64> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 8 * index);
|
||||
|
||||
Pointer<Uint8> _elementAtUint8(Pointer<Uint8> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 1 * index);
|
||||
|
||||
Pointer<Uint16> _elementAtUint16(Pointer<Uint16> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 2 * index);
|
||||
|
||||
Pointer<Uint32> _elementAtUint32(Pointer<Uint32> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 4 * index);
|
||||
|
||||
Pointer<Uint64> _elementAtUint64(Pointer<Uint64> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 8 * index);
|
||||
|
||||
Pointer<Float> _elementAtFloat(Pointer<Float> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 4 * index);
|
||||
|
||||
Pointer<Double> _elementAtDouble(Pointer<Double> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + 8 * index);
|
||||
|
||||
Pointer<Pointer<S>> _elementAtPointer<S extends NativeType>(
|
||||
Pointer<Pointer<S>> pointer, int index) =>
|
||||
Pointer.fromAddress(pointer.address + _intPtrSize * index);
|
||||
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:entry-point")
|
||||
T _checkAbiSpecificIntegerMapping<T>(T? object) {
|
||||
|
@ -520,6 +475,9 @@ extension Int8Pointer on Pointer<Int8> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeInt8(this, index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Int8> elementAt(int index) => Pointer.fromAddress(address + index);
|
||||
|
||||
@patch
|
||||
Int8List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Int8>");
|
||||
|
@ -543,6 +501,10 @@ extension Int16Pointer on Pointer<Int16> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeInt16(this, 2 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Int16> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 2 * index);
|
||||
|
||||
@patch
|
||||
Int16List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Int16>");
|
||||
|
@ -566,6 +528,10 @@ extension Int32Pointer on Pointer<Int32> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeInt32(this, 4 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Int32> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 4 * index);
|
||||
|
||||
@patch
|
||||
Int32List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Int32>");
|
||||
|
@ -589,6 +555,10 @@ extension Int64Pointer on Pointer<Int64> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeInt64(this, 8 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Int64> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 8 * index);
|
||||
|
||||
@patch
|
||||
Int64List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Int64>");
|
||||
|
@ -612,6 +582,9 @@ extension Uint8Pointer on Pointer<Uint8> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeUint8(this, index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Uint8> elementAt(int index) => Pointer.fromAddress(address + index);
|
||||
|
||||
@patch
|
||||
Uint8List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Uint8>");
|
||||
|
@ -635,6 +608,10 @@ extension Uint16Pointer on Pointer<Uint16> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeUint16(this, 2 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Uint16> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 2 * index);
|
||||
|
||||
@patch
|
||||
Uint16List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Uint16>");
|
||||
|
@ -658,6 +635,10 @@ extension Uint32Pointer on Pointer<Uint32> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeUint32(this, 4 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Uint32> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 4 * index);
|
||||
|
||||
@patch
|
||||
Uint32List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Uint32>");
|
||||
|
@ -681,6 +662,10 @@ extension Uint64Pointer on Pointer<Uint64> {
|
|||
@patch
|
||||
operator []=(int index, int value) => _storeUint64(this, 8 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Uint64> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 8 * index);
|
||||
|
||||
@patch
|
||||
Uint64List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Uint64>");
|
||||
|
@ -704,6 +689,10 @@ extension FloatPointer on Pointer<Float> {
|
|||
@patch
|
||||
operator []=(int index, double value) => _storeFloat(this, 4 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Float> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 4 * index);
|
||||
|
||||
@patch
|
||||
Float32List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Float>");
|
||||
|
@ -727,6 +716,10 @@ extension DoublePointer on Pointer<Double> {
|
|||
@patch
|
||||
operator []=(int index, double value) => _storeDouble(this, 8 * index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Double> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + 8 * index);
|
||||
|
||||
@patch
|
||||
Float64List asTypedList(int length) {
|
||||
ArgumentError.checkNotNull(this, "Pointer<Double>");
|
||||
|
@ -749,6 +742,9 @@ extension BoolPointer on Pointer<Bool> {
|
|||
|
||||
@patch
|
||||
operator []=(int index, bool value) => _storeBool(this, index, value);
|
||||
|
||||
@patch
|
||||
Pointer<Bool> elementAt(int index) => Pointer.fromAddress(address + index);
|
||||
}
|
||||
|
||||
extension Int8Array on Array<Int8> {
|
||||
|
@ -919,6 +915,10 @@ extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
|
|||
@patch
|
||||
Pointer<T> operator [](int index) => _loadPointer(this, _intPtrSize * index);
|
||||
|
||||
@patch
|
||||
Pointer<Pointer<T>> elementAt(int index) =>
|
||||
Pointer.fromAddress(address + _intPtrSize * index);
|
||||
|
||||
@patch
|
||||
operator []=(int index, Pointer<T> value) =>
|
||||
_storePointer(this, _intPtrSize * index, value);
|
||||
|
@ -940,6 +940,10 @@ extension StructPointer<T extends Struct> on Pointer<T> {
|
|||
@patch
|
||||
void operator []=(int index, T value) =>
|
||||
throw "UNREACHABLE: This case should have been rewritten in the CFE.";
|
||||
|
||||
@patch
|
||||
Pointer<T> elementAt(int index) =>
|
||||
throw "UNREACHABLE: This case should have been rewritten in the CFE.";
|
||||
}
|
||||
|
||||
extension UnionPointer<T extends Union> on Pointer<T> {
|
||||
|
@ -958,6 +962,10 @@ extension UnionPointer<T extends Union> on Pointer<T> {
|
|||
@patch
|
||||
void operator []=(int index, T value) =>
|
||||
throw "UNREACHABLE: This case should have been rewritten in the CFE.";
|
||||
|
||||
@patch
|
||||
Pointer<T> elementAt(int index) =>
|
||||
throw "UNREACHABLE: This case should have been rewritten in the CFE.";
|
||||
}
|
||||
|
||||
extension AbiSpecificIntegerPointer<T extends AbiSpecificInteger>
|
||||
|
@ -977,6 +985,10 @@ extension AbiSpecificIntegerPointer<T extends AbiSpecificInteger>
|
|||
@patch
|
||||
void operator []=(int index, int value) =>
|
||||
throw "UNREACHABLE: This case should have been rewritten in the CFE.";
|
||||
|
||||
@patch
|
||||
Pointer<T> elementAt(int index) =>
|
||||
throw "UNREACHABLE: This case should have been rewritten in the CFE.";
|
||||
}
|
||||
|
||||
extension PointerArray<T extends NativeType> on Array<Pointer<T>> {
|
||||
|
|
|
@ -32,5 +32,4 @@ class Unsized {
|
|||
/// This [NativeType] does not have predefined size.
|
||||
///
|
||||
/// Unsized NativeTypes do not support [sizeOf] because their size is unknown.
|
||||
/// Consequently, [Pointer.elementAt] is not available.
|
||||
const unsized = const Unsized();
|
||||
|
|
|
@ -67,14 +67,6 @@ class Pointer<T extends NativeType> extends NativeType {
|
|||
/// On 32-bit systems, the upper 32-bits of the result are 0.
|
||||
external int get address;
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
///
|
||||
/// This method must be invoked with a compile-time constant [T].
|
||||
///
|
||||
/// Does not accept dynamic invocations -- where the type of the receiver is
|
||||
/// [dynamic].
|
||||
external Pointer<T> elementAt(int index);
|
||||
|
||||
/// Cast Pointer<T> to a Pointer<V>.
|
||||
external Pointer<U> cast<U extends NativeType>();
|
||||
|
||||
|
@ -191,6 +183,9 @@ extension Int8Pointer on Pointer<Int8> {
|
|||
/// being stored, and the 8-bit value is sign-extended when it is loaded.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Int8> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -229,6 +224,9 @@ extension Int16Pointer on Pointer<Int16> {
|
|||
/// The [address] must be 2-byte aligned.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Int16> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -269,6 +267,9 @@ extension Int32Pointer on Pointer<Int32> {
|
|||
/// The [address] must be 4-byte aligned.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Int32> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -300,6 +301,9 @@ extension Int64Pointer on Pointer<Int64> {
|
|||
/// The [address] must be 8-byte aligned.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Int64> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -334,6 +338,9 @@ extension Uint8Pointer on Pointer<Uint8> {
|
|||
/// being stored, and the 8-bit value is zero-extended when it is loaded.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Uint8> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -372,6 +379,9 @@ extension Uint16Pointer on Pointer<Uint16> {
|
|||
/// The [address] must be 2-byte aligned.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Uint16> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -412,6 +422,9 @@ extension Uint32Pointer on Pointer<Uint32> {
|
|||
/// The [address] must be 4-byte aligned.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Uint32> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -443,6 +456,9 @@ extension Uint64Pointer on Pointer<Uint64> {
|
|||
/// The [address] must be 8-byte aligned.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Uint64> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -483,6 +499,9 @@ extension FloatPointer on Pointer<Float> {
|
|||
/// The [address] must be 4-byte aligned.
|
||||
external void operator []=(int index, double value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Float> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -514,6 +533,9 @@ extension DoublePointer on Pointer<Double> {
|
|||
/// The [address] must be 8-byte aligned.
|
||||
external void operator []=(int index, double value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Double> elementAt(int index);
|
||||
|
||||
/// Creates a typed list view backed by memory in the address space.
|
||||
///
|
||||
/// The returned view will allow access to the memory range from [address]
|
||||
|
@ -539,6 +561,9 @@ extension BoolPointer on Pointer<Bool> {
|
|||
|
||||
/// The bool at `address + index`.
|
||||
external void operator []=(int index, bool value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Bool> elementAt(int index);
|
||||
}
|
||||
|
||||
/// Bounds checking indexing methods on [Array]s of [Int8].
|
||||
|
@ -663,6 +688,9 @@ extension PointerPointer<T extends NativeType> on Pointer<Pointer<T>> {
|
|||
/// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit
|
||||
/// platforms the [address] must be 8-byte aligned.
|
||||
external void operator []=(int index, Pointer<T> value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<Pointer<T>> elementAt(int index);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Struct].
|
||||
|
@ -699,6 +727,9 @@ extension StructPointer<T extends Struct> on Pointer<T> {
|
|||
/// This extension method must be invoked on a receiver of type `Pointer<T>`
|
||||
/// where `T` is a compile-time constant type.
|
||||
external void operator []=(int index, T value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<T> elementAt(int index);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument [Union].
|
||||
|
@ -735,6 +766,9 @@ extension UnionPointer<T extends Union> on Pointer<T> {
|
|||
/// This extension method must be invoked on a receiver of type `Pointer<T>`
|
||||
/// where `T` is a compile-time constant type.
|
||||
external void operator []=(int index, T value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<T> elementAt(int index);
|
||||
}
|
||||
|
||||
/// Extension on [Pointer] specialized for the type argument
|
||||
|
@ -752,6 +786,9 @@ extension AbiSpecificIntegerPointer<T extends AbiSpecificInteger>
|
|||
|
||||
/// The integer at `address + sizeOf<T>() * index`.
|
||||
external void operator []=(int index, int value);
|
||||
|
||||
/// Pointer arithmetic (takes element size into account).
|
||||
external Pointer<T> elementAt(int index);
|
||||
}
|
||||
|
||||
/// Bounds checking indexing methods on [Array]s of [Pointer].
|
||||
|
|
Loading…
Reference in a new issue