internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax) { var method = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.GetObjectAtAddressMethodName, (c, n, s) => { var parameterType = compilation.GetSpecialType(SpecialType.System_UInt64); return new PlaceholderMethodSymbol( c, s, n, this.Type, m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None))); }); var argument = new BoundLiteral( syntax, Microsoft.CodeAnalysis.ConstantValue.Create(_address), method.Parameters[0].Type); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create<BoundExpression>(argument)); Debug.Assert(call.Type == this.Type); return call; }
internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, BoundNode node) { var builder = ArrayBuilder<BoundStatement>.GetInstance(); bool hasChanged; // Rewrite top-level declarations only. switch (node.Kind) { case BoundKind.LocalDeclaration: RewriteLocalDeclaration(compilation, container, declaredLocals, builder, (BoundLocalDeclaration)node); hasChanged = true; break; case BoundKind.MultipleLocalDeclarations: foreach (var declaration in ((BoundMultipleLocalDeclarations)node).LocalDeclarations) { RewriteLocalDeclaration(compilation, container, declaredLocals, builder, declaration); } hasChanged = true; break; default: hasChanged = false; break; } if (hasChanged) { node = new BoundBlock(node.Syntax, ImmutableArray<LocalSymbol>.Empty, builder.ToImmutable()) { WasCompilerGenerated = true }; } builder.Free(); return node; }
internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet <LocalSymbol> declaredLocals, BoundNode node) { var builder = ArrayBuilder <BoundStatement> .GetInstance(); bool hasChanged; // Rewrite top-level declarations only. switch (node.Kind) { case BoundKind.LocalDeclaration: RewriteLocalDeclaration(compilation, container, declaredLocals, builder, (BoundLocalDeclaration)node); hasChanged = true; break; case BoundKind.MultipleLocalDeclarations: foreach (var declaration in ((BoundMultipleLocalDeclarations)node).LocalDeclarations) { RewriteLocalDeclaration(compilation, container, declaredLocals, builder, declaration); } hasChanged = true; break; default: hasChanged = false; break; } if (hasChanged) { node = BoundBlock.SynthesizedNoLocals(node.Syntax, builder.ToImmutable()); } builder.Free(); return(node); }
internal override BoundExpression RewriteLocal( CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, DiagnosticBag diagnostics ) { var method = GetIntrinsicMethod( compilation, ExpressionCompilerConstants.GetReturnValueMethodName ); var argument = new BoundLiteral( syntax, Microsoft.CodeAnalysis.ConstantValue.Create(_index), method.Parameters[0].Type ); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create <BoundExpression>(argument) ); return(ConvertToLocalType(compilation, call, this.Type, diagnostics)); }
private static BoundExpression RewriteLocalInternal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, LocalSymbol local) { var parameterType = compilation.GetSpecialType(SpecialType.System_String); var getValueMethod = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.GetVariableValueMethodName, (c, n, s) => { var returnType = compilation.GetSpecialType(SpecialType.System_Object); return new PlaceholderMethodSymbol( c, s, n, returnType, m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None))); }); var getAddressMethod = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.GetVariableAddressMethodName, (c, n, s) => { return new PlaceholderMethodSymbol( c, s, n, m => ImmutableArray.Create<TypeParameterSymbol>(new SimpleTypeParameterSymbol(m, 0, "<>T")), m => m.TypeParameters[0], // return type is <>T& m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)), returnValueIsByRef: true); }); return new BoundPseudoVariable( syntax, local, new ObjectIdExpressions(compilation, getValueMethod, getAddressMethod), local.Type); }
private PlaceholderLocalRewriter(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, DiagnosticBag diagnostics) { _compilation = compilation; _container = container; _declaredLocals = declaredLocals; _diagnostics = diagnostics; }
internal override BoundExpression RewriteLocal( CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, DiagnosticBag diagnostics ) { var method = GetIntrinsicMethod( compilation, ExpressionCompilerConstants.GetObjectAtAddressMethodName ); var argument = new BoundLiteral( syntax, Microsoft.CodeAnalysis.ConstantValue.Create(_address), method.Parameters[0].Type ); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create <BoundExpression>(argument) ); Debug.Assert( TypeSymbol.Equals(call.Type, this.Type, TypeCompareKind.ConsiderEverything2) ); return(call); }
private PlaceholderLocalRewriter(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet <LocalSymbol> declaredLocals, DiagnosticBag diagnostics) { _compilation = compilation; _container = container; _declaredLocals = declaredLocals; _diagnostics = diagnostics; }
private static BoundExpression RewriteLocalInternal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, LocalSymbol local) { return new BoundPseudoVariable( syntax, local, new ObjectIdExpressions(compilation), local.Type); }
internal override BoundExpression RewriteLocal( CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, DiagnosticBag diagnostics ) { return(RewriteLocalInternal(compilation, container, syntax, this)); }
internal static BoundExpression RewriteLocal( CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, LocalSymbol local ) { return(RewriteLocalInternal(compilation, container, syntax, local)); }
private static void RewriteLocalDeclaration( CSharpCompilation compilation, EENamedTypeSymbol container, HashSet <LocalSymbol> declaredLocals, ArrayBuilder <BoundStatement> statements, BoundLocalDeclaration node) { Debug.Assert(node.ArgumentsOpt.IsDefault); var local = node.LocalSymbol; var syntax = node.Syntax; declaredLocals.Add(local); var voidType = compilation.GetSpecialType(SpecialType.System_Void); var objectType = compilation.GetSpecialType(SpecialType.System_Object); var typeType = compilation.GetWellKnownType(WellKnownType.System_Type); var stringType = compilation.GetSpecialType(SpecialType.System_String); // <>CreateVariable(Type type, string name) var method = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.CreateVariableMethodName, (c, n, s) => new PlaceholderMethodSymbol( c, s, n, voidType, m => ImmutableArray.Create <ParameterSymbol>( new SynthesizedParameterSymbol(m, typeType, ordinal: 0, refKind: RefKind.None), new SynthesizedParameterSymbol(m, stringType, ordinal: 1, refKind: RefKind.None)))); var type = new BoundTypeOfOperator(syntax, new BoundTypeExpression(syntax, aliasOpt: null, type: local.Type), null, typeType); var name = new BoundLiteral(syntax, ConstantValue.Create(local.Name), stringType); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create <BoundExpression>(type, name)); statements.Add(new BoundExpressionStatement(syntax, call)); var initializer = node.InitializerOpt; if (initializer != null) { // Generate assignment to local. The assignment will // be rewritten in PlaceholderLocalRewriter. var assignment = new BoundAssignmentOperator( syntax, new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type), initializer, RefKind.None, local.Type); statements.Add(new BoundExpressionStatement(syntax, assignment)); } }
private static void RewriteLocalDeclaration( CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, ArrayBuilder<BoundStatement> statements, BoundLocalDeclaration node) { Debug.Assert(node.ArgumentsOpt.IsDefault); var local = node.LocalSymbol; var syntax = node.Syntax; declaredLocals.Add(local); var voidType = compilation.GetSpecialType(SpecialType.System_Void); var objectType = compilation.GetSpecialType(SpecialType.System_Object); var typeType = compilation.GetWellKnownType(WellKnownType.System_Type); var stringType = compilation.GetSpecialType(SpecialType.System_String); // <>CreateVariable(Type type, string name) var method = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.CreateVariableMethodName, (c, n, s) => new PlaceholderMethodSymbol( c, s, n, voidType, m => ImmutableArray.Create<ParameterSymbol>( new SynthesizedParameterSymbol(m, typeType, ordinal: 0, refKind: RefKind.None), new SynthesizedParameterSymbol(m, stringType, ordinal: 1, refKind: RefKind.None)))); var type = new BoundTypeOfOperator(syntax, new BoundTypeExpression(syntax, aliasOpt: null, type: local.Type), null, typeType); var name = new BoundLiteral(syntax, ConstantValue.Create(local.Name), stringType); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create<BoundExpression>(type, name)); statements.Add(new BoundExpressionStatement(syntax, call)); var initializer = node.InitializerOpt; if (initializer != null) { // Generate assignment to local. The assignment will // be rewritten in PlaceholderLocalRewriter. var assignment = new BoundAssignmentOperator( syntax, new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type), initializer, RefKind.None, local.Type); statements.Add(new BoundExpressionStatement(syntax, assignment)); } }
internal override BoundExpression RewriteLocal( CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, DiagnosticBag diagnostics ) { var method = GetIntrinsicMethod(compilation, _getExceptionMethodName); var call = BoundCall.Synthesized(syntax, receiverOpt: null, method: method); return(ConvertToLocalType(compilation, call, this.Type, diagnostics)); }
private static BoundExpression RewriteLocalInternal( CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, LocalSymbol local ) { return(new BoundPseudoVariable( syntax, local, new ObjectIdExpressions(compilation), local.Type )); }
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { var method = GetIntrinsicMethod(compilation, ExpressionCompilerConstants.GetReturnValueMethodName); var argument = new BoundLiteral( syntax, Microsoft.CodeAnalysis.ConstantValue.Create(_index), method.Parameters[0].Type); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create<BoundExpression>(argument)); return ConvertToLocalType(compilation, call, this.Type, diagnostics); }
private static void RewriteLocalDeclaration( CSharpCompilation compilation, EENamedTypeSymbol container, HashSet <LocalSymbol> declaredLocals, ArrayBuilder <BoundStatement> statements, BoundLocalDeclaration node) { Debug.Assert(node.ArgumentsOpt.IsDefault); var local = node.LocalSymbol; var syntax = node.Syntax; declaredLocals.Add(local); var typeType = compilation.GetWellKnownType(WellKnownType.System_Type); var stringType = compilation.GetSpecialType(SpecialType.System_String); var guidConstructor = (MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Guid__ctor); // CreateVariable(Type type, string name) var method = PlaceholderLocalSymbol.GetIntrinsicMethod(compilation, ExpressionCompilerConstants.CreateVariableMethodName); var type = new BoundTypeOfOperator(syntax, new BoundTypeExpression(syntax, aliasOpt: null, type: local.Type), null, typeType); var name = new BoundLiteral(syntax, ConstantValue.Create(local.Name), stringType); bool hasCustomTypeInfoPayload; var customTypeInfoPayload = GetCustomTypeInfoPayload(local, syntax, compilation, out hasCustomTypeInfoPayload); var customTypeInfoPayloadId = GetCustomTypeInfoPayloadId(syntax, guidConstructor, hasCustomTypeInfoPayload); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create(type, name, customTypeInfoPayloadId, customTypeInfoPayload)); statements.Add(new BoundExpressionStatement(syntax, call)); var initializer = node.InitializerOpt; if (initializer != null) { // Generate assignment to local. The assignment will // be rewritten in PlaceholderLocalRewriter. var assignment = new BoundAssignmentOperator( syntax, new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type), initializer, RefKind.None, local.Type); statements.Add(new BoundExpressionStatement(syntax, assignment)); } }
internal static BoundStatement Rewrite( CSharpCompilation compilation, EENamedTypeSymbol container, HashSet <LocalSymbol> declaredLocals, BoundStatement node, ImmutableArray <LocalSymbol> declaredLocalsArray, DiagnosticBag diagnostics ) { var builder = ArrayBuilder <BoundStatement> .GetInstance(); foreach (var local in declaredLocalsArray) { CreateLocal(compilation, declaredLocals, builder, local, node.Syntax, diagnostics); } // Rewrite top-level declarations only. switch (node.Kind) { case BoundKind.LocalDeclaration: Debug.Assert( declaredLocals.Contains(((BoundLocalDeclaration)node).LocalSymbol) ); RewriteLocalDeclaration(builder, (BoundLocalDeclaration)node); break; case BoundKind.MultipleLocalDeclarations: foreach ( var declaration in ((BoundMultipleLocalDeclarations)node).LocalDeclarations ) { Debug.Assert(declaredLocals.Contains(declaration.LocalSymbol)); RewriteLocalDeclaration(builder, declaration); } break; default: if (builder.Count == 0) { builder.Free(); return(node); } builder.Add(node); break; } return(BoundBlock.SynthesizedNoLocals(node.Syntax, builder.ToImmutableAndFree())); }
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, DiagnosticBag diagnostics) { var method = GetIntrinsicMethod(compilation, ExpressionCompilerConstants.GetObjectAtAddressMethodName); var argument = new BoundLiteral( syntax, Microsoft.CodeAnalysis.ConstantValue.Create(_address), method.Parameters[0].Type); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create<BoundExpression>(argument)); Debug.Assert(call.Type == this.Type); return call; }
private static void RewriteLocalDeclaration( CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, ArrayBuilder<BoundStatement> statements, BoundLocalDeclaration node) { Debug.Assert(node.ArgumentsOpt.IsDefault); var local = node.LocalSymbol; var syntax = node.Syntax; declaredLocals.Add(local); var typeType = compilation.GetWellKnownType(WellKnownType.System_Type); var stringType = compilation.GetSpecialType(SpecialType.System_String); var guidConstructor = (MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Guid__ctor); // CreateVariable(Type type, string name) var method = PlaceholderLocalSymbol.GetIntrinsicMethod(compilation, ExpressionCompilerConstants.CreateVariableMethodName); var type = new BoundTypeOfOperator(syntax, new BoundTypeExpression(syntax, aliasOpt: null, type: local.Type), null, typeType); var name = new BoundLiteral(syntax, ConstantValue.Create(local.Name), stringType); bool hasCustomTypeInfoPayload; var customTypeInfoPayload = GetCustomTypeInfoPayload(local, syntax, compilation, out hasCustomTypeInfoPayload); var customTypeInfoPayloadId = GetCustomTypeInfoPayloadId(syntax, guidConstructor, hasCustomTypeInfoPayload); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create(type, name, customTypeInfoPayloadId, customTypeInfoPayload)); statements.Add(new BoundExpressionStatement(syntax, call)); var initializer = node.InitializerOpt; if (initializer != null) { // Generate assignment to local. The assignment will // be rewritten in PlaceholderLocalRewriter. var assignment = new BoundAssignmentOperator( syntax, new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type), initializer, RefKind.None, local.Type); statements.Add(new BoundExpressionStatement(syntax, assignment)); } }
internal static BoundNode Rewrite( CSharpCompilation compilation, EENamedTypeSymbol container, HashSet <LocalSymbol> declaredLocals, BoundNode node, DiagnosticBag diagnostics ) { var rewriter = new PlaceholderLocalRewriter( compilation, container, declaredLocals, diagnostics ); return(rewriter.Visit(node)); }
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax) { Debug.Assert(this.Name == this.Name.ToLowerInvariant()); var method = container.GetOrAddSynthesizedMethod( this.Name, (c, n, s) => { var returnType = compilation.GetWellKnownType(WellKnownType.System_Exception); return new PlaceholderMethodSymbol( c, s, n, returnType, m => ImmutableArray<ParameterSymbol>.Empty); }); var call = BoundCall.Synthesized(syntax, receiverOpt: null, method: method); return ConvertToLocalType(compilation, call, this.Type); }
internal static BoundStatement Rewrite(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, BoundStatement node, ImmutableArray<LocalSymbol> declaredLocalsArray) { var builder = ArrayBuilder<BoundStatement>.GetInstance(); foreach (var local in declaredLocalsArray) { CreateLocal(compilation, declaredLocals, builder, local, node.Syntax); } // Rewrite top-level declarations only. switch (node.Kind) { case BoundKind.LocalDeclaration: Debug.Assert(declaredLocals.Contains(((BoundLocalDeclaration)node).LocalSymbol)); RewriteLocalDeclaration(builder, (BoundLocalDeclaration)node); break; case BoundKind.MultipleLocalDeclarations: foreach (var declaration in ((BoundMultipleLocalDeclarations)node).LocalDeclarations) { Debug.Assert(declaredLocals.Contains(declaration.LocalSymbol)); RewriteLocalDeclaration(builder, declaration); } break; default: if (builder.Count == 0) { builder.Free(); return node; } builder.Add(node); break; } return BoundBlock.SynthesizedNoLocals(node.Syntax, builder.ToImmutableAndFree()); }
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, DiagnosticBag diagnostics) { return RewriteLocalInternal(compilation, container, syntax, this); }
internal EEMethodSymbol( EENamedTypeSymbol container, string name, Location location, MethodSymbol sourceMethod, ImmutableArray<LocalSymbol> sourceLocals, ImmutableArray<LocalSymbol> sourceLocalsForBinding, ImmutableDictionary<string, DisplayClassVariable> sourceDisplayClassVariables, GenerateMethodBody generateMethodBody) { Debug.Assert(sourceMethod.IsDefinition); Debug.Assert(sourceMethod.ContainingSymbol == container.SubstitutedSourceType.OriginalDefinition); Debug.Assert(sourceLocals.All(l => l.ContainingSymbol == sourceMethod)); _container = container; _name = name; _locations = ImmutableArray.Create(location); // What we want is to map all original type parameters to the corresponding new type parameters // (since the old ones have the wrong owners). Unfortunately, we have a circular dependency: // 1) Each new type parameter requires the entire map in order to be able to construct its constraint list. // 2) The map cannot be constructed until all new type parameters exist. // Our solution is to pass each new type parameter a lazy reference to the type map. We then // initialize the map as soon as the new type parameters are available - and before they are // handed out - so that there is never a period where they can require the type map and find // it uninitialized. var sourceMethodTypeParameters = sourceMethod.TypeParameters; var allSourceTypeParameters = container.SourceTypeParameters.Concat(sourceMethodTypeParameters); var getTypeMap = new Func<TypeMap>(() => this.TypeMap); _typeParameters = sourceMethodTypeParameters.SelectAsArray( (tp, i, arg) => (TypeParameterSymbol)new EETypeParameterSymbol(this, tp, i, getTypeMap), (object)null); _allTypeParameters = container.TypeParameters.Concat(_typeParameters); this.TypeMap = new TypeMap(allSourceTypeParameters, _allTypeParameters); EENamedTypeSymbol.VerifyTypeParameters(this, _typeParameters); var substitutedSourceType = container.SubstitutedSourceType; this.SubstitutedSourceMethod = sourceMethod.AsMember(substitutedSourceType); if (sourceMethod.Arity > 0) { this.SubstitutedSourceMethod = this.SubstitutedSourceMethod.Construct(_typeParameters.As<TypeSymbol>()); } TypeParameterChecker.Check(this.SubstitutedSourceMethod, _allTypeParameters); // Create a map from original parameter to target parameter. var parameterBuilder = ArrayBuilder<ParameterSymbol>.GetInstance(); var substitutedSourceThisParameter = this.SubstitutedSourceMethod.ThisParameter; var substitutedSourceHasThisParameter = (object)substitutedSourceThisParameter != null; if (substitutedSourceHasThisParameter) { _thisParameter = MakeParameterSymbol(0, GeneratedNames.ThisProxyFieldName(), substitutedSourceThisParameter); Debug.Assert(_thisParameter.Type == this.SubstitutedSourceMethod.ContainingType); parameterBuilder.Add(_thisParameter); } var ordinalOffset = (substitutedSourceHasThisParameter ? 1 : 0); foreach (var substitutedSourceParameter in this.SubstitutedSourceMethod.Parameters) { var ordinal = substitutedSourceParameter.Ordinal + ordinalOffset; Debug.Assert(ordinal == parameterBuilder.Count); var parameter = MakeParameterSymbol(ordinal, substitutedSourceParameter.Name, substitutedSourceParameter); parameterBuilder.Add(parameter); } _parameters = parameterBuilder.ToImmutableAndFree(); var localsBuilder = ArrayBuilder<LocalSymbol>.GetInstance(); var localsMap = PooledDictionary<LocalSymbol, LocalSymbol>.GetInstance(); foreach (var sourceLocal in sourceLocals) { var local = sourceLocal.ToOtherMethod(this, this.TypeMap); localsMap.Add(sourceLocal, local); localsBuilder.Add(local); } this.Locals = localsBuilder.ToImmutableAndFree(); localsBuilder = ArrayBuilder<LocalSymbol>.GetInstance(); foreach (var sourceLocal in sourceLocalsForBinding) { LocalSymbol local; if (!localsMap.TryGetValue(sourceLocal, out local)) { local = sourceLocal.ToOtherMethod(this, this.TypeMap); localsMap.Add(sourceLocal, local); } localsBuilder.Add(local); } this.LocalsForBinding = localsBuilder.ToImmutableAndFree(); // Create a map from variable name to display class field. var displayClassVariables = PooledDictionary<string, DisplayClassVariable>.GetInstance(); foreach (var pair in sourceDisplayClassVariables) { var variable = pair.Value; var displayClassInstanceFromLocal = variable.DisplayClassInstance as DisplayClassInstanceFromLocal; var displayClassInstance = (displayClassInstanceFromLocal == null) ? (DisplayClassInstance)new DisplayClassInstanceFromThis(_parameters[0]) : new DisplayClassInstanceFromLocal((EELocalSymbol)localsMap[displayClassInstanceFromLocal.Local]); variable = variable.SubstituteFields(displayClassInstance, this.TypeMap); displayClassVariables.Add(pair.Key, variable); } _displayClassVariables = displayClassVariables.ToImmutableDictionary(); displayClassVariables.Free(); localsMap.Free(); _generateMethodBody = generateMethodBody; }
private static BoundExpression RewriteLocalInternal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, LocalSymbol local) { var parameterType = compilation.GetSpecialType(SpecialType.System_String); var getValueMethod = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.GetVariableValueMethodName, (c, n, s) => { var returnType = compilation.GetSpecialType(SpecialType.System_Object); return(new PlaceholderMethodSymbol( c, s, n, returnType, m => ImmutableArray.Create <ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)))); }); var getAddressMethod = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.GetVariableAddressMethodName, (c, n, s) => { return(new PlaceholderMethodSymbol( c, s, n, m => ImmutableArray.Create <TypeParameterSymbol>(new SimpleTypeParameterSymbol(m, 0, "<>T")), m => m.TypeParameters[0], // return type is <>T& m => ImmutableArray.Create <ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)), returnValueIsByRef: true)); }); return(new BoundPseudoVariable( syntax, local, new ObjectIdExpressions(compilation, getValueMethod, getAddressMethod), local.Type)); }
private static void AppendLocalAndMethod( ArrayBuilder<LocalAndMethod> localBuilder, ArrayBuilder<MethodSymbol> methodBuilder, string name, Func<EENamedTypeSymbol, string, string, int, MethodSymbol> getMethod, EENamedTypeSymbol container, int localOrParameterIndex, DkmClrCompilationResultFlags resultFlags) { // Note: The native EE doesn't do this, but if we don't escape keyword identifiers, // the ResultProvider needs to be able to disambiguate cases like "this" and "@this", // which it can't do correctly without semantic information. name = SyntaxHelpers.EscapeKeywordIdentifiers(name); var methodName = GetNextMethodName(methodBuilder); var method = getMethod(container, methodName, name, localOrParameterIndex); localBuilder.Add(new CSharpLocalAndMethod(name, method, resultFlags)); methodBuilder.Add(method); }
private EEMethodSymbol GetParameterMethod(EENamedTypeSymbol container, string methodName, string parameterName, int parameterIndex) { var syntax = SyntaxFactory.IdentifierName(parameterName); return this.CreateMethod(container, methodName, syntax, (EEMethodSymbol method, DiagnosticBag diagnostics, out ImmutableArray<LocalSymbol> declaredLocals) => { declaredLocals = ImmutableArray<LocalSymbol>.Empty; var parameter = method.Parameters[parameterIndex]; var expression = new BoundParameter(syntax, parameter); return new BoundReturnStatement(syntax, RefKind.None, expression) { WasCompilerGenerated = true }; }); }
/// <summary> /// Rewrite the local reference as a call to a synthesized method. /// </summary> internal abstract BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax);
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax) { Debug.Assert(this.Name == this.Name.ToLowerInvariant()); var method = container.GetOrAddSynthesizedMethod( this.Name, (c, n, s) => { var returnType = compilation.GetWellKnownType(WellKnownType.System_Exception); return(new PlaceholderMethodSymbol( c, s, n, returnType, m => ImmutableArray <ParameterSymbol> .Empty)); }); var call = BoundCall.Synthesized(syntax, receiverOpt: null, method: method); return(ConvertToLocalType(compilation, call, this.Type)); }
internal EEMethodSymbol CreateMethod( EENamedTypeSymbol container, string methodName, CSharpSyntaxNode syntax, GenerateMethodBody generateMethodBody) { return new EEMethodSymbol( container, methodName, syntax.Location, _currentFrame, _locals, _localsForBinding, _displayClassVariables, generateMethodBody); }
private static EEAssemblyBuilder CreateModuleBuilder( CSharpCompilation compilation, ImmutableArray<MethodSymbol> methods, ImmutableArray<NamedTypeSymbol> additionalTypes, EENamedTypeSymbol synthesizedType, Microsoft.CodeAnalysis.CodeGen.CompilationTestData testData, DiagnosticBag diagnostics) { // Each assembly must have a unique name. var emitOptions = new EmitOptions(outputNameOverride: ExpressionCompilerUtilities.GenerateUniqueName()); var dynamicOperationContextType = GetNonDisplayClassContainer(synthesizedType.SubstitutedSourceType); string runtimeMetadataVersion = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics); var serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMetadataVersion); return new EEAssemblyBuilder(compilation.SourceAssembly, emitOptions, methods, serializationProperties, additionalTypes, dynamicOperationContextType, testData); }
private void AppendParameterAndMethod( ArrayBuilder<LocalAndMethod> localBuilder, ArrayBuilder<MethodSymbol> methodBuilder, ParameterSymbol parameter, EENamedTypeSymbol container, int parameterIndex) { // Note: The native EE doesn't do this, but if we don't escape keyword identifiers, // the ResultProvider needs to be able to disambiguate cases like "this" and "@this", // which it can't do correctly without semantic information. var name = SyntaxHelpers.EscapeKeywordIdentifiers(parameter.Name); var methodName = GetNextMethodName(methodBuilder); var method = this.GetParameterMethod(container, methodName, name, parameterIndex); localBuilder.Add(new CSharpLocalAndMethod(name, name, method, DkmClrCompilationResultFlags.None)); methodBuilder.Add(method); }
private void AppendLocalAndMethod( ArrayBuilder<LocalAndMethod> localBuilder, ArrayBuilder<MethodSymbol> methodBuilder, LocalSymbol local, EENamedTypeSymbol container, int localIndex, DkmClrCompilationResultFlags resultFlags) { var methodName = GetNextMethodName(methodBuilder); var method = this.GetLocalMethod(container, methodName, local.Name, localIndex); localBuilder.Add(MakeLocalAndMethod(local, method, resultFlags)); methodBuilder.Add(method); }
/// <summary> /// Generate a class containing methods that represent /// the set of arguments and locals at the current scope. /// </summary> internal CommonPEModuleBuilder CompileGetLocals( string typeName, ArrayBuilder<LocalAndMethod> localBuilder, bool argumentsOnly, ImmutableArray<Alias> aliases, Microsoft.CodeAnalysis.CodeGen.CompilationTestData testData, DiagnosticBag diagnostics) { var objectType = this.Compilation.GetSpecialType(SpecialType.System_Object); var allTypeParameters = _currentFrame.GetAllTypeParameters(); var additionalTypes = ArrayBuilder<NamedTypeSymbol>.GetInstance(); EENamedTypeSymbol typeVariablesType = null; if (!argumentsOnly && (allTypeParameters.Length > 0)) { // Generate a generic type with matching type parameters. // A null instance of the type will be used to represent the // "Type variables" local. typeVariablesType = new EENamedTypeSymbol( this.Compilation.SourceModule.GlobalNamespace, objectType, _syntax, _currentFrame, ExpressionCompilerConstants.TypeVariablesClassName, (m, t) => ImmutableArray.Create<MethodSymbol>(new EEConstructorSymbol(t)), allTypeParameters, (t1, t2) => allTypeParameters.SelectAsArray((tp, i, t) => (TypeParameterSymbol)new SimpleTypeParameterSymbol(t, i, tp.Name), t2)); additionalTypes.Add(typeVariablesType); } var synthesizedType = new EENamedTypeSymbol( Compilation.SourceModule.GlobalNamespace, objectType, _syntax, _currentFrame, typeName, (m, container) => { var methodBuilder = ArrayBuilder<MethodSymbol>.GetInstance(); if (!argumentsOnly) { // Pseudo-variables: $exception, $ReturnValue, etc. if (aliases.Length > 0) { var sourceAssembly = Compilation.SourceAssembly; var typeNameDecoder = new EETypeNameDecoder(Compilation, (PEModuleSymbol)_currentFrame.ContainingModule); foreach (var alias in aliases) { if (alias.IsReturnValueWithoutIndex()) { Debug.Assert(aliases.Count(a => a.Kind == DkmClrAliasKind.ReturnValue) > 1); continue; } var local = PlaceholderLocalSymbol.Create( typeNameDecoder, _currentFrame, sourceAssembly, alias); var methodName = GetNextMethodName(methodBuilder); var syntax = SyntaxFactory.IdentifierName(SyntaxFactory.MissingToken(SyntaxKind.IdentifierToken)); var aliasMethod = this.CreateMethod(container, methodName, syntax, (method, diags) => { var expression = new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type); return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; }); var flags = local.IsWritable ? DkmClrCompilationResultFlags.None : DkmClrCompilationResultFlags.ReadOnlyResult; localBuilder.Add(MakeLocalAndMethod(local, aliasMethod, flags)); methodBuilder.Add(aliasMethod); } } // "this" for non-static methods that are not display class methods or // display class methods where the display class contains "<>4__this". if (!m.IsStatic && (!IsDisplayClassType(m.ContainingType) || _displayClassVariables.ContainsKey(GeneratedNames.ThisProxyFieldName()))) { var methodName = GetNextMethodName(methodBuilder); var method = this.GetThisMethod(container, methodName); localBuilder.Add(new CSharpLocalAndMethod("this", "this", method, DkmClrCompilationResultFlags.None)); // Note: writable in dev11. methodBuilder.Add(method); } } // Hoisted method parameters (represented as locals in the EE). if (!_hoistedParameterNames.IsEmpty) { int localIndex = 0; foreach (var local in _localsForBinding) { // Since we are showing hoisted method parameters first, the parameters may appear out of order // in the Locals window if only some of the parameters are hoisted. This is consistent with the // behavior of the old EE. if (_hoistedParameterNames.Contains(local.Name)) { AppendLocalAndMethod(localBuilder, methodBuilder, local, container, localIndex, GetLocalResultFlags(local)); } localIndex++; } } // Method parameters (except those that have been hoisted). int parameterIndex = m.IsStatic ? 0 : 1; foreach (var parameter in m.Parameters) { var parameterName = parameter.Name; if (!_hoistedParameterNames.Contains(parameterName) && GeneratedNames.GetKind(parameterName) == GeneratedNameKind.None) { AppendParameterAndMethod(localBuilder, methodBuilder, parameter, container, parameterIndex); } parameterIndex++; } if (!argumentsOnly) { // Locals. int localIndex = 0; foreach (var local in _localsForBinding) { if (!_hoistedParameterNames.Contains(local.Name)) { AppendLocalAndMethod(localBuilder, methodBuilder, local, container, localIndex, GetLocalResultFlags(local)); } localIndex++; } // "Type variables". if ((object)typeVariablesType != null) { var methodName = GetNextMethodName(methodBuilder); var returnType = typeVariablesType.Construct(allTypeParameters.Cast<TypeParameterSymbol, TypeSymbol>()); var method = this.GetTypeVariablesMethod(container, methodName, returnType); localBuilder.Add(new CSharpLocalAndMethod( ExpressionCompilerConstants.TypeVariablesLocalName, ExpressionCompilerConstants.TypeVariablesLocalName, method, DkmClrCompilationResultFlags.ReadOnlyResult)); methodBuilder.Add(method); } } return methodBuilder.ToImmutableAndFree(); }); additionalTypes.Add(synthesizedType); var module = CreateModuleBuilder( this.Compilation, synthesizedType.Methods, additionalTypes: additionalTypes.ToImmutableAndFree(), synthesizedType: synthesizedType, testData: testData, diagnostics: diagnostics); Debug.Assert(module != null); this.Compilation.Compile( module, win32Resources: null, xmlDocStream: null, emittingPdb: false, diagnostics: diagnostics, filterOpt: null, cancellationToken: CancellationToken.None); return diagnostics.HasAnyErrors() ? null : module; }
internal CommonPEModuleBuilder CompileAssignment( string typeName, string methodName, ImmutableArray<Alias> aliases, Microsoft.CodeAnalysis.CodeGen.CompilationTestData testData, DiagnosticBag diagnostics, out ResultProperties resultProperties) { var objectType = this.Compilation.GetSpecialType(SpecialType.System_Object); var synthesizedType = new EENamedTypeSymbol( Compilation.SourceModule.GlobalNamespace, objectType, _syntax, _currentFrame, typeName, methodName, this, (method, diags) => { var hasDisplayClassThis = _displayClassVariables.ContainsKey(GeneratedNames.ThisProxyFieldName()); var binder = ExtendBinderChain( _syntax, aliases, method, this.NamespaceBinder, hasDisplayClassThis, methodNotType: true); return BindAssignment(binder, (ExpressionSyntax)_syntax, diags); }); var module = CreateModuleBuilder( this.Compilation, synthesizedType.Methods, additionalTypes: ImmutableArray.Create((NamedTypeSymbol)synthesizedType), synthesizedType: synthesizedType, testData: testData, diagnostics: diagnostics); Debug.Assert(module != null); this.Compilation.Compile( module, win32Resources: null, xmlDocStream: null, emittingPdb: false, diagnostics: diagnostics, filterOpt: null, cancellationToken: CancellationToken.None); if (diagnostics.HasAnyErrors()) { resultProperties = default(ResultProperties); return null; } // Should be no name mangling since the caller provided explicit names. Debug.Assert(synthesizedType.MetadataName == typeName); Debug.Assert(synthesizedType.GetMembers()[0].MetadataName == methodName); resultProperties = new ResultProperties(DkmClrCompilationResultFlags.PotentialSideEffect); return module; }
/// <summary> /// Rewrite the local reference as a call to a synthesized method. /// </summary> internal abstract BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, SyntaxNode syntax, DiagnosticBag diagnostics);
internal static BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, LocalSymbol local) { return RewriteLocalInternal(compilation, container, syntax, local); }
internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, BoundNode node, DiagnosticBag diagnostics) { var rewriter = new PlaceholderLocalRewriter(compilation, container, declaredLocals, diagnostics); return rewriter.Visit(node); }
private EEMethodSymbol GetLocalMethod(EENamedTypeSymbol container, string methodName, string localName, int localIndex) { var syntax = SyntaxFactory.IdentifierName(localName); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var local = method.LocalsForBinding[localIndex]; var expression = new BoundLocal(syntax, local, constantValueOpt: local.GetConstantValue(null, null, diagnostics), type: local.Type); return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; }); }
internal EEMethodSymbol( EENamedTypeSymbol container, string name, Location location, MethodSymbol sourceMethod, ImmutableArray <LocalSymbol> sourceLocals, ImmutableArray <LocalSymbol> sourceLocalsForBinding, ImmutableDictionary <string, DisplayClassVariable> sourceDisplayClassVariables, GenerateMethodBody generateMethodBody) { Debug.Assert(sourceMethod.IsDefinition); Debug.Assert(sourceMethod.ContainingSymbol == container.SubstitutedSourceType.OriginalDefinition); Debug.Assert(sourceLocals.All(l => l.ContainingSymbol == sourceMethod)); _container = container; _name = name; _locations = ImmutableArray.Create(location); // What we want is to map all original type parameters to the corresponding new type parameters // (since the old ones have the wrong owners). Unfortunately, we have a circular dependency: // 1) Each new type parameter requires the entire map in order to be able to construct its constraint list. // 2) The map cannot be constructed until all new type parameters exist. // Our solution is to pass each new type parameter a lazy reference to the type map. We then // initialize the map as soon as the new type parameters are available - and before they are // handed out - so that there is never a period where they can require the type map and find // it uninitialized. var sourceMethodTypeParameters = sourceMethod.TypeParameters; var allSourceTypeParameters = container.SourceTypeParameters.Concat(sourceMethodTypeParameters); var getTypeMap = new Func <TypeMap>(() => this.TypeMap); _typeParameters = sourceMethodTypeParameters.SelectAsArray( (tp, i, arg) => (TypeParameterSymbol) new EETypeParameterSymbol(this, tp, i, getTypeMap), (object)null); _allTypeParameters = container.TypeParameters.Concat(_typeParameters); this.TypeMap = new TypeMap(allSourceTypeParameters, _allTypeParameters); EENamedTypeSymbol.VerifyTypeParameters(this, _typeParameters); var substitutedSourceType = container.SubstitutedSourceType; this.SubstitutedSourceMethod = sourceMethod.AsMember(substitutedSourceType); if (sourceMethod.Arity > 0) { this.SubstitutedSourceMethod = this.SubstitutedSourceMethod.Construct(_typeParameters.As <TypeSymbol>()); } TypeParameterChecker.Check(this.SubstitutedSourceMethod, _allTypeParameters); // Create a map from original parameter to target parameter. var parameterBuilder = ArrayBuilder <ParameterSymbol> .GetInstance(); var substitutedSourceThisParameter = this.SubstitutedSourceMethod.ThisParameter; var substitutedSourceHasThisParameter = (object)substitutedSourceThisParameter != null; if (substitutedSourceHasThisParameter) { _thisParameter = MakeParameterSymbol(0, GeneratedNames.ThisProxyFieldName(), substitutedSourceThisParameter); Debug.Assert(_thisParameter.Type == this.SubstitutedSourceMethod.ContainingType); parameterBuilder.Add(_thisParameter); } var ordinalOffset = (substitutedSourceHasThisParameter ? 1 : 0); foreach (var substitutedSourceParameter in this.SubstitutedSourceMethod.Parameters) { var ordinal = substitutedSourceParameter.Ordinal + ordinalOffset; Debug.Assert(ordinal == parameterBuilder.Count); var parameter = MakeParameterSymbol(ordinal, substitutedSourceParameter.Name, substitutedSourceParameter); parameterBuilder.Add(parameter); } _parameters = parameterBuilder.ToImmutableAndFree(); var localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance(); var localsMap = PooledDictionary <LocalSymbol, LocalSymbol> .GetInstance(); foreach (var sourceLocal in sourceLocals) { var local = sourceLocal.ToOtherMethod(this, this.TypeMap); localsMap.Add(sourceLocal, local); localsBuilder.Add(local); } this.Locals = localsBuilder.ToImmutableAndFree(); localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance(); foreach (var sourceLocal in sourceLocalsForBinding) { LocalSymbol local; if (!localsMap.TryGetValue(sourceLocal, out local)) { local = sourceLocal.ToOtherMethod(this, this.TypeMap); localsMap.Add(sourceLocal, local); } localsBuilder.Add(local); } this.LocalsForBinding = localsBuilder.ToImmutableAndFree(); // Create a map from variable name to display class field. var displayClassVariables = PooledDictionary <string, DisplayClassVariable> .GetInstance(); foreach (var pair in sourceDisplayClassVariables) { var variable = pair.Value; var oldDisplayClassInstance = variable.DisplayClassInstance; // Note: we don't call ToOtherMethod in the local case because doing so would produce // a new LocalSymbol that would not be ReferenceEquals to the one in this.LocalsForBinding. var oldDisplayClassInstanceFromLocal = oldDisplayClassInstance as DisplayClassInstanceFromLocal; var newDisplayClassInstance = (oldDisplayClassInstanceFromLocal == null) ? oldDisplayClassInstance.ToOtherMethod(this, this.TypeMap) : new DisplayClassInstanceFromLocal((EELocalSymbol)localsMap[oldDisplayClassInstanceFromLocal.Local]); variable = variable.SubstituteFields(newDisplayClassInstance, this.TypeMap); displayClassVariables.Add(pair.Key, variable); } _displayClassVariables = displayClassVariables.ToImmutableDictionary(); displayClassVariables.Free(); localsMap.Free(); _generateMethodBody = generateMethodBody; }
private EEMethodSymbol GetParameterMethod(EENamedTypeSymbol container, string methodName, string parameterName, int parameterIndex) { var syntax = SyntaxFactory.IdentifierName(parameterName); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var parameter = method.Parameters[parameterIndex]; var expression = new BoundParameter(syntax, parameter); return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; }); }
private EEMethodSymbol GetThisMethod(EENamedTypeSymbol container, string methodName) { var syntax = SyntaxFactory.ThisExpression(); return this.CreateMethod(container, methodName, syntax, (EEMethodSymbol method, DiagnosticBag diagnostics, out ImmutableArray<LocalSymbol> declaredLocals) => { declaredLocals = ImmutableArray<LocalSymbol>.Empty; var expression = new BoundThisReference(syntax, GetNonDisplayClassContainer(container.SubstitutedSourceType)); return new BoundReturnStatement(syntax, RefKind.None, expression) { WasCompilerGenerated = true }; }); }
private EEMethodSymbol GetThisMethod(EENamedTypeSymbol container, string methodName) { var syntax = SyntaxFactory.ThisExpression(); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var expression = new BoundThisReference(syntax, GetNonDisplayClassContainer(container.SubstitutedSourceType)); return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; }); }
private EEMethodSymbol GetPseudoVariableMethod( TypeNameDecoder<PEModuleSymbol, TypeSymbol> typeNameDecoder, EENamedTypeSymbol container, string methodName, Alias alias) { var syntax = SyntaxFactory.IdentifierName(SyntaxFactory.MissingToken(SyntaxKind.IdentifierToken)); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var local = PlaceholderLocalBinder.CreatePlaceholderLocal(typeNameDecoder, method, alias); var expression = new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type); return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; }); }
private EEMethodSymbol GetTypeVariablesMethod(EENamedTypeSymbol container, string methodName, NamedTypeSymbol typeVariablesType) { var syntax = SyntaxFactory.IdentifierName(SyntaxFactory.MissingToken(SyntaxKind.IdentifierToken)); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var type = method.TypeMap.SubstituteNamedType(typeVariablesType); var expression = new BoundObjectCreationExpression(syntax, type.InstanceConstructors[0]); var statement = new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; return statement; }); }
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax) { var method = container.GetOrAddSynthesizedMethod( ExpressionCompilerConstants.GetReturnValueMethodName, (c, n, s) => { var parameterType = compilation.GetSpecialType(SpecialType.System_Int32); var returnType = compilation.GetSpecialType(SpecialType.System_Object); return(new PlaceholderMethodSymbol( c, s, n, returnType, m => ImmutableArray.Create <ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)))); }); var argument = new BoundLiteral( syntax, Microsoft.CodeAnalysis.ConstantValue.Create(_index), method.Parameters[0].Type); var call = BoundCall.Synthesized( syntax, receiverOpt: null, method: method, arguments: ImmutableArray.Create <BoundExpression>(argument)); return(ConvertToLocalType(compilation, call, this.Type)); }