kernel -> ssa: support static invocations and variable gets
R=sigmund@google.com
Review URL: https://codereview.chromium.org/2290893002 .
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 2dc4895..83f22ab 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -4899,7 +4899,7 @@
instruction = new HInvokeStatic(element.declaration, arguments, typeMask,
targetCanThrow: targetCanThrow)
..sourceInformation = sourceInformation;
- if (!currentInlinedInstantiations.isEmpty) {
+ if (currentInlinedInstantiations.isNotEmpty) {
instruction.instantiatedTypes =
new List<DartType>.from(currentInlinedInstantiations);
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 8879413..9c91c0f 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -15,6 +15,7 @@
import '../kernel/kernel_visitor.dart';
import '../resolution/tree_elements.dart';
import '../tree/dartstring.dart';
+import '../types/masks.dart';
import 'graph_builder.dart';
import 'kernel_ast_adapter.dart';
@@ -50,7 +51,8 @@
backend.compiler,
work.registry,
sourceInformationFactory,
- visitor);
+ visitor,
+ kernel);
return builder.build();
});
}
@@ -76,7 +78,8 @@
this.compiler,
this.registry,
SourceInformationStrategy sourceInformationFactory,
- KernelVisitor visitor) {
+ KernelVisitor visitor,
+ Kernel kernel) {
graph.element = functionElement;
// TODO(het): Should sourceInformationBuilder be in GraphBuilder?
this.sourceInformationBuilder =
@@ -85,8 +88,8 @@
sourceInformationBuilder.buildVariableDeclaration();
this.localsHandler =
new LocalsHandler(this, functionElement, null, compiler);
- this.astAdapter =
- new KernelAstAdapter(compiler.backend, resolvedAst, visitor.nodeToAst);
+ this.astAdapter = new KernelAstAdapter(compiler.backend, resolvedAst,
+ visitor.nodeToAst, visitor.nodeToElement, kernel.functions);
}
HGraph build() {
@@ -186,8 +189,8 @@
@override
visitSymbolLiteral(ir.SymbolLiteral symbolLiteral) {
- stack.add(
- graph.addConstant(astAdapter.getConstantFor(symbolLiteral), compiler));
+ stack.add(graph.addConstant(
+ astAdapter.getConstantForSymbol(symbolLiteral), compiler));
registry?.registerConstSymbol(symbolLiteral.value);
}
@@ -195,4 +198,41 @@
visitNullLiteral(ir.NullLiteral nullLiteral) {
stack.add(graph.addConstantNull(compiler));
}
+
+ @override
+ visitVariableGet(ir.VariableGet variableGet) {
+ LocalElement local = astAdapter.getElement(variableGet.variable);
+ stack.add(localsHandler.readLocal(local));
+ }
+
+ @override
+ visitStaticInvocation(ir.StaticInvocation invocation) {
+ List<HInstruction> inputs = <HInstruction>[];
+
+ for (ir.Expression argument in invocation.arguments.positional) {
+ argument.accept(this);
+ inputs.add(pop());
+ }
+ for (ir.NamedExpression argument in invocation.arguments.named) {
+ argument.value.accept(this);
+ inputs.add(pop());
+ }
+
+ ir.Procedure target = invocation.target;
+ bool targetCanThrow = astAdapter.getCanThrow(target);
+ TypeMask typeMask = astAdapter.returnTypeOf(target);
+
+ HInstruction instruction = new HInvokeStatic(
+ astAdapter.getElement(target).declaration, inputs, typeMask,
+ targetCanThrow: targetCanThrow);
+ instruction.sideEffects = astAdapter.getSideEffects(target);
+
+ push(instruction);
+ }
+
+ @override
+ visitExpressionStatement(ir.ExpressionStatement exprStatement) {
+ exprStatement.expression.accept(this);
+ pop();
+ }
}
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index f5d271f..2076899 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -9,23 +9,53 @@
import '../elements/elements.dart';
import '../js_backend/js_backend.dart';
import '../tree/tree.dart' as ast;
+import '../types/masks.dart';
+import '../universe/side_effects.dart';
+
+import 'types.dart';
/// A helper class that abstracts all accesses of the AST from Kernel nodes.
///
/// The goal is to remove all need for the AST from the Kernel SSA builder.
class KernelAstAdapter {
- final JavaScriptBackend backend;
- final ResolvedAst resolvedAst;
- final Map<ir.Node, ast.Node> nodeToAst;
+ final JavaScriptBackend _backend;
+ final ResolvedAst _resolvedAst;
+ final Map<ir.Node, ast.Node> _nodeToAst;
+ final Map<ir.Node, Element> _nodeToElement;
- KernelAstAdapter(this.backend, this.resolvedAst, this.nodeToAst);
+ KernelAstAdapter(this._backend, this._resolvedAst, this._nodeToAst,
+ this._nodeToElement, Map<FunctionElement, ir.Member> functions) {
+ for (FunctionElement functionElement in functions.keys) {
+ _nodeToElement[functions[functionElement]] = functionElement;
+ }
+ }
- ConstantValue getConstantFor(ir.Node node) {
- ast.Node astNode = nodeToAst[node];
- ConstantValue constantValue = backend.constants
- .getConstantValueForNode(astNode, resolvedAst.elements);
+ ConstantValue getConstantForSymbol(ir.SymbolLiteral node) {
+ ast.Node astNode = _nodeToAst[node];
+ ConstantValue constantValue = _backend.constants
+ .getConstantValueForNode(astNode, _resolvedAst.elements);
assert(invariant(astNode, constantValue != null,
message: 'No constant computed for $node'));
return constantValue;
}
+
+ Element getElement(ir.Node node) {
+ Element result = _nodeToElement[node];
+ assert(result != null);
+ return result;
+ }
+
+ bool getCanThrow(ir.Procedure procedure) {
+ FunctionElement function = getElement(procedure);
+ return !_backend.compiler.world.getCannotThrow(function);
+ }
+
+ TypeMask returnTypeOf(ir.Procedure node) {
+ return TypeMaskFactory.inferredReturnTypeForElement(
+ getElement(node), _backend.compiler);
+ }
+
+ SideEffects getSideEffects(ir.Node node) {
+ return _backend.compiler.world.getSideEffectsOfElement(getElement(node));
+ }
}
diff --git a/tests/compiler/dart2js/kernel/helper.dart b/tests/compiler/dart2js/kernel/helper.dart
index 37dfe15..30512d8 100644
--- a/tests/compiler/dart2js/kernel/helper.dart
+++ b/tests/compiler/dart2js/kernel/helper.dart
@@ -36,5 +36,5 @@
Future check(String code, {String entry: 'main'}) async {
var original = await compile(code, entry: entry, useKernel: false);
var kernel = await compile(code, entry: entry, useKernel: true);
- expect(original, kernel);
+ expect(kernel, original);
}
diff --git a/tests/compiler/dart2js/kernel/simple_function_test.dart b/tests/compiler/dart2js/kernel/simple_function_test.dart
index c252716..5b1985d 100644
--- a/tests/compiler/dart2js/kernel/simple_function_test.dart
+++ b/tests/compiler/dart2js/kernel/simple_function_test.dart
@@ -5,27 +5,39 @@
main() {
group('compile function that returns a value', () {
test('constant int', () {
- return check("main() { return 1; }");
+ return check('main() { return 1; }');
});
test('constant double', () {
- return check("main() { return 1.0; }");
+ return check('main() { return 1.0; }');
});
test('constant string', () {
- return check("main() { return 'hello'; }");
+ return check('main() { return "hello"; }');
});
test('constant bool', () {
- return check("main() { return true; }");
+ return check('main() { return true; }');
});
test('constant symbol', () {
- return check("main() { return #hello; }");
+ return check('main() { return #hello; }');
});
test('null', () {
- return check("main() { return null; }");
+ return check('main() { return null; }');
});
});
+
+ test('compile function that returns its argument', () {
+ String code = '''
+ foo(x) {
+ return x;
+ }
+
+ main() {
+ foo(1);
+ }''';
+ return check(code, entry: 'foo');
+ });
}