blob: a7827e1c1a835fe4f35c201020a9ce8785d406cb [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/clone.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/reference_from_index.dart';
import 'package:kernel/target/changed_structure_notifier.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/transformations/mixin_full_resolution.dart'
as transformMixins show transformLibraries;
import 'package:dart2wasm/constants_backend.dart';
import 'package:dart2wasm/transformers.dart' as wasmTrans;
class WasmTarget extends Target {
Class? _growableList;
Class? _immutableList;
Class? _immutableMap;
Class? _unmodifiableSet;
Class? _compactLinkedCustomHashMap;
Class? _compactLinkedHashSet;
Class? _oneByteString;
Class? _twoByteString;
@override
late final ConstantsBackend constantsBackend;
@override
String get name => 'wasm';
@override
TargetFlags get flags => TargetFlags(enableNullSafety: true);
@override
List<String> get extraIndexedLibraries => const <String>[
"dart:collection",
"dart:typed_data",
];
void _patchHostEndian(CoreTypes coreTypes) {
// Fix Endian.host to be a const field equal to Endian.little instead of
// a final field. Wasm is a little-endian platform.
// Can't use normal patching process for this because CFE does not
// support patching fields.
// See http://dartbug.com/32836 for the background.
final Field host =
coreTypes.index.getField('dart:typed_data', 'Endian', 'host');
final Field little =
coreTypes.index.getField('dart:typed_data', 'Endian', 'little');
host.isConst = true;
host.initializer = new CloneVisitorNotMembers().clone(little.initializer!)
..parent = host;
}
@override
void performPreConstantEvaluationTransformations(
Component component,
CoreTypes coreTypes,
List<Library> libraries,
DiagnosticReporter diagnosticReporter,
{void Function(String msg)? logger,
ChangedStructureNotifier? changedStructureNotifier}) {
constantsBackend = WasmConstantsBackend(coreTypes);
_patchHostEndian(coreTypes);
}
@override
void performModularTransformationsOnLibraries(
Component component,
CoreTypes coreTypes,
ClassHierarchy hierarchy,
List<Library> libraries,
Map<String, String>? environmentDefines,
DiagnosticReporter diagnosticReporter,
ReferenceFromIndex? referenceFromIndex,
{void logger(String msg)?,
ChangedStructureNotifier? changedStructureNotifier}) {
transformMixins.transformLibraries(
this, coreTypes, hierarchy, libraries, referenceFromIndex);
logger?.call("Transformed mixin applications");
wasmTrans.transformLibraries(libraries, coreTypes, hierarchy);
}
@override
void performTransformationsOnProcedure(
CoreTypes coreTypes,
ClassHierarchy hierarchy,
Procedure procedure,
Map<String, String>? environmentDefines,
{void logger(String msg)?}) {
wasmTrans.transformProcedure(procedure, coreTypes, hierarchy);
}
@override
Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
String name, Arguments arguments, int offset, bool isSuper) {
throw "Unsupported: instantiateInvocation";
}
Expression instantiateNoSuchMethodError(CoreTypes coreTypes,
Expression receiver, String name, Arguments arguments, int offset,
{bool isMethod: false,
bool isGetter: false,
bool isSetter: false,
bool isField: false,
bool isLocalVariable: false,
bool isDynamic: false,
bool isSuper: false,
bool isStatic: false,
bool isConstructor: false,
bool isTopLevel: false}) {
throw "Unsupported: instantiateNoSuchMethodError";
}
@override
bool get supportsSetLiterals => false;
@override
int get enabledLateLowerings => LateLowering.all;
@override
int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.all;
@override
bool get supportsExplicitGetterCalls => true;
@override
bool get supportsLateLoweringSentinel => false;
@override
bool get useStaticFieldLowering => false;
@override
bool enableNative(Uri uri) => true;
@override
Class concreteListLiteralClass(CoreTypes coreTypes) {
return _growableList ??=
coreTypes.index.getClass('dart:core', '_GrowableList');
}
@override
Class concreteConstListLiteralClass(CoreTypes coreTypes) {
return _immutableList ??=
coreTypes.index.getClass('dart:core', '_ImmutableList');
}
@override
Class concreteMapLiteralClass(CoreTypes coreTypes) {
return _compactLinkedCustomHashMap ??= coreTypes.index
.getClass('dart:collection', '_CompactLinkedCustomHashMap');
}
@override
Class concreteConstMapLiteralClass(CoreTypes coreTypes) {
return _immutableMap ??=
coreTypes.index.getClass('dart:collection', '_ImmutableMap');
}
@override
Class concreteSetLiteralClass(CoreTypes coreTypes) {
return _compactLinkedHashSet ??=
coreTypes.index.getClass('dart:collection', '_CompactLinkedHashSet');
}
@override
Class concreteConstSetLiteralClass(CoreTypes coreTypes) {
return _unmodifiableSet ??=
coreTypes.index.getClass('dart:collection', '_UnmodifiableSet');
}
@override
Class concreteStringLiteralClass(CoreTypes coreTypes, String value) {
const int maxLatin1 = 0xff;
for (int i = 0; i < value.length; ++i) {
if (value.codeUnitAt(i) > maxLatin1) {
return _twoByteString ??=
coreTypes.index.getClass('dart:core', '_TwoByteString');
}
}
return _oneByteString ??=
coreTypes.index.getClass('dart:core', '_OneByteString');
}
@override
bool isSupportedPragma(String pragmaName) => pragmaName.startsWith("wasm:");
}