public static NamedTypeSymbol Construct(this NamedTypeSymbol type, TypeSymbol arguments)
        {
            Debug.Assert(type != null);
            Debug.Assert(arguments != null);
            TypeMap map = new TypeMap(ReadOnlyArray <TypeSymbol> .CreateFrom(type.ConstructedFrom.TypeParameters),
                                      ReadOnlyArray.Singleton(arguments));

            return(map.SubstituteNamedType(type.ConstructedFrom));
        }
Beispiel #2
0
        internal static Assembly CreateAssemblyFromBytes(AssemblyBytesReference reference)
        {
            // make a copy of the byte[], so that the user can't change the bytes that the reader consumes:
            PEFileReader peFileReader = CreatePEFileReaderFromBytes(reference.UniqueName, (byte[])reference.Bytes.Clone());

            if (!peFileReader.IsAssembly)
            {
                throw new MetadataReaderException(MetadataReaderErrorKind.InvalidPEKind);
            }

            return(new Assembly(reference.UniqueName, ReadOnlyArray.Singleton(new Module(peFileReader))));
        }
        private static ReadOnlyArray <string> GetAliases(MetadataReference reference, Dictionary <MetadataReference, ArrayBuilder <string> > aliasMap)
        {
            ArrayBuilder <string> aliases;

            if (aliasMap != null && aliasMap.TryGetValue(reference, out aliases))
            {
                return(aliases.ToReadOnlyAndFree());
            }

            if (reference.Properties.Alias != null)
            {
                return(ReadOnlyArray.Singleton(reference.Properties.Alias));
            }

            return(ReadOnlyArray <string> .Empty);
        }
Beispiel #4
0
 protected BoundCall MakeInvocation(SyntaxNode node, BoundExpression receiver, string methodName, TypeSyntax typeArgSyntax, TypeSymbol typeArg, DiagnosticBag diagnostics)
 {
     return(MakeInvocation(node, receiver, methodName, new SeparatedSyntaxList <TypeSyntax>(new SyntaxNodeOrTokenList(typeArgSyntax)), ReadOnlyArray.Singleton(typeArg), ReadOnlyArray <BoundExpression> .Empty, diagnostics));
 }
Beispiel #5
0
 protected BoundCall MakeInvocation(SyntaxNode node, BoundExpression receiver, string methodName, BoundExpression arg, DiagnosticBag diagnostics)
 {
     return(MakeInvocation(node, receiver, methodName, default(SeparatedSyntaxList <TypeSyntax>), ReadOnlyArray <TypeSymbol> .Empty, ReadOnlyArray.Singleton(arg), diagnostics));
 }
