[vm,modular_aot] Lowering of type parameters
Issue: https://github.com/dart-lang/sdk/issues/61635 Change-Id: I06098a379ba3f04b5e13bad11acc0dcc391fb30c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/482364 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Slava Egorov <vegorov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
8852aa5c19
commit
dc2d8a06b9
@@ -19,6 +19,14 @@ import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
|
||||
import 'package:kernel/core_types.dart' show CoreTypes;
|
||||
import 'package:kernel/type_environment.dart' show StaticTypeContext;
|
||||
|
||||
/// Strategy for adding [TypeParameters] instructions when building CFG IR.
|
||||
enum TypeParametersStyle {
|
||||
/// Maintain separate [TypeParameters] for function type parameters and
|
||||
/// class type parameters.
|
||||
/// Represent incoming function type parameters as the first parameter.
|
||||
separateFunctionAndClassTypeParameters,
|
||||
}
|
||||
|
||||
/// Translates kernel AST to the flow graph.
|
||||
///
|
||||
/// Not implemented yet:
|
||||
@@ -41,6 +49,7 @@ class AstToIr extends ast.RecursiveVisitor {
|
||||
final RecognizedMethods recognizedMethods;
|
||||
final FlowGraphBuilder builder;
|
||||
final bool enableAsserts;
|
||||
final TypeParametersStyle typeParametersStyle;
|
||||
late final AstToIrTypes _typeTranslator;
|
||||
late final LocalVariableIndexer localVarIndexer;
|
||||
late final StaticTypeContext _staticTypeContext = StaticTypeContext(
|
||||
@@ -51,13 +60,17 @@ class AstToIr extends ast.RecursiveVisitor {
|
||||
Map<ast.LabeledStatement, JoinBlock>? labeledStatements;
|
||||
Map<ast.SwitchCase, JoinBlock>? switchCases;
|
||||
Map<ast.TryFinally, List<FinallyBlock>>? finallyBlocks;
|
||||
TypeParameters? typeParameters;
|
||||
|
||||
bool _hasTypeParametersInScope = false;
|
||||
TypeParameters? functionTypeParameters;
|
||||
TypeParameters? classTypeParameters;
|
||||
|
||||
AstToIr(
|
||||
this.function,
|
||||
this.functionRegistry,
|
||||
this.recognizedMethods, {
|
||||
required this.enableAsserts,
|
||||
required this.typeParametersStyle,
|
||||
}) : coreTypes = GlobalContext.instance.coreTypes,
|
||||
hierarchy = GlobalContext.instance.classHierarchy,
|
||||
builder = FlowGraphBuilder(function) {
|
||||
@@ -76,11 +89,23 @@ class AstToIr extends ast.RecursiveVisitor {
|
||||
for (final param in localVarIndexer.parameters) {
|
||||
builder.addParameter(param);
|
||||
}
|
||||
if (function.hasClassTypeParameters) {
|
||||
builder.addLoadLocal(localVarIndexer.receiver);
|
||||
typeParameters = builder.addTypeParameters(receiver: builder.pop());
|
||||
} else if (function.hasFunctionTypeParameters) {
|
||||
typeParameters = builder.addTypeParameters();
|
||||
if (function.hasFunctionTypeParameters || function.hasClassTypeParameters) {
|
||||
_hasTypeParametersInScope = true;
|
||||
switch (typeParametersStyle) {
|
||||
case .separateFunctionAndClassTypeParameters:
|
||||
if (function.hasFunctionTypeParameters) {
|
||||
builder.addLoadLocal(localVarIndexer.functionTypeParameters);
|
||||
functionTypeParameters = builder.addTypeParameters(
|
||||
.functionTypeParameters,
|
||||
);
|
||||
}
|
||||
if (function.hasClassTypeParameters) {
|
||||
builder.addLoadLocal(localVarIndexer.receiver);
|
||||
classTypeParameters = builder.addTypeParameters(
|
||||
.classTypeParameters,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
final member = function.member;
|
||||
switch (function) {
|
||||
@@ -334,25 +359,41 @@ class AstToIr extends ast.RecursiveVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
bool _hasTypeParameterReferences(ast.DartType type) =>
|
||||
type.accept(const _FindTypeParameters());
|
||||
|
||||
TypeParameters? _typeParametersForType(ast.DartType type) {
|
||||
if (typeParameters != null && _hasTypeParameterReferences(type)) {
|
||||
return typeParameters;
|
||||
List<Definition> _referencedTypeParameters(_FindTypeParameters visitor) {
|
||||
if (!visitor.containsClassTypeParams &&
|
||||
!visitor.containsFunctionTypeParams) {
|
||||
return const [];
|
||||
}
|
||||
return null;
|
||||
return switch (typeParametersStyle) {
|
||||
.separateFunctionAndClassTypeParameters => [
|
||||
visitor.containsFunctionTypeParams
|
||||
? functionTypeParameters!
|
||||
: builder.graph.getConstant(ConstantValue.fromNull()),
|
||||
visitor.containsClassTypeParams
|
||||
? classTypeParameters!
|
||||
: builder.graph.getConstant(ConstantValue.fromNull()),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
TypeParameters? _typeParametersForTypes(List<ast.DartType> types) {
|
||||
if (typeParameters != null) {
|
||||
for (final type in types) {
|
||||
if (_hasTypeParameterReferences(type)) {
|
||||
return typeParameters;
|
||||
}
|
||||
}
|
||||
List<Definition> _typeParametersForType(ast.DartType type) {
|
||||
if (!_hasTypeParametersInScope) {
|
||||
return const [];
|
||||
}
|
||||
return null;
|
||||
final visitor = _FindTypeParameters();
|
||||
type.accept(visitor);
|
||||
return _referencedTypeParameters(visitor);
|
||||
}
|
||||
|
||||
List<Definition> _typeParametersForTypes(List<ast.DartType> types) {
|
||||
if (!_hasTypeParametersInScope) {
|
||||
return const [];
|
||||
}
|
||||
final visitor = _FindTypeParameters();
|
||||
for (final type in types) {
|
||||
type.accept(visitor);
|
||||
}
|
||||
return _referencedTypeParameters(visitor);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -386,12 +427,10 @@ class AstToIr extends ast.RecursiveVisitor {
|
||||
|
||||
@override
|
||||
void visitTypeLiteral(ast.TypeLiteral node) {
|
||||
final typeParameters = _typeParametersForType(node.type);
|
||||
if (typeParameters != null) {
|
||||
builder.addTypeLiteral(node.type, typeParameters: typeParameters);
|
||||
} else {
|
||||
builder.addConstant(ConstantValue(ast.TypeLiteralConstant(node.type)));
|
||||
}
|
||||
builder.addTypeLiteral(
|
||||
node.type,
|
||||
typeParameters: _typeParametersForType(node.type),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1667,7 +1706,8 @@ class LocalVariableIndexer {
|
||||
final Map<ast.TreeNode, LocalVariable> _stackTraceVariables = {};
|
||||
|
||||
final List<LocalVariable> parameters = [];
|
||||
LocalVariable get receiver => parameters[0];
|
||||
late final LocalVariable functionTypeParameters;
|
||||
late final LocalVariable receiver;
|
||||
|
||||
LocalVariableIndexer(
|
||||
this.builder,
|
||||
@@ -1675,17 +1715,24 @@ class LocalVariableIndexer {
|
||||
this.typeTranslator,
|
||||
CFunction function,
|
||||
) {
|
||||
if (function.hasFunctionTypeParameters) {
|
||||
functionTypeParameters = builder.declareLocalVariable(
|
||||
'#functionTypeParameters',
|
||||
null,
|
||||
const TypeParametersType(),
|
||||
);
|
||||
parameters.add(functionTypeParameters);
|
||||
}
|
||||
if (function.hasReceiverParameter) {
|
||||
final cls = function.member.enclosingClass!;
|
||||
parameters.add(
|
||||
builder.declareLocalVariable(
|
||||
'this',
|
||||
null,
|
||||
typeTranslator.translate(
|
||||
cls.getThisType(coreTypes, ast.Nullability.nonNullable),
|
||||
),
|
||||
receiver = builder.declareLocalVariable(
|
||||
'this',
|
||||
null,
|
||||
typeTranslator.translate(
|
||||
cls.getThisType(coreTypes, ast.Nullability.nonNullable),
|
||||
),
|
||||
);
|
||||
parameters.add(receiver);
|
||||
}
|
||||
if (function.hasClosureParameter) {
|
||||
parameters.add(
|
||||
@@ -1760,94 +1807,25 @@ class FinallyBlock {
|
||||
FinallyBlock(FlowGraphBuilder builder, this.generateContinuation);
|
||||
}
|
||||
|
||||
/// Look up references to free type parameters.
|
||||
class _FindTypeParameters
|
||||
with ast.DartTypeVisitorExperimentExclusionMixin<bool>
|
||||
implements ast.DartTypeVisitor<bool> {
|
||||
const _FindTypeParameters();
|
||||
/// Look up references to type parameters.
|
||||
class _FindTypeParameters extends ast.RecursiveVisitor {
|
||||
_FindTypeParameters();
|
||||
|
||||
bool containsClassTypeParams = false;
|
||||
bool containsFunctionTypeParams = false;
|
||||
|
||||
@override
|
||||
bool visitFunctionType(ast.FunctionType node) {
|
||||
if (node.returnType.accept(this)) return true;
|
||||
for (final param in node.positionalParameters) {
|
||||
if (param.accept(this)) return true;
|
||||
void visitTypeParameterType(ast.TypeParameterType node) {
|
||||
final declaration = node.parameter.declaration;
|
||||
switch (declaration) {
|
||||
case ast.Class():
|
||||
containsClassTypeParams = true;
|
||||
break;
|
||||
case ast.GenericFunction():
|
||||
containsFunctionTypeParams = true;
|
||||
break;
|
||||
default:
|
||||
throw 'Unexpected type parameter $node declaration ${declaration.runtimeType} $declaration';
|
||||
}
|
||||
for (final namedParam in node.namedParameters) {
|
||||
if (namedParam.type.accept(this)) return true;
|
||||
}
|
||||
for (final typeParam in node.typeParameters) {
|
||||
if (typeParam.bound.accept(this)) return true;
|
||||
if (typeParam.defaultType.accept(this)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitInterfaceType(ast.InterfaceType node) {
|
||||
for (final type in node.typeArguments) {
|
||||
if (type.accept(this)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitTypedefType(ast.TypedefType node) {
|
||||
for (final type in node.typeArguments) {
|
||||
if (type.accept(this)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitTypeParameterType(ast.TypeParameterType node) => true;
|
||||
|
||||
@override
|
||||
bool visitStructuralParameterType(ast.StructuralParameterType node) => false;
|
||||
|
||||
@override
|
||||
bool visitIntersectionType(ast.IntersectionType node) {
|
||||
return node.left.accept(this) || node.right.accept(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ast.ExtensionType node) {
|
||||
for (final type in node.typeArguments) {
|
||||
if (type.accept(this)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitRecordType(ast.RecordType node) {
|
||||
for (final type in node.positional) {
|
||||
if (type.accept(this)) return true;
|
||||
}
|
||||
for (final namedType in node.named) {
|
||||
if (namedType.type.accept(this)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFutureOrType(ast.FutureOrType node) =>
|
||||
node.typeArgument.accept(this);
|
||||
|
||||
@override
|
||||
bool visitInvalidType(ast.InvalidType node) => false;
|
||||
|
||||
@override
|
||||
bool visitNeverType(ast.NeverType node) => false;
|
||||
|
||||
@override
|
||||
bool visitNullType(ast.NullType node) => false;
|
||||
|
||||
@override
|
||||
bool visitVoidType(ast.VoidType node) => false;
|
||||
|
||||
@override
|
||||
bool visitDynamicType(ast.DynamicType node) => false;
|
||||
|
||||
@override
|
||||
bool visitAuxiliaryType(ast.AuxiliaryType node) =>
|
||||
throw 'Unsupported type ${node.runtimeType} $node';
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:cfg/ir/source_position.dart';
|
||||
import 'package:cfg/ir/types.dart';
|
||||
import 'package:kernel/ast.dart'
|
||||
as ast
|
||||
show DartType, Name, VariableDeclaration;
|
||||
show DartType, Name, TypeLiteralConstant, VariableDeclaration;
|
||||
|
||||
/// Helper class to create IR instructions and populate [FlowGraph].
|
||||
///
|
||||
@@ -418,12 +418,10 @@ class FlowGraphBuilder {
|
||||
return instr;
|
||||
}
|
||||
|
||||
/// Append [TypeParameters] to the graph.
|
||||
///
|
||||
/// Optional [receiver] input should be passed if there are class type
|
||||
/// parameters in scope.
|
||||
TypeParameters addTypeParameters({Definition? receiver}) {
|
||||
final instr = TypeParameters(graph, currentSourcePosition, receiver);
|
||||
/// Append [TypeParameters] taking a parameter as input to the graph.
|
||||
TypeParameters addTypeParameters(TypeParametersKind kind) {
|
||||
final parameter = pop();
|
||||
final instr = TypeParameters(graph, currentSourcePosition, kind, parameter);
|
||||
appendInstruction(instr);
|
||||
return instr;
|
||||
}
|
||||
@@ -437,7 +435,7 @@ class FlowGraphBuilder {
|
||||
/// check at runtime.
|
||||
TypeCast addTypeCast(
|
||||
CType testedType, {
|
||||
Definition? typeParameters,
|
||||
List<Definition> typeParameters = const [],
|
||||
bool isChecked = true,
|
||||
}) {
|
||||
final object = pop();
|
||||
@@ -446,9 +444,12 @@ class FlowGraphBuilder {
|
||||
currentSourcePosition,
|
||||
object,
|
||||
testedType,
|
||||
typeParameters,
|
||||
inputCount: 1 + typeParameters.length,
|
||||
isChecked: isChecked,
|
||||
);
|
||||
for (var i = 0, n = typeParameters.length; i < n; ++i) {
|
||||
instr.setInputAt(1 + i, typeParameters[i]);
|
||||
}
|
||||
push(instr);
|
||||
appendInstruction(instr);
|
||||
return instr;
|
||||
@@ -458,15 +459,21 @@ class FlowGraphBuilder {
|
||||
///
|
||||
/// Optional [typeParameters] input should be passed if tested type
|
||||
/// depends on type parameters (not fully instantiated).
|
||||
TypeTest addTypeTest(CType testedType, {Definition? typeParameters}) {
|
||||
TypeTest addTypeTest(
|
||||
CType testedType, {
|
||||
List<Definition> typeParameters = const [],
|
||||
}) {
|
||||
final object = pop();
|
||||
final instr = TypeTest(
|
||||
graph,
|
||||
currentSourcePosition,
|
||||
object,
|
||||
testedType,
|
||||
typeParameters,
|
||||
inputCount: 1 + typeParameters.length,
|
||||
);
|
||||
for (var i = 0, n = typeParameters.length; i < n; ++i) {
|
||||
instr.setInputAt(1 + i, typeParameters[i]);
|
||||
}
|
||||
push(instr);
|
||||
appendInstruction(instr);
|
||||
return instr;
|
||||
@@ -479,9 +486,9 @@ class FlowGraphBuilder {
|
||||
/// depend on type parameters (not fully instantiated).
|
||||
void addTypeArguments(
|
||||
List<ast.DartType> types, {
|
||||
Definition? typeParameters,
|
||||
List<Definition> typeParameters = const [],
|
||||
}) {
|
||||
if (typeParameters == null) {
|
||||
if (typeParameters.isEmpty) {
|
||||
addConstant(ConstantValue(TypeArgumentsConstant(types)));
|
||||
return;
|
||||
}
|
||||
@@ -489,26 +496,35 @@ class FlowGraphBuilder {
|
||||
graph,
|
||||
currentSourcePosition,
|
||||
types,
|
||||
typeParameters,
|
||||
inputCount: typeParameters.length,
|
||||
);
|
||||
for (var i = 0, n = typeParameters.length; i < n; ++i) {
|
||||
instr.setInputAt(i, typeParameters[i]);
|
||||
}
|
||||
push(instr);
|
||||
appendInstruction(instr);
|
||||
}
|
||||
|
||||
/// Append [TypeLiteral] to the graph.
|
||||
TypeLiteral addTypeLiteral(
|
||||
ast.DartType uninstantiatedType, {
|
||||
required Definition typeParameters,
|
||||
/// Append [TypeLiteral] or [Constant] representing type to the graph.
|
||||
void addTypeLiteral(
|
||||
ast.DartType type, {
|
||||
required List<Definition> typeParameters,
|
||||
}) {
|
||||
if (typeParameters.isEmpty) {
|
||||
addConstant(ConstantValue(ast.TypeLiteralConstant(type)));
|
||||
return;
|
||||
}
|
||||
final instr = TypeLiteral(
|
||||
graph,
|
||||
currentSourcePosition,
|
||||
uninstantiatedType,
|
||||
typeParameters,
|
||||
type,
|
||||
inputCount: typeParameters.length,
|
||||
);
|
||||
for (var i = 0, n = typeParameters.length; i < n; ++i) {
|
||||
instr.setInputAt(i, typeParameters[i]);
|
||||
}
|
||||
push(instr);
|
||||
appendInstruction(instr);
|
||||
return instr;
|
||||
}
|
||||
|
||||
/// Append [AllocateObject] to the graph.
|
||||
|
||||
@@ -316,19 +316,14 @@ final class FlowGraphChecker extends Pass implements InstructionVisitor<void> {
|
||||
|
||||
@override
|
||||
void visitTypeParameters(TypeParameters instr) {
|
||||
assert(instr.block is EntryBlock);
|
||||
// TypeParameters can only be used in TypeCast, TypeTest,
|
||||
// TypeArguments and TypeLiteral.
|
||||
for (final use in instr.inputUses) {
|
||||
final user = use.getInstruction(graph);
|
||||
switch (user) {
|
||||
case TypeCast():
|
||||
assert(instr == user.typeParameters);
|
||||
case TypeTest():
|
||||
assert(instr == user.typeParameters);
|
||||
case TypeArguments():
|
||||
assert(instr == user.typeParameters);
|
||||
case TypeLiteral():
|
||||
assert(instr == user.typeParameters);
|
||||
case TypeCast() || TypeTest() || TypeArguments() || TypeLiteral():
|
||||
break;
|
||||
default:
|
||||
throw 'Unexpected user ${IrToText.instruction(user)} of TypeParameters';
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@ sealed class CFunction {
|
||||
bool get hasFunctionTypeParameters =>
|
||||
member is ast.Procedure && member.function!.typeParameters.isNotEmpty;
|
||||
|
||||
/// Total number of parameters including receiver, closure and optional parameters.
|
||||
/// Total number of parameters including function type parameters
|
||||
/// (represented with a single parameter), receiver, closure and
|
||||
/// optional parameters.
|
||||
int get numberOfParameters;
|
||||
|
||||
/// Return type of this function.
|
||||
@@ -115,6 +117,7 @@ final class RegularFunction extends CFunction {
|
||||
|
||||
@override
|
||||
int get numberOfParameters =>
|
||||
(hasFunctionTypeParameters ? 1 : 0) +
|
||||
(hasReceiverParameter ? 1 : 0) +
|
||||
member.function!.positionalParameters.length +
|
||||
member.function!.namedParameters.length;
|
||||
@@ -170,6 +173,7 @@ final class LocalFunction extends ClosureFunction {
|
||||
|
||||
@override
|
||||
int get numberOfParameters =>
|
||||
(hasFunctionTypeParameters ? 1 : 0) +
|
||||
1 /* closure */ +
|
||||
localFunction.function.positionalParameters.length +
|
||||
localFunction.function.namedParameters.length;
|
||||
@@ -200,6 +204,7 @@ final class TearOffFunction extends ClosureFunction {
|
||||
|
||||
@override
|
||||
int get numberOfParameters =>
|
||||
(hasFunctionTypeParameters ? 1 : 0) +
|
||||
1 /* closure */ +
|
||||
member.function!.positionalParameters.length +
|
||||
member.function!.namedParameters.length;
|
||||
|
||||
@@ -93,6 +93,8 @@ abstract base class Instruction {
|
||||
_inputs.truncateTo(graph, newInputCount);
|
||||
}
|
||||
|
||||
int getInputIndex(Use use) => _inputs.indexOf(graph, use);
|
||||
|
||||
/// Link this instruction to the [next] instruction in basic block.
|
||||
void linkTo(Instruction next) {
|
||||
assert(!identical(this, next));
|
||||
@@ -1099,15 +1101,30 @@ final class NullCheck extends Definition with CanThrow, Pure, Idempotent {
|
||||
R accept<R>(InstructionVisitor<R> v) => v.visitNullCheck(this);
|
||||
}
|
||||
|
||||
/// Represents collection of class and function type parameters.
|
||||
enum TypeParametersKind {
|
||||
functionTypeParameters,
|
||||
classTypeParameters,
|
||||
// Add kinds for a single function/class type parameter.
|
||||
}
|
||||
|
||||
/// Represents collection of type parameters corresponding to the
|
||||
/// given parameter.
|
||||
/// Can be used as inputs in [TypeCast], [TypeTest], [TypeArguments] and
|
||||
/// [TypeLiteral] instructions.
|
||||
final class TypeParameters extends Definition with NoThrow, Pure {
|
||||
TypeParameters(super.graph, super.sourcePosition, Definition? receiver)
|
||||
: super(inputCount: receiver != null ? 1 : 0) {
|
||||
if (receiver != null) {
|
||||
setInputAt(0, receiver);
|
||||
}
|
||||
final TypeParametersKind kind;
|
||||
|
||||
TypeParameters(
|
||||
super.graph,
|
||||
super.sourcePosition,
|
||||
this.kind,
|
||||
Definition parameter,
|
||||
) : super(inputCount: 1) {
|
||||
setInputAt(0, parameter);
|
||||
}
|
||||
|
||||
Definition get parameter => inputDefAt(0);
|
||||
|
||||
@override
|
||||
CType get type => const TypeParametersType();
|
||||
|
||||
@@ -1117,8 +1134,7 @@ final class TypeParameters extends Definition with NoThrow, Pure {
|
||||
|
||||
/// Casts input object to the given type.
|
||||
///
|
||||
/// Checked casts throw TypeError if
|
||||
/// object is not assignable to the given type.
|
||||
/// Checked casts throw TypeError if object is not assignable to the given type.
|
||||
final class TypeCast extends Definition with CanThrow, Pure, Idempotent {
|
||||
/// Target type for the type cast.
|
||||
final CType testedType;
|
||||
@@ -1130,18 +1146,15 @@ final class TypeCast extends Definition with CanThrow, Pure, Idempotent {
|
||||
super.graph,
|
||||
super.sourcePosition,
|
||||
Definition object,
|
||||
this.testedType,
|
||||
Definition? typeParameters, {
|
||||
this.testedType, {
|
||||
required super.inputCount,
|
||||
this.isChecked = true,
|
||||
}) : super(inputCount: typeParameters != null ? 2 : 1) {
|
||||
}) {
|
||||
assert(inputCount > 0);
|
||||
setInputAt(0, object);
|
||||
if (typeParameters != null) {
|
||||
setInputAt(1, typeParameters);
|
||||
}
|
||||
}
|
||||
|
||||
Definition get operand => inputDefAt(0);
|
||||
Definition? get typeParameters => (inputCount > 1) ? inputDefAt(1) : null;
|
||||
|
||||
@override
|
||||
CType get type => testedType;
|
||||
@@ -1167,17 +1180,14 @@ final class TypeTest extends Definition with NoThrow, Pure, Idempotent {
|
||||
super.graph,
|
||||
super.sourcePosition,
|
||||
Definition object,
|
||||
this.testedType,
|
||||
Definition? typeParameters,
|
||||
) : super(inputCount: typeParameters != null ? 2 : 1) {
|
||||
this.testedType, {
|
||||
required super.inputCount,
|
||||
}) {
|
||||
assert(inputCount > 0);
|
||||
setInputAt(0, object);
|
||||
if (typeParameters != null) {
|
||||
setInputAt(1, typeParameters);
|
||||
}
|
||||
}
|
||||
|
||||
Definition get operand => inputDefAt(0);
|
||||
Definition? get typeParameters => (inputCount > 1) ? inputDefAt(1) : null;
|
||||
|
||||
@override
|
||||
CType get type => const BoolType();
|
||||
@@ -1200,13 +1210,9 @@ final class TypeArguments extends Definition with NoThrow, Pure, Idempotent {
|
||||
TypeArguments(
|
||||
super.graph,
|
||||
super.sourcePosition,
|
||||
this.types,
|
||||
Definition typeParameters,
|
||||
) : super(inputCount: 1) {
|
||||
setInputAt(0, typeParameters);
|
||||
}
|
||||
|
||||
Definition get typeParameters => inputDefAt(0);
|
||||
this.types, {
|
||||
required super.inputCount,
|
||||
});
|
||||
|
||||
@override
|
||||
CType get type => const TypeArgumentsType();
|
||||
@@ -1225,13 +1231,9 @@ final class TypeLiteral extends Definition with NoThrow, Pure, Idempotent {
|
||||
TypeLiteral(
|
||||
super.graph,
|
||||
super.sourcePosition,
|
||||
this.uninstantiatedType,
|
||||
Definition typeParameters,
|
||||
) : super(inputCount: 1) {
|
||||
setInputAt(0, typeParameters);
|
||||
}
|
||||
|
||||
Definition get typeParameters => inputDefAt(0);
|
||||
this.uninstantiatedType, {
|
||||
required super.inputCount,
|
||||
});
|
||||
|
||||
@override
|
||||
CType get type =>
|
||||
|
||||
@@ -81,6 +81,15 @@ extension type const UsesArray(ArenaPointer _ptr) {
|
||||
return Use(_ptr + elementsOffset + index * Use.useSize);
|
||||
}
|
||||
|
||||
int indexOf(FlowGraph graph, Use use) {
|
||||
assert(_ptr != ArenaPointer.Null);
|
||||
final offset = use._ptr - (_ptr + elementsOffset);
|
||||
assert((offset % Use.useSize) == 0);
|
||||
final index = offset ~/ Use.useSize;
|
||||
assert(0 <= index && index < getLength(graph));
|
||||
return index;
|
||||
}
|
||||
|
||||
void truncateTo(FlowGraph graph, int newLength) {
|
||||
assert(_ptr != ArenaPointer.Null);
|
||||
assert((0 <= newLength) && (newLength <= getLength(graph)));
|
||||
|
||||
@@ -18,6 +18,13 @@ extension type const ArenaPointer(int _index) {
|
||||
return ArenaPointer(_index + size);
|
||||
}
|
||||
|
||||
/// Number of 32-bit elements between [base] and [this] pointers.
|
||||
int operator -(ArenaPointer base) {
|
||||
assert(this != Null);
|
||||
assert(base != Null);
|
||||
return this._index - base._index;
|
||||
}
|
||||
|
||||
/// 32-bit unsigned integer value of this pointer.
|
||||
int toInt() => _index;
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ class CompileAndDumpIr extends RecursiveVisitor {
|
||||
functionRegistry,
|
||||
recognizedMethods,
|
||||
enableAsserts: true,
|
||||
typeParametersStyle: .separateFunctionAndClassTypeParameters,
|
||||
).buildFlowGraph();
|
||||
final pipeline = Pipeline([
|
||||
SSAComputation(),
|
||||
|
||||
@@ -1,58 +1,60 @@
|
||||
--- listLiterals
|
||||
B0 = EntryBlock()
|
||||
v3 = Constant(<dynamic>)
|
||||
v4 = Constant(0)
|
||||
v10 = Constant(<int>)
|
||||
v11 = Constant(1)
|
||||
v12 = Constant(2)
|
||||
v13 = Constant(3)
|
||||
v16 = Constant(4)
|
||||
v17 = Constant(5)
|
||||
v18 = Constant(6)
|
||||
v19 = Constant(7)
|
||||
v20 = Constant(8)
|
||||
v21 = Constant(9)
|
||||
v36 = Constant(null)
|
||||
v1 = Parameter(x)
|
||||
v2 = TypeParameters()
|
||||
v5 = DirectCall _GrowableList.(v3, v4)
|
||||
DirectCall print(v5)
|
||||
v7 = TypeArguments(v2, <listLiterals.T%>)
|
||||
v8 = DirectCall _GrowableList.(v7, v4)
|
||||
DirectCall print(v8)
|
||||
v14 = DirectCall _GrowableList._literal3(v10, v11, v12, v13)
|
||||
DirectCall print(v14)
|
||||
v22 = AllocateListLiteral(v10, v11, v12, v13, v16, v17, v18, v19, v20, v21)
|
||||
DirectCall print(v22)
|
||||
v34 = AllocateListLiteral(v7, v1, v1, v1, v1, v1, v1, v1, v1, v1)
|
||||
DirectCall print(v34)
|
||||
Return(v36)
|
||||
v5 = Constant(<dynamic>)
|
||||
v6 = Constant(0)
|
||||
v9 = Constant(null)
|
||||
v13 = Constant(<int>)
|
||||
v14 = Constant(1)
|
||||
v15 = Constant(2)
|
||||
v16 = Constant(3)
|
||||
v19 = Constant(4)
|
||||
v20 = Constant(5)
|
||||
v21 = Constant(6)
|
||||
v22 = Constant(7)
|
||||
v23 = Constant(8)
|
||||
v24 = Constant(9)
|
||||
v1 = Parameter(#functionTypeParameters)
|
||||
v2 = Parameter(x)
|
||||
v4 = TypeParameters(v1)
|
||||
v7 = DirectCall _GrowableList.(v5, v6)
|
||||
DirectCall print(v7)
|
||||
v10 = TypeArguments(v4, v9, <listLiterals.T%>)
|
||||
v11 = DirectCall _GrowableList.(v10, v6)
|
||||
DirectCall print(v11)
|
||||
v17 = DirectCall _GrowableList._literal3(v13, v14, v15, v16)
|
||||
DirectCall print(v17)
|
||||
v25 = AllocateListLiteral(v13, v14, v15, v16, v19, v20, v21, v22, v23, v24)
|
||||
DirectCall print(v25)
|
||||
v37 = AllocateListLiteral(v10, v2, v2, v2, v2, v2, v2, v2, v2, v2)
|
||||
DirectCall print(v37)
|
||||
Return(v9)
|
||||
|
||||
--- mapLiterals
|
||||
B0 = EntryBlock()
|
||||
v6 = Constant(<dynamic, dynamic>)
|
||||
v12 = Constant(<String, String>)
|
||||
v13 = Constant("a")
|
||||
v14 = Constant("aa")
|
||||
v15 = Constant("b")
|
||||
v16 = Constant("bb")
|
||||
v27 = Constant(null)
|
||||
v1 = Parameter(key)
|
||||
v2 = Parameter(value)
|
||||
v3 = Parameter(key2)
|
||||
v4 = Parameter(value2)
|
||||
v5 = TypeParameters()
|
||||
v7 = AllocateMapLiteral(v6)
|
||||
DirectCall print(v7)
|
||||
v9 = TypeArguments(v5, <mapLiterals.S%, mapLiterals.T%>)
|
||||
v10 = AllocateMapLiteral(v9)
|
||||
DirectCall print(v10)
|
||||
v17 = AllocateMapLiteral(v12, v13, v14, v15, v16)
|
||||
DirectCall print(v17)
|
||||
v22 = ClosureCall(v2)
|
||||
v25 = AllocateMapLiteral(v9, v1, v22, v3, v4)
|
||||
DirectCall print(v25)
|
||||
Return(v27)
|
||||
v8 = Constant(<dynamic, dynamic>)
|
||||
v11 = Constant(null)
|
||||
v15 = Constant(<String, String>)
|
||||
v16 = Constant("a")
|
||||
v17 = Constant("aa")
|
||||
v18 = Constant("b")
|
||||
v19 = Constant("bb")
|
||||
v1 = Parameter(#functionTypeParameters)
|
||||
v2 = Parameter(key)
|
||||
v3 = Parameter(value)
|
||||
v4 = Parameter(key2)
|
||||
v5 = Parameter(value2)
|
||||
v7 = TypeParameters(v1)
|
||||
v9 = AllocateMapLiteral(v8)
|
||||
DirectCall print(v9)
|
||||
v12 = TypeArguments(v7, v11, <mapLiterals.S%, mapLiterals.T%>)
|
||||
v13 = AllocateMapLiteral(v12)
|
||||
DirectCall print(v13)
|
||||
v20 = AllocateMapLiteral(v15, v16, v17, v18, v19)
|
||||
DirectCall print(v20)
|
||||
v25 = ClosureCall(v3)
|
||||
v28 = AllocateMapLiteral(v12, v2, v25, v4, v5)
|
||||
DirectCall print(v28)
|
||||
Return(v11)
|
||||
|
||||
--- nullChecks
|
||||
B0 = EntryBlock()
|
||||
|
||||
@@ -10,52 +10,58 @@ B0 = EntryBlock()
|
||||
B0 = EntryBlock()
|
||||
v4 = Constant(<int>)
|
||||
v6 = Constant(1)
|
||||
v10 = Constant(2)
|
||||
v12 = Constant(null)
|
||||
v8 = Constant(null)
|
||||
v11 = Constant(2)
|
||||
v1 = Parameter(this)
|
||||
v3 = TypeParameters(v1)
|
||||
InterfaceCall A.foo(v4, v1, v6)
|
||||
v8 = TypeArguments(v3, <Map<String, A.T%>>)
|
||||
InterfaceCall A.foo(v8, v1, v10)
|
||||
Return(v12)
|
||||
v9 = TypeArguments(v8, v3, <Map<String, A.T%>>)
|
||||
InterfaceCall A.foo(v9, v1, v11)
|
||||
Return(v8)
|
||||
|
||||
--- A.foo
|
||||
B0 = EntryBlock() dominates:(B8, B10, B7)
|
||||
v16 = Constant(null)
|
||||
v1 = Parameter(this)
|
||||
v2 = Parameter(o)
|
||||
v4 = TypeParameters(v1)
|
||||
v6 = TypeTest(v2, v4, List<A.T%>)
|
||||
Branch(v6, true: B7, false: B8)
|
||||
B7 = TargetBlock() idom:B0
|
||||
v13 = TypeCast(v2, v4, List<A.T%>, unchecked)
|
||||
TypeCast(v13, Map<dynamic, dynamic>)
|
||||
Goto(B10)
|
||||
B8 = TargetBlock() idom:B0
|
||||
Goto(B10)
|
||||
B10 = JoinBlock(B8, B7) idom:B0
|
||||
Return(v16)
|
||||
B0 = EntryBlock() dominates:(B12, B14, B11)
|
||||
v9 = Constant(null)
|
||||
v1 = Parameter(#functionTypeParameters)
|
||||
v2 = Parameter(this)
|
||||
v3 = Parameter(o)
|
||||
TypeParameters(v1)
|
||||
v7 = TypeParameters(v2)
|
||||
v10 = TypeTest(v3, v9, v7, List<A.T%>)
|
||||
Branch(v10, true: B11, false: B12)
|
||||
B11 = TargetBlock() idom:B0
|
||||
v17 = TypeCast(v3, v9, v7, List<A.T%>, unchecked)
|
||||
TypeCast(v17, Map<dynamic, dynamic>)
|
||||
Goto(B14)
|
||||
B12 = TargetBlock() idom:B0
|
||||
Goto(B14)
|
||||
B14 = JoinBlock(B12, B11) idom:B0
|
||||
Return(v9)
|
||||
|
||||
--- A.baz
|
||||
B0 = EntryBlock()
|
||||
v4 = Constant(TypeLiteralConstant(List<dynamic>))
|
||||
v10 = Constant(null)
|
||||
v1 = Parameter(this)
|
||||
v3 = TypeParameters(v1)
|
||||
DirectCall print(v4)
|
||||
v6 = TypeLiteral(A.T%, v3)
|
||||
DirectCall print(v6)
|
||||
v8 = TypeLiteral(Map<A.baz.S%, A.T%>, v3)
|
||||
DirectCall print(v8)
|
||||
Return(v10)
|
||||
v7 = Constant(TypeLiteralConstant(List<dynamic>))
|
||||
v9 = Constant(null)
|
||||
v1 = Parameter(#functionTypeParameters)
|
||||
v2 = Parameter(this)
|
||||
v4 = TypeParameters(v1)
|
||||
v6 = TypeParameters(v2)
|
||||
DirectCall print(v7)
|
||||
v10 = TypeLiteral(A.T%, v9, v6)
|
||||
DirectCall print(v10)
|
||||
v12 = TypeLiteral(Map<A.baz.S%, A.T%>, v4, v6)
|
||||
DirectCall print(v12)
|
||||
Return(v9)
|
||||
|
||||
--- A.
|
||||
B0 = EntryBlock()
|
||||
v1 = TypeParameters()
|
||||
v2 = TypeArguments(v1, <A..T%>)
|
||||
v3 = AllocateObject A<A..T%>(v2)
|
||||
DirectCall A._(v3)
|
||||
Return(v3)
|
||||
v4 = Constant(null)
|
||||
v1 = Parameter(#functionTypeParameters)
|
||||
v3 = TypeParameters(v1)
|
||||
v5 = TypeArguments(v3, v4, <A..T%>)
|
||||
v6 = AllocateObject A<A..T%>(v5)
|
||||
DirectCall A._(v6)
|
||||
Return(v6)
|
||||
|
||||
--- main
|
||||
B0 = EntryBlock()
|
||||
|
||||
@@ -443,11 +443,6 @@ final class Arm64CodeGenerator extends CodeGenerator {
|
||||
_asm.unimplemented('Unimplemented: code generation for NullCheck');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitTypeParameters(TypeParameters instr) {
|
||||
_asm.unimplemented('Unimplemented: code generation for TypeParameters');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitTypeCast(TypeCast instr) {
|
||||
_asm.unimplemented('Unimplemented: code generation for TypeCast');
|
||||
|
||||
@@ -175,33 +175,39 @@ final class Arm64Constraints extends Constraints {
|
||||
InstructionConstraints? visitNullCheck(NullCheck instr) =>
|
||||
const InstructionConstraints(anyCpuRegister, [anyCpuRegister]);
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitTypeParameters(TypeParameters instr) =>
|
||||
InstructionConstraints(anyCpuRegister, [
|
||||
if (instr.inputCount == 1) anyCpuRegister,
|
||||
]);
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitTypeCast(TypeCast instr) =>
|
||||
InstructionConstraints(anyCpuRegister, [
|
||||
anyCpuRegister,
|
||||
if (instr.inputCount == 2) anyCpuRegister,
|
||||
if (instr.inputCount > 1) ...[
|
||||
anyRegisterOrImmediate(instr.inputDefAt(1)),
|
||||
anyRegisterOrImmediate(instr.inputDefAt(2)),
|
||||
],
|
||||
]);
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitTypeTest(TypeTest instr) =>
|
||||
InstructionConstraints(anyCpuRegister, [
|
||||
anyCpuRegister,
|
||||
if (instr.inputCount == 2) anyCpuRegister,
|
||||
if (instr.inputCount > 1) ...[
|
||||
anyRegisterOrImmediate(instr.inputDefAt(1)),
|
||||
anyRegisterOrImmediate(instr.inputDefAt(2)),
|
||||
],
|
||||
]);
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitTypeArguments(TypeArguments instr) =>
|
||||
const InstructionConstraints(anyCpuRegister, [anyCpuRegister]);
|
||||
InstructionConstraints(anyCpuRegister, [
|
||||
anyRegisterOrImmediate(instr.inputDefAt(0)),
|
||||
anyRegisterOrImmediate(instr.inputDefAt(1)),
|
||||
]);
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitTypeLiteral(TypeLiteral instr) =>
|
||||
const InstructionConstraints(anyCpuRegister, [anyCpuRegister]);
|
||||
InstructionConstraints(anyCpuRegister, [
|
||||
anyRegisterOrImmediate(instr.inputDefAt(0)),
|
||||
anyRegisterOrImmediate(instr.inputDefAt(1)),
|
||||
]);
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitAllocateObject(AllocateObject instr) =>
|
||||
|
||||
@@ -286,6 +286,10 @@ abstract base class CodeGenerator extends Pass
|
||||
void generatePush(Location loc);
|
||||
void generatePop(Location loc);
|
||||
|
||||
@override
|
||||
void visitTypeParameters(TypeParameters instr) =>
|
||||
throw 'Unexpected TypeParameters (should be lowered)';
|
||||
|
||||
@override
|
||||
void visitAllocateListLiteral(AllocateListLiteral instr) =>
|
||||
throw 'Unexpected AllocateListLiteral (should be lowered)';
|
||||
|
||||
@@ -127,6 +127,10 @@ abstract base class Constraints
|
||||
@override
|
||||
InstructionConstraints? visitParallelMove(ParallelMove instr) => null;
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitTypeParameters(TypeParameters instr) =>
|
||||
throw 'Unexpected TypeParameters (should be lowered)';
|
||||
|
||||
@override
|
||||
InstructionConstraints? visitAllocateListLiteral(AllocateListLiteral instr) =>
|
||||
throw 'Unexpected AllocateListLiteral (should be lowered)';
|
||||
|
||||
@@ -87,8 +87,10 @@ final class LinearScanRegisterAllocator extends RegisterAllocator {
|
||||
Instruction instructionByPos(int pos) =>
|
||||
graph.instructions[_instructionByPos[pos ~/ step]];
|
||||
|
||||
bool hasLiveRange(Definition instr) => instr is! Constant;
|
||||
|
||||
LiveRange liveRangeFor(Definition instr) {
|
||||
assert(instr is! Constant);
|
||||
assert(hasLiveRange(instr));
|
||||
return _liveRanges[instr.id] ??= LiveRange(registerClass(instr));
|
||||
}
|
||||
|
||||
@@ -172,7 +174,7 @@ final class LinearScanRegisterAllocator extends RegisterAllocator {
|
||||
// Add intervals for values which are live-out.
|
||||
for (final instrId in liveness.liveOut(block).elements) {
|
||||
final instr = graph.instructions[instrId] as Definition;
|
||||
if (instr is! Constant) {
|
||||
if (hasLiveRange(instr)) {
|
||||
final liveRange = liveRangeFor(instr);
|
||||
liveRange.addInterval(blockStart, blockEnd);
|
||||
}
|
||||
@@ -241,7 +243,7 @@ final class LinearScanRegisterAllocator extends RegisterAllocator {
|
||||
_processTemp(pos, constr.temps[i], operandId);
|
||||
}
|
||||
// Process output.
|
||||
if (instr is Definition && instr is! Constant) {
|
||||
if (instr is Definition && hasLiveRange(instr)) {
|
||||
final operandId = OperandId.result(instr.id);
|
||||
final liveRange = liveRangeFor(instr);
|
||||
final resultConstr = constr.result;
|
||||
@@ -262,7 +264,7 @@ final class LinearScanRegisterAllocator extends RegisterAllocator {
|
||||
errorContext.annotator = (Instruction instr) {
|
||||
if (instr is ParallelMove) return null;
|
||||
return '[${instructionPos(instr)}]' +
|
||||
((instr is Definition && instr is! Constant)
|
||||
((instr is Definition && hasLiveRange(instr))
|
||||
? ' ${liveRangeFor(instr)}'
|
||||
: '');
|
||||
};
|
||||
|
||||
@@ -119,6 +119,7 @@ class CompilationSet {
|
||||
functionRegistry,
|
||||
recognizedMethods,
|
||||
enableAsserts: config.enableAsserts,
|
||||
typeParametersStyle: .separateFunctionAndClassTypeParameters,
|
||||
).buildFlowGraph();
|
||||
} catch (_) {
|
||||
print('Compiler crashed while compiling $function');
|
||||
|
||||
@@ -132,7 +132,7 @@ final class DevelopmentCompilerConfiguration extends Configuration {
|
||||
ValueNumbering(simplification: Simplification()),
|
||||
ConstantPropagation(),
|
||||
ControlFlowOptimizations(),
|
||||
Lowering(functionRegistry),
|
||||
Lowering(functionRegistry, objectLayout),
|
||||
ReorderBlocks(backEndState),
|
||||
LinearScanRegisterAllocator(backEndState, constraints),
|
||||
RegisterAllocationChecker(backEndState, constraints),
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:cfg/ir/visitor.dart';
|
||||
import 'package:cfg/passes/pass.dart';
|
||||
import 'package:cfg/utils/misc.dart';
|
||||
import 'package:kernel/ast.dart' as ast;
|
||||
import 'package:native_compiler/runtime/object_layout.dart';
|
||||
|
||||
/// IR lowering for native back-end.
|
||||
///
|
||||
@@ -21,8 +22,9 @@ import 'package:kernel/ast.dart' as ast;
|
||||
/// TODO: insert boxing/unboxing
|
||||
final class Lowering extends Pass with DefaultInstructionVisitor<void> {
|
||||
final FunctionRegistry functionRegistry;
|
||||
final ObjectLayout objectLayout;
|
||||
|
||||
Lowering(this.functionRegistry) : super('Lowering');
|
||||
Lowering(this.functionRegistry, this.objectLayout) : super('Lowering');
|
||||
|
||||
late final CFunction _growableListLiteral = functionRegistry.getFunction(
|
||||
GlobalContext.instance.coreTypes.index.getProcedure(
|
||||
@@ -139,6 +141,35 @@ final class Lowering extends Pass with DefaultInstructionVisitor<void> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitTypeParameters(TypeParameters instr) {
|
||||
switch (instr.kind) {
|
||||
case .classTypeParameters:
|
||||
final receiver = instr.inputDefAt(0);
|
||||
final receiverClass =
|
||||
(receiver.type.dartType as ast.InterfaceType).classNode;
|
||||
final typeArgsField = objectLayout.getTypeArgumentsField(
|
||||
receiverClass,
|
||||
)!;
|
||||
for (final use in instr.inputUses) {
|
||||
final user = use.getInstruction(graph);
|
||||
final load = LoadInstanceField(
|
||||
graph,
|
||||
user.sourcePosition,
|
||||
typeArgsField,
|
||||
receiver,
|
||||
);
|
||||
load.insertBefore(user);
|
||||
user.replaceInputAt(user.getInputIndex(use), load);
|
||||
}
|
||||
case .functionTypeParameters:
|
||||
final replacement = instr.inputDefAt(0);
|
||||
instr.replaceUsesWith(replacement);
|
||||
break;
|
||||
}
|
||||
instr.removeFromGraph();
|
||||
}
|
||||
|
||||
@override
|
||||
void visitAllocateListLiteral(AllocateListLiteral instr) {
|
||||
// List literals up to 8 elements are lowered in the front-end
|
||||
|
||||
@@ -34,6 +34,8 @@ import 'package:native_compiler/back_end/regalloc_checker.dart';
|
||||
import 'package:native_compiler/back_end/register_allocator.dart';
|
||||
import 'package:native_compiler/passes/lowering.dart';
|
||||
import 'package:native_compiler/passes/reorder_blocks.dart';
|
||||
import 'package:native_compiler/runtime/object_layout.dart';
|
||||
import 'package:native_compiler/runtime/vm_defs.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vm/modular/target/vm.dart';
|
||||
|
||||
@@ -151,16 +153,23 @@ class CompileAndDumpIr extends RecursiveVisitor {
|
||||
functionRegistry,
|
||||
recognizedMethods,
|
||||
enableAsserts: true,
|
||||
typeParametersStyle: .separateFunctionAndClassTypeParameters,
|
||||
).buildFlowGraph();
|
||||
final backEndState = BackEndState();
|
||||
final constraints = Arm64Constraints();
|
||||
final vmOffsets = Arm64VMOffsets();
|
||||
final objectLayout = ObjectLayout(
|
||||
vmOffsets,
|
||||
wordSize: 8,
|
||||
compressedWordSize: 8,
|
||||
);
|
||||
backEndState.stackFrame = Arm64StackFrame(function);
|
||||
final pipeline = Pipeline([
|
||||
SSAComputation(),
|
||||
ValueNumbering(simplification: Simplification()),
|
||||
ConstantPropagation(),
|
||||
ControlFlowOptimizations(),
|
||||
Lowering(functionRegistry),
|
||||
Lowering(functionRegistry, objectLayout),
|
||||
ReorderBlocks(backEndState),
|
||||
LinearScanRegisterAllocator(backEndState, constraints),
|
||||
RegisterAllocationChecker(backEndState, constraints),
|
||||
|
||||
@@ -70,4 +70,12 @@ void stringInterpolation(int x, String s, Object o) {
|
||||
print('Hey, x=$x, s=$s, o=$o');
|
||||
}
|
||||
|
||||
class C<T> {
|
||||
void typeParameters<U>(Object x) {
|
||||
print(x is List<T>);
|
||||
print(x is List<U>);
|
||||
print(x as Map<T, U>);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {}
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
--- C.
|
||||
B0 = EntryBlock()
|
||||
v6 = Constant(null)
|
||||
v1 = Parameter(this) # RA: param[0] <- ()
|
||||
ParallelMove output(param[0] -> vloc:R0)
|
||||
DirectCall Object.(v1) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(NullConstant(null) -> R0)
|
||||
Return(v6) # RA: (R0)
|
||||
|
||||
--- C.typeParameters
|
||||
B0 = EntryBlock()
|
||||
v9 = Constant(null)
|
||||
v1 = Parameter(#functionTypeParameters) # RA: param[0] <- ()
|
||||
ParallelMove output(param[0] -> vloc:R0)
|
||||
v2 = Parameter(this) # RA: param[1] <- ()
|
||||
ParallelMove output(param[1] -> vloc:R1)
|
||||
v3 = Parameter(x) # RA: param[2] <- ()
|
||||
ParallelMove output(param[2] -> vloc:R2)
|
||||
v20 = LoadInstanceField(C.#typeArguments, v2) # RA: R3 <- (R1)
|
||||
v10 = TypeTest(v3, v9, v20, List<C.T%>) # RA: R3 <- (R2, -, R3)
|
||||
DirectCall print(v10) # RA: R0 <- (R3) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(param[0] -> R1, param[2] -> R2)
|
||||
v13 = TypeTest(v3, v1, v9, List<C.typeParameters.U%>) # RA: R0 <- (R2, R1, -)
|
||||
DirectCall print(v13) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(param[1] -> R1)
|
||||
v19 = LoadInstanceField(C.#typeArguments, v2) # RA: R0 <- (R1)
|
||||
ParallelMove split(param[0] -> R1, param[2] -> R2)
|
||||
v16 = TypeCast(v3, v1, v19, Map<C.T%, C.typeParameters.U%>) # RA: R0 <- (R2, R1, R0)
|
||||
DirectCall print(v16) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(NullConstant(null) -> R0)
|
||||
Return(v9) # RA: (R0)
|
||||
|
||||
--- test1
|
||||
B0 = EntryBlock()
|
||||
Constant(0)
|
||||
@@ -145,155 +177,155 @@ B43 = TargetBlock() idom:B33
|
||||
|
||||
--- listLiterals
|
||||
B0 = EntryBlock()
|
||||
v3 = Constant(<dynamic>)
|
||||
v4 = Constant(0)
|
||||
v10 = Constant(<int>)
|
||||
v11 = Constant(1)
|
||||
v12 = Constant(2)
|
||||
v13 = Constant(3)
|
||||
v16 = Constant(4)
|
||||
v17 = Constant(5)
|
||||
v18 = Constant(6)
|
||||
v19 = Constant(7)
|
||||
v20 = Constant(8)
|
||||
v21 = Constant(9)
|
||||
v36 = Constant(null)
|
||||
v1 = Parameter(x) # RA: param[0] <- ()
|
||||
v5 = Constant(<dynamic>)
|
||||
v6 = Constant(0)
|
||||
v9 = Constant(null)
|
||||
v13 = Constant(<int>)
|
||||
v14 = Constant(1)
|
||||
v15 = Constant(2)
|
||||
v16 = Constant(3)
|
||||
v19 = Constant(4)
|
||||
v20 = Constant(5)
|
||||
v21 = Constant(6)
|
||||
v22 = Constant(7)
|
||||
v23 = Constant(8)
|
||||
v24 = Constant(9)
|
||||
v1 = Parameter(#functionTypeParameters) # RA: param[0] <- ()
|
||||
ParallelMove output(param[0] -> vloc:R0)
|
||||
v2 = TypeParameters() # RA: R1 <- ()
|
||||
ParallelMove spill(R1 -> stack[0])
|
||||
v5 = DirectCall _GrowableList.(v3, v4) # RA: R0 <- (-, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
v2 = Parameter(x) # RA: param[1] <- ()
|
||||
ParallelMove output(param[1] -> vloc:R1)
|
||||
v7 = DirectCall _GrowableList.(v5, v6) # RA: R0 <- (-, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v5) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(stack[0] -> R1)
|
||||
v7 = TypeArguments(v2, <listLiterals.T%>) # RA: R0 <- (R1)
|
||||
ParallelMove spill(R0 -> stack[1])
|
||||
v8 = DirectCall _GrowableList.(v7, v4) # RA: R0 <- (R0, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v7) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(param[0] -> R1)
|
||||
v10 = TypeArguments(v1, v9, <listLiterals.T%>) # RA: R0 <- (R1, -)
|
||||
ParallelMove spill(R0 -> stack[0])
|
||||
v11 = DirectCall _GrowableList.(v10, v6) # RA: R0 <- (R0, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v8) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
v14 = DirectCall _GrowableList._literal3(v10, v11, v12, v13) # RA: R0 <- (-, -, -, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v11) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
v17 = DirectCall _GrowableList._literal3(v13, v14, v15, v16) # RA: R0 <- (-, -, -, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v14) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v17) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(IntConstant(9) -> vloc:R0)
|
||||
v38 = AllocateList(v21) # RA: R0 <- (R0)
|
||||
v40 = AllocateList(v24) # RA: R0 <- (R0)
|
||||
ParallelMove input(IntConstant(0) -> vloc:R2, IntConstant(1) -> vloc:R1)
|
||||
SetListElement(v38, v4, v11) # RA: (R0, R2, R1)
|
||||
SetListElement(v40, v6, v14) # RA: (R0, R2, R1)
|
||||
ParallelMove input(IntConstant(1) -> vloc:R2, IntConstant(2) -> vloc:R1)
|
||||
SetListElement(v38, v11, v12) # RA: (R0, R2, R1)
|
||||
SetListElement(v40, v14, v15) # RA: (R0, R2, R1)
|
||||
ParallelMove input(IntConstant(2) -> vloc:R2, IntConstant(3) -> vloc:R1)
|
||||
SetListElement(v38, v12, v13) # RA: (R0, R2, R1)
|
||||
SetListElement(v40, v15, v16) # RA: (R0, R2, R1)
|
||||
ParallelMove input(IntConstant(3) -> vloc:R2, IntConstant(4) -> vloc:R1)
|
||||
SetListElement(v38, v13, v16) # RA: (R0, R2, R1)
|
||||
SetListElement(v40, v16, v19) # RA: (R0, R2, R1)
|
||||
ParallelMove input(IntConstant(4) -> vloc:R1, IntConstant(5) -> vloc:R2)
|
||||
SetListElement(v38, v16, v17) # RA: (R0, R1, R2)
|
||||
SetListElement(v40, v19, v20) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(5) -> vloc:R1, IntConstant(6) -> vloc:R2)
|
||||
SetListElement(v38, v17, v18) # RA: (R0, R1, R2)
|
||||
SetListElement(v40, v20, v21) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(6) -> vloc:R1, IntConstant(7) -> vloc:R2)
|
||||
SetListElement(v38, v18, v19) # RA: (R0, R1, R2)
|
||||
SetListElement(v40, v21, v22) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(7) -> vloc:R2, IntConstant(8) -> vloc:R1)
|
||||
SetListElement(v38, v19, v20) # RA: (R0, R2, R1)
|
||||
SetListElement(v40, v22, v23) # RA: (R0, R2, R1)
|
||||
ParallelMove input(IntConstant(8) -> vloc:R1, IntConstant(9) -> vloc:R2)
|
||||
SetListElement(v38, v20, v21) # RA: (R0, R1, R2)
|
||||
v48 = DirectCall _GrowableList._literal(v10, v38) # RA: R0 <- (-, R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
SetListElement(v40, v23, v24) # RA: (R0, R1, R2)
|
||||
v50 = DirectCall _GrowableList._literal(v13, v40) # RA: R0 <- (-, R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v48) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v50) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(IntConstant(9) -> vloc:R0)
|
||||
v49 = AllocateList(v21) # RA: R0 <- (R0)
|
||||
ParallelMove split(param[0] -> R2)
|
||||
v51 = AllocateList(v24) # RA: R0 <- (R0)
|
||||
ParallelMove split(param[1] -> R2)
|
||||
ParallelMove input(IntConstant(0) -> vloc:R1)
|
||||
SetListElement(v49, v4, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v6, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(1) -> vloc:R1)
|
||||
SetListElement(v49, v11, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v14, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(2) -> vloc:R1)
|
||||
SetListElement(v49, v12, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v15, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(3) -> vloc:R1)
|
||||
SetListElement(v49, v13, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v16, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(4) -> vloc:R1)
|
||||
SetListElement(v49, v16, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v19, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(5) -> vloc:R1)
|
||||
SetListElement(v49, v17, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v20, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(6) -> vloc:R1)
|
||||
SetListElement(v49, v18, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v21, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(7) -> vloc:R1)
|
||||
SetListElement(v49, v19, v1) # RA: (R0, R1, R2)
|
||||
SetListElement(v51, v22, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(8) -> vloc:R1)
|
||||
SetListElement(v49, v20, v1) # RA: (R0, R1, R2)
|
||||
ParallelMove split(stack[1] -> R1)
|
||||
v59 = DirectCall _GrowableList._literal(v7, v49) # RA: R0 <- (R1, R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
SetListElement(v51, v23, v2) # RA: (R0, R1, R2)
|
||||
ParallelMove split(stack[0] -> R1)
|
||||
v61 = DirectCall _GrowableList._literal(v10, v51) # RA: R0 <- (R1, R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v59) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v61) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(NullConstant(null) -> R0)
|
||||
Return(v36) # RA: (R0)
|
||||
Return(v9) # RA: (R0)
|
||||
|
||||
--- mapLiterals
|
||||
B0 = EntryBlock()
|
||||
v6 = Constant(<dynamic, dynamic>)
|
||||
v12 = Constant(<String, String>)
|
||||
v13 = Constant("a")
|
||||
v14 = Constant("aa")
|
||||
v15 = Constant("b")
|
||||
v16 = Constant("bb")
|
||||
v27 = Constant(null)
|
||||
v29 = Constant(InstanceConstant(const List<dynamic>{}))
|
||||
v32 = Constant(4)
|
||||
v34 = Constant(0)
|
||||
v36 = Constant(1)
|
||||
v38 = Constant(2)
|
||||
v40 = Constant(3)
|
||||
v1 = Parameter(key) # RA: param[0] <- ()
|
||||
v8 = Constant(<dynamic, dynamic>)
|
||||
v11 = Constant(null)
|
||||
v15 = Constant(<String, String>)
|
||||
v16 = Constant("a")
|
||||
v17 = Constant("aa")
|
||||
v18 = Constant("b")
|
||||
v19 = Constant("bb")
|
||||
v31 = Constant(InstanceConstant(const List<dynamic>{}))
|
||||
v34 = Constant(4)
|
||||
v36 = Constant(0)
|
||||
v38 = Constant(1)
|
||||
v40 = Constant(2)
|
||||
v42 = Constant(3)
|
||||
v1 = Parameter(#functionTypeParameters) # RA: param[0] <- ()
|
||||
ParallelMove output(param[0] -> vloc:R0)
|
||||
v2 = Parameter(value) # RA: param[1] <- ()
|
||||
v2 = Parameter(key) # RA: param[1] <- ()
|
||||
ParallelMove output(param[1] -> vloc:R1)
|
||||
v3 = Parameter(key2) # RA: param[2] <- ()
|
||||
v3 = Parameter(value) # RA: param[2] <- ()
|
||||
ParallelMove output(param[2] -> vloc:R2)
|
||||
v4 = Parameter(value2) # RA: param[3] <- ()
|
||||
v4 = Parameter(key2) # RA: param[3] <- ()
|
||||
ParallelMove output(param[3] -> vloc:R3)
|
||||
v5 = TypeParameters() # RA: R4 <- ()
|
||||
ParallelMove spill(R4 -> stack[0])
|
||||
v30 = DirectCall Map._fromLiteral(v6, v29) # RA: R0 <- (-, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
v5 = Parameter(value2) # RA: param[4] <- ()
|
||||
ParallelMove output(param[4] -> vloc:R4)
|
||||
v32 = DirectCall Map._fromLiteral(v8, v31) # RA: R0 <- (-, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v30) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(stack[0] -> R1)
|
||||
v9 = TypeArguments(v5, <mapLiterals.S%, mapLiterals.T%>) # RA: R0 <- (R1)
|
||||
ParallelMove spill(R0 -> stack[1])
|
||||
v31 = DirectCall Map._fromLiteral(v9, v29) # RA: R0 <- (R0, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v32) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(param[0] -> R1)
|
||||
v12 = TypeArguments(v1, v11, <mapLiterals.S%, mapLiterals.T%>) # RA: R0 <- (R1, -)
|
||||
ParallelMove spill(R0 -> stack[0])
|
||||
v33 = DirectCall Map._fromLiteral(v12, v31) # RA: R0 <- (R0, -) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v31) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v33) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(IntConstant(4) -> vloc:R1)
|
||||
v33 = AllocateList(v32) # RA: R0 <- (R1)
|
||||
v35 = AllocateList(v34) # RA: R0 <- (R1)
|
||||
ParallelMove input(IntConstant(0) -> vloc:R1, StringConstant("a") -> vloc:R2)
|
||||
SetListElement(v33, v34, v13) # RA: (R0, R1, R2)
|
||||
SetListElement(v35, v36, v16) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(1) -> vloc:R1, StringConstant("aa") -> vloc:R2)
|
||||
SetListElement(v33, v36, v14) # RA: (R0, R1, R2)
|
||||
SetListElement(v35, v38, v17) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(2) -> vloc:R1, StringConstant("b") -> vloc:R2)
|
||||
SetListElement(v33, v38, v15) # RA: (R0, R1, R2)
|
||||
SetListElement(v35, v40, v18) # RA: (R0, R1, R2)
|
||||
ParallelMove input(IntConstant(3) -> vloc:R1, StringConstant("bb") -> vloc:R2)
|
||||
SetListElement(v33, v40, v16) # RA: (R0, R1, R2)
|
||||
v42 = DirectCall Map._fromLiteral(v12, v33) # RA: R0 <- (-, R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
SetListElement(v35, v42, v19) # RA: (R0, R1, R2)
|
||||
v44 = DirectCall Map._fromLiteral(v15, v35) # RA: R0 <- (-, R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v42) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(param[1] -> R1)
|
||||
v22 = ClosureCall(v2) # RA: R0 <- (R1) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v44) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove split(param[2] -> R1)
|
||||
v25 = ClosureCall(v3) # RA: R0 <- (R1) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
ParallelMove input(IntConstant(4) -> vloc:R1)
|
||||
v43 = AllocateList(v32) # RA: R1 <- (R1)
|
||||
ParallelMove split(param[0] -> R3)
|
||||
v45 = AllocateList(v34) # RA: R1 <- (R1)
|
||||
ParallelMove split(param[1] -> R3)
|
||||
ParallelMove input(IntConstant(0) -> vloc:R2)
|
||||
SetListElement(v43, v34, v1) # RA: (R1, R2, R3)
|
||||
SetListElement(v45, v36, v2) # RA: (R1, R2, R3)
|
||||
ParallelMove input(IntConstant(1) -> vloc:R2)
|
||||
SetListElement(v43, v36, v22) # RA: (R1, R2, R0)
|
||||
ParallelMove split(param[2] -> R2)
|
||||
ParallelMove input(IntConstant(2) -> vloc:R0)
|
||||
SetListElement(v43, v38, v3) # RA: (R1, R0, R2)
|
||||
SetListElement(v45, v38, v25) # RA: (R1, R2, R0)
|
||||
ParallelMove split(param[3] -> R2)
|
||||
ParallelMove input(IntConstant(2) -> vloc:R0)
|
||||
SetListElement(v45, v40, v4) # RA: (R1, R0, R2)
|
||||
ParallelMove split(param[4] -> R2)
|
||||
ParallelMove input(IntConstant(3) -> vloc:R0)
|
||||
SetListElement(v43, v40, v4) # RA: (R1, R0, R2)
|
||||
ParallelMove split(stack[1] -> R0)
|
||||
v48 = DirectCall Map._fromLiteral(v9, v43) # RA: R0 <- (R0, R1) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
SetListElement(v45, v42, v5) # RA: (R1, R0, R2)
|
||||
ParallelMove split(stack[0] -> R0)
|
||||
v50 = DirectCall Map._fromLiteral(v12, v45) # RA: R0 <- (R0, R1) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove output(R0 -> vloc:R0)
|
||||
DirectCall print(v48) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
DirectCall print(v50) # RA: R0 <- (R0) temps: [R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R19, R20, R23, R25, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30]
|
||||
ParallelMove input(NullConstant(null) -> R0)
|
||||
Return(v27) # RA: (R0)
|
||||
Return(v11) # RA: (R0)
|
||||
|
||||
--- stringInterpolation
|
||||
B0 = EntryBlock()
|
||||
|
||||
Reference in New Issue
Block a user