protected internal override object VisitArrayType(ArrayTypeSymbol symbol, ArrayBuilder<SymbolDescriptionPart> builder)
        {
            //See spec section 12.1 for the order of rank specificiers
            //e.g. int[][,][,,] is stored as 
            //     ArrayType
            //         Rank = 1
            //         ElementType = ArrayType
            //             Rank = 2
            //             ElementType = ArrayType
            //                 Rank = 3
            //                 ElementType = int

            TypeSymbol underlyingNonArrayType = symbol.ElementType;
            while (underlyingNonArrayType.TypeKind == TypeKind.ArrayType)
            {
                underlyingNonArrayType = ((ArrayTypeSymbol)underlyingNonArrayType).ElementType;
            }

            VisitType(underlyingNonArrayType, builder);

            ArrayTypeSymbol arrayType = symbol;
            while (arrayType != null)
            {
                AddArrayRank(arrayType, builder);
                arrayType = arrayType.ElementType as ArrayTypeSymbol;
            }

            return null;
        }
示例#2
0
        public ArrayTypeReference(Module moduleBeingBuilt, ArrayTypeSymbol underlyingArrayType)
            : base(moduleBeingBuilt)
        {
            Contract.ThrowIfNull(underlyingArrayType);

            this.underlyingArrayType = underlyingArrayType;
        }
 private static void AddArrayRank(ArrayTypeSymbol symbol, ArrayBuilder<SymbolDescriptionPart> builder)
 {
     AddPunctuation(SyntaxKind.OpenBracketToken, builder);
     for (int i = 0; i < symbol.Rank - 1; i++)
     {
         AddPunctuation(SyntaxKind.CommaToken, builder);
     }
     AddPunctuation(SyntaxKind.CloseBracketToken, builder);
 }
示例#4
0
        private ArrayTypeSymbol DecodeArrayType(ArrayTypeSymbol type)
        {
            TypeSymbolWithAnnotations decodedElementType = DecodeTypeInternal(type.ElementType);

            return(type.WithElementType(decodedElementType));
        }
示例#5
0
 protected override IArrayTypeSymbol CommonCreateArrayTypeSymbol(ITypeSymbol elementType, int rank)
 {
     return(ArrayTypeSymbol.CreateCSharpArray(SourceAssembly, (TypeSymbol)elementType, rank: rank));
 }
示例#6
0
 public virtual TResult VisitArrayType(ArrayTypeSymbol symbol)
 {
     return(DefaultVisit(symbol));
 }
示例#7
0
        public override BoundStatement CreateBlockPrologue(BoundBlock original, out LocalSymbol synthesizedLocal)
        {
            BoundStatement previousPrologue = base.CreateBlockPrologue(original, out synthesizedLocal);

            if (_methodBody == original)
            {
                _dynamicAnalysisSpans = _spansBuilder.ToImmutableAndFree();
                // In the future there will be multiple analysis kinds.
                const int analysisKind = 0;

                ArrayTypeSymbol modulePayloadType =
                    ArrayTypeSymbol.CreateCSharpArray(_methodBodyFactory.Compilation.Assembly, _payloadType);

                // Synthesize the initialization of the instrumentation payload array, using concurrency-safe code:
                //
                // var payload = PID.PayloadRootField[methodIndex];
                // if (payload == null)
                //     payload = Instrumentation.CreatePayload(mvid, methodIndex, fileIndexOrIndices, ref PID.PayloadRootField[methodIndex], payloadLength);

                BoundStatement payloadInitialization =
                    _methodBodyFactory.Assignment(
                        _methodBodyFactory.Local(_methodPayload),
                        _methodBodyFactory.ArrayAccess(
                            _methodBodyFactory.InstrumentationPayloadRoot(analysisKind, modulePayloadType),
                            ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method))));

                BoundExpression mvid        = _methodBodyFactory.ModuleVersionId();
                BoundExpression methodToken = _methodBodyFactory.MethodDefIndex(_method);

                BoundExpression payloadSlot =
                    _methodBodyFactory.ArrayAccess(
                        _methodBodyFactory.InstrumentationPayloadRoot(analysisKind, modulePayloadType),
                        ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method)));

                BoundStatement createPayloadCall =
                    GetCreatePayloadStatement(
                        _dynamicAnalysisSpans,
                        _methodBody.Syntax,
                        _methodPayload,
                        _createPayloadForMethodsSpanningSingleFile,
                        _createPayloadForMethodsSpanningMultipleFiles,
                        mvid,
                        methodToken,
                        payloadSlot,
                        _methodBodyFactory,
                        _debugDocumentProvider);

                BoundExpression payloadNullTest =
                    _methodBodyFactory.Binary(
                        BinaryOperatorKind.ObjectEqual,
                        _methodBodyFactory.SpecialType(SpecialType.System_Boolean),
                        _methodBodyFactory.Local(_methodPayload),
                        _methodBodyFactory.Null(_payloadType));

                BoundStatement payloadIf = _methodBodyFactory.If(payloadNullTest, createPayloadCall);

                Debug.Assert(synthesizedLocal == null);
                synthesizedLocal = _methodPayload;

                ArrayBuilder <BoundStatement> prologueStatements = ArrayBuilder <BoundStatement> .GetInstance(previousPrologue == null? 3 : 4);

                prologueStatements.Add(payloadInitialization);
                prologueStatements.Add(payloadIf);
                if (_methodEntryInstrumentation != null)
                {
                    prologueStatements.Add(_methodEntryInstrumentation);
                }

                if (previousPrologue != null)
                {
                    prologueStatements.Add(previousPrologue);
                }

                return(_methodBodyFactory.StatementList(prologueStatements.ToImmutableAndFree()));
            }

            return(previousPrologue);
        }
 internal Microsoft.Cci.IArrayTypeReference Translate(ArrayTypeSymbol symbol)
 {
     return symbol;
 }
示例#9
0
        private ArrayTypeSymbol DecodeArrayType(ArrayTypeSymbol type)
        {
            var decodedElementType = DecodeType(type.ElementType);
            return ReferenceEquals(decodedElementType, type)
                ? type
                : type.IsSZArray
                    ? ArrayTypeSymbol.CreateSZArray(_containingAssembly,
                                                    decodedElementType,
                                                    type.CustomModifiers)
                    : ArrayTypeSymbol.CreateMDArray(_containingAssembly,
                                                    decodedElementType,
                                                    type.Rank,
                                                    type.Sizes,
                                                    type.LowerBounds,
                                                    type.CustomModifiers);

        }
