Skip to content

Commit 55b4542

Browse files
dcharkesCommit Queue
authored and
Commit Queue
committed
[pkg/vm] Native assets validator and synthesizer
Validates a yaml format encoding a native asset mapping, and synthesizes a component containing a pragma with this information. Yaml example: ``` format-version: [1,0,0] native-assets: linux_x64: 'package:foo/foo.dart': ['absolute', '/path/to/libfoo.so'] ``` Generated format example: ``` @pragma('vm:ffi:native-assets': { 'linux_x64' : { 'package:foo/foo.dart': ['absolute', '/path/to/libfoo.so'] } }) library; ``` TEST=pkg/vm/test/native_assets/synthesizer_test.dart TEST=pkg/vm/test/native_assets/validator_test.dart In a follow-up CL, we will consume the yaml from `gen_kernel` and consume the pragma in the VM for `@FfiNative`s. Bug: #49803 Change-Id: Ie8d93b38ff4406ef7485e5513807e89b2772164b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272660 Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
1 parent e7bd696 commit 55b4542

9 files changed

+681
-4
lines changed

pkg/kernel/lib/ast.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14811,10 +14811,12 @@ class Component extends TreeNode {
1481114811
Component(
1481214812
{CanonicalName? nameRoot,
1481314813
List<Library>? libraries,
14814-
Map<Uri, Source>? uriToSource})
14814+
Map<Uri, Source>? uriToSource,
14815+
NonNullableByDefaultCompiledMode? mode})
1481514816
: root = nameRoot ?? new CanonicalName.root(),
1481614817
libraries = libraries ?? <Library>[],
14817-
uriToSource = uriToSource ?? <Uri, Source>{} {
14818+
uriToSource = uriToSource ?? <Uri, Source>{},
14819+
_mode = mode {
1481814820
adoptChildren();
1481914821
}
1482014822

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2022, 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+
import 'package:front_end/src/api_unstable/vm.dart';
6+
7+
class NativeAssetsDiagnosticMessage implements DiagnosticMessage {
8+
final String message;
9+
10+
@override
11+
final Severity severity;
12+
13+
NativeAssetsDiagnosticMessage({
14+
required this.message,
15+
this.severity = Severity.error,
16+
this.involvedFiles,
17+
});
18+
19+
@override
20+
Iterable<String> get ansiFormatted => [message];
21+
22+
@override
23+
String? get codeName => null;
24+
25+
@override
26+
final List<Uri>? involvedFiles;
27+
28+
@override
29+
Iterable<String> get plainTextFormatted => [message];
30+
31+
@override
32+
String toString() => 'NativeAssetsDiagnosticMessage($message)';
33+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) 2022, 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+
import 'package:kernel/kernel.dart';
6+
7+
/// Converts a [jsonObject] into a kernel [Constant].
8+
///
9+
/// [jsonObject] must consist only of [double], [int], [String], [List], and
10+
/// [Map] recurively.
11+
Constant jsonToKernelConstant(Object jsonObject) {
12+
if (jsonObject is int) {
13+
return IntConstant(jsonObject);
14+
}
15+
16+
if (jsonObject is double) {
17+
return DoubleConstant(jsonObject);
18+
}
19+
20+
if (jsonObject is String) {
21+
return StringConstant(jsonObject);
22+
}
23+
24+
if (jsonObject is List) {
25+
return ListConstant(
26+
DynamicType(),
27+
[
28+
for (final element in jsonObject)
29+
jsonToKernelConstant(element as Object),
30+
],
31+
);
32+
}
33+
34+
if (jsonObject is Map) {
35+
return MapConstant(
36+
DynamicType(),
37+
DynamicType(),
38+
[
39+
for (final entry in jsonObject.entries)
40+
ConstantMapEntry(
41+
jsonToKernelConstant(entry.key as Object),
42+
jsonToKernelConstant(entry.value as Object),
43+
)
44+
],
45+
);
46+
}
47+
48+
throw UnsupportedError(
49+
'Unknown data type: ${jsonObject.runtimeType} $jsonObject');
50+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) 2022, 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+
import 'package:kernel/kernel.dart';
6+
import 'package:vm/native_assets/validator.dart';
7+
8+
import 'json_to_kernel_constant.dart';
9+
10+
final _dummyFileUri = Uri.parse('dummy');
11+
12+
class NativeAssetsSynthesizer {
13+
/// Returns a [Class] that another component may use to refer to
14+
/// pragma.
15+
///
16+
/// Since uses are of symbolic nature, this class itself doesn't
17+
/// have to be serialized - it's needed since kernel AST needs
18+
/// non-symbolic AST nodes / References in-memory (when serializing
19+
/// they will be string-based, symbolic references)
20+
static Class _pragmaClass() {
21+
final corelibUri = Uri.parse('dart:core');
22+
final pragma = Class(
23+
name: 'pragma',
24+
fileUri: corelibUri,
25+
fields: [
26+
Field.immutable(Name('name'), fileUri: _dummyFileUri),
27+
Field.immutable(Name('options'), fileUri: _dummyFileUri),
28+
],
29+
);
30+
Component(
31+
libraries: [
32+
Library(
33+
corelibUri,
34+
fileUri: _dummyFileUri,
35+
classes: [pragma],
36+
)
37+
],
38+
);
39+
return pragma;
40+
}
41+
42+
/// Synthesizes a [Library] to be included in a kernel snapshot for the VM.
43+
///
44+
/// [nativeAssetsYaml] must have been validated with [NativeAssetsValidator].
45+
///
46+
/// The VM consumes this component in runtime/vm/ffi/native_assets.cc.
47+
static Library synthesizeLibrary(
48+
Map nativeAssetsYaml, {
49+
nonNullableByDefaultCompiledMode = NonNullableByDefaultCompiledMode.Strong,
50+
}) {
51+
// We don't need the format-version in the VM.
52+
final jsonForVM = nativeAssetsYaml['native-assets'] as Map;
53+
final nativeAssetsConstant = jsonToKernelConstant(jsonForVM);
54+
55+
final pragma = _pragmaClass();
56+
final pragmaName = pragma.fields.singleWhere((f) => f.name.text == 'name');
57+
final pragmaOptions =
58+
pragma.fields.singleWhere((f) => f.name.text == 'options');
59+
60+
return Library(
61+
Uri.parse('vm:ffi:native-assets'),
62+
fileUri: _dummyFileUri,
63+
annotations: [
64+
ConstantExpression(InstanceConstant(pragma.reference, [], {
65+
pragmaName.fieldReference: StringConstant('vm:ffi:native-assets'),
66+
pragmaOptions.fieldReference: nativeAssetsConstant,
67+
}))
68+
],
69+
)..nonNullableByDefaultCompiledMode = nonNullableByDefaultCompiledMode;
70+
}
71+
}

0 commit comments

Comments
 (0)