blob: dcb81c775291ef4af86fa4d4f0291a35fe3b553b [file] [log] [blame] [edit]
// 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:front_end/src/api_unstable/vm.dart' as fe;
import 'package:path/path.dart' as path;
import 'dynamic_modules.dart' show DynamicModuleType;
import 'translator.dart';
/// Represents a discrete phase of dart2wasm's compilation process.
///
/// cfe: Runs the common frontend and applies any modular transforms as part of
/// that process.
///
/// tfa: Runs global transforms on kernel including, but not limited to, TFA.
///
/// codegen: Runs the main dart2wasm translation process converting the kernel
/// into WASM modules.
enum CompilerPhase {
cfe,
tfa,
codegen;
static CompilerPhase parse(String name) {
for (final phase in values) {
if (phase.name == name) return phase;
}
throw ArgumentError('Invalid compiler phase name: $name');
}
}
class WasmCompilerOptions {
final TranslatorOptions translatorOptions = TranslatorOptions();
Uri? platformPath;
Uri? librariesSpecPath;
Uri? packagesPath;
Uri mainUri;
String outputFile;
String? depFile;
DynamicModuleType? dynamicModuleType;
Uri? dynamicMainModuleUri;
Uri? dynamicInterfaceUri;
Uri? dynamicModuleMetadataFile;
Uri? loadsIdsUri;
bool validateDynamicModules = true;
Map<String, String> environment = {};
Map<fe.ExperimentalFlag, bool> feExperimentalFlags = const {};
String? multiRootScheme;
List<Uri> multiRoots = const [];
List<String> deleteToStringPackageUri = const [];
String? dumpKernelAfterCfe;
String? dumpKernelBeforeTfa;
String? dumpKernelAfterTfa;
bool dryRun = false;
List<CompilerPhase> phases = const [
CompilerPhase.cfe,
CompilerPhase.tfa,
CompilerPhase.codegen
];
factory WasmCompilerOptions.defaultOptions() =>
WasmCompilerOptions(mainUri: Uri(), outputFile: '');
WasmCompilerOptions({required this.mainUri, required this.outputFile});
bool get enableDynamicModules => dynamicModuleType != null;
void validate() {
if (translatorOptions.importSharedMemory &&
translatorOptions.sharedMemoryMaxPages == null) {
throw ArgumentError("--shared-memory-max-pages must be specified if "
"--import-shared-memory is used.");
}
if (!translatorOptions.enableDeferredLoading) {
if (loadsIdsUri != null) {
throw ArgumentError("--load-ids can only be used with "
"--enable-deferred-loading");
}
}
if (enableDynamicModules) {
if (dynamicMainModuleUri == null) {
throw ArgumentError("--dynamic-module-main must be specified if "
"compiling dynamic modules.");
}
if (dynamicInterfaceUri == null) {
throw ArgumentError("--dynamic-module-interface must be specified if "
"compiling dynamic modules.");
}
}
_validatePhases();
}
void _validatePhases() {
if (phases.isEmpty) {
throw ArgumentError('--phases must contain at least one phase.');
}
CompilerPhase? previousPhase;
for (final phase in phases) {
// Ensure phases are consecutive
if (previousPhase != null && previousPhase.index != phase.index - 1) {
throw ArgumentError('--phases must contain consecutive phases.');
}
previousPhase = phase;
}
// Ensure correct input file type
final inputExtension = path.extension(mainUri.path);
switch (phases.first) {
case CompilerPhase.cfe:
if (inputExtension != '.dart') {
throw ArgumentError('Input to cfe phase must be a .dart file.');
}
case CompilerPhase.tfa:
if (inputExtension != '.dill') {
throw ArgumentError('Input to tfa phase must be a .dill file.');
}
case CompilerPhase.codegen:
if (inputExtension != '.dill') {
throw ArgumentError('Input to codegen phase must be a .dill file.');
}
}
// Ensure correct output file type
final outputExtension = path.extension(outputFile);
switch (phases.last) {
case CompilerPhase.cfe:
if (outputExtension != '.dill') {
throw ArgumentError('Output from cfe phase must be a .dill file.');
}
case CompilerPhase.tfa:
if (outputExtension != '.dill') {
throw ArgumentError('Output from tfa phase must be a .dill file.');
}
case CompilerPhase.codegen:
if (outputExtension != '.wasm') {
throw ArgumentError(
'Output from codegen phase must be a .wasm file.');
}
}
}
}