blob: 8e7320a91af00c977246b1cb71daf50696d15502 [file] [log] [blame]
// Copyright (c) 2017, 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' as ir;
import '../closure.dart';
import '../common.dart';
import '../constants/values.dart';
import '../common_elements.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../js/js.dart' as js;
import '../js_backend/namer.dart';
import '../js_emitter/code_emitter_task.dart';
import '../native/native.dart' as native;
import '../types/types.dart';
import '../universe/call_structure.dart';
import '../universe/selector.dart';
import '../world.dart';
/// Interface that translates between Kernel IR nodes and entities.
abstract class KernelToElementMap {
/// Access to the commonly used elements and types.
CommonElements get commonElements;
/// Returns the [DartType] corresponding to [type].
DartType getDartType(ir.DartType type);
/// Returns the [InterfaceType] corresponding to [type].
InterfaceType getInterfaceType(ir.InterfaceType type);
/// Returns the [FunctionType] of the [node].
FunctionType getFunctionType(ir.FunctionNode node);
/// Return the [InterfaceType] corresponding to the [cls] with the given
/// [typeArguments].
InterfaceType createInterfaceType(
ir.Class cls, List<ir.DartType> typeArguments);
/// Returns the [CallStructure] corresponding to the [arguments].
CallStructure getCallStructure(ir.Arguments arguments);
/// Returns the [Selector] corresponding to the invocation or getter/setter
/// access of [node].
Selector getSelector(ir.Expression node);
/// Returns the [MemberEntity] corresponding to the member [node].
MemberEntity getMember(ir.Member node);
/// Returns the [FunctionEntity] corresponding to the procedure [node].
FunctionEntity getMethod(ir.Procedure node);
/// Returns the [ConstructorEntity] corresponding to the generative or factory
/// constructor [node].
ConstructorEntity getConstructor(ir.Member node);
/// Returns the [FieldEntity] corresponding to the field [node].
FieldEntity getField(ir.Field node);
/// Returns the [ClassEntity] corresponding to the class [node].
ClassEntity getClass(ir.Class node);
/// Returns the [Local] corresponding to the [node]. The node must be either
/// a [ir.FunctionDeclaration] or [ir.FunctionExpression].
Local getLocalFunction(ir.TreeNode node);
/// Returns the super [MemberEntity] for a super invocation, get or set of
/// [name] from the member [context].
///
/// The IR doesn't always resolve super accesses to the corresponding
/// [target]. If not, the target is computed using [name] and [setter] from
/// the enclosing class of [context].
MemberEntity getSuperMember(ir.Member context, ir.Name name, ir.Member target,
{bool setter: false});
/// Returns the [Name] corresponding to [name].
Name getName(ir.Name name);
/// Return `true` if [node] is the `dart:_foreign_helper` library.
bool isForeignLibrary(ir.Library node);
/// Computes the [native.NativeBehavior] for a call to the [JS] function.
native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
/// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
/// function.
native.NativeBehavior getNativeBehaviorForJsBuiltinCall(
ir.StaticInvocation node);
/// Computes the [native.NativeBehavior] for a call to the
/// [JS_EMBEDDED_GLOBAL] function.
native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
ir.StaticInvocation node);
/// Returns the [js.Name] for the `JsGetName` [constant] value.
js.Name getNameForJsGetName(ConstantValue constant, Namer namer);
/// Computes the [ConstantValue] for the constant [expression].
// TODO(johnniwinther): Move to [KernelToElementMapForBuilding]. This is only
// used in impact builder for symbol constants.
ConstantValue getConstantValue(ir.Expression expression,
{bool requireConstant: true, bool implicitNull: false});
}
/// Interface that translates between Kernel IR nodes and entities used for
/// computing the [WorldImpact] for members.
abstract class KernelToElementMapForImpact extends KernelToElementMap {
/// Adds libraries in [program] to the set of libraries.
///
/// The main method of the first program is used as the main method for the
/// compilation.
void addProgram(ir.Program program);
/// Returns the [ConstructorEntity] corresponding to a super initializer in
/// [constructor].
///
/// The IR resolves super initializers to a [target] up in the type hierarchy.
/// Most of the time, the result of this function will be the entity
/// corresponding to that target. In the presence of unnamed mixins, this
/// function returns an entity for an intermediate synthetic constructor that
/// kernel doesn't explicitly represent.
///
/// For example:
/// class M {}
/// class C extends Object with M {}
///
/// Kernel will say that C()'s super initializer resolves to Object(), but
/// this function will return an entity representing the unnamed mixin
/// application "Object+M"'s constructor.
ConstructorEntity getSuperConstructor(
ir.Constructor constructor, ir.Member target);
/// Returns `true` is [node] has a `@Native(...)` annotation.
bool isNativeClass(ir.Class node);
/// Computes the native behavior for reading the native [field].
native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field,
{bool isJsInterop});
/// Computes the native behavior for writing to the native [field].
native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field);
/// Computes the native behavior for calling [procedure].
native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure,
{bool isJsInterop});
/// Compute the kind of foreign helper function called by [node], if any.
ForeignKind getForeignKind(ir.StaticInvocation node);
/// Computes the [InterfaceType] referenced by a call to the
/// [JS_INTERCEPTOR_CONSTANT] function, if any.
InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node);
}
/// Interface that translates between Kernel IR nodes and entities used for
/// global type inference and building the SSA graph for members.
abstract class KernelToElementMapForBuilding implements KernelToElementMap {
/// [ElementEnvironment] for library, class and member lookup.
ElementEnvironment get elementEnvironment;
/// Returns the list of [DartType]s corresponding to [types].
List<DartType> getDartTypes(List<ir.DartType> types);
/// Returns the kernel IR node that defines the [member].
ir.Node getMemberNode(covariant MemberEntity member);
/// Returns the kernel IR node that defines the [cls].
ir.Class getClassNode(covariant ClassEntity cls);
/// Returns the [LibraryEntity] corresponding to the library [node].
LibraryEntity getLibrary(ir.Library node);
/// Returns the [js.Template] for the `JsBuiltin` [constant] value.
js.Template getJsBuiltinTemplate(
ConstantValue constant, CodeEmitterTask emitter);
/// Return the [ConstantValue] the initial value of [field] or `null` if
/// the initializer is not a constant expression.
ConstantValue getFieldConstantValue(ir.Field field);
/// Returns the `noSuchMethod` [FunctionEntity] call from a
/// `super.noSuchMethod` invocation within [cls].
FunctionEntity getSuperNoSuchMethod(ClassEntity cls);
/// Returns a [Spannable] for a message pointing to the IR [node] in the
/// context of [member].
Spannable getSpannable(MemberEntity member, ir.Node node);
/// Returns the constructor body entity corresponding to [constructor].
FunctionEntity getConstructorBody(ir.Constructor node);
/// Returns the uri for the deferred import [node].
// TODO(johnniwinther): Avoid this method by deriving the uri directly from
// the node.
String getDeferredUri(ir.LibraryDependency node);
}
/// Kinds of foreign functions.
enum ForeignKind {
JS,
JS_BUILTIN,
JS_EMBEDDED_GLOBAL,
JS_INTERCEPTOR_CONSTANT,
NONE,
}
/// Interface for type inference results for kernel IR nodes.
abstract class KernelToTypeInferenceMap {
/// Returns the inferred return type of [function].
TypeMask getReturnTypeOf(FunctionEntity function);
/// Returns the inferred receiver type of the dynamic [invocation].
TypeMask typeOfInvocation(
ir.MethodInvocation invocation, ClosedWorld closedWorld);
/// Returns the inferred receiver type of the dynamic [read].
TypeMask typeOfGet(ir.PropertyGet read);
/// Returns the inferred receiver type of the dynamic [write].
TypeMask typeOfSet(ir.PropertySet write, ClosedWorld closedWorld);
/// Returns the inferred type of [listLiteral].
TypeMask typeOfListLiteral(covariant MemberEntity owner,
ir.ListLiteral listLiteral, ClosedWorld closedWorld);
/// Returns the inferred type of iterator in [forInStatement].
TypeMask typeOfIterator(ir.ForInStatement forInStatement);
/// Returns the inferred type of `current` in [forInStatement].
TypeMask typeOfIteratorCurrent(ir.ForInStatement forInStatement);
/// Returns the inferred type of `moveNext` in [forInStatement].
TypeMask typeOfIteratorMoveNext(ir.ForInStatement forInStatement);
/// Returns `true` if [forInStatement] is inferred to be a JavaScript
/// indexable iterator.
bool isJsIndexableIterator(
ir.ForInStatement forInStatement, ClosedWorld closedWorld);
/// Returns `true` if [mask] is inferred to have a JavaScript `length`
/// property.
bool isFixedLength(TypeMask mask, ClosedWorld closedWorld);
/// Returns the inferred index type of [forInStatement].
TypeMask inferredIndexType(ir.ForInStatement forInStatement);
/// Returns the inferred type of [member].
TypeMask getInferredTypeOf(MemberEntity member);
/// Returns the inferred type of the [parameter].
TypeMask getInferredTypeOfParameter(Local parameter);
/// Returns the inferred type of a dynamic [selector] access on a receiver of
/// type [mask].
TypeMask selectorTypeOf(Selector selector, TypeMask mask);
/// Returns the returned type annotation in the [nativeBehavior].
TypeMask typeFromNativeBehavior(
native.NativeBehavior nativeBehavior, ClosedWorld closedWorld);
}
/// Map from kernel IR nodes to local entities.
abstract class KernelToLocalsMap {
/// The member currently being built.
MemberEntity get currentMember;
// TODO(johnniwinther): Make these return the [KernelToLocalsMap] to use from
// now on.
/// Call to notify that [member] is currently being inlined.
void enterInlinedMember(covariant MemberEntity member);
/// Call to notify that [member] is no longer being inlined.
void leaveInlinedMember(covariant MemberEntity member);
/// Returns the [Local] for [node].
Local getLocal(ir.VariableDeclaration node);
/// Returns the [JumpTarget] for the break statement [node].
JumpTarget getJumpTargetForBreak(ir.BreakStatement node);
/// Returns `true` if [node] should generate a `continue` to its [JumpTarget].
bool generateContinueForBreak(ir.BreakStatement node);
/// Returns the [JumpTarget] defined by the labelled statement [node] or
/// `null` if [node] is not a jump target.
JumpTarget getJumpTargetForLabel(ir.LabeledStatement node);
/// Returns the [JumpTarget] defined by the switch statement [node] or `null`
/// if [node] is not a jump target.
JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node);
/// Returns the [JumpTarget] for the continue switch statement [node].
JumpTarget getJumpTargetForContinueSwitch(ir.ContinueSwitchStatement node);
/// Returns the [JumpTarget] defined by the switch case [node] or `null`
/// if [node] is not a jump target.
JumpTarget getJumpTargetForSwitchCase(ir.SwitchCase node);
/// Returns the [JumpTarget] defined the do statement [node] or `null`
/// if [node] is not a jump target.
JumpTarget getJumpTargetForDo(ir.DoStatement node);
/// Returns the [JumpTarget] defined by the for statement [node] or `null`
/// if [node] is not a jump target.
JumpTarget getJumpTargetForFor(ir.ForStatement node);
/// Returns the [JumpTarget] defined by the for-in statement [node] or `null`
/// if [node] is not a jump target.
JumpTarget getJumpTargetForForIn(ir.ForInStatement node);
/// Returns the [JumpTarget] defined by the while statement [node] or `null`
/// if [node] is not a jump target.
JumpTarget getJumpTargetForWhile(ir.WhileStatement node);
/// Returns the [LoopClosureScope] for the loop [node] in [closureClassMaps].
LoopClosureScope getLoopClosureScope(
ClosureDataLookup closureLookup, ir.TreeNode node);
}
/// Comparator for the canonical order or named arguments.
// TODO(johnniwinther): Remove this when named parameters are sorted in dill.
int namedOrdering(ir.VariableDeclaration a, ir.VariableDeclaration b) {
return a.name.compareTo(b.name);
}