示例#10
0
        /// <summary>
        /// Create real CIL entry point, where it calls given method.
        /// </summary>
        internal void CreateEntryPoint(MethodSymbol method, DiagnosticBag diagnostic)
        {
            // "static int Main(string[] args)"
            var realmethod = new SynthesizedMethodSymbol(this.ScriptType, "Main", true, false, _compilation.CoreTypes.Int32, Accessibility.Private);

            realmethod.SetParameters(new SynthesizedParameterSymbol(realmethod, ArrayTypeSymbol.CreateSZArray(this.Compilation.SourceAssembly, this.Compilation.CoreTypes.String), 0, RefKind.None, "args"));

            //
            var body = MethodGenerator.GenerateMethodBody(this, realmethod,
                                                          (il) =>
            {
                var types      = this.Compilation.CoreTypes;
                var methods    = this.Compilation.CoreMethods;
                var args_place = new ParamPlace(realmethod.Parameters[0]);

                // AddScriptReference<Script>()
                var AddScriptReferenceMethod = (MethodSymbol)methods.Context.AddScriptReference_TScript.Symbol.Construct(this.ScriptType);
                il.EmitCall(this, diagnostic, ILOpCode.Call, AddScriptReferenceMethod);

                // int exitcode = 0;
                var exitcode_loc = il.LocalSlotManager.AllocateSlot(types.Int32.Symbol, LocalSlotConstraints.None);
                il.EmitIntConstant(0);
                il.EmitLocalStore(exitcode_loc);

                // create Context
                var ctx_loc = il.LocalSlotManager.AllocateSlot(types.Context.Symbol, LocalSlotConstraints.None);

                if (_compilation.Options.OutputKind == OutputKind.ConsoleApplication)
                {
                    // CreateConsole(mainscript, args)
                    MethodSymbol create_method = types.Context.Symbol.LookupMember <MethodSymbol>("CreateConsole");
                    Debug.Assert(create_method != null);
                    Debug.Assert(create_method.ParameterCount == 2);
                    Debug.Assert(create_method.Parameters[0].Type == types.String);
                    Debug.Assert(create_method.Parameters[1].Type == args_place.TypeOpt);

                    il.EmitStringConstant(EntryPointScriptName(method));        // mainscript
                    args_place.EmitLoad(il);                                    // args

                    il.EmitOpCode(ILOpCode.Call, +2);
                    il.EmitToken(create_method, null, diagnostic);
                }
                else
                {
                    // CreateEmpty(args)
                    MethodSymbol create_method = types.Context.Symbol.LookupMember <MethodSymbol>("CreateEmpty");
                    Debug.Assert(create_method != null);
                    Debug.Assert(create_method.ParameterCount == 1);
                    Debug.Assert(create_method.Parameters[0].Type == args_place.TypeOpt);
                    args_place.EmitLoad(il);        // args
                    il.EmitOpCode(ILOpCode.Call, +1);
                    il.EmitToken(create_method, null, diagnostic);
                }

                il.EmitLocalStore(ctx_loc);

                // Template:
                // try { Main(...); } catch (ScriptDiedException) { } finally { ctx.Dispose; }

                il.OpenLocalScope(ScopeType.TryCatchFinally);       // try { try ... } finally {}
                il.OpenLocalScope(ScopeType.Try);
                {
                    // IL requires catches and finally block to be distinct try

                    il.OpenLocalScope(ScopeType.TryCatchFinally);       // try {} catch (ScriptDiedException) {}
                    il.OpenLocalScope(ScopeType.Try);
                    {
                        // emit .call method;
                        if (method.HasThis)
                        {
                            throw new NotImplementedException();        // TODO: create instance of ContainingType
                        }

                        // params
                        foreach (var p in method.Parameters)
                        {
                            switch (p.Name)
                            {
                            case SpecialParameterSymbol.ContextName:
                                // <ctx>
                                il.EmitLocalLoad(ctx_loc);
                                break;

                            case SpecialParameterSymbol.LocalsName:
                                // <ctx>.Globals
                                il.EmitLocalLoad(ctx_loc);
                                il.EmitCall(this, diagnostic, ILOpCode.Call, methods.Context.Globals.Getter)
                                .Expect(p.Type);
                                break;

                            case SpecialParameterSymbol.ThisName:
                                // null
                                il.EmitNullConstant();
                                break;

                            case SpecialParameterSymbol.SelfName:
                                // default(RuntimeTypeHandle)
                                var runtimetypehandle_loc = il.LocalSlotManager.AllocateSlot(types.RuntimeTypeHandle.Symbol, LocalSlotConstraints.None);
                                il.EmitValueDefault(this, diagnostic, runtimetypehandle_loc);
                                break;

                            default:
                                throw new ArgumentException(p.Name);
                            }
                        }

                        if (il.EmitCall(this, diagnostic, ILOpCode.Call, method).SpecialType != SpecialType.System_Void)
                        {
                            il.EmitOpCode(ILOpCode.Pop);
                        }
                    }
                    il.CloseLocalScope();  // /Try

                    il.AdjustStack(1);     // Account for exception on the stack.
                    il.OpenLocalScope(ScopeType.Catch, Compilation.CoreTypes.ScriptDiedException.Symbol);
                    {
                        // exitcode = <exception>.ProcessStatus(ctx)
                        il.EmitLocalLoad(ctx_loc);
                        il.EmitCall(this, diagnostic, ILOpCode.Callvirt, Compilation.CoreTypes.ScriptDiedException.Symbol.LookupMember <MethodSymbol>("ProcessStatus"));
                        il.EmitLocalStore(exitcode_loc);
                    }
                    il.CloseLocalScope();   // /Catch
                    il.CloseLocalScope();   // /TryCatch
                }
                il.CloseLocalScope();       // /Try

                il.OpenLocalScope(ScopeType.Finally);
                {
                    // ctx.Dispose
                    il.EmitLocalLoad(ctx_loc);
                    il.EmitOpCode(ILOpCode.Call, -1);
                    il.EmitToken(methods.Context.Dispose.Symbol, null, diagnostic);
                }
                il.CloseLocalScope();       // /Finally
                il.CloseLocalScope();       // /TryCatch

                // return ctx.ExitCode
                il.EmitLocalLoad(exitcode_loc);
                il.EmitRet(false);
            },
                                                          null, diagnostic, false);

            SetMethodBody(realmethod, body);

            //
            this.ScriptType.EntryPointSymbol = realmethod;
        }
