564970c10e
The concept of a binary library file no longer exists. A kernel file can contain any number of libraries, and some of these libraries can be "external". To reference a class or member from another build, the class or member must be declared in an external library. Members in an external library contain all their type information, but have no body. Classes in an external library have their hierarchy information present, but are not guaranteed to contain all their actual members. The idea is that references themselves don't really cross module boundaries, but rather refer to a local definition whose body is contributed from elsewhere, much like 'external' members in Dart. A modular backend such as DDC should be able to compile from one of these kernel files without needing to load auxiliary information from summaries or other kernel files. For whole program transformations or backends, a linking step, which is not yet implemented, must merge classes and members in external libraries based on their name. External libraries share the same IR and binary format as ordinary libraries. Transformations that affect the interface for a member or class should transform the external libraries alongside with the internal ones, ideally without needing to treat them any different. R=kmillikin@google.com Review URL: https://chromereviews.googleplex.com/516847013 .
117 lines
3.5 KiB
Dart
117 lines
3.5 KiB
Dart
// Copyright (c) 2016, 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.
|
|
library kernel.binary.loader;
|
|
|
|
import '../repository.dart';
|
|
import '../ast.dart';
|
|
import 'tag.dart';
|
|
import 'dart:io';
|
|
import 'ast_from_binary.dart';
|
|
|
|
abstract class BinaryReferenceLoader {
|
|
Library getLibraryReference(Library from, String relativePath);
|
|
Class getClassReference(Library library, int tag, int index);
|
|
Member getMemberReference(TreeNode classOrLibrary, int tag, int index);
|
|
Member getLibraryMemberReference(Library library, int tag, int index);
|
|
Member getClassMemberReference(Class classNode, int tag, int index);
|
|
}
|
|
|
|
class BinaryLoader implements BinaryReferenceLoader {
|
|
final Repository repository;
|
|
|
|
BinaryLoader(this.repository);
|
|
|
|
Library getLibraryReference(Library from, String relativePath) {
|
|
var fullUri = from.importUri.resolve(relativePath);
|
|
return repository.getLibraryReference(fullUri);
|
|
}
|
|
|
|
static int _pow2roundup(int x) {
|
|
--x;
|
|
x |= x >> 1;
|
|
x |= x >> 2;
|
|
x |= x >> 4;
|
|
x |= x >> 8;
|
|
x |= x >> 16;
|
|
return x + 1;
|
|
}
|
|
|
|
TreeNode _extendList(
|
|
TreeNode parent, List<TreeNode> items, int index, TreeNode build()) {
|
|
if (items.length <= index) {
|
|
// Avoid excessive resizing by growing the list in steps.
|
|
items.length = _pow2roundup(index + 1);
|
|
}
|
|
return items[index] ??= build()..parent = parent;
|
|
}
|
|
|
|
Class getClassReference(Library library, int tag, int index) {
|
|
return _extendList(
|
|
library, library.classes, index, () => _buildClassReference(tag));
|
|
}
|
|
|
|
Class _buildClassReference(int tag) {
|
|
return new Class();
|
|
}
|
|
|
|
Field _buildFieldReference() {
|
|
return new Field(null);
|
|
}
|
|
|
|
Constructor _buildConstructorReference() {
|
|
return new Constructor(null);
|
|
}
|
|
|
|
Procedure _buildProcedureReference() {
|
|
return new Procedure(null, null, null);
|
|
}
|
|
|
|
Member getMemberReference(TreeNode classOrLibrary, int tag, int index) {
|
|
if (classOrLibrary is Class) {
|
|
return getClassMemberReference(classOrLibrary, tag, index);
|
|
} else {
|
|
return getLibraryMemberReference(classOrLibrary, tag, index);
|
|
}
|
|
}
|
|
|
|
Member getLibraryMemberReference(Library library, int tag, int index) {
|
|
switch (tag) {
|
|
case Tag.LibraryFieldReference:
|
|
case Tag.Field:
|
|
return _extendList(
|
|
library, library.fields, index, _buildFieldReference);
|
|
case Tag.LibraryProcedureReference:
|
|
case Tag.Procedure:
|
|
return _extendList(
|
|
library, library.procedures, index, _buildProcedureReference);
|
|
default:
|
|
throw 'Invalid library member reference tag: $tag';
|
|
}
|
|
}
|
|
|
|
Member getClassMemberReference(Class classNode, int tag, int index) {
|
|
switch (tag) {
|
|
case Tag.ClassFieldReference:
|
|
case Tag.Field:
|
|
return _extendList(
|
|
classNode, classNode.fields, index, _buildFieldReference);
|
|
case Tag.ClassConstructorReference:
|
|
case Tag.Constructor:
|
|
return _extendList(classNode, classNode.constructors, index,
|
|
_buildConstructorReference);
|
|
case Tag.ClassProcedureReference:
|
|
case Tag.Procedure:
|
|
return _extendList(
|
|
classNode, classNode.procedures, index, _buildProcedureReference);
|
|
default:
|
|
throw 'Invalid library member reference tag: $tag';
|
|
}
|
|
}
|
|
|
|
Program loadProgram(String filename) {
|
|
var bytes = new File(filename).readAsBytesSync();
|
|
return new BinaryBuilder(this, bytes, filename).readProgramFile();
|
|
}
|
|
}
|