Beispiel #6
0
        /// <summary>
        /// Rewrites arguments of an invocation according to the receiving method. It is assumed
        /// that arguments match parameters, but may need to be expanded/reordered.
        /// </summary>
        private void RewriteArguments(
            MethodSymbol method,
            bool expanded,
            ReadOnlyArray <int> argsToParamsOpt,
            ref ReadOnlyArray <RefKind> argumentRefKinds,
            ref ReadOnlyArray <BoundExpression> rewrittenArguments,
            out ReadOnlyArray <LocalSymbol> temporaries)
        {
            // We have:
            // * a list of arguments, already converted to their proper types,
            //   in source code order. Some optional arguments might be missing.
            // * a map showing which parameter each argument corresponds to. If
            //   this is null, then the argument to parameter mapping is one-to-one.
            // * the ref kind of each argument, in source code order. That is, whether
            //   the argument was marked as ref, out, or value (neither).
            // * a method symbol.
            // * whether the call is expanded or normal form.

            // We rewrite the call so that:
            // * if in its expanded form, we create the params array.
            // * if the call requires reordering of arguments because of named arguments, temporaries are generated as needed

            // Doing this transformation can move around refness in interesting ways. For example, consider
            //
            // A().M(y : ref B()[C()], x : out D());
            //
            // This will be created as a call with receiver A(), symbol M, argument list ( B()[C()], D() ),
            // name list ( y, x ) and ref list ( ref, out ).  We can rewrite this into temporaries:
            //
            // A().M(
            //    seq ( ref int temp_y = ref B()[C()], out D() ),
            //    temp_y );
            //
            // Now we have a call with receiver A(), symbol M, argument list as shown, no name list,
            // and ref list ( out, value ). We do not want to pass a *ref* to temp_y; the temporary
            // storage is not the thing being ref'd! We want to pass the *value* of temp_y, which
            // *contains* a reference.

            // We attempt to minimize the number of temporaries required. Arguments which neither
            // produce nor observe a side effect can be placed into their proper position without
            // recourse to a temporary. For example:
            //
            // Where(predicate: x=>x.Length!=0, sequence: S())
            //
            // can be rewritten without any temporaries because the conversion from lambda to
            // delegate does not produce any side effect that could be observed by S().
            //
            // By contrast:
            //
            // Foo(z: this.p, y: this.Q(), x: (object)10)
            //
            // The boxing of 10 can be reordered, but the fetch of this.p has to happen before the
            // call to this.Q() because the call could change the value of this.p.
            //
            // We start by binding everything that is not obviously reorderable as a temporary, and
            // then run an optimizer to remove unnecessary temporaries.

            ReadOnlyArray <ParameterSymbol> parameters = method.Parameters;
            var parameterCount = parameters.Count;
            var arguments      = new BoundExpression[parameterCount];

            temporaries = ReadOnlyArray <LocalSymbol> .Null;  // not using temps by default.

            List <RefKind> refKinds = null;

            if (argumentRefKinds.IsNotNull)
            {
                refKinds = new List <RefKind>(parameterCount);
                for (int p = 0; p < parameterCount; ++p)
                {
                    refKinds.Add(RefKind.None);
                }
            }

            ArrayBuilder <BoundAssignmentOperator> storesToTemps = null;
            ArrayBuilder <BoundExpression>         paramArray    = null;

            if (expanded)
            {
                paramArray = ArrayBuilder <BoundExpression> .GetInstance();
            }

            for (int a = 0; a < rewrittenArguments.Count; ++a)
            {
                var argument = rewrittenArguments[a];
                var p        = (argsToParamsOpt.IsNotNull) ? argsToParamsOpt[a] : a;
                var refKind  = argumentRefKinds.RefKinds(a);
                Debug.Assert(arguments[p] == null);
                if (expanded && p == parameterCount - 1)
                {
                    paramArray.Add(argument);
                    Debug.Assert(refKind == RefKind.None);
                }
                else if (IsSafeForReordering(argument, refKind))
                {
                    arguments[p] = argument;
                    if (refKinds != null)
                    {
                        refKinds[p] = refKind;
                    }
                }
                else
                {
                    if (storesToTemps == null)
                    {
                        storesToTemps = ArrayBuilder <BoundAssignmentOperator> .GetInstance(rewrittenArguments.Count);
                    }

                    var tempStore = TempHelpers.StoreToTemp(argument, refKind, containingSymbol);
                    storesToTemps.Add(tempStore.Item1);
                    arguments[p] = tempStore.Item2;
                }
            }

            if (expanded)
            {
                var paramArrayType = parameters[parameterCount - 1].Type;
                var arrayArgs      = paramArray.ToReadOnlyAndFree();

                var int32Type = method.ContainingAssembly.GetPrimitiveType(Microsoft.Cci.PrimitiveTypeCode.Int32);

                arguments[parameterCount - 1] = new BoundArrayCreation(
                    null,
                    null,
                    ReadOnlyArray.Singleton <BoundExpression>(
                        new BoundLiteral(null, null, ConstantValue.Create(arrayArgs.Count), int32Type)),
                    new BoundArrayInitialization(null, null, arrayArgs),
                    paramArrayType);
            }

            for (int p = 0; p < parameterCount; ++p)
            {
                if (arguments[p] == null)
                {
                    Debug.Assert(parameters[p].IsOptional);

                    // UNDONE: Add optional arguments.
                }
            }

            if (storesToTemps != null)
            {
                int tempsNeeded = MergeArgumentsAndSideEffects(storesToTemps, arguments);

                if (tempsNeeded > 0)
                {
                    var temps = new LocalSymbol[tempsNeeded];
                    for (int i = 0, j = 0; i < storesToTemps.Count; i++)
                    {
                        var s = storesToTemps[i];
                        if (s != null)
                        {
                            temps[j++] = ((BoundLocal)s.Left).LocalSymbol;
                        }
                    }

                    temporaries = temps.AsReadOnlyWrap();
                }

                storesToTemps.Free();
            }

            // * The rewritten list of names is now null because the arguments have been reordered.
            // * The args-to-params map is now null because every argument exactly matches its parameter.
            // * The call is no longer in its expanded form.

            argumentRefKinds   = refKinds == null ? ReadOnlyArray <RefKind> .Null : refKinds.AsReadOnly <RefKind>();
            rewrittenArguments = arguments.AsReadOnlyWrap();
        }
        private AssemblyMetadata CreateAssemblyMetadata(ShadowCopy manifestModuleCopy)
        {
            // We don't need to use the global metadata cache here since the shadow copy
            // won't change and is private to us - only users of the same shadow copy provider see it.

            ArrayBuilder <ModuleMetadata> moduleBuilder = null;

            bool           fault          = true;
            ModuleMetadata manifestModule = null;

            try
            {
                manifestModule = CreateModuleMetadata(manifestModuleCopy);

                string originalDirectory = null, shadowCopyDirectory = null;
                foreach (string moduleName in manifestModule.GetModuleNames())
                {
                    if (moduleBuilder == null)
                    {
                        moduleBuilder = ArrayBuilder <ModuleMetadata> .GetInstance();

                        moduleBuilder.Add(manifestModule);
                        originalDirectory   = Path.GetDirectoryName(manifestModuleCopy.OriginalPath);
                        shadowCopyDirectory = Path.GetDirectoryName(manifestModuleCopy.FullPath);
                    }

                    string originalPath   = Path.Combine(originalDirectory, moduleName);
                    string shadowCopyPath = Path.Combine(shadowCopyDirectory, moduleName);

                    var moduleCopy = CopyFile(originalPath, shadowCopyPath);
                    moduleBuilder.Add(CreateModuleMetadata(moduleCopy));
                }

                var modules = (moduleBuilder != null) ? moduleBuilder.ToReadOnly() : ReadOnlyArray.Singleton(manifestModule);

                fault = false;
                return(new AssemblyMetadata(modules));
            }
            finally
            {
                if (fault)
                {
                    if (manifestModule != null)
                    {
                        manifestModule.Dispose();
                    }

                    if (moduleBuilder != null)
                    {
                        for (int i = 1; i < moduleBuilder.Count; i++)
                        {
                            moduleBuilder[i].Dispose();
                        }
                    }
                }

                if (moduleBuilder != null)
                {
                    moduleBuilder.Free();
                }
            }
        }