示例#11
0
        public void Test1()
        {
            var assemblies = MetadataTestHelpers.GetSymbolsForReferences(new[]
            {
                TestReferences.SymbolsTests.CustomModifiers.Modifiers.dll,
                TestReferences.NetFx.v4_0_21006.mscorlib
            });

            var modifiersModule = assemblies[0].Modules[0];


            var modifiers = modifiersModule.GlobalNamespace.GetTypeMembers("Modifiers").Single();

            FieldSymbol f0 = modifiers.GetMembers("F0").OfType <FieldSymbol>().Single();

            Assert.Equal(1, f0.CustomModifiers.Length);

            var f0Mod = f0.CustomModifiers[0];

            Assert.True(f0Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", f0Mod.Modifier.ToTestDisplayString());

            MethodSymbol    m1 = modifiers.GetMembers("F1").OfType <MethodSymbol>().Single();
            ParameterSymbol p1 = m1.Parameters[0];
            ParameterSymbol p2 = modifiers.GetMembers("F2").OfType <MethodSymbol>().Single().Parameters[0];

            ParameterSymbol p4 = modifiers.GetMembers("F4").OfType <MethodSymbol>().Single().Parameters[0];

            MethodSymbol    m5 = modifiers.GetMembers("F5").OfType <MethodSymbol>().Single();
            ParameterSymbol p5 = m5.Parameters[0];

            ParameterSymbol p6 = modifiers.GetMembers("F6").OfType <MethodSymbol>().Single().Parameters[0];

            MethodSymbol m7 = modifiers.GetMembers("F7").OfType <MethodSymbol>().Single();

            Assert.Equal(0, m1.ReturnTypeCustomModifiers.Length);

            Assert.Equal(1, p1.CustomModifiers.Length);

            var p1Mod = p1.CustomModifiers[0];

            Assert.True(p1Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", p1Mod.Modifier.ToTestDisplayString());

            Assert.Equal(2, p2.CustomModifiers.Length);

            foreach (var p2Mod in p2.CustomModifiers)
            {
                Assert.True(p2Mod.IsOptional);
                Assert.Equal("System.Runtime.CompilerServices.IsConst", p2Mod.Modifier.ToTestDisplayString());
            }

            Assert.Equal(SymbolKind.ErrorType, p4.Type.Kind);

            Assert.True(m5.ReturnsVoid);
            Assert.Equal(1, m5.ReturnTypeCustomModifiers.Length);

            var m5Mod = m5.ReturnTypeCustomModifiers[0];

            Assert.True(m5Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", m5Mod.Modifier.ToTestDisplayString());

            Assert.Equal(0, p5.CustomModifiers.Length);

            ArrayTypeSymbol p5Type = (ArrayTypeSymbol)p5.Type;

            Assert.Equal("System.Int32", p5Type.ElementType.ToTestDisplayString());

            Assert.Equal(1, p5Type.CustomModifiers.Length);
            var p5TypeMod = p5Type.CustomModifiers[0];

            Assert.True(p5TypeMod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", p5TypeMod.Modifier.ToTestDisplayString());

            Assert.Equal(0, p6.CustomModifiers.Length);

            PointerTypeSymbol p6Type = (PointerTypeSymbol)p6.Type;

            Assert.Equal("System.Int32", p6Type.PointedAtType.ToTestDisplayString());

            Assert.Equal(1, p6Type.CustomModifiers.Length);
            var p6TypeMod = p6Type.CustomModifiers[0];

            Assert.True(p6TypeMod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", p6TypeMod.Modifier.ToTestDisplayString());

            Assert.False(m7.ReturnsVoid);
            Assert.Equal(1, m7.ReturnTypeCustomModifiers.Length);

            var m7Mod = m7.ReturnTypeCustomModifiers[0];

            Assert.True(m7Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", m7Mod.Modifier.ToTestDisplayString());
        }
示例#12
0
        /// <summary>
        /// Determine whether there is any substitution of type parameters that will
        /// make two types identical.
        /// </summary>
        /// <param name="t1">LHS</param>
        /// <param name="t2">RHS</param>
        /// <param name="substitution">
        /// Substitutions performed so far (or null for none).
        /// Keys are type parameters, values are types (possibly type parameters).
        /// Will be updated with new subsitutions by the callee.
        /// Should be ignored when false is returned.
        /// </param>
        /// <returns>True if there exists a type map such that Map(LHS) == Map(RHS).</returns>
        /// <remarks>
        /// Derived from Dev10's BSYMMGR::UnifyTypes.
        /// Two types will not unify if they have different custom modifiers.
        /// </remarks>
        private static bool CanUnifyHelper(TypeSymbol t1, TypeSymbol t2, ref MutableTypeMap substitution)
        {
            if (ReferenceEquals(t1, t2))
            {
                return(true);
            }
            else if ((object)t1 == null || (object)t2 == null)
            {
                // Can't both be null or they would have been ReferenceEquals
                return(false);
            }

            if (substitution != null)
            {
                t1 = substitution.SubstituteType(t1);
                t2 = substitution.SubstituteType(t2);
            }

            // If one of the types is a type parameter, then the substitution could make them ReferenceEquals.
            if (ReferenceEquals(t1, t2))
            {
                return(true);
            }

            // We can avoid a lot of redundant checks if we ensure that we only have to check
            // for type parameters on the LHS
            if (!t1.IsTypeParameter() && t2.IsTypeParameter())
            {
                TypeSymbol tmp = t1;
                t1 = t2;
                t2 = tmp;
            }

            // If t1 is not a type parameter, then neither is t2
            Debug.Assert(t1.IsTypeParameter() || !t2.IsTypeParameter());

            switch (t1.Kind)
            {
            case SymbolKind.ArrayType:
            {
                if (t2.TypeKind != t1.TypeKind)
                {
                    return(false);
                }

                ArrayTypeSymbol at1 = (ArrayTypeSymbol)t1;
                ArrayTypeSymbol at2 = (ArrayTypeSymbol)t2;

                if (at1.Rank != at2.Rank || !at1.CustomModifiers.SequenceEqual(at2.CustomModifiers))
                {
                    return(false);
                }

                return(CanUnifyHelper(at1.ElementType, at2.ElementType, ref substitution));
            }

            case SymbolKind.PointerType:
            {
                if (t2.TypeKind != t1.TypeKind)
                {
                    return(false);
                }

                PointerTypeSymbol pt1 = (PointerTypeSymbol)t1;
                PointerTypeSymbol pt2 = (PointerTypeSymbol)t2;

                if (!pt1.CustomModifiers.SequenceEqual(pt2.CustomModifiers))
                {
                    return(false);
                }

                return(CanUnifyHelper(pt1.PointedAtType, pt2.PointedAtType, ref substitution));
            }

            case SymbolKind.NamedType:
            case SymbolKind.ErrorType:
            {
                if (t2.TypeKind != t1.TypeKind)
                {
                    return(false);
                }

                NamedTypeSymbol nt1 = (NamedTypeSymbol)t1;
                NamedTypeSymbol nt2 = (NamedTypeSymbol)t2;

                if (!nt1.IsGenericType)
                {
                    return(!nt2.IsGenericType && nt1 == nt2);
                }
                else if (!nt2.IsGenericType)
                {
                    return(false);
                }

                int arity = nt1.Arity;

                if (nt2.Arity != arity || nt2.OriginalDefinition != nt1.OriginalDefinition)
                {
                    return(false);
                }

                for (int i = 0; i < arity; i++)
                {
                    if (!CanUnifyHelper(nt1.TypeArgumentsNoUseSiteDiagnostics[i], nt2.TypeArgumentsNoUseSiteDiagnostics[i], ref substitution))
                    {
                        return(false);
                    }
                }

                // Note: Dev10 folds this into the loop since GetTypeArgsAll includes type args for containing types
                return((object)nt1.ContainingType == null || CanUnifyHelper(nt1.ContainingType, nt2.ContainingType, ref substitution));
            }

            case SymbolKind.TypeParameter:
            {
                // These substitutions are not allowed in C#
                if (t2.TypeKind == TypeKind.Pointer || t2.SpecialType == SpecialType.System_Void)
                {
                    return(false);
                }

                TypeParameterSymbol tp1 = (TypeParameterSymbol)t1;

                // Perform the "occurs check" - i.e. ensure that t2 doesn't contain t1 to avoid recursive types
                // Note: t2 can't be the same type param - we would have caught that with ReferenceEquals above
                if (Contains(t2, tp1))
                {
                    return(false);
                }

                if (substitution == null)
                {
                    substitution = new MutableTypeMap();
                }

                // MutableTypeMap.Add will throw if the key has already been added.  However,
                // if t1 was already in the substitution, it would have been substituted at the
                // start of this method and we wouldn't be here.
                substitution.Add(tp1, t2);

                return(true);
            }

            default:
            {
                return(t1 == t2);
            }
            }
        }
示例#13
0
        public void Test1()
        {
            var oldMsCorLib = TestMetadata.Net40.mscorlib;
            var newMsCorLib = TestMetadata.Net451.mscorlib;

            var c1 = CSharpCompilation.Create("C1", references: new[]
            {
                oldMsCorLib,
                TestReferences.SymbolsTests.CustomModifiers.Modifiers.netmodule
            });

            var c1Assembly = c1.Assembly;

            CSharpCompilation c2 = CSharpCompilation.Create("C2", references: new MetadataReference[] { newMsCorLib, new CSharpCompilationReference(c1) });

            var mscorlibAssembly = c2.GetReferencedAssemblySymbol(newMsCorLib);

            Assert.NotSame(mscorlibAssembly, c1.GetReferencedAssemblySymbol(oldMsCorLib));

            var modifiers = c2.GlobalNamespace.GetTypeMembers("Modifiers").Single();

            Assert.IsAssignableFrom <PENamedTypeSymbol>(modifiers);

            FieldSymbol f0 = modifiers.GetMembers("F0").OfType <FieldSymbol>().Single();

            Assert.Equal(1, f0.TypeWithAnnotations.CustomModifiers.Length);

            var f0Mod = f0.TypeWithAnnotations.CustomModifiers[0];

            Assert.True(f0Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", f0Mod.Modifier.ToTestDisplayString());
            Assert.Same(mscorlibAssembly, f0Mod.Modifier.ContainingAssembly.GetSymbol());

            MethodSymbol    m1 = modifiers.GetMembers("F1").OfType <MethodSymbol>().Single();
            ParameterSymbol p1 = m1.Parameters[0];
            ParameterSymbol p2 = modifiers.GetMembers("F2").OfType <MethodSymbol>().Single().Parameters[0];

            MethodSymbol    m5 = modifiers.GetMembers("F5").OfType <MethodSymbol>().Single();
            ParameterSymbol p5 = m5.Parameters[0];

            ParameterSymbol p6 = modifiers.GetMembers("F6").OfType <MethodSymbol>().Single().Parameters[0];

            MethodSymbol m7 = modifiers.GetMembers("F7").OfType <MethodSymbol>().Single();

            Assert.Equal(0, m1.ReturnTypeWithAnnotations.CustomModifiers.Length);

            Assert.Equal(1, p1.TypeWithAnnotations.CustomModifiers.Length);

            var p1Mod = p1.TypeWithAnnotations.CustomModifiers[0];

            Assert.True(p1Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", p1Mod.Modifier.ToTestDisplayString());
            Assert.Same(mscorlibAssembly, p1Mod.Modifier.ContainingAssembly.GetSymbol());

            Assert.Equal(2, p2.TypeWithAnnotations.CustomModifiers.Length);

            foreach (var p2Mod in p2.TypeWithAnnotations.CustomModifiers)
            {
                Assert.True(p2Mod.IsOptional);
                Assert.Equal("System.Runtime.CompilerServices.IsConst", p2Mod.Modifier.ToTestDisplayString());
                Assert.Same(mscorlibAssembly, p2Mod.Modifier.ContainingAssembly.GetSymbol());
            }

            Assert.True(m5.ReturnsVoid);
            Assert.Equal(1, m5.ReturnTypeWithAnnotations.CustomModifiers.Length);

            var m5Mod = m5.ReturnTypeWithAnnotations.CustomModifiers[0];

            Assert.True(m5Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", m5Mod.Modifier.ToTestDisplayString());
            Assert.Same(mscorlibAssembly, m5Mod.Modifier.ContainingAssembly.GetSymbol());

            Assert.Equal(0, p5.TypeWithAnnotations.CustomModifiers.Length);

            ArrayTypeSymbol p5Type = (ArrayTypeSymbol)p5.Type;

            Assert.Equal("System.Int32", p5Type.ElementType.ToTestDisplayString());

            Assert.Equal(1, p5Type.ElementTypeWithAnnotations.CustomModifiers.Length);
            var p5TypeMod = p5Type.ElementTypeWithAnnotations.CustomModifiers[0];

            Assert.True(p5TypeMod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", p5TypeMod.Modifier.ToTestDisplayString());
            Assert.Same(mscorlibAssembly, p5TypeMod.Modifier.ContainingAssembly.GetSymbol());

            Assert.Equal(0, p6.TypeWithAnnotations.CustomModifiers.Length);

            PointerTypeSymbol p6Type = (PointerTypeSymbol)p6.Type;

            Assert.Equal("System.Int32", p6Type.PointedAtType.ToTestDisplayString());

            Assert.Equal(1, p6Type.PointedAtTypeWithAnnotations.CustomModifiers.Length);
            var p6TypeMod = p6Type.PointedAtTypeWithAnnotations.CustomModifiers[0];

            Assert.True(p6TypeMod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", p6TypeMod.Modifier.ToTestDisplayString());
            Assert.Same(mscorlibAssembly, p6TypeMod.Modifier.ContainingAssembly.GetSymbol());

            Assert.False(m7.ReturnsVoid);
            Assert.Equal(1, m7.ReturnTypeWithAnnotations.CustomModifiers.Length);

            var m7Mod = m7.ReturnTypeWithAnnotations.CustomModifiers[0];

            Assert.True(m7Mod.IsOptional);
            Assert.Equal("System.Runtime.CompilerServices.IsConst", m7Mod.Modifier.ToTestDisplayString());
            Assert.Same(mscorlibAssembly, m7Mod.Modifier.ContainingAssembly.GetSymbol());
        }
示例#14
0
        public void TestBaseTypeDynamicTransforms()
        {
            CommonTestInitialization();

            // public class Base0 { }
            Assert.Equal(_objectType, _base0Class.BaseType());
            Assert.False(_base0Class.ContainsDynamic());

            // public class Base1<T> { }
            Assert.Equal(_objectType, _base1Class.BaseType());
            Assert.False(_base1Class.ContainsDynamic());

            // public class Base2<T, U> { }
            Assert.Equal(_objectType, _base2Class.BaseType());
            Assert.False(_base2Class.ContainsDynamic());

            // public class Derived<T> : Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic> where T : Derived<T> { ... }
            Assert.False(_derivedClass.ContainsDynamic());
            Assert.True(_derivedClass.BaseType().ContainsDynamic());

            // Outer<dynamic>
            var outerClassOfDynamic = _outerClass.Construct(s_dynamicType);
            // Outer<dynamic>.Inner<T[], dynamic>
            var t        = _derivedClass.TypeParameters[0];
            var arrayOfT = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(t));
            var innerClassOfTArrDynamic = outerClassOfDynamic.GetTypeMember("Inner").Construct(arrayOfT, s_dynamicType);
            // Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[]
            var memberInnerInnerOfInt  = innerClassOfTArrDynamic.GetTypeMember("InnerInner").Construct(_intType);
            var arrayOfInnerInnerOfInt = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(memberInnerInnerOfInt));
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>
            var memberComplicatedInner = outerClassOfDynamic.GetTypeMember("Inner").Construct(arrayOfInnerInnerOfInt, s_dynamicType);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>
            var memberInnerInnerOfDynamic = memberComplicatedInner.GetTypeMember("InnerInner").Construct(s_dynamicType);

            Assert.Equal(memberInnerInnerOfDynamic, _derivedClass.BaseType());

            // public class Outer<T> : Base1<dynamic>
            Assert.False(_outerClass.ContainsDynamic());
            Assert.True(_outerClass.BaseType().ContainsDynamic());
            var base1OfDynamic = _base1Class.Construct(s_dynamicType);

            Assert.Equal(base1OfDynamic, _outerClass.BaseType());

            // public class Inner<U, V> : Base2<dynamic, V>
            Assert.False(_innerClass.ContainsDynamic());
            Assert.True(_innerClass.BaseType().ContainsDynamic());
            var base2OfDynamicV = _base2Class.Construct(s_dynamicType, _innerClass.TypeParameters[1]);

            Assert.Equal(base2OfDynamicV, _innerClass.BaseType());

            // public class InnerInner<W> : Base1<dynamic> { }
            Assert.False(_innerInnerClass.ContainsDynamic());
            Assert.True(_innerInnerClass.BaseType().ContainsDynamic());
            Assert.Equal(base1OfDynamic, _innerInnerClass.BaseType());

            // public class Outer2<T> : Base1<dynamic>
            Assert.False(_outer2Class.ContainsDynamic());
            Assert.True(_outer2Class.BaseType().ContainsDynamic());
            Assert.Equal(base1OfDynamic, _outer2Class.BaseType());

            // public class Inner2<U, V> : Base0
            Assert.False(_inner2Class.ContainsDynamic());
            Assert.False(_inner2Class.BaseType().ContainsDynamic());
            Assert.Equal(_base0Class, _inner2Class.BaseType());

            // public class InnerInner2<W> : Base0 { }
            Assert.False(_innerInner2Class.ContainsDynamic());
            Assert.False(_innerInner2Class.BaseType().ContainsDynamic());
            Assert.Equal(_base0Class, _innerInner2Class.BaseType());

            // public class Inner3<U>
            Assert.False(_inner3Class.ContainsDynamic());
        }
示例#15
0
        public void TestReturnValueParameterAndPropertyTransforms()
        {
            CommonTestInitialization();

            //public static dynamic F1(dynamic x) { return x; }
            var f1 = _derivedClass.GetMember <MethodSymbol>("F1");

            Assert.Equal(s_dynamicType, f1.ReturnType);
            Assert.Equal(s_dynamicType, f1.GetParameterType(0));

            //public static dynamic F2(ref dynamic x) { return x; }
            var f2 = _derivedClass.GetMember <MethodSymbol>("F2");

            Assert.Equal(s_dynamicType, f2.ReturnType);
            Assert.Equal(s_dynamicType, f2.GetParameterType(0));
            Assert.Equal(RefKind.Ref, f2.Parameters[0].RefKind);

            //public static dynamic[] F3(dynamic[] x) { return x; }
            var f3             = _derivedClass.GetMember <MethodSymbol>("F3");
            var arrayOfDynamic = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(s_dynamicType));

            Assert.Equal(arrayOfDynamic, f3.ReturnType);
            Assert.Equal(arrayOfDynamic, f3.GetParameterType(0));
            Assert.Equal(RefKind.None, f3.Parameters[0].RefKind);

            var derivedTypeParam        = _derivedClass.TypeParameters[0];
            var arrayOfDerivedTypeParam = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(derivedTypeParam));
            // Outer<dynamic>
            var outerClassOfDynamic = _outerClass.Construct(s_dynamicType);
            // Outer<dynamic>.Inner<T[], dynamic>
            var complicatedInner = outerClassOfDynamic.GetTypeMember("Inner").Construct(arrayOfDerivedTypeParam, s_dynamicType);
            // Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>
            var complicatedInnerInner = complicatedInner.GetTypeMember("InnerInner").Construct(_intType);
            // Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[]
            var complicatedInnerInnerArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInner));

            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>
            complicatedInner = outerClassOfDynamic.GetTypeMember("Inner").Construct(complicatedInnerInnerArray, s_dynamicType);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>
            complicatedInnerInner = complicatedInner.GetTypeMember("InnerInner").Construct(s_dynamicType);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>[][]
            complicatedInnerInnerArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInner));
            var complicatedInnerInnerArrayOfArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInnerArray));

            //public static Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>[][] F4(Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>[][] x) { return x; }
            var f4 = _derivedClass.GetMember <MethodSymbol>("F4");

            Assert.Equal(complicatedInnerInnerArrayOfArray, f4.ReturnType);
            Assert.Equal(complicatedInnerInnerArrayOfArray, f4.GetParameterType(0));
            Assert.Equal(RefKind.None, f4.Parameters[0].RefKind);

            //public static dynamic Prop1 { get { return field1; } }
            var prop1 = _derivedClass.GetMember <PropertySymbol>("Prop1");

            Assert.Equal(s_dynamicType, prop1.Type);
            Assert.Equal(s_dynamicType, prop1.GetMethod.ReturnType);

            //public static Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>[][] Prop2 { get { return field17; } set { field17 = value; } }
            var prop2 = _derivedClass.GetMember <PropertySymbol>("Prop2");

            Assert.Equal(complicatedInnerInnerArrayOfArray, prop2.Type);
            Assert.Equal(complicatedInnerInnerArrayOfArray, prop2.GetMethod.ReturnType);
            Assert.Equal(SpecialType.System_Void, prop2.SetMethod.ReturnType.SpecialType);
            Assert.Equal(complicatedInnerInnerArrayOfArray, prop2.SetMethod.GetParameterType(0));
        }
示例#16
0
        public void TestFieldDynamicTransforms()
        {
            CommonTestInitialization();

            //public static dynamic field1;
            var field1 = _derivedClass.GetMember <FieldSymbol>("field1");

            Assert.Equal(s_dynamicType, field1.Type);

            //public static dynamic[] field2;
            var field2         = _derivedClass.GetMember <FieldSymbol>("field2");
            var arrayOfDynamic = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(s_dynamicType), 1);

            Assert.Equal(arrayOfDynamic, field2.Type);

            //public static dynamic[][] field3;
            var field3 = _derivedClass.GetMember <FieldSymbol>("field3");
            var arrayOfArrayOfDynamic = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(arrayOfDynamic), 1);

            Assert.Equal(arrayOfArrayOfDynamic, field3.Type);

            //public const dynamic field4 = null;
            var field4 = _derivedClass.GetMember <FieldSymbol>("field4");

            Assert.Equal(s_dynamicType, field4.Type);

            //public const dynamic[] field5 = null;
            var field5 = _derivedClass.GetMember <FieldSymbol>("field5");

            Assert.Equal(arrayOfDynamic, field5.Type);

            //public const dynamic[][] field6 = null;
            var field6 = _derivedClass.GetMember <FieldSymbol>("field6");

            Assert.Equal(arrayOfArrayOfDynamic, field6.Type);

            //public const dynamic[][] field7 = null;
            var field7 = _derivedClass.GetMember <FieldSymbol>("field7");

            Assert.Equal(arrayOfArrayOfDynamic, field7.Type);

            //public Outer<T>.Inner<int, T>.InnerInner<Outer<dynamic>> field8 = null;
            var field8                  = _derivedClass.GetMember <FieldSymbol>("field8");
            var derivedTypeParam        = _derivedClass.TypeParameters[0];
            var outerOfT                = _outerClass.Construct(derivedTypeParam);
            var innerOfIntOfTWithOuterT = outerOfT.GetTypeMember("Inner").Construct(_intType, derivedTypeParam);
            // Outer<dynamic>
            var outerClassOfDynamic   = _outerClass.Construct(s_dynamicType);
            var complicatedInnerInner = innerOfIntOfTWithOuterT.GetTypeMember("InnerInner").Construct(outerClassOfDynamic);

            Assert.Equal(complicatedInnerInner, field8.Type);

            //public Outer<dynamic>.Inner<T, T>.InnerInner<T> field9 = null;
            var field9 = _derivedClass.GetMember <FieldSymbol>("field9");
            var innerOfTTWithOuterOfDynamic = outerClassOfDynamic.GetTypeMember("Inner").Construct(derivedTypeParam, derivedTypeParam);

            complicatedInnerInner = innerOfTTWithOuterOfDynamic.GetTypeMember("InnerInner").Construct(derivedTypeParam);
            Assert.Equal(complicatedInnerInner, field9.Type);

            //public Outer<Outer<dynamic>.Inner<T, dynamic>>.Inner<dynamic, T>.InnerInner<T> field10 = null;
            var field10 = _derivedClass.GetMember <FieldSymbol>("field10");
            // Outer<dynamic>.Inner<T, dynamic>
            var innerOfTDynamicWithOuterOfDynamic = outerClassOfDynamic.GetTypeMember("Inner").Construct(derivedTypeParam, s_dynamicType);
            // Outer<Outer<dynamic>.Inner<T, dynamic>>
            var complicatedOuter = _outerClass.Construct(innerOfTDynamicWithOuterOfDynamic);
            // Outer<Outer<dynamic>.Inner<T, dynamic>>.Inner<dynamic, T>
            var complicatedInner = complicatedOuter.GetTypeMember("Inner").Construct(s_dynamicType, derivedTypeParam);

            complicatedInnerInner = complicatedInner.GetTypeMember("InnerInner").Construct(derivedTypeParam);
            Assert.Equal(complicatedInnerInner, field10.Type);

            //public Outer<T>.Inner<dynamic, dynamic>.InnerInner<T> field11 = null;
            var field11 = _derivedClass.GetMember <FieldSymbol>("field11");
            // Outer<T>.Inner<dynamic, dynamic>
            var innerOfDynamicDynamicWithOuterOfT = outerOfT.GetTypeMember("Inner").Construct(s_dynamicType, s_dynamicType);

            complicatedInnerInner = innerOfDynamicDynamicWithOuterOfT.GetTypeMember("InnerInner").Construct(derivedTypeParam);
            Assert.Equal(complicatedInnerInner, field11.Type);

            //public Outer<T>.Inner<T, T>.InnerInner<Outer<dynamic>.Inner<T, dynamic>.InnerInner<int>> field12 = null;
            var field12 = _derivedClass.GetMember <FieldSymbol>("field12");
            // Outer<T>.Inner<T, T>
            var innerOfTTWithOuterOfT = outerOfT.GetTypeMember("Inner").Construct(derivedTypeParam, derivedTypeParam);

            // Outer<dynamic>.Inner<T, dynamic>.InnerInner<int>
            complicatedInnerInner = innerOfTDynamicWithOuterOfDynamic.GetTypeMember("InnerInner").Construct(_intType);
            complicatedInnerInner = innerOfTTWithOuterOfT.GetTypeMember("InnerInner").Construct(complicatedInnerInner);
            Assert.Equal(complicatedInnerInner, field12.Type);

            //public Outer<dynamic>.Inner<Outer<T>, T>.InnerInner<dynamic> field13 = null;
            var field13 = _derivedClass.GetMember <FieldSymbol>("field13");
            // Outer<dynamic>.Inner<Outer<T>, T>
            var innerOfOuterOfTTWithOuterDynamic = outerClassOfDynamic.GetTypeMember("Inner").Construct(outerOfT, derivedTypeParam);

            complicatedInnerInner = innerOfOuterOfTTWithOuterDynamic.GetTypeMember("InnerInner").Construct(s_dynamicType);
            Assert.Equal(complicatedInnerInner, field13.Type);

            //public Outer<dynamic>.Inner<dynamic, dynamic>.InnerInner<dynamic> field14 = null;
            var field14 = _derivedClass.GetMember <FieldSymbol>("field14");
            // Outer<dynamic>.Inner<dynamic, dynamic>
            var innerOfDynamicDynamicWithOuterOfDynamic = outerClassOfDynamic.GetTypeMember("Inner").Construct(s_dynamicType, s_dynamicType);

            complicatedInnerInner = innerOfDynamicDynamicWithOuterOfDynamic.GetTypeMember("InnerInner").Construct(s_dynamicType);
            Assert.Equal(complicatedInnerInner, field14.Type);

            //public Outer<dynamic>.Inner<Outer<dynamic>, T>.InnerInner<dynamic>[] field15 = null;
            var field15 = _derivedClass.GetMember <FieldSymbol>("field15");
            // Outer<dynamic>.Inner<Outer<dynamic>, T>
            var innerOfOuterOfDynamicTWithOuterDynamic = outerClassOfDynamic.GetTypeMember("Inner").Construct(outerClassOfDynamic, derivedTypeParam);

            // Outer<dynamic>.Inner<Outer<dynamic>, T>.InnerInner<dynamic>
            complicatedInnerInner = innerOfOuterOfDynamicTWithOuterDynamic.GetTypeMember("InnerInner").Construct(s_dynamicType);
            var complicatedInnerInnerArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInner), 1);

            Assert.Equal(complicatedInnerInnerArray, field15.Type);

            //public Outer<dynamic>.Inner<Outer<dynamic>.Inner<T, dynamic.InnerInner<int>, dynamic[]>.InnerInner<dynamic>[][] field16 = null;
            var field16 = _derivedClass.GetMember <FieldSymbol>("field16");

            // Outer<dynamic>.Inner<T, dynamic>.InnerInner<int>
            complicatedInnerInner = innerOfTDynamicWithOuterOfDynamic.GetTypeMember("InnerInner").Construct(_intType);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T, dynamic>.InnerInner<int>, dynamic[]>
            complicatedInner = outerClassOfDynamic.GetTypeMember("Inner").Construct(complicatedInnerInner, arrayOfDynamic);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T, dynamic>.InnerInner<int>, dynamic[]>.InnerInner<dynamic>
            complicatedInnerInner      = complicatedInner.GetTypeMember("InnerInner").Construct(s_dynamicType);
            complicatedInnerInnerArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInner), 1);
            var complicatedInnerInnerArrayOfArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInnerArray), 1);

            Assert.Equal(complicatedInnerInnerArrayOfArray, field16.Type);

            //public static Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>[][] field17 = null;
            var field17 = _derivedClass.GetMember <FieldSymbol>("field17");
            // T[]
            var arrayOfDerivedTypeParam = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(derivedTypeParam), 1);

            // Outer<dynamic>.Inner<T[], dynamic>
            complicatedInner = outerClassOfDynamic.GetTypeMember("Inner").Construct(arrayOfDerivedTypeParam, s_dynamicType);
            // Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>
            complicatedInnerInner = complicatedInner.GetTypeMember("InnerInner").Construct(_intType);
            // Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[]
            complicatedInnerInnerArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInner), 1);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>
            complicatedInner = outerClassOfDynamic.GetTypeMember("Inner").Construct(complicatedInnerInnerArray, s_dynamicType);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>
            complicatedInnerInner = complicatedInner.GetTypeMember("InnerInner").Construct(s_dynamicType);
            // Outer<dynamic>.Inner<Outer<dynamic>.Inner<T[], dynamic>.InnerInner<int>[], dynamic>.InnerInner<dynamic>[][]
            complicatedInnerInnerArray        = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInner), 1);
            complicatedInnerInnerArrayOfArray = ArrayTypeSymbol.CreateCSharpArray(_assembly, TypeWithAnnotations.Create(complicatedInnerInnerArray), 1);
            Assert.Equal(complicatedInnerInnerArrayOfArray, field17.Type);

            //public static Outer3.Inner3<dynamic> field1 = null;
            field1 = _inner3Class.GetMember <FieldSymbol>("field1");
            var inner3OfDynamic = _inner3Class.Construct(s_dynamicType);

            Assert.Equal(inner3OfDynamic, field1.Type);
        }
