public LoweredDynamicOperation(SyntheticBoundNodeFactory factory, BoundExpression siteInitialization, BoundExpression siteInvocation, TypeSymbol resultType) { this.Factory = factory; this.resultType = resultType; this.SiteInitialization = siteInitialization; this.SiteInvocation = siteInvocation; }
internal static BoundBlock Rewrite(SourceMethodSymbol sourceMethodSymbol, MethodContractSyntax contract, BoundBlock body, TypeCompilationState compilationState, DiagnosticBag diagsForCurrentMethod) { var binder = compilationState.Compilation.GetBinderFactory(sourceMethodSymbol.SyntaxTree) .GetBinder(body.Syntax); SyntheticBoundNodeFactory factory = new SyntheticBoundNodeFactory(sourceMethodSymbol, sourceMethodSymbol.SyntaxNode, compilationState, diagsForCurrentMethod); var contractType = compilationState.Compilation.GetTypeByReflectionType(typeof(System.Diagnostics.Contracts.Contract), diagsForCurrentMethod); var contractStatements = ArrayBuilder<BoundStatement>.GetInstance(contract.Requires.Count); foreach (var requires in contract.Requires) { var condition = binder.BindExpression(requires.Condition, diagsForCurrentMethod); var methodCall = factory.StaticCall(contractType, "Requires", condition); var statement = factory.ExpressionStatement(methodCall); contractStatements.Add(statement); } foreach (var requires in contract.Ensures) { var condition = binder.BindExpression(requires.Condition, diagsForCurrentMethod); var methodCall = factory.StaticCall(contractType, "Ensures", condition); var statement = factory.ExpressionStatement(methodCall); contractStatements.Add(statement); } return body.Update(body.Locals, body.Statements.InsertRange(0, contractStatements.ToImmutableAndFree())); }
public MethodToStateMachineRewriter( SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, IReadOnlySet<Symbol> variablesCaptured, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies, DiagnosticBag diagnostics, bool useFinalizerBookkeeping) : base(F.CompilationState, diagnostics) { Debug.Assert(F != null); Debug.Assert(originalMethod != null); Debug.Assert(state != null); Debug.Assert(nonReusableLocalProxies != null); Debug.Assert(diagnostics != null); Debug.Assert(variablesCaptured != null); this.F = F; this.stateField = state; this.cachedState = F.SynthesizedLocal(F.SpecialType(SpecialType.System_Int32), kind: SynthesizedLocalKind.StateMachineCachedState); this.useFinalizerBookkeeping = useFinalizerBookkeeping; this.hasFinalizerState = useFinalizerBookkeeping; this.originalMethod = originalMethod; this.variablesCaptured = variablesCaptured; foreach (var proxy in nonReusableLocalProxies) { this.proxies.Add(proxy.Key, proxy.Value); } }
internal AsyncMethodToStateMachineRewriter( MethodSymbol method, int methodOrdinal, AsyncMethodBuilderMemberCollection asyncMethodBuilderMemberCollection, SyntheticBoundNodeFactory F, FieldSymbol state, FieldSymbol builder, IReadOnlySet<Symbol> hoistedVariables, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies, SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals, VariableSlotAllocator slotAllocatorOpt, int nextFreeHoistedLocalSlot, DiagnosticBag diagnostics) : base(F, method, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics, useFinalizerBookkeeping: false) { _method = method; _asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection; _asyncMethodBuilderField = builder; _exprReturnLabel = F.GenerateLabel("exprReturn"); _exitLabel = F.GenerateLabel("exitLabel"); _exprRetValue = method.IsGenericTaskReturningAsync(F.Compilation) ? F.SynthesizedLocal(asyncMethodBuilderMemberCollection.ResultType, syntax: F.Syntax, kind: SynthesizedLocalKind.AsyncMethodReturnValue) : null; _dynamicFactory = new LoweredDynamicOperationFactory(F, methodOrdinal); _awaiterFields = new Dictionary<TypeSymbol, FieldSymbol>(TypeSymbol.EqualsIgnoringDynamicComparer); _nextAwaiterId = slotAllocatorOpt?.PreviousAwaiterSlotCount ?? 0; }
internal SpillFieldAllocator(SyntheticBoundNodeFactory F, TypeCompilationState CompilationState) { allocatedFields = new KeyedStack<TypeSymbol, FieldSymbol>(); realizedSpills = new Dictionary<BoundSpillTemp, FieldSymbol>(); this.F = F; this.CompilationState = CompilationState; }
internal AsyncMethodToClassRewriter( MethodSymbol method, AsyncMethodBuilderMemberCollection asyncMethodBuilderMemberCollection, SyntheticBoundNodeFactory F, FieldSymbol state, FieldSymbol builder, HashSet<Symbol> variablesCaptured, Dictionary<Symbol, CapturedSymbolReplacement> initialProxies, DiagnosticBag diagnostics, bool generateDebugInfo) : base(F, method, state, variablesCaptured, initialProxies, diagnostics, useFinalizerBookkeeping: false, generateDebugInfo: generateDebugInfo) { this.method = method; this.asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection; this.asyncMethodBuilderField = builder; this.exprReturnLabel = F.GenerateLabel("exprReturn"); this.exitLabel = F.GenerateLabel("exitLabel"); this.exprRetValue = method.IsGenericTaskReturningAsync(F.Compilation) ? F.SynthesizedLocal(asyncMethodBuilderMemberCollection.ResultType, GeneratedNames.AsyncExprRetValueFieldName()) : null; this.dynamicFactory = new LoweredDynamicOperationFactory(F); }
public static DynamicAnalysisInjector TryCreate(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, DiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous) { // Do not instrument implicitly-declared methods, except for constructors. // Instrument implicit constructors in order to instrument member initializers. if (method.IsImplicitlyDeclared && !method.IsImplicitConstructor) { return null; } // Do not instrument methods marked with or in scope of ExcludeFromCodeCoverageAttribute. if (IsExcludedFromCodeCoverage(method)) { return null; } MethodSymbol createPayload = GetCreatePayload(methodBodyFactory.Compilation, methodBody.Syntax, diagnostics); // Do not instrument any methods if CreatePayload is not present. if ((object)createPayload == null) { return null; } // Do not instrument CreatePayload if it is part of the current compilation (which occurs only during testing). // CreatePayload will fail at run time with an infinite recursion if it is instrumented. if (method.Equals(createPayload)) { return null; } return new DynamicAnalysisInjector(method, methodBody, methodBodyFactory, createPayload, diagnostics, debugDocumentProvider, previous); }
protected StateMachineRewriter( BoundStatement body, MethodSymbol method, SynthesizedContainer stateMachineType, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, DiagnosticBag diagnostics) { Debug.Assert(body != null); Debug.Assert(method != null); Debug.Assert(stateMachineType != null); Debug.Assert(compilationState != null); Debug.Assert(diagnostics != null); this.body = body; this.method = method; this.stateMachineType = stateMachineType; this.slotAllocatorOpt = slotAllocatorOpt; this.synthesizedLocalOrdinals = new SynthesizedLocalOrdinalsDispenser(); this.diagnostics = diagnostics; this.F = new SyntheticBoundNodeFactory(method, body.Syntax, compilationState, diagnostics); Debug.Assert(F.CurrentType == method.ContainingType); Debug.Assert(F.Syntax == body.Syntax); }
public LoweredDynamicOperation(SyntheticBoundNodeFactory factory, BoundExpression siteInitialization, BoundExpression siteInvocation, TypeSymbol resultType, ImmutableArray<LocalSymbol> temps) { _factory = factory; _resultType = resultType; _temps = temps; this.SiteInitialization = siteInitialization; this.SiteInvocation = siteInvocation; }
private ExpressionLambdaRewriter(TypeCompilationState compilationState, CSharpSyntaxNode node, DiagnosticBag diagnostics) { Bound = new SyntheticBoundNodeFactory((NamedTypeSymbol)null, node, compilationState, diagnostics); Int32Type = Bound.SpecialType(SpecialType.System_Int32); ObjectType = Bound.SpecialType(SpecialType.System_Object); NullableType = Bound.SpecialType(SpecialType.System_Nullable_T); IEnumerableType = Bound.SpecialType(SpecialType.System_Collections_Generic_IEnumerable_T); }
internal void AddSequence(SyntheticBoundNodeFactory F, BoundSequence sequence) { locals.AddRange(sequence.Locals); foreach (var sideEffect in sequence.SideEffects) { statements.Add(F.ExpressionStatement(sideEffect)); } }
public PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node) { this.LocalRewriter = localRewriter; this._factory = localRewriter._factory; foreach (var section in node.SwitchSections) { SwitchSections.Add(section, ArrayBuilder<BoundStatement>.GetInstance()); } }
internal BoundExpression BuildSequenceAndFree(SyntheticBoundNodeFactory F, BoundExpression expression) { var result = (locals.Count > 0 || statements.Count > 0 || temps.Count > 0) ? F.SpillSequence(locals.ToReadOnly(), temps.ToReadOnly(), fields.ToReadOnly(), statements.ToReadOnly(), expression) : expression; Free(); return result; }
private PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node) : base(localRewriter._factory.CurrentMethod, localRewriter._factory.Compilation.Conversions) { this._localRewriter = localRewriter; this._factory = localRewriter._factory; this._factory.Syntax = node.Syntax; foreach (var section in node.SwitchSections) { _switchSections.Add((SyntaxNode)section.Syntax, ArrayBuilder<BoundStatement>.GetInstance()); } }
private int nextFinalizeState = StateMachineStates.FinishedStateMachine - 1; // -3 internal IteratorMethodToStateMachineRewriter( SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, FieldSymbol current, IReadOnlySet<Symbol> variablesCaptured, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> initialProxies, DiagnosticBag diagnostics) : base(F, originalMethod, state, variablesCaptured, initialProxies, diagnostics, useFinalizerBookkeeping: false) { this.current = current; }
private AsyncExceptionHandlerRewriter( MethodSymbol containingMethod, NamedTypeSymbol containingType, SyntheticBoundNodeFactory factory, DiagnosticBag diagnostics, AwaitInFinallyAnalysis analysis) { _F = factory; _F.CurrentMethod = containingMethod; Debug.Assert(factory.CurrentType == (containingType ?? containingMethod.ContainingType)); _diagnostics = diagnostics; _analysis = analysis; }
private int nextFinalizeState = StateMachineStates.FinishedStateMachine - 1; // -3 internal IteratorMethodToClassRewriter( SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, FieldSymbol current, HashSet<Symbol> variablesCaptured, Dictionary<Symbol, CapturedSymbolReplacement> initialProxies, DiagnosticBag diagnostics, bool generateDebugInfo) : base(F, originalMethod, state, variablesCaptured, initialProxies, diagnostics, useFinalizerBookkeeping: false, generateDebugInfo: generateDebugInfo) { this.current = current; }
private int _nextFinalizeState = StateMachineStates.FinishedStateMachine - 1; // -3 internal IteratorMethodToStateMachineRewriter( SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, FieldSymbol current, IReadOnlySet<Symbol> hoistedVariables, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies, SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals, VariableSlotAllocator slotAllocatorOpt, int nextFreeHoistedLocalSlot, DiagnosticBag diagnostics) : base(F, originalMethod, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics, useFinalizerBookkeeping: false) { _current = current; }
protected StateMachineRewriter( BoundStatement body, MethodSymbol method, SynthesizedContainer stateMachineClass, TypeCompilationState compilationState, DiagnosticBag diagnostics) { this.body = body; this.method = method; this.stateMachineClass = stateMachineClass; this.compilationState = compilationState; this.diagnostics = diagnostics; this.F = new SyntheticBoundNodeFactory(method, body.Syntax, compilationState, diagnostics); Debug.Assert(F.CurrentClass == method.ContainingType); Debug.Assert(F.Syntax == body.Syntax); }
private AsyncExceptionHandlerRewriter( MethodSymbol containingMethod, NamedTypeSymbol containingType, SyntheticBoundNodeFactory factory, CSharpCompilation compilation, DiagnosticBag diagnostics, AwaitInFinallyAnalysis analysis) { this.generateDebugInfo = containingMethod.GenerateDebugInfo; this.compilation = compilation; this.F = factory; this.F.CurrentMethod = containingMethod; Debug.Assert(factory.CurrentClass == (containingType ?? containingMethod.ContainingType)); this.diagnostics = diagnostics; this.analysis = analysis; }
private DynamicAnalysisInjector(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, MethodSymbol createPayload, DiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous) : base(previous) { _createPayload = createPayload; _method = method; _methodBody = methodBody; _spansBuilder = ArrayBuilder<SourceSpan>.GetInstance(); TypeSymbol payloadElementType = methodBodyFactory.SpecialType(SpecialType.System_Boolean); _payloadType = ArrayTypeSymbol.CreateCSharpArray(methodBodyFactory.Compilation.Assembly, payloadElementType); _methodPayload = methodBodyFactory.SynthesizedLocal(_payloadType, kind: SynthesizedLocalKind.InstrumentationPayload, syntax: methodBody.Syntax); _diagnostics = diagnostics; _debugDocumentProvider = debugDocumentProvider; _methodHasExplicitBlock = MethodHasExplicitBlock(method); _methodBodyFactory = methodBodyFactory; // The first point indicates entry into the method and has the span of the method definition. _methodEntryInstrumentation = AddAnalysisPoint(MethodDeclarationIfAvailable(methodBody.Syntax), methodBodyFactory); }
public static DynamicAnalysisInjector TryCreate(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, DiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous) { // Do not instrument implicitly-declared methods. if (!method.IsImplicitlyDeclared) { MethodSymbol createPayload = GetCreatePayload(methodBodyFactory.Compilation, methodBody.Syntax, diagnostics); // Do not instrument any methods if CreatePayload is not present. // Do not instrument CreatePayload if it is part of the current compilation (which occurs only during testing). // CreatePayload will fail at run time with an infinite recursion if it Is instrumented. if ((object)createPayload != null && !method.Equals(createPayload)) { return new DynamicAnalysisInjector(method, methodBody, methodBodyFactory, createPayload, diagnostics, debugDocumentProvider, previous); } } return null; }
public StateMachineMethodToClassRewriter( SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, HashSet<Symbol> variablesCaptured, Dictionary<Symbol, CapturedSymbolReplacement> initialProxies, DiagnosticBag diagnostics, bool useFinalizerBookkeeping, bool generateDebugInfo) : base(F.CompilationState, diagnostics, generateDebugInfo) { this.F = F; this.stateField = state; this.cachedState = F.SynthesizedLocal(F.SpecialType(SpecialType.System_Int32), "cachedState"); this.variablesCaptured = variablesCaptured; this.useFinalizerBookkeeping = useFinalizerBookkeeping; this.hasFinalizerState = useFinalizerBookkeeping; this.originalMethod = originalMethod; foreach (var p in initialProxies) this.proxies.Add(p.Key, p.Value); }
internal AsyncMethodToClassRewriter( MethodSymbol method, AsyncMethodBuilderMemberCollection asyncMethodBuilderMemberCollection, SyntheticBoundNodeFactory factory, FieldSymbol state, FieldSymbol builder, Dictionary<Symbol, CapturedSymbol> localProxies, DiagnosticBag diagnostics) : base(factory, state, localProxies, diagnostics) { this.method = method; this.asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection; this.asyncMethodBuilderField = builder; this.exprReturnLabel = factory.GenerateLabel("exprReturn"); this.exprRetValue = method.IsGenericTaskReturningAsync() ? factory.SynthesizedLocal(asyncMethodBuilderMemberCollection.ResultType, GeneratedNames.AsyncExprRetValueFieldName()) : null; this.dynamicFactory = new LoweredDynamicOperationFactory(factory); }
internal AsyncMethodToStateMachineRewriter( MethodSymbol method, AsyncMethodBuilderMemberCollection asyncMethodBuilderMemberCollection, SyntheticBoundNodeFactory F, FieldSymbol state, FieldSymbol builder, IReadOnlySet<Symbol> variablesCaptured, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies, DiagnosticBag diagnostics) : base(F, method, state, variablesCaptured, nonReusableLocalProxies, diagnostics, useFinalizerBookkeeping: false) { this.method = method; this.asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection; this.asyncMethodBuilderField = builder; this.exprReturnLabel = F.GenerateLabel("exprReturn"); this.exitLabel = F.GenerateLabel("exitLabel"); this.exprRetValue = method.IsGenericTaskReturningAsync(F.Compilation) ? F.SynthesizedLocal(asyncMethodBuilderMemberCollection.ResultType, kind: SynthesizedLocalKind.AsyncMethodReturnValue) : null; this.dynamicFactory = new LoweredDynamicOperationFactory(F); }
public PatternLocalRewriter(SyntaxNode node, LocalRewriter localRewriter) { _localRewriter = localRewriter; _factory = localRewriter._factory; _tempAllocator = new DagTempAllocator(_factory, node, IsSwitchStatement); }
private static BoundExpressionStatement GetCreatePayloadStatement( ImmutableArray <SourceSpan> dynamicAnalysisSpans, SyntaxNode methodBodySyntax, LocalSymbol methodPayload, MethodSymbol createPayloadForMethodsSpanningSingleFile, MethodSymbol createPayloadForMethodsSpanningMultipleFiles, BoundExpression mvid, BoundExpression methodToken, BoundExpression payloadSlot, SyntheticBoundNodeFactory methodBodyFactory, DebugDocumentProvider debugDocumentProvider) { MethodSymbol createPayloadOverload; BoundExpression fileIndexOrIndicesArgument; if (dynamicAnalysisSpans.IsEmpty) { createPayloadOverload = createPayloadForMethodsSpanningSingleFile; // For a compiler generated method that has no 'real' spans, we emit the index for // the document corresponding to the syntax node that is associated with its bound node. var document = GetSourceDocument(debugDocumentProvider, methodBodySyntax); fileIndexOrIndicesArgument = methodBodyFactory.SourceDocumentIndex(document); } else { var documents = PooledHashSet <DebugSourceDocument> .GetInstance(); var fileIndices = ArrayBuilder <BoundExpression> .GetInstance(); foreach (var span in dynamicAnalysisSpans) { var document = span.Document; if (documents.Add(document)) { fileIndices.Add(methodBodyFactory.SourceDocumentIndex(document)); } } documents.Free(); // At this point, we should have at least one document since we have already // handled the case where method has no 'real' spans (and therefore no documents) above. if (fileIndices.Count == 1) { createPayloadOverload = createPayloadForMethodsSpanningSingleFile; fileIndexOrIndicesArgument = fileIndices.Single(); } else { createPayloadOverload = createPayloadForMethodsSpanningMultipleFiles; // Order of elements in fileIndices should be deterministic because these // elements were added based on order of spans in dynamicAnalysisSpans above. fileIndexOrIndicesArgument = methodBodyFactory.Array( methodBodyFactory.SpecialType(SpecialType.System_Int32), fileIndices.ToImmutable()); } fileIndices.Free(); } return(methodBodyFactory.Assignment( methodBodyFactory.Local(methodPayload), methodBodyFactory.Call( null, createPayloadOverload, mvid, methodToken, fileIndexOrIndicesArgument, payloadSlot, methodBodyFactory.Literal(dynamicAnalysisSpans.Length)))); }
private static BoundExpression AddConditionSequencePoint(BoundExpression condition, SyntaxNode synthesizedVariableSyntax, SyntheticBoundNodeFactory factory) { if (!factory.Compilation.Options.EnableEditAndContinue) { return(condition); } // The local has to be associated with a syntax that is tracked by EnC source mapping. // At most one ConditionalBranchDiscriminator variable shall be associated with any given EnC tracked syntax node. var local = factory.SynthesizedLocal(condition.Type, synthesizedVariableSyntax, kind: SynthesizedLocalKind.ConditionalBranchDiscriminator); // Add hidden sequence point unless the condition is a constant expression. // Constant expression must stay a const to not invalidate results of control flow analysis. var valueExpression = (condition.ConstantValue == null) ? new BoundSequencePointExpression(syntax: null, expression: factory.Local(local), type: condition.Type) : condition; return(new BoundSequence( condition.Syntax, ImmutableArray.Create(local), ImmutableArray.Create <BoundExpression>(factory.AssignmentExpression(factory.Local(local), condition)), valueExpression, condition.Type)); }
public DagTempAllocator(SyntheticBoundNodeFactory factory, SyntaxNode node) { this._factory = factory; this._node = node; }
internal LoweredDynamicOperationFactory(SyntheticBoundNodeFactory factory, int methodOrdinal) { Debug.Assert(factory != null); _factory = factory; _methodOrdinal = methodOrdinal; }
/// <summary> /// Lower a block of code by performing local rewritings. /// </summary> public static BoundStatement Rewrite( CSharpCompilation compilation, MethodSymbol method, int methodOrdinal, NamedTypeSymbol containingType, BoundStatement statement, TypeCompilationState compilationState, SynthesizedSubmissionFields previousSubmissionFields, bool allowOmissionOfConditionalCalls, bool instrumentForDynamicAnalysis, ref ImmutableArray <SourceSpan> dynamicAnalysisSpans, DebugDocumentProvider debugDocumentProvider, DiagnosticBag diagnostics, out bool sawLambdas, out bool sawLocalFunctions, out bool sawAwaitInExceptionHandler) { Debug.Assert(statement != null); Debug.Assert(compilationState != null); try { var factory = new SyntheticBoundNodeFactory(method, statement.Syntax, compilationState, diagnostics); DynamicAnalysisInjector dynamicInstrumenter = instrumentForDynamicAnalysis ? DynamicAnalysisInjector.TryCreate(method, statement, factory, diagnostics, debugDocumentProvider, Instrumenter.NoOp) : null; // We don’t want IL to differ based upon whether we write the PDB to a file/stream or not. // Presence of sequence points in the tree affects final IL, therefore, we always generate them. var localRewriter = new LocalRewriter(compilation, method, methodOrdinal, statement, containingType, factory, previousSubmissionFields, allowOmissionOfConditionalCalls, diagnostics, dynamicInstrumenter != null ? new DebugInfoInjector(dynamicInstrumenter) : DebugInfoInjector.Singleton); statement.CheckLocalsDefined(); var loweredStatement = (BoundStatement)localRewriter.Visit(statement); loweredStatement.CheckLocalsDefined(); sawLambdas = localRewriter._sawLambdas; sawLocalFunctions = localRewriter._sawLocalFunctions; sawAwaitInExceptionHandler = localRewriter._sawAwaitInExceptionHandler; if (localRewriter._needsSpilling && !loweredStatement.HasErrors) { // Move spill sequences to a top-level statement. This handles "lifting" await and the switch expression. var spilledStatement = SpillSequenceSpiller.Rewrite(loweredStatement, method, compilationState, diagnostics); spilledStatement.CheckLocalsDefined(); loweredStatement = spilledStatement; } if (dynamicInstrumenter != null) { dynamicAnalysisSpans = dynamicInstrumenter.DynamicAnalysisSpans; } #if DEBUG LocalRewritingValidator.Validate(loweredStatement); #endif return(loweredStatement); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); sawLambdas = sawLocalFunctions = sawAwaitInExceptionHandler = false; return(new BoundBadStatement(statement.Syntax, ImmutableArray.Create <BoundNode>(statement), hasErrors: true)); } }
public override BoundExpression InstrumentDoStatementCondition(BoundDoStatement original, BoundExpression rewrittenCondition, SyntheticBoundNodeFactory factory) { return(Previous.InstrumentDoStatementCondition(original, rewrittenCondition, factory)); }
public virtual BoundExpression InstrumentCatchClauseFilter(BoundCatchBlock original, BoundExpression rewrittenFilter, SyntheticBoundNodeFactory factory) { Debug.Assert(!original.WasCompilerGenerated); Debug.Assert(original.Syntax.Kind() == SyntaxKind.CatchClause); Debug.Assert(((CatchClauseSyntax)original.Syntax).Filter != null); Debug.Assert(factory != null); return(rewrittenFilter); }
private BoundStatement InitializeFixedStatementStringLocal( LocalSymbol localSymbol, BoundFixedLocalCollectionInitializer fixedInitializer, SyntheticBoundNodeFactory factory, out LocalSymbol stringTemp, out LocalSymbol localToClear) { TypeSymbol localType = localSymbol.Type; BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression); TypeSymbol initializerType = initializerExpr.Type; // intervening parens may have been skipped by the binder; find the declarator VariableDeclaratorSyntax declarator = fixedInitializer.Syntax.FirstAncestorOrSelf<VariableDeclaratorSyntax>(); Debug.Assert(declarator != null); stringTemp = factory.SynthesizedLocal(initializerType, syntax: declarator, isPinned: true, kind: SynthesizedLocalKind.FixedString); // NOTE: we pin the string, not the pointer. Debug.Assert(stringTemp.IsPinned); Debug.Assert(!localSymbol.IsPinned); BoundStatement stringTempInit = factory.Assignment(factory.Local(stringTemp), initializerExpr); var convertedStringTemp = factory.Convert( localType, factory.Local(stringTemp), fixedInitializer.ElementPointerTypeConversion); BoundStatement localInit = AddLocalDeclarationSequencePointIfNecessary(declarator, localSymbol, factory.Assignment(factory.Local(localSymbol), convertedStringTemp)); BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, factory.Local(stringTemp), BinaryOperatorKind.NotEqual); BoundExpression helperCall; MethodSymbol offsetMethod; if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__get_OffsetToStringData, out offsetMethod)) { helperCall = factory.Call(receiver: null, method: offsetMethod); } else { helperCall = new BoundBadExpression(fixedInitializer.Syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray<BoundNode>.Empty, ErrorTypeSymbol.UnknownResultType); } BoundExpression addition = factory.Binary(BinaryOperatorKind.PointerAndIntAddition, localType, factory.Local(localSymbol), helperCall); BoundStatement conditionalAdd = factory.If(notNullCheck, factory.Assignment(factory.Local(localSymbol), addition)); localToClear = stringTemp; return factory.Block(stringTempInit, localInit, conditionalAdd); }
private static bool TryCreate( SyntheticBoundNodeFactory F, bool customBuilder, NamedTypeSymbol builderType, TypeSymbol resultType, MethodSymbol createBuilderMethod, PropertySymbol taskProperty, WellKnownMember?setException, WellKnownMember setResult, WellKnownMember awaitOnCompleted, WellKnownMember awaitUnsafeOnCompleted, WellKnownMember start, WellKnownMember?setStateMachine, out AsyncMethodBuilderMemberCollection collection ) { MethodSymbol setExceptionMethod; MethodSymbol setResultMethod; MethodSymbol awaitOnCompletedMethod; MethodSymbol awaitUnsafeOnCompletedMethod; MethodSymbol startMethod; MethodSymbol setStateMachineMethod; if ( TryGetBuilderMember( F, setException, builderType, customBuilder, out setExceptionMethod ) && TryGetBuilderMember( F, setResult, builderType, customBuilder, out setResultMethod ) && TryGetBuilderMember( F, awaitOnCompleted, builderType, customBuilder, out awaitOnCompletedMethod ) && TryGetBuilderMember( F, awaitUnsafeOnCompleted, builderType, customBuilder, out awaitUnsafeOnCompletedMethod ) && TryGetBuilderMember(F, start, builderType, customBuilder, out startMethod) && TryGetBuilderMember( F, setStateMachine, builderType, customBuilder, out setStateMachineMethod ) ) { collection = new AsyncMethodBuilderMemberCollection( builderType, resultType, createBuilderMethod, setExceptionMethod, setResultMethod, awaitOnCompletedMethod, awaitUnsafeOnCompletedMethod, startMethod, setStateMachineMethod, taskProperty, checkGenericMethodConstraints: customBuilder ); return(true); } collection = default(AsyncMethodBuilderMemberCollection); return(false); }
private ExpressionLambdaRewriter(TypeCompilationState compilationState, TypeMap typeMap, CSharpSyntaxNode node, DiagnosticBag diagnostics) { _bound = new SyntheticBoundNodeFactory(null, compilationState.Type, node, compilationState, diagnostics); _ignoreAccessibility = compilationState.ModuleBuilderOpt.IgnoreAccessibility; _int32Type = _bound.SpecialType(SpecialType.System_Int32); _objectType = _bound.SpecialType(SpecialType.System_Object); _nullableType = _bound.SpecialType(SpecialType.System_Nullable_T); _IEnumerableType = _bound.SpecialType(SpecialType.System_Collections_Generic_IEnumerable_T); _typeMap = typeMap; }
public virtual BoundExpression InstrumentSwitchStatementExpression(BoundStatement original, BoundExpression rewrittenExpression, SyntheticBoundNodeFactory factory) { Debug.Assert(original.Kind == BoundKind.SwitchStatement); Debug.Assert(!original.WasCompilerGenerated); Debug.Assert(original.Syntax.Kind() == SyntaxKind.SwitchStatement); Debug.Assert(factory != null); return(rewrittenExpression); }
/// <summary> /// fixed(char* ptr = stringVar){ ... } == becomes ===> /// /// pinned string pinnedTemp = stringVar; // pinning managed ref /// char* ptr = (char*)pinnedTemp; // unsafe cast to unmanaged ptr /// if (pinnedTemp != null) ptr += OffsetToStringData(); /// . . . /// </summary> private BoundStatement InitializeFixedStatementStringLocal( BoundLocalDeclaration localDecl, LocalSymbol localSymbol, BoundFixedLocalCollectionInitializer fixedInitializer, SyntheticBoundNodeFactory factory, out LocalSymbol pinnedTemp) { TypeSymbol localType = localSymbol.Type; BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression); TypeSymbol initializerType = initializerExpr.Type; // intervening parens may have been skipped by the binder; find the declarator VariableDeclaratorSyntax declarator = fixedInitializer.Syntax.FirstAncestorOrSelf <VariableDeclaratorSyntax>(); Debug.Assert(declarator != null); pinnedTemp = factory.SynthesizedLocal( initializerType, syntax: declarator, isPinned: true, kind: SynthesizedLocalKind.FixedReference); // NOTE: we pin the string, not the pointer. Debug.Assert(pinnedTemp.IsPinned); Debug.Assert(!localSymbol.IsPinned); BoundStatement stringTempInit = factory.Assignment(factory.Local(pinnedTemp), initializerExpr); // (char*)pinnedTemp; var addr = factory.Convert( fixedInitializer.ElementPointerType, factory.Local(pinnedTemp), Conversion.PinnedObjectToPointer); var convertedStringTemp = factory.Convert( localType, addr, fixedInitializer.ElementPointerTypeConversion); BoundStatement localInit = InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, factory.Assignment(factory.Local(localSymbol), convertedStringTemp)); BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, factory.Local(localSymbol), BinaryOperatorKind.NotEqual); BoundExpression helperCall; MethodSymbol offsetMethod; if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__get_OffsetToStringData, out offsetMethod)) { helperCall = factory.Call(receiver: null, method: offsetMethod); } else { helperCall = new BoundBadExpression(fixedInitializer.Syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray <BoundExpression> .Empty, ErrorTypeSymbol.UnknownResultType); } BoundExpression addition = factory.Binary(BinaryOperatorKind.PointerAndIntAddition, localType, factory.Local(localSymbol), helperCall); BoundStatement conditionalAdd = factory.If(notNullCheck, factory.Assignment(factory.Local(localSymbol), addition)); return(factory.Block(stringTempInit, localInit, conditionalAdd)); }
private LocalRewriter(bool generateDebugInfo, MethodSymbol containingMethod, NamedTypeSymbol containingType, SyntheticBoundNodeFactory factory, SynthesizedSubmissionFields previousSubmissionFields, CSharpCompilation compilation, DiagnosticBag diagnostics) { this.generateDebugInfo = generateDebugInfo && containingMethod.GenerateDebugInfo; this.compilation = compilation; this.factory = factory; this.factory.CurrentMethod = containingMethod; Debug.Assert(factory.CurrentClass == (containingType ?? containingMethod.ContainingType)); this.dynamicFactory = new LoweredDynamicOperationFactory(factory); this.previousSubmissionFields = previousSubmissionFields; this.diagnostics = diagnostics; }
private AwaitExpressionSpiller(MethodSymbol method, CSharpSyntaxNode syntaxNode, TypeCompilationState compilationState, PooledDictionary <LocalSymbol, LocalSymbol> tempSubstitution, DiagnosticBag diagnostics) { _F = new SyntheticBoundNodeFactory(method, syntaxNode, compilationState, diagnostics); _tempSubstitution = tempSubstitution; }
internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection) { if (method.IsVoidReturningAsync()) { return(TryCreate( F: F, builderType: F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder), resultType: F.SpecialType(SpecialType.System_Void), setException: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetException, setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetResult, awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Start_T, setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetStateMachine, task: null, collection: out collection)); } if (method.IsTaskReturningAsync(F.Compilation)) { NamedTypeSymbol builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder); PropertySymbol task; if (!TryGetWellKnownPropertyAsMember(F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Task, builderType, out task)) { collection = default(AsyncMethodBuilderMemberCollection); return(false); } return(TryCreate( F: F, builderType: F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder), resultType: F.SpecialType(SpecialType.System_Void), setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetException, setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetResult, awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Start_T, setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetStateMachine, task: task, collection: out collection)); } if (method.IsGenericTaskReturningAsync(F.Compilation)) { TypeSymbol resultType = method.ReturnType.GetMemberTypeArgumentsNoUseSiteDiagnostics().Single(); if (resultType.IsDynamic()) { resultType = F.SpecialType(SpecialType.System_Object); } if (typeMap != null) { resultType = typeMap.SubstituteType(resultType); } NamedTypeSymbol builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T).Construct(resultType); PropertySymbol task; if (!TryGetWellKnownPropertyAsMember(F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Task, builderType, out task)) { collection = default(AsyncMethodBuilderMemberCollection); return(false); } return(TryCreate( F: F, builderType: builderType, resultType: resultType, setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetException, setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetResult, awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Start_T, setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetStateMachine, task: task, collection: out collection)); } throw ExceptionUtilities.UnexpectedValue(method); }
public override BoundExpression InstrumentSwitchStatementExpression(BoundStatement original, BoundExpression rewrittenExpression, SyntheticBoundNodeFactory factory) { // EnC: We need to insert a hidden sequence point to handle function remapping in case // the containing method is edited while methods invoked in the expression are being executed. return(AddConditionSequencePoint(base.InstrumentSwitchStatementExpression(original, rewrittenExpression, factory), original.Syntax, factory)); }
internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection) { if (method.IsIterator) { var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder); Debug.Assert((object)builderType != null); TryGetBuilderMember <MethodSymbol>( F, WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Create, builderType, customBuilder: false, out MethodSymbol createBuilderMethod); if (createBuilderMethod is null) { collection = default; return(false); } return(TryCreate( F, customBuilder: false, builderType: builderType, resultType: F.SpecialType(SpecialType.System_Void), createBuilderMethod: createBuilderMethod, taskProperty: null, setException: null, // unused setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Complete, // AsyncIteratorMethodBuilder.Complete is the corresponding method to AsyncTaskMethodBuilder.SetResult awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T, setStateMachine: null, // unused collection: out collection)); } if (method.IsVoidReturningAsync()) { var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder); Debug.Assert((object)builderType != null); MethodSymbol createBuilderMethod; bool customBuilder = false; TryGetBuilderMember <MethodSymbol>( F, WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Create, builderType, customBuilder, out createBuilderMethod); if ((object)createBuilderMethod == null) { collection = default(AsyncMethodBuilderMemberCollection); return(false); } return(TryCreate( F, customBuilder: customBuilder, builderType: builderType, resultType: F.SpecialType(SpecialType.System_Void), createBuilderMethod: createBuilderMethod, taskProperty: null, setException: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetException, setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetResult, awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Start_T, setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetStateMachine, collection: out collection)); } if (method.IsTaskReturningAsync(F.Compilation)) { var returnType = (NamedTypeSymbol)method.ReturnType; NamedTypeSymbol builderType; MethodSymbol createBuilderMethod = null; PropertySymbol taskProperty = null; object builderArgument; bool customBuilder = returnType.IsCustomTaskType(out builderArgument); if (customBuilder) { builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false); if ((object)builderType != null) { taskProperty = GetCustomTaskProperty(F, builderType, returnType); createBuilderMethod = GetCustomCreateMethod(F, builderType); } } else { builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder); Debug.Assert((object)builderType != null); TryGetBuilderMember <MethodSymbol>( F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Create, builderType, customBuilder, out createBuilderMethod); TryGetBuilderMember <PropertySymbol>( F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Task, builderType, customBuilder, out taskProperty); } if ((object)builderType == null || (object)createBuilderMethod == null || (object)taskProperty == null) { collection = default(AsyncMethodBuilderMemberCollection); return(false); } return(TryCreate( F, customBuilder: customBuilder, builderType: builderType, resultType: F.SpecialType(SpecialType.System_Void), createBuilderMethod: createBuilderMethod, taskProperty: taskProperty, setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetException, setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetResult, awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Start_T, setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetStateMachine, collection: out collection)); } if (method.IsGenericTaskReturningAsync(F.Compilation)) { var returnType = (NamedTypeSymbol)method.ReturnType; var resultType = returnType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().Type; if (resultType.IsDynamic()) { resultType = F.SpecialType(SpecialType.System_Object); } if (typeMap != null) { resultType = typeMap.SubstituteType(resultType).Type; } returnType = returnType.ConstructedFrom.Construct(resultType); NamedTypeSymbol builderType; MethodSymbol createBuilderMethod = null; PropertySymbol taskProperty = null; object builderArgument; bool customBuilder = returnType.IsCustomTaskType(out builderArgument); if (customBuilder) { builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true); if ((object)builderType != null) { builderType = builderType.ConstructedFrom.Construct(resultType); taskProperty = GetCustomTaskProperty(F, builderType, returnType); createBuilderMethod = GetCustomCreateMethod(F, builderType); } } else { builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T); Debug.Assert((object)builderType != null); builderType = builderType.Construct(resultType); TryGetBuilderMember <MethodSymbol>( F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Create, builderType, customBuilder, out createBuilderMethod); TryGetBuilderMember <PropertySymbol>( F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Task, builderType, customBuilder, out taskProperty); } if ((object)builderType == null || (object)taskProperty == null || (object)createBuilderMethod == null) { collection = default(AsyncMethodBuilderMemberCollection); return(false); } return(TryCreate( F, customBuilder: customBuilder, builderType: builderType, resultType: resultType, createBuilderMethod: createBuilderMethod, taskProperty: taskProperty, setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetException, setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetResult, awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitOnCompleted, awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitUnsafeOnCompleted, start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Start_T, setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetStateMachine, collection: out collection)); } throw ExceptionUtilities.UnexpectedValue(method); }
public override BoundExpression InstrumentCatchClauseFilter(BoundCatchBlock original, BoundExpression rewrittenFilter, SyntheticBoundNodeFactory factory) { rewrittenFilter = base.InstrumentCatchClauseFilter(original, rewrittenFilter, factory); // EnC: We need to insert a hidden sequence point to handle function remapping in case // the containing method is edited while methods invoked in the condition are being executed. CatchFilterClauseSyntax filterClause = ((CatchClauseSyntax)original.Syntax).Filter; return(AddConditionSequencePoint(new BoundSequencePointExpression(filterClause, rewrittenFilter, rewrittenFilter.Type), filterClause, factory)); }
public MethodToStateMachineRewriter( SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, IReadOnlySet <Symbol> hoistedVariables, IReadOnlyDictionary <Symbol, CapturedSymbolReplacement> nonReusableLocalProxies, SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals, VariableSlotAllocator slotAllocatorOpt, int nextFreeHoistedLocalSlot, BindingDiagnosticBag diagnostics, bool useFinalizerBookkeeping ) : base(slotAllocatorOpt, F.CompilationState, diagnostics) { Debug.Assert(F != null); Debug.Assert(originalMethod != null); Debug.Assert(state != null); Debug.Assert(nonReusableLocalProxies != null); Debug.Assert(diagnostics != null); Debug.Assert(hoistedVariables != null); Debug.Assert(nextFreeHoistedLocalSlot >= 0); this.F = F; this.stateField = state; this.cachedState = F.SynthesizedLocal( F.SpecialType(SpecialType.System_Int32), syntax: F.Syntax, kind: SynthesizedLocalKind.StateMachineCachedState ); _useFinalizerBookkeeping = useFinalizerBookkeeping; _hasFinalizerState = useFinalizerBookkeeping; this.OriginalMethod = originalMethod; _hoistedVariables = hoistedVariables; _synthesizedLocalOrdinals = synthesizedLocalOrdinals; _nextFreeHoistedLocalSlot = nextFreeHoistedLocalSlot; foreach (var proxy in nonReusableLocalProxies) { this.proxies.Add(proxy.Key, proxy.Value); } // create cache local for reference type "this" in Release var thisParameter = originalMethod.ThisParameter; CapturedSymbolReplacement thisProxy; if ( (object)thisParameter != null && thisParameter.Type.IsReferenceType && proxies.TryGetValue(thisParameter, out thisProxy) && F.Compilation.Options.OptimizationLevel == OptimizationLevel.Release ) { BoundExpression thisProxyReplacement = thisProxy.Replacement( F.Syntax, frameType => F.This() ); this.cachedThis = F.SynthesizedLocal( thisProxyReplacement.Type, syntax: F.Syntax, kind: SynthesizedLocalKind.FrameCache ); } }
private static BoundExpression AddConditionSequencePoint(BoundExpression condition, BoundStatement containingStatement, SyntheticBoundNodeFactory factory) { return(AddConditionSequencePoint(condition, containingStatement.Syntax, factory)); }
/// <summary> /// <![CDATA[ /// fixed(int* ptr = &v){ ... } == becomes ===> /// /// pinned ref int pinnedTemp = ref v; // pinning managed ref /// int* ptr = (int*)&pinnedTemp; // unsafe cast to unmanaged ptr /// . . . /// ]]> /// </summary> private BoundStatement InitializeFixedStatementGetPinnable( BoundLocalDeclaration localDecl, LocalSymbol localSymbol, BoundFixedLocalCollectionInitializer fixedInitializer, SyntheticBoundNodeFactory factory, out LocalSymbol pinnedTemp) { TypeSymbol localType = localSymbol.Type; BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression); var initializerType = initializerExpr.Type; var initializerSyntax = initializerExpr.Syntax; var getPinnableMethod = fixedInitializer.GetPinnableOpt; // intervening parens may have been skipped by the binder; find the declarator VariableDeclaratorSyntax declarator = fixedInitializer.Syntax.FirstAncestorOrSelf <VariableDeclaratorSyntax>(); Debug.Assert(declarator != null); // pinned ref int pinnedTemp pinnedTemp = factory.SynthesizedLocal( getPinnableMethod.ReturnType, syntax: declarator, isPinned: true, //NOTE: different from the array and string cases // RefReadOnly to allow referring to readonly variables. (technically we only "read" through the temp anyways) refKind: RefKind.RefReadOnly, kind: SynthesizedLocalKind.FixedReference); BoundExpression callReceiver; int currentConditionalAccessID = 0; bool needNullCheck = !initializerType.IsValueType; if (needNullCheck) { currentConditionalAccessID = _currentConditionalAccessID++; callReceiver = new BoundConditionalReceiver( initializerSyntax, currentConditionalAccessID, initializerType); } else { callReceiver = initializerExpr; } // .GetPinnable() var getPinnableCall = getPinnableMethod.IsStatic ? factory.Call(null, getPinnableMethod, callReceiver) : factory.Call(callReceiver, getPinnableMethod); // temp =ref .GetPinnable() var tempAssignment = factory.AssignmentExpression( factory.Local(pinnedTemp), getPinnableCall, isRef: true); // &pinnedTemp var addr = new BoundAddressOfOperator( factory.Syntax, factory.Local(pinnedTemp), type: fixedInitializer.ElementPointerType); // (int*)&pinnedTemp var pointerValue = factory.Convert( localType, addr, fixedInitializer.ElementPointerTypeConversion); // {pinnedTemp =ref .GetPinnable(), (int*)&pinnedTemp} BoundExpression pinAndGetPtr = factory.Sequence( locals: ImmutableArray <LocalSymbol> .Empty, sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment), result: pointerValue); if (needNullCheck) { // initializer?.{temp =ref .GetPinnable(), (int*)&pinnedTemp} ?? default; pinAndGetPtr = new BoundLoweredConditionalAccess( initializerSyntax, initializerExpr, hasValueMethodOpt: null, whenNotNull: pinAndGetPtr, whenNullOpt: null, // just return default(T*) currentConditionalAccessID, localType); } // ptr = initializer?.{temp =ref .GetPinnable(), (int*)&pinnedTemp} ?? default; BoundStatement localInit = InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, factory.Assignment(factory.Local(localSymbol), pinAndGetPtr)); return(localInit); }
public DagTempAllocator(SyntheticBoundNodeFactory factory, SyntaxNode node, bool generateSequencePoints) { _factory = factory; _node = node; _generateSequencePoints = generateSequencePoints; }
public PatternLocalRewriter(SyntaxNode node, LocalRewriter localRewriter) { this._localRewriter = localRewriter; this._factory = localRewriter._factory; this._tempAllocator = new DagTempAllocator(_factory, node); }
public DagTempAllocator(SyntheticBoundNodeFactory factory, SyntaxNode node, bool isSwitchStatement) { _factory = factory; _node = node; _isSwitchStatement = isSwitchStatement; }
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, Text.TextSpan alternateSpan, SyntheticBoundNodeFactory statementFactory) { return(AddAnalysisPoint(syntaxForSpan, syntaxForSpan.SyntaxTree.GetMappedLineSpan(alternateSpan), statementFactory)); }
/// <summary> /// fixed(int* ptr = arr){ ... } == becomes ===> /// /// pinned int[] pinnedTemp = arr; // pinning managed ref /// int* ptr = pinnedTemp != null && pinnedTemp.Length != 0 /// (int*)&pinnedTemp[0]: // unsafe cast to unmanaged ptr /// 0; /// . . . /// </summary> private BoundStatement InitializeFixedStatementArrayLocal( BoundLocalDeclaration localDecl, LocalSymbol localSymbol, BoundFixedLocalCollectionInitializer fixedInitializer, SyntheticBoundNodeFactory factory, out LocalSymbol pinnedTemp) { TypeSymbol localType = localSymbol.Type; BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression); TypeSymbol initializerType = initializerExpr.Type; pinnedTemp = factory.SynthesizedLocal(initializerType, isPinned: true); ArrayTypeSymbol arrayType = (ArrayTypeSymbol)pinnedTemp.Type; TypeSymbol arrayElementType = arrayType.ElementType; // NOTE: we pin the array, not the pointer. Debug.Assert(pinnedTemp.IsPinned); Debug.Assert(!localSymbol.IsPinned); //(pinnedTemp = array) BoundExpression arrayTempInit = factory.AssignmentExpression(factory.Local(pinnedTemp), initializerExpr); //(pinnedTemp = array) != null BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, arrayTempInit, BinaryOperatorKind.NotEqual); BoundExpression lengthCall; if (arrayType.IsSZArray) { lengthCall = factory.ArrayLength(factory.Local(pinnedTemp)); } else { MethodSymbol lengthMethod; if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Array__get_Length, out lengthMethod)) { lengthCall = factory.Call(factory.Local(pinnedTemp), lengthMethod); } else { lengthCall = new BoundBadExpression(fixedInitializer.Syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundExpression>(factory.Local(pinnedTemp)), ErrorTypeSymbol.UnknownResultType); } } // NOTE: dev10 comment says ">", but code actually checks "!=" //temp.Length != 0 BoundExpression lengthCheck = factory.Binary(BinaryOperatorKind.IntNotEqual, factory.SpecialType(SpecialType.System_Boolean), lengthCall, factory.Literal(0)); //((temp = array) != null && temp.Length != 0) BoundExpression condition = factory.Binary(BinaryOperatorKind.LogicalBoolAnd, factory.SpecialType(SpecialType.System_Boolean), notNullCheck, lengthCheck); //temp[0] BoundExpression firstElement = factory.ArrayAccessFirstElement(factory.Local(pinnedTemp)); // NOTE: this is a fixed statement address-of in that it's the initial value of the pointer. //&temp[0] BoundExpression firstElementAddress = new BoundAddressOfOperator(factory.Syntax, firstElement, type: new PointerTypeSymbol(arrayElementType)); BoundExpression convertedFirstElementAddress = factory.Convert( localType, firstElementAddress, fixedInitializer.ElementPointerTypeConversion); //loc = &temp[0] BoundExpression consequenceAssignment = factory.AssignmentExpression(factory.Local(localSymbol), convertedFirstElementAddress); //loc = null BoundExpression alternativeAssignment = factory.AssignmentExpression(factory.Local(localSymbol), factory.Null(localType)); //(((temp = array) != null && temp.Length != 0) ? loc = &temp[0] : loc = null) BoundStatement localInit = factory.ExpressionStatement( new BoundConditionalOperator(factory.Syntax, false, condition, consequenceAssignment, alternativeAssignment, ConstantValue.NotAvailable, localType)); return(InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, localInit)); }
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, SyntheticBoundNodeFactory statementFactory) { return(AddAnalysisPoint(syntaxForSpan, syntaxForSpan.GetLocation().GetMappedLineSpan(), statementFactory)); }
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, FileLinePositionSpan span, SyntheticBoundNodeFactory statementFactory) { // Add an entry in the spans array. int spansIndex = _spansBuilder.Count; _spansBuilder.Add(new SourceSpan( GetSourceDocument(_debugDocumentProvider, syntaxForSpan, span), span.StartLinePosition.Line, span.StartLinePosition.Character, span.EndLinePosition.Line, span.EndLinePosition.Character)); // Generate "_payload[pointIndex] = true". BoundArrayAccess payloadCell = statementFactory.ArrayAccess( statementFactory.Local(_methodPayload), statementFactory.Literal(spansIndex)); return(statementFactory.Assignment(payloadCell, statementFactory.Literal(true))); }
public AwaitLiftingRewriter(MethodSymbol method, CSharpSyntaxNode syntaxNode, TypeCompilationState compilationState, DiagnosticBag diagnostics) { this.F = new SyntheticBoundNodeFactory(method, syntaxNode, compilationState, diagnostics); }
public override BoundExpression InstrumentCatchClauseFilter(BoundCatchBlock original, BoundExpression rewrittenFilter, SyntheticBoundNodeFactory factory) { return(Previous.InstrumentCatchClauseFilter(original, rewrittenFilter, factory)); }
private BoundStatement InitializeFixedStatementLocal( BoundLocalDeclaration localDecl, SyntheticBoundNodeFactory factory, out LocalSymbol temp, out LocalSymbol localToClear) { BoundExpression initializer = localDecl.InitializerOpt; Debug.Assert(!ReferenceEquals(initializer, null)); LocalSymbol localSymbol = localDecl.LocalSymbol; if (initializer.Kind == BoundKind.FixedLocalCollectionInitializer) { var fixedInitializer = (BoundFixedLocalCollectionInitializer)initializer; if (fixedInitializer.Expression.Type.SpecialType == SpecialType.System_String) { return InitializeFixedStatementStringLocal(localSymbol, fixedInitializer, factory, out temp, out localToClear); } else { Debug.Assert(fixedInitializer.Expression.Type.IsArray()); localToClear = localSymbol; return InitializeFixedStatementArrayLocal(localSymbol, fixedInitializer, factory, out temp); } } else { temp = null; localToClear = localSymbol; return RewriteLocalDeclaration(localDecl.Syntax, localSymbol, VisitExpression(initializer)); } }
public override BoundExpression InstrumentSwitchExpressionArmExpression(BoundExpression original, BoundExpression rewrittenExpression, SyntheticBoundNodeFactory factory) { return(Previous.InstrumentSwitchExpressionArmExpression(original, rewrittenExpression, factory)); }
private BoundStatement InitializeFixedStatementArrayLocal( LocalSymbol localSymbol, BoundFixedLocalCollectionInitializer fixedInitializer, SyntheticBoundNodeFactory factory, out LocalSymbol arrayTemp) { // From ExpressionBinder::BindPtrToArray: // (((temp = array) != null && temp.Length > 0) ? loc = &temp[0] : loc = null) // NOTE: The assignment needs to be inside the EK_QUESTIONMARK. See Whidbey bug #397859. // We can't do loc = (... ? ... : ...) since the CLR type of &temp[0] is a managed // pointer and null is a UIntPtr - which confuses the JIT. We can't just convert // &temp[0] to UIntPtr with a conv.u instruction because then if a GC occurs between // the time of the cast and the assignment to the local, we're toast. TypeSymbol localType = localSymbol.Type; BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression); TypeSymbol initializerType = initializerExpr.Type; arrayTemp = factory.SynthesizedLocal(initializerType); ArrayTypeSymbol arrayType = (ArrayTypeSymbol)arrayTemp.Type; TypeSymbol arrayElementType = arrayType.ElementType; int arrayRank = arrayType.Rank; // NOTE: we pin the pointer, not the array. Debug.Assert(!arrayTemp.IsPinned); Debug.Assert(localSymbol.IsPinned); //(temp = array) BoundExpression arrayTempInit = factory.AssignmentExpression(factory.Local(arrayTemp), initializerExpr); //(temp = array) != null BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, arrayTempInit, BinaryOperatorKind.NotEqual); BoundExpression lengthCall; if (arrayRank == 1) { lengthCall = factory.ArrayLength(factory.Local(arrayTemp)); } else { MethodSymbol lengthMethod; if (TryGetWellKnownTypeMember(fixedInitializer.Syntax, WellKnownMember.System_Array__get_Length, out lengthMethod)) { lengthCall = factory.Call(factory.Local(arrayTemp), lengthMethod); } else { lengthCall = new BoundBadExpression(fixedInitializer.Syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(factory.Local(arrayTemp)), ErrorTypeSymbol.UnknownResultType); } } // NOTE: dev10 comment says ">", but code actually checks "!=" //temp.Length != 0 BoundExpression lengthCheck = factory.Binary(BinaryOperatorKind.IntNotEqual, factory.SpecialType(SpecialType.System_Boolean), lengthCall, factory.Literal(0)); //((temp = array) != null && temp.Length != 0) BoundExpression condition = factory.Binary(BinaryOperatorKind.LogicalBoolAnd, factory.SpecialType(SpecialType.System_Boolean), notNullCheck, lengthCheck); //temp[0] BoundExpression firstElement = factory.ArrayAccessFirstElement(factory.Local(arrayTemp)); // NOTE: this is a fixed statement address-of in that it's the initial value of pinned local. //&temp[0] BoundExpression firstElementAddress = new BoundAddressOfOperator(factory.Syntax, firstElement, isFixedStatementAddressOf: true, type: new PointerTypeSymbol(arrayElementType)); BoundExpression convertedFirstElementAddress = factory.Convert( localType, firstElementAddress, fixedInitializer.ElementPointerTypeConversion); //loc = &temp[0] BoundExpression consequenceAssignment = factory.AssignmentExpression(factory.Local(localSymbol), convertedFirstElementAddress); //loc = null BoundExpression alternativeAssignment = factory.AssignmentExpression(factory.Local(localSymbol), factory.Null(localType)); //(((temp = array) != null && temp.Length != 0) ? loc = &temp[0] : loc = null) BoundStatement localInit = factory.ExpressionStatement( new BoundConditionalOperator(factory.Syntax, condition, consequenceAssignment, alternativeAssignment, ConstantValue.NotAvailable, localType)); return AddLocalDeclarationSequencePointIfNecessary(fixedInitializer.Syntax.Parent.Parent, localSymbol, localInit); }
private static BoundStatement ConstructThrowInvalidOperationExceptionHelperCall(SyntheticBoundNodeFactory factory) { Debug.Assert(factory.ModuleBuilderOpt is not null); var module = factory.ModuleBuilderOpt !; var diagnosticSyntax = factory.CurrentFunction.GetNonNullSyntaxNode(); var diagnostics = factory.Diagnostics.DiagnosticBag; Debug.Assert(diagnostics is not null); var throwMethod = module.EnsureThrowInvalidOperationExceptionExists(diagnosticSyntax, factory, diagnostics); var call = factory.Call( receiver: null, throwMethod); return(factory.HiddenSequencePoint(factory.ExpressionStatement(call))); }