public override BoundNode VisitBinaryOperator(BoundBinaryOperator node) { BoundExpression left = (BoundExpression)this.Visit(node.Left); BoundExpression right = (BoundExpression)this.Visit(node.Right); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(left, right)) { return(node.Update(node.OperatorKind, left, right, node.ConstantValueOpt, node.MethodOpt, node.ResultKind, type)); } var subExprs = ReadOnlyArray <BoundExpression> .CreateFrom(left, right); var spillBuilder = new SpillBuilder(); var newArgs = SpillExpressionList(spillBuilder, subExprs); Debug.Assert(newArgs.Count == 2); var newBinaryOperator = node.Update( node.OperatorKind, newArgs[0], newArgs[1], node.ConstantValueOpt, node.MethodOpt, node.ResultKind, type); return(spillBuilder.BuildSequenceAndFree(F, newBinaryOperator)); }
private BoundNode SpillAssignmentOperator(BoundAssignmentOperator node, BoundExpression left, BoundSpillSequence right) { var spillBuilder = new SpillBuilder(); var spilledLeftNode = SpillLValue(left, spillBuilder); var innerSpill = node.Update(spilledLeftNode, right.Value, node.RefKind, node.Type); spillBuilder.AddSpill(right); return spillBuilder.BuildSequenceAndFree(F, innerSpill); }
private BoundNode SpillAssignmentOperator(BoundAssignmentOperator node, BoundExpression left, BoundSpillSequence right) { var spillBuilder = new SpillBuilder(); var spilledLeftNode = SpillLValue(left, spillBuilder); var innerSpill = node.Update(spilledLeftNode, right.Value, node.RefKind, node.Type); spillBuilder.AddSpill(right); return(spillBuilder.BuildSequenceAndFree(F, innerSpill)); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundExpression expression = (BoundExpression)this.Visit(node.Expression); ReadOnlyArray <BoundExpression> indices = (ReadOnlyArray <BoundExpression>) this.VisitList(node.Indices); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence) { return(node.Update(expression, indices, type)); } var spillBuilder = new SpillBuilder(); var spillResult = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray <RefKind> .Empty); BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type); return(spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess)); }
public override BoundNode VisitArrayCreation(BoundArrayCreation node) { ReadOnlyArray <BoundExpression> bounds = this.VisitList(node.Bounds); BoundArrayInitialization visitedInitializer = (BoundArrayInitialization)this.Visit(node.InitializerOpt); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(bounds) && (visitedInitializer == null || !RequiresSpill(visitedInitializer.Initializers))) { return(node.Update(bounds, visitedInitializer, type)); } var spillBuilder = new SpillBuilder(); ReadOnlyArray <BoundExpression> newBounds = SpillExpressionList(spillBuilder, bounds); BoundArrayInitialization newInitializerOpt = (visitedInitializer == null) ? visitedInitializer : visitedInitializer.Update(SpillExpressionList(spillBuilder, visitedInitializer.Initializers)); BoundArrayCreation newArrayCreation = node.Update(newBounds, newInitializerOpt, type); return(spillBuilder.BuildSequenceAndFree(F, newArrayCreation)); }
public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node) { ReadOnlyArray <BoundExpression> arguments = (ReadOnlyArray <BoundExpression>) this.VisitList(node.Arguments); BoundExpression initializerExpressionOpt = (BoundExpression)this.Visit(node.InitializerExpressionOpt); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(arguments) && (initializerExpressionOpt == null || initializerExpressionOpt.Kind != BoundKind.SpillSequence)) { return(node.Update(node.Constructor, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, initializerExpressionOpt, type)); } var spillBuilder = new SpillBuilder(); ReadOnlyArray <BoundExpression> newArguments = SpillExpressionList(spillBuilder, arguments); BoundExpression newInitializerExpressionOpt; if (initializerExpressionOpt != null && initializerExpressionOpt.Kind == BoundKind.SpillSequence) { var spill = (BoundSpillSequence)initializerExpressionOpt; spillBuilder.AddSpill(spill); newInitializerExpressionOpt = spill.Value; } else { newInitializerExpressionOpt = initializerExpressionOpt; } BoundObjectCreationExpression newObjectCreation = node.Update( node.Constructor, newArguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, newInitializerExpressionOpt, type); return(spillBuilder.BuildSequenceAndFree(F, newObjectCreation)); }
public override BoundNode VisitConditionalOperator(BoundConditionalOperator node) { BoundExpression condition = (BoundExpression)this.Visit(node.Condition); BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence); BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(condition, consequence, alternative)) { return(node.Update(condition, consequence, alternative, node.ConstantValueOpt, type)); } var spillBuilder = new SpillBuilder(); LocalSymbol resultLocal = F.SynthesizedLocal(type, null); spillBuilder.Locals.Add(resultLocal); BoundExpression newCondition; if (condition.Kind == BoundKind.SpillSequence) { var spill = (BoundSpillSequence)condition; spillBuilder.AddSpill(spill); newCondition = spill.Value; } else { newCondition = condition; } spillBuilder.Statements.Add( F.If( condition: newCondition, thenClause: CrushExpression(consequence, resultLocal), elseClause: CrushExpression(alternative, resultLocal))); return(spillBuilder.BuildSequenceAndFree(F, F.Local(resultLocal))); }
public override BoundNode VisitCall(BoundCall node) { BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt); ReadOnlyArray <BoundExpression> arguments = this.VisitList(node.Arguments); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(arguments) && !RequiresSpill(receiverOpt)) { return(node.Update( receiverOpt, node.Method, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.ResultKind, type)); } var spillBuilder = new SpillBuilder(); var spillResult = SpillExpressionsWithReceiver(receiverOpt, arguments, spillBuilder, node.Method.ParameterRefKinds); var newCall = node.Update( spillResult.Item1, node.Method, spillResult.Item2, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.ResultKind, type); return(spillBuilder.BuildSequenceAndFree(F, newCall)); }
public override BoundNode VisitSequence(BoundSequence node) { ReadOnlyArray <BoundExpression> sideEffects = (ReadOnlyArray <BoundExpression>) this.VisitList(node.SideEffects); BoundExpression value = (BoundExpression)this.Visit(node.Value); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(sideEffects) && value.Kind != BoundKind.SpillSequence) { return(node.Update(node.Locals, sideEffects, value, type)); } var spillBuilder = new SpillBuilder(); spillBuilder.Locals.AddRange(node.Locals); foreach (var sideEffect in sideEffects) { spillBuilder.Statements.Add( (sideEffect.Kind == BoundKind.SpillSequence) ? RewriteSpillSequenceAsBlock((BoundSpillSequence)sideEffect) : F.ExpressionStatement(sideEffect)); } BoundExpression newValue; if (value.Kind == BoundKind.SpillSequence) { var awaitEffect = (BoundSpillSequence)value; spillBuilder.AddSpill(awaitEffect); newValue = awaitEffect.Value; } else { newValue = value; } return(spillBuilder.BuildSequenceAndFree(F, newValue)); }
public override BoundNode VisitSequence(BoundSequence node) { ReadOnlyArray<BoundExpression> sideEffects = (ReadOnlyArray<BoundExpression>)this.VisitList(node.SideEffects); BoundExpression value = (BoundExpression)this.Visit(node.Value); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(sideEffects) && value.Kind != BoundKind.SpillSequence) { return node.Update(node.Locals, sideEffects, value, type); } var spillBuilder = new SpillBuilder(); spillBuilder.Locals.AddRange(node.Locals); foreach (var sideEffect in sideEffects) { spillBuilder.Statements.Add( (sideEffect.Kind == BoundKind.SpillSequence) ? RewriteSpillSequenceAsBlock((BoundSpillSequence)sideEffect) : F.ExpressionStatement(sideEffect)); } BoundExpression newValue; if (value.Kind == BoundKind.SpillSequence) { var awaitEffect = (BoundSpillSequence)value; spillBuilder.AddSpill(awaitEffect); newValue = awaitEffect.Value; } else { newValue = value; } return spillBuilder.BuildSequenceAndFree(F, newValue); }
public override BoundNode VisitConditionalOperator(BoundConditionalOperator node) { BoundExpression condition = (BoundExpression)this.Visit(node.Condition); BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence); BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(condition, consequence, alternative)) { return node.Update(condition, consequence, alternative, node.ConstantValueOpt, type); } var spillBuilder = new SpillBuilder(); LocalSymbol resultLocal = F.SynthesizedLocal(type, null); spillBuilder.Locals.Add(resultLocal); BoundExpression newCondition; if (condition.Kind == BoundKind.SpillSequence) { var spill = (BoundSpillSequence)condition; spillBuilder.AddSpill(spill); newCondition = spill.Value; } else { newCondition = condition; } spillBuilder.Statements.Add( F.If( condition: newCondition, thenClause: CrushExpression(consequence, resultLocal), elseClause: CrushExpression(alternative, resultLocal))); return spillBuilder.BuildSequenceAndFree(F, F.Local(resultLocal)); }
public override BoundNode VisitBinaryOperator(BoundBinaryOperator node) { BoundExpression left = (BoundExpression)this.Visit(node.Left); BoundExpression right = (BoundExpression)this.Visit(node.Right); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(left, right)) { return node.Update(node.OperatorKind, left, right, node.ConstantValueOpt, node.MethodOpt, node.ResultKind, type); } var subExprs = ReadOnlyArray<BoundExpression>.CreateFrom(left, right); var spillBuilder = new SpillBuilder(); var newArgs = SpillExpressionList(spillBuilder, subExprs); Debug.Assert(newArgs.Count == 2); var newBinaryOperator = node.Update( node.OperatorKind, newArgs[0], newArgs[1], node.ConstantValueOpt, node.MethodOpt, node.ResultKind, type); return spillBuilder.BuildSequenceAndFree(F, newBinaryOperator); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundExpression expression = (BoundExpression)this.Visit(node.Expression); ReadOnlyArray<BoundExpression> indices = (ReadOnlyArray<BoundExpression>)this.VisitList(node.Indices); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence) { return node.Update(expression, indices, type); } var spillBuilder = new SpillBuilder(); var spillResult = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray<RefKind>.Empty); BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type); return spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess); }
public override BoundNode VisitCall(BoundCall node) { BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt); ReadOnlyArray<BoundExpression> arguments = this.VisitList(node.Arguments); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(arguments) && !RequiresSpill(receiverOpt)) { return node.Update( receiverOpt, node.Method, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.ResultKind, type); } var spillBuilder = new SpillBuilder(); var spillResult = SpillExpressionsWithReceiver(receiverOpt, arguments, spillBuilder, node.Method.ParameterRefKinds); var newCall = node.Update( spillResult.Item1, node.Method, spillResult.Item2, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.ResultKind, type); return spillBuilder.BuildSequenceAndFree(F, newCall); }
public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node) { ReadOnlyArray<BoundExpression> arguments = (ReadOnlyArray<BoundExpression>)this.VisitList(node.Arguments); BoundExpression initializerExpressionOpt = (BoundExpression)this.Visit(node.InitializerExpressionOpt); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(arguments) && (initializerExpressionOpt == null || initializerExpressionOpt.Kind != BoundKind.SpillSequence)) { return node.Update(node.Constructor, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, initializerExpressionOpt, type); } var spillBuilder = new SpillBuilder(); ReadOnlyArray<BoundExpression> newArguments = SpillExpressionList(spillBuilder, arguments); BoundExpression newInitializerExpressionOpt; if (initializerExpressionOpt != null && initializerExpressionOpt.Kind == BoundKind.SpillSequence) { var spill = (BoundSpillSequence)initializerExpressionOpt; spillBuilder.AddSpill(spill); newInitializerExpressionOpt = spill.Value; } else { newInitializerExpressionOpt = initializerExpressionOpt; } BoundObjectCreationExpression newObjectCreation = node.Update( node.Constructor, newArguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, newInitializerExpressionOpt, type); return spillBuilder.BuildSequenceAndFree(F, newObjectCreation); }
public override BoundNode VisitArrayCreation(BoundArrayCreation node) { ReadOnlyArray<BoundExpression> bounds = this.VisitList(node.Bounds); BoundArrayInitialization visitedInitializer = (BoundArrayInitialization)this.Visit(node.InitializerOpt); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(bounds) && (visitedInitializer == null || !RequiresSpill(visitedInitializer.Initializers))) { return node.Update(bounds, visitedInitializer, type); } var spillBuilder = new SpillBuilder(); ReadOnlyArray<BoundExpression> newBounds = SpillExpressionList(spillBuilder, bounds); BoundArrayInitialization newInitializerOpt = (visitedInitializer == null) ? visitedInitializer : visitedInitializer.Update(SpillExpressionList(spillBuilder, visitedInitializer.Initializers)); BoundArrayCreation newArrayCreation = node.Update(newBounds, newInitializerOpt, type); return spillBuilder.BuildSequenceAndFree(F, newArrayCreation); }