示例#17
0
        private BoundStatement InitializeFixedStatementArrayLocal(
            BoundLocalDeclaration localDecl,
            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;

            // 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 (arrayType.IsSZArray)
            {
                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(InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, localInit));
        }
        /// <summary>
        /// fixed(int* ptr = arr){ ... }    == becomes ===>
        ///
        /// pinned int[] pinnedTemp = arr;         // pinning managed ref
        /// int* ptr = pinnedTemp != null &amp;&amp; pinnedTemp.Length != 0
        ///                (int*)&amp;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));
        }
示例#19
0
 /// <summary>
 /// Called when visiting an <see cref="ArrayTypeSymbol" />; Override this with specific
 /// implementation; Calling <see cref="DefaultVisit" /> if it's not overridden
 /// </summary>
 /// <param name="symbol">The visited symbol</param>
 /// <param name="argument">Additional argument</param>
 /// <returns></returns>
 public virtual TResult VisitArrayType(ArrayTypeSymbol symbol, TArgument argument)
 {
     return(DefaultVisit(symbol, argument));
 }
示例#20
0
        /// <summary>
        /// Lower a foreach loop that will enumerate a multi-dimensional array.
        ///
        /// A[...] a = x;
        /// int q_0 = a.GetUpperBound(0), q_1 = a.GetUpperBound(1), ...;
        /// for (int p_0 = a.GetLowerBound(0); p_0 &lt;= q_0; p_0 = p_0 + 1)
        ///     for (int p_1 = a.GetLowerBound(1); p_1 &lt;= q_1; p_1 = p_1 + 1)
        ///         ...
        ///             { V v = (V)a[p_0, p_1, ...]; /* body */ }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's
        /// implementation of IEnumerable and just indexing into its elements.
        ///
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to nested for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);

            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            int rank = arrayType.Rank;

            Debug.Assert(rank > 1);

            TypeSymbol intType  = compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            // Values we'll use every iteration
            MethodSymbol getLowerBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetLowerBound);
            MethodSymbol getUpperBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetUpperBound);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement  rewrittenBody       = (BoundStatement)Visit(node.Body);

            // A[...] a
            LocalSymbol arrayVar      = factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray);
            BoundLocal  boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // A[...] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // NOTE: dev10 initializes all of the upper bound temps before entering the loop (as opposed to
            // initializing each one at the corresponding level of nesting).  Doing it at the same time as
            // the lower bound would make this code a bit simpler, but it would make it harder to compare
            // the roslyn and dev10 IL.

            // int q_0, q_1, ...
            LocalSymbol[]    upperVar      = new LocalSymbol[rank];
            BoundLocal[]     boundUpperVar = new BoundLocal[rank];
            BoundStatement[] upperVarDecl  = new BoundStatement[rank];
            for (int dimension = 0; dimension < rank; dimension++)
            {
                // int q_/*dimension*/
                upperVar[dimension] = factory.SynthesizedLocal(
                    intType,
                    syntax: forEachSyntax,
                    kind: (SynthesizedLocalKind)((int)SynthesizedLocalKind.ForEachArrayLimit0 + dimension));
                boundUpperVar[dimension] = MakeBoundLocal(forEachSyntax, upperVar[dimension], intType);

                ImmutableArray <BoundExpression> dimensionArgument = ImmutableArray.Create <BoundExpression>(
                    MakeLiteral(forEachSyntax,
                                constantValue: ConstantValue.Create(dimension, ConstantValueTypeDiscriminator.Int32),
                                type: intType));

                // a.GetUpperBound(/*dimension*/)
                BoundExpression currentDimensionUpperBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getUpperBoundMethod, dimensionArgument);

                // int q_/*dimension*/ = a.GetUpperBound(/*dimension*/);
                upperVarDecl[dimension] = MakeLocalDeclaration(forEachSyntax, upperVar[dimension], currentDimensionUpperBound);
            }

            // int p_0, p_1, ...
            LocalSymbol[] positionVar      = new LocalSymbol[rank];
            BoundLocal[]  boundPositionVar = new BoundLocal[rank];
            for (int dimension = 0; dimension < rank; dimension++)
            {
                positionVar[dimension] = factory.SynthesizedLocal(
                    intType,
                    syntax: forEachSyntax,
                    kind: (SynthesizedLocalKind)((int)SynthesizedLocalKind.ForEachArrayIndex0 + dimension));
                boundPositionVar[dimension] = MakeBoundLocal(forEachSyntax, positionVar[dimension], intType);
            }

            // V v
            LocalSymbol iterationVar     = node.IterationVariable;
            TypeSymbol  iterationVarType = iterationVar.Type;

            // (V)a[p_0, p_1, ...]
            BoundExpression iterationVarInitValue = MakeConversion(
                syntax: forEachSyntax,
                rewrittenOperand: new BoundArrayAccess(forEachSyntax,
                                                       expression: boundArrayVar,
                                                       indices: ImmutableArray.Create <BoundExpression>((BoundExpression[])boundPositionVar),
                                                       type: arrayType.ElementType),
                conversion: node.ElementConversion,
                rewrittenType: iterationVarType,
                @checked: node.Checked);

            // V v = (V)a[p_0, p_1, ...];
            BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl);

            // { V v = (V)a[p_0, p_1, ...]; /* node.Body */ }
            BoundStatement innermostLoopBody = new BoundBlock(forEachSyntax,
                                                              locals: ImmutableArray.Create <LocalSymbol>(iterationVar),
                                                              statements: ImmutableArray.Create <BoundStatement>(iterationVarDecl, rewrittenBody));

            // work from most-nested to least-nested
            // for (int p_0 = a.GetLowerBound(0); p_0 <= q_0; p_0 = p_0 + 1)
            //     for (int p_1 = a.GetLowerBound(0); p_1 <= q_1; p_1 = p_1 + 1)
            //         ...
            //             { V v = (V)a[p_0, p_1, ...]; /* node.Body */ }
            BoundStatement forLoop = null;

            for (int dimension = rank - 1; dimension >= 0; dimension--)
            {
                ImmutableArray <BoundExpression> dimensionArgument = ImmutableArray.Create <BoundExpression>(
                    MakeLiteral(forEachSyntax,
                                constantValue: ConstantValue.Create(dimension, ConstantValueTypeDiscriminator.Int32),
                                type: intType));

                // a.GetLowerBound(/*dimension*/)
                BoundExpression currentDimensionLowerBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getLowerBoundMethod, dimensionArgument);

                // int p_/*dimension*/ = a.GetLowerBound(/*dimension*/);
                BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar[dimension], currentDimensionLowerBound);

                GeneratedLabelSymbol breakLabel = dimension == 0 // outermost for-loop
                    ? node.BreakLabel                            // i.e. the one that break statements will jump to
                    : new GeneratedLabelSymbol("break");         // Should not affect emitted code since unused

                // p_/*dimension*/ <= q_/*dimension*/  //NB: OrEqual
                BoundExpression exitCondition = new BoundBinaryOperator(
                    syntax: forEachSyntax,
                    operatorKind: BinaryOperatorKind.IntLessThanOrEqual,
                    left: boundPositionVar[dimension],
                    right: boundUpperVar[dimension],
                    constantValueOpt: null,
                    methodOpt: null,
                    resultKind: LookupResultKind.Viable,
                    type: boolType);

                // p_/*dimension*/ = p_/*dimension*/ + 1;
                BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar[dimension], intType);

                BoundStatement       body;
                GeneratedLabelSymbol continueLabel;

                if (forLoop == null)
                {
                    // innermost for-loop
                    body          = innermostLoopBody;
                    continueLabel = node.ContinueLabel; //i.e. the one continue statements will actually jump to
                }
                else
                {
                    body          = forLoop;
                    continueLabel = new GeneratedLabelSymbol("continue"); // Should not affect emitted code since unused
                }

                forLoop = RewriteForStatement(
                    syntax: forEachSyntax,
                    outerLocals: ImmutableArray.Create(positionVar[dimension]),
                    rewrittenInitializer: positionVarDecl,
                    rewrittenCondition: exitCondition,
                    conditionSyntaxOpt: null,
                    conditionSpanOpt: forEachSyntax.InKeyword.Span,
                    rewrittenIncrement: positionIncrement,
                    rewrittenBody: body,
                    breakLabel: breakLabel,
                    continueLabel: continueLabel,
                    hasErrors: node.HasErrors);
            }

            Debug.Assert(forLoop != null);

            BoundStatement result = new BoundBlock(
                forEachSyntax,
                ImmutableArray.Create <LocalSymbol>(arrayVar).Concat(upperVar.AsImmutableOrNull()),
                ImmutableArray.Create <BoundStatement>(arrayVarDecl).Concat(upperVarDecl.AsImmutableOrNull()).Add(forLoop));

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return(result);
        }
示例#21
0
 private ArrayTypeSymbol DecodeArrayType(ArrayTypeSymbol type)
 {
     var decodedElementType = DecodeType(type.ElementType);
     return ReferenceEquals(decodedElementType, type.ElementType)
         ? type
         : type.WithElementType(decodedElementType);
 }
示例#22
0
        /// <summary>
        /// Lower a foreach loop that will enumerate a single-dimensional array.
        ///
        /// A[] a = x;
        /// for (int p = 0; p &lt; a.Length; p = p + 1) {
        ///     V v = (V)a[p];
        ///     // body
        /// }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's
        /// implementation of IEnumerable and just indexing into its elements.
        ///
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);

            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            Debug.Assert(arrayType.Rank == 1);

            TypeSymbol intType  = compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement  rewrittenBody       = (BoundStatement)Visit(node.Body);

            // A[] a
            LocalSymbol arrayVar = factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray);

            // A[] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // Reference to a.
            BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // int p
            LocalSymbol positionVar = factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayIndex0);

            // Reference to p.
            BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType);

            // int p = 0;
            BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar,
                                                                  MakeLiteral(forEachSyntax, ConstantValue.Default(SpecialType.System_Int32), intType));

            // V v
            LocalSymbol iterationVar     = node.IterationVariable;
            TypeSymbol  iterationVarType = iterationVar.Type;

            // (V)a[p]
            BoundExpression iterationVarInitValue = MakeConversion(
                syntax: forEachSyntax,
                rewrittenOperand: new BoundArrayAccess(
                    syntax: forEachSyntax,
                    expression: boundArrayVar,
                    indices: ImmutableArray.Create <BoundExpression>(boundPositionVar),
                    type: arrayType.ElementType),
                conversion: node.ElementConversion,
                rewrittenType: iterationVarType,
                @checked: node.Checked);

            // V v = (V)a[p];
            BoundStatement iterationVariableDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVariableDecl);

            BoundStatement initializer = new BoundStatementList(forEachSyntax,
                                                                statements: ImmutableArray.Create <BoundStatement>(arrayVarDecl, positionVarDecl));

            // a.Length
            BoundExpression arrayLength = new BoundArrayLength(
                syntax: forEachSyntax,
                expression: boundArrayVar,
                type: intType);

            // p < a.Length
            BoundExpression exitCondition = new BoundBinaryOperator(
                syntax: forEachSyntax,
                operatorKind: BinaryOperatorKind.IntLessThan,
                left: boundPositionVar,
                right: arrayLength,
                constantValueOpt: null,
                methodOpt: null,
                resultKind: LookupResultKind.Viable,
                type: boolType);

            // p = p + 1;
            BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType);

            // { V v = (V)a[p]; /* node.Body */ }
            BoundStatement loopBody = new BoundBlock(forEachSyntax,
                                                     locals: ImmutableArray.Create <LocalSymbol>(iterationVar),
                                                     statements: ImmutableArray.Create <BoundStatement>(iterationVariableDecl, rewrittenBody));

            // for (A[] a = /*node.Expression*/, int p = 0; p < a.Length; p = p + 1) {
            //     V v = (V)a[p];
            //     /*node.Body*/
            // }
            BoundStatement result = RewriteForStatement(
                syntax: node.Syntax,
                outerLocals: ImmutableArray.Create <LocalSymbol>(arrayVar, positionVar),
                rewrittenInitializer: initializer,
                rewrittenCondition: exitCondition,
                conditionSyntaxOpt: null,
                conditionSpanOpt: forEachSyntax.InKeyword.Span,
                rewrittenIncrement: positionIncrement,
                rewrittenBody: loopBody,
                breakLabel: node.BreakLabel,
                continueLabel: node.ContinueLabel,
                hasErrors: node.HasErrors);

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return(result);
        }
 public override Microsoft.Cci.IReference VisitArrayType(ArrayTypeSymbol symbol, bool a)
 {
     return Translate(symbol);
 }
示例#24
0
        /// <summary>
        /// Determine whether there is any substitution of type parameters that will
        /// make two types identical.
        /// </summary>
        /// <param name="t1">LHS</param>
        /// <param name="t2">RHS</param>
        /// <param name="substitution">
        /// Substitutions performed so far (or null for none).
        /// Keys are type parameters, values are types (possibly type parameters).
        /// Will be updated with new substitutions by the callee.
        /// Should be ignored when false is returned.
        /// </param>
        /// <param name="untouchables">
        /// Set of type symbols that cannot be replaced by substitution.
        /// </param>
        /// <returns>True if there exists a type map such that Map(LHS) == Map(RHS).</returns>
        /// <remarks>
        /// Derived from Dev10's BSYMMGR::UnifyTypes.
        /// Two types will not unify if they have different custom modifiers.
        /// </remarks>
        private static bool CanUnifyHelper(TypeWithModifiers t1, TypeWithModifiers t2, ref MutableTypeMap substitution, ImmutableHashSet <TypeParameterSymbol> untouchables)
        {
            if (t1 == t2)
            {
                return(true);
            }
            else if ((object)t1.Type == null || (object)t2.Type == null)
            {
                // Can't both be null or they would have been equal
                return(false);
            }

            if (substitution != null)
            {
                t1 = t1.SubstituteType(substitution);
                t2 = t2.SubstituteType(substitution);
            }

            // If one of the types is a type parameter, then the substitution could make them equal.
            if (t1 == t2)
            {
                return(true);
            }

            // We can avoid a lot of redundant checks if we ensure that we only have to check
            // for type parameters on the LHS
            if (!t1.Type.IsTypeParameter() && t2.Type.IsTypeParameter())
            {
                TypeWithModifiers tmp = t1;
                t1 = t2;
                t2 = tmp;
            }

            // If t1 is not a type parameter, then neither is t2
            Debug.Assert(t1.Type.IsTypeParameter() || !t2.Type.IsTypeParameter());

            switch (t1.Type.Kind)
            {
            case SymbolKind.ArrayType:
            {
                if (t2.Type.TypeKind != t1.Type.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers))
                {
                    return(false);
                }

                ArrayTypeSymbol at1 = (ArrayTypeSymbol)t1.Type;
                ArrayTypeSymbol at2 = (ArrayTypeSymbol)t2.Type;

                if (!at1.HasSameShapeAs(at2))
                {
                    return(false);
                }

                return(CanUnifyHelper(new TypeWithModifiers(at1.ElementType, at1.CustomModifiers), new TypeWithModifiers(at2.ElementType, at2.CustomModifiers), ref substitution, untouchables));
            }

            case SymbolKind.PointerType:
            {
                if (t2.Type.TypeKind != t1.Type.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers))
                {
                    return(false);
                }

                PointerTypeSymbol pt1 = (PointerTypeSymbol)t1.Type;
                PointerTypeSymbol pt2 = (PointerTypeSymbol)t2.Type;

                return(CanUnifyHelper(new TypeWithModifiers(pt1.PointedAtType, pt1.CustomModifiers), new TypeWithModifiers(pt2.PointedAtType, pt2.CustomModifiers), ref substitution, untouchables));
            }

            case SymbolKind.NamedType:
            case SymbolKind.ErrorType:
            {
                if (t2.Type.TypeKind != t1.Type.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers))
                {
                    return(false);
                }

                NamedTypeSymbol nt1 = (NamedTypeSymbol)t1.Type;
                NamedTypeSymbol nt2 = (NamedTypeSymbol)t2.Type;

                if (nt1.IsTupleType)
                {
                    if (!nt2.IsTupleType)
                    {
                        return(false);
                    }

                    return(CanUnifyHelper(new TypeWithModifiers(nt1.TupleUnderlyingType), new TypeWithModifiers(nt2.TupleUnderlyingType), ref substitution, untouchables));
                }

                if (!nt1.IsGenericType)
                {
                    return(!nt2.IsGenericType && nt1 == nt2);
                }
                else if (!nt2.IsGenericType)
                {
                    return(false);
                }

                int arity = nt1.Arity;

                if (nt2.Arity != arity || nt2.OriginalDefinition != nt1.OriginalDefinition)
                {
                    return(false);
                }

                var nt1Arguments = nt1.TypeArgumentsNoUseSiteDiagnostics;
                var nt2Arguments = nt2.TypeArgumentsNoUseSiteDiagnostics;

                var nt1ArgumentsCustomModifiers = nt1.HasTypeArgumentsCustomModifiers ? nt1.TypeArgumentsCustomModifiers : default(ImmutableArray <ImmutableArray <CustomModifier> >);
                var nt2ArgumentsCustomModifiers = nt2.HasTypeArgumentsCustomModifiers ? nt2.TypeArgumentsCustomModifiers : default(ImmutableArray <ImmutableArray <CustomModifier> >);

                for (int i = 0; i < arity; i++)
                {
                    if (!CanUnifyHelper(new TypeWithModifiers(nt1Arguments[i], nt1ArgumentsCustomModifiers.IsDefault ? default(ImmutableArray <CustomModifier>) : nt1ArgumentsCustomModifiers[i]),
                                        new TypeWithModifiers(nt2Arguments[i], nt2ArgumentsCustomModifiers.IsDefault ? default(ImmutableArray <CustomModifier>) : nt2ArgumentsCustomModifiers[i]),
                                        ref substitution,
                                        untouchables))
                    {
                        return(false);
                    }
                }

                // Note: Dev10 folds this into the loop since GetTypeArgsAll includes type args for containing types
                // TODO: Calling CanUnifyHelper for the containing type is an overkill, we simply need to go through type arguments for all containers.
                return((object)nt1.ContainingType == null || CanUnifyHelper(new TypeWithModifiers(nt1.ContainingType), new TypeWithModifiers(nt2.ContainingType), ref substitution, untouchables));
            }

            case SymbolKind.TypeParameter:
            {
                // These substitutions are not allowed in C#
                if (t2.Type.TypeKind == TypeKind.Pointer || t2.Type.SpecialType == SpecialType.System_Void)
                {
                    return(false);
                }

                TypeParameterSymbol tp1 = (TypeParameterSymbol)t1.Type;

                // Perform the "occurs check" - i.e. ensure that t2 doesn't contain t1 to avoid recursive types
                // Note: t2 can't be the same type param - we would have caught that with ReferenceEquals above
                if (Contains(t2.Type, tp1))
                {
                    return(false);
                }

                if (!untouchables.Contains(tp1))
                {
                    if (t1.CustomModifiers.IsDefaultOrEmpty)
                    {
                        AddSubstitution(ref substitution, tp1, t2);
                        return(true);
                    }

                    if (t1.CustomModifiers.SequenceEqual(t2.CustomModifiers))
                    {
                        AddSubstitution(ref substitution, tp1, new TypeWithModifiers(t2.Type));
                        return(true);
                    }

                    if (t1.CustomModifiers.Length < t2.CustomModifiers.Length &&
                        t1.CustomModifiers.SequenceEqual(t2.CustomModifiers.Take(t1.CustomModifiers.Length)))
                    {
                        AddSubstitution(ref substitution, tp1,
                                        new TypeWithModifiers(t2.Type,
                                                              ImmutableArray.Create(t2.CustomModifiers, t1.CustomModifiers.Length, t2.CustomModifiers.Length - t1.CustomModifiers.Length)));
                        return(true);
                    }
                }

                if (t2.Type.IsTypeParameter())
                {
                    var tp2 = (TypeParameterSymbol)t2.Type;

                    if (!untouchables.Contains(tp2))
                    {
                        if (t2.CustomModifiers.IsDefaultOrEmpty)
                        {
                            AddSubstitution(ref substitution, tp2, t1);
                            return(true);
                        }

                        if (t2.CustomModifiers.Length < t1.CustomModifiers.Length &&
                            t2.CustomModifiers.SequenceEqual(t1.CustomModifiers.Take(t2.CustomModifiers.Length)))
                        {
                            AddSubstitution(ref substitution, tp2,
                                            new TypeWithModifiers(t1.Type,
                                                                  ImmutableArray.Create(t1.CustomModifiers, t2.CustomModifiers.Length, t1.CustomModifiers.Length - t2.CustomModifiers.Length)));
                            return(true);
                        }
                    }
                }

                return(false);
            }

            default:
            {
                return(t1 == t2);
            }
            }
        }
示例#25
0
        /// <summary>
        /// Create real CIL entry point, where it calls given method.
        /// </summary>
        internal void CreateEntryPoint(MethodSymbol method, DiagnosticBag diagnostic)
        {
            // "static int Main(string[] args)"
            var realmethod = new SynthesizedMethodSymbol(this.ScriptType, "Main", true, false, _compilation.CoreTypes.Int32, Accessibility.Private);

            realmethod.SetParameters(new SynthesizedParameterSymbol(realmethod, ArrayTypeSymbol.CreateSZArray(this.Compilation.SourceAssembly, this.Compilation.CoreTypes.String), 0, RefKind.None, "args"));

            //
            var body = MethodGenerator.GenerateMethodBody(this, realmethod,
                                                          (il) =>
            {
                var types       = this.Compilation.CoreTypes;
                var methods     = this.Compilation.CoreMethods;
                var conversions = this.Compilation.Conversions;
                var args_place  = new ParamPlace(realmethod.Parameters[0]);

                // int exitcode = 0;
                var exitcode_loc = il.LocalSlotManager.AllocateSlot(types.Int32.Symbol, LocalSlotConstraints.None);
                il.EmitIntConstant(0);
                il.EmitLocalStore(exitcode_loc);

                // create Context
                var ctx_loc = il.LocalSlotManager.AllocateSlot(types.Context.Symbol, LocalSlotConstraints.None);
                var ex_loc  = il.LocalSlotManager.AllocateSlot(types.Exception.Symbol, LocalSlotConstraints.None);
                var onUnhandledException_method = types.Context.Symbol.LookupMember <MethodSymbol>("OnUnhandledException");

                var cg = new CodeGenerator(il,
                                           moduleBuilder: this,
                                           diagnostics: diagnostic,
                                           optimizations: PhpOptimizationLevel.Release,
                                           emittingPdb: false,
                                           container: realmethod.ContainingType,
                                           contextPlace: new LocalPlace(ctx_loc),
                                           thisPlace: null);

                if (_compilation.Options.OutputKind == OutputKind.ConsoleApplication)
                {
                    // CreateConsole(string mainscript, params string[] args)
                    var create_method = types.Context.Symbol.LookupMember <MethodSymbol>("CreateConsole", m =>
                    {
                        return
                        (m.ParameterCount == 2 &&
                         m.Parameters[0].Type == types.String &&            // string mainscript
                         m.Parameters[1].Type == args_place.Type);          // params string[] args
                    });
                    Debug.Assert(create_method != null);

                    il.EmitStringConstant(EntryPointScriptName(method));        // mainscript
                    args_place.EmitLoad(il);                                    // args

                    il.EmitOpCode(ILOpCode.Call, +2);
                    il.EmitToken(create_method, null, diagnostic);
                }
                else
                {
                    // CreateEmpty(args)
                    MethodSymbol create_method = types.Context.Symbol.LookupMember <MethodSymbol>("CreateEmpty");
                    Debug.Assert(create_method != null);
                    Debug.Assert(create_method.ParameterCount == 1);
                    Debug.Assert(create_method.Parameters[0].Type == args_place.Type);
                    args_place.EmitLoad(il);        // args
                    il.EmitOpCode(ILOpCode.Call, +1);
                    il.EmitToken(create_method, null, diagnostic);
                }

                il.EmitLocalStore(ctx_loc);

                // Template:
                // try { Main(...); } catch (ScriptDiedException) { } catch (Exception) { ... } finally { ctx.Dispose(); }

                il.OpenLocalScope(ScopeType.TryCatchFinally);       // try { try ... } finally {}
                il.OpenLocalScope(ScopeType.Try);
                {
                    // IL requires catches and finally block to be distinct try

                    il.OpenLocalScope(ScopeType.TryCatchFinally);       // try {} catch (ScriptDiedException) {}
                    il.OpenLocalScope(ScopeType.Try);
                    {
                        // emit .call method;
                        if (method.HasThis)
                        {
                            // TODO: error code for this
                            throw new NotImplementedException("Startup method must be static.");        // CONSIDER: create instance of ContainingType
                        }

                        // params
                        foreach (var p in method.Parameters)
                        {
                            switch (p.Name)
                            {
                            case SpecialParameterSymbol.ContextName:
                                // <ctx>
                                il.EmitLocalLoad(ctx_loc);
                                break;

                            case SpecialParameterSymbol.LocalsName:
                                // <ctx>.Globals
                                il.EmitLocalLoad(ctx_loc);
                                il.EmitCall(this, diagnostic, ILOpCode.Call, methods.Context.Globals.Getter)
                                .Expect(p.Type);
                                break;

                            case SpecialParameterSymbol.ThisName:
                                // null
                                il.EmitNullConstant();
                                break;

                            case SpecialParameterSymbol.SelfName:
                                // default(RuntimeTypeHandle)
                                var runtimetypehandle_loc = il.LocalSlotManager.AllocateSlot(types.RuntimeTypeHandle.Symbol, LocalSlotConstraints.None);
                                il.EmitValueDefault(this, diagnostic, runtimetypehandle_loc);
                                il.LocalSlotManager.FreeSlot(runtimetypehandle_loc);
                                break;

                            default:
                                throw new ArgumentException($"Startup method's argument '${p.Name}' of type '{p.Type.Name}' cannot be fullfilled.");
                            }
                        }

                        var rettype = il.EmitCall(this, diagnostic, ILOpCode.Call, method);
                        if (rettype.SpecialType != SpecialType.System_Void)
                        {
                            cg.EmitConvert(rettype, 0, types.Int32, Semantics.ConversionKind.Explicit);
                            il.EmitLocalStore(exitcode_loc);
                        }
                    }
                    il.CloseLocalScope();  // /Try

                    il.AdjustStack(1);     // Account for exception on the stack.
                    il.OpenLocalScope(ScopeType.Catch, types.ScriptDiedException.Symbol);
                    {
                        // exitcode = <exception>.ProcessStatus(ctx)
                        il.EmitLocalLoad(ctx_loc);
                        il.EmitCall(this, diagnostic, ILOpCode.Callvirt, types.ScriptDiedException.Symbol.LookupMember <MethodSymbol>("ProcessStatus"));
                        il.EmitLocalStore(exitcode_loc);
                    }
                    il.CloseLocalScope();                    // /Catch
                    if (onUnhandledException_method != null) // only if runtime defines the method (backward compat.)
                    {
                        il.OpenLocalScope(ScopeType.Catch, types.Exception.Symbol);
                        {
                            // <ex_loc> = <stack>
                            il.EmitLocalStore(ex_loc);

                            // <ctx_loc>.OnUnhandledException( <ex_loc> ) : bool
                            il.EmitLocalLoad(ctx_loc);
                            il.EmitLocalLoad(ex_loc);
                            il.EmitCall(this, diagnostic, ILOpCode.Callvirt, onUnhandledException_method)
                            .Expect(SpecialType.System_Boolean);

                            // if ( !<bool> )
                            // {
                            var lbl_end = new object();
                            il.EmitBranch(ILOpCode.Brtrue, lbl_end);

                            // rethrow <ex_loc>;
                            il.EmitLocalLoad(ex_loc);
                            il.EmitThrow(true);

                            // }
                            il.MarkLabel(lbl_end);
                        }
                        il.CloseLocalScope(); // /Catch
                    }
                    il.CloseLocalScope();     // /TryCatch
                }
                il.CloseLocalScope();         // /Try

                il.OpenLocalScope(ScopeType.Finally);
                {
                    // ctx.Dispose
                    il.EmitLocalLoad(ctx_loc);
                    il.EmitOpCode(ILOpCode.Call, -1);
                    il.EmitToken(methods.Context.Dispose.Symbol, null, diagnostic);
                }
                il.CloseLocalScope();       // /Finally
                il.CloseLocalScope();       // /TryCatch

                // return ctx.ExitCode
                il.EmitLocalLoad(exitcode_loc);
                il.EmitRet(false);
            },
                                                          null, diagnostic, false);

            SetMethodBody(realmethod, body);

            //
            this.ScriptType.EntryPointSymbol = realmethod;
        }
示例#26
0
 public ArrayBackpatcher(ArrayTypeSymbol symbol, Type type)
     : base(type)
 {
     this.symbol = symbol;
 }