예제 #1
0
        internal static TResult CompileWithRetry <TResult>(
            ImmutableArray <MetadataBlock> metadataBlocks,
            DiagnosticFormatter formatter,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage)
        {
            errorMessage = null;
            TResult compileResult;

            bool tryAgain;

            do
            {
                var context     = createContext(metadataBlocks, useReferencedModulesOnly: false);
                var diagnostics = DiagnosticBag.GetInstance();
                compileResult = compile(context, diagnostics);
                tryAgain      = false;
                if (diagnostics.HasAnyErrors())
                {
                    bool useReferencedModulesOnly;
                    ImmutableArray <AssemblyIdentity> missingAssemblyIdentities;
                    errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities(
                        diagnostics,
                        formatter,
                        preferredUICulture: null,
                        useReferencedModulesOnly: out useReferencedModulesOnly,
                        missingAssemblyIdentities: out missingAssemblyIdentities);
                    if (useReferencedModulesOnly)
                    {
                        Debug.Assert(missingAssemblyIdentities.IsEmpty);
                        var otherContext     = createContext(metadataBlocks, useReferencedModulesOnly: true);
                        var otherDiagnostics = DiagnosticBag.GetInstance();
                        var otherResult      = compile(otherContext, otherDiagnostics);
                        if (!otherDiagnostics.HasAnyErrors())
                        {
                            errorMessage  = null;
                            compileResult = otherResult;
                        }
                        otherDiagnostics.Free();
                    }
                    else
                    {
                        tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks);
                    }
                }
                diagnostics.Free();
            } while (tryAgain);

            return(compileResult);
        }
예제 #2
0
 private TResult CompileWithRetry <TResult>(
     DkmClrModuleInstance moduleInstance,
     ImmutableArray <MetadataBlock> metadataBlocks,
     CreateContextDelegate createContext,
     CompileDelegate <TResult> compile,
     out string errorMessage)
 {
     return(CompileWithRetry(
                metadataBlocks,
                this.DiagnosticFormatter,
                createContext,
                compile,
                (AssemblyIdentity assemblyIdentity, out uint size) => moduleInstance.AppDomain.GetMetaDataBytesPtr(assemblyIdentity.GetDisplayName(), out size),
                out errorMessage));
 }
예제 #3
0
        private TResult CompileWithRetry <TResult>(
            DkmClrAppDomain appDomain,
            DkmClrRuntimeInstance runtimeInstance,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            out string errorMessage)
        {
            var metadataBlocks = GetMetadataBlocks(appDomain, runtimeInstance);

            return(CompileWithRetry(
                       metadataBlocks,
                       this.DiagnosticFormatter,
                       createContext,
                       compile,
                       (AssemblyIdentity assemblyIdentity, out uint size) => appDomain.GetMetaDataBytesPtr(assemblyIdentity.GetDisplayName(), out size),
                       out errorMessage));
        }
예제 #4
0
        internal static TResult CompileWithRetry <TResult>(
            ImmutableArray <MetadataBlock> metadataBlocks,
            DiagnosticFormatter formatter,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage)
        {
            TResult compileResult;

            PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null;
            bool tryAgain;

            do
            {
                errorMessage = null;

                var context     = createContext(metadataBlocks, useReferencedModulesOnly: false);
                var diagnostics = DiagnosticBag.GetInstance();
                compileResult = compile(context, diagnostics);
                tryAgain      = false;
                if (diagnostics.HasAnyErrors())
                {
                    bool useReferencedModulesOnly;
                    ImmutableArray <AssemblyIdentity> missingAssemblyIdentities;
                    errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities(
                        diagnostics,
                        formatter,
                        preferredUICulture: null,
                        useReferencedModulesOnly: out useReferencedModulesOnly,
                        missingAssemblyIdentities: out missingAssemblyIdentities);
                    if (useReferencedModulesOnly)
                    {
                        Debug.Assert(missingAssemblyIdentities.IsEmpty);
                        var otherContext     = createContext(metadataBlocks, useReferencedModulesOnly: true);
                        var otherDiagnostics = DiagnosticBag.GetInstance();
                        var otherResult      = compile(otherContext, otherDiagnostics);
                        if (!otherDiagnostics.HasAnyErrors())
                        {
                            errorMessage  = null;
                            compileResult = otherResult;
                        }
                        otherDiagnostics.Free();
                    }
                    else
                    {
                        if (!missingAssemblyIdentities.IsEmpty)
                        {
                            if (assembliesLoadedInRetryLoop == null)
                            {
                                assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance();
                            }
                            // If any identities failed to add (they were already in the list), then don't retry.
                            if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities))
                            {
                                tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks);
                            }
                        }
                    }
                }
                diagnostics.Free();
            } while (tryAgain);
            assembliesLoadedInRetryLoop?.Free();

            return(compileResult);
        }
예제 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ToolChain" /> class.  For now tool chains are single tools, but this
        /// could be easily extended to support multiple steps.
        /// </summary>
        /// <param name="graphicsBackend">The graphics backend.</param>
        /// <param name="backendType">Type of the backend.</param>
        /// <param name="createBackend">The function to create the backend.</param>
        /// <param name="compileFunction">The compile function.</param>
        /// <param name="createHeadless">The function to create a headless graphics device.</param>
        /// <param name="createWindowed">The create windowed.</param>
        /// <exception cref="ArgumentOutOfRangeException">backendType</exception>
        private ToolChain(GraphicsBackend graphicsBackend,
                          Type backendType,
                          Func <Compilation, LanguageBackend> createBackend,
                          CompileDelegate compileFunction,
                          Func <GraphicsDevice> createHeadless,
                          Func <GraphicsDevice> createWindowed)
        {
            if (!backendType.IsSubclassOf(typeof(LanguageBackend)))
            {
                throw new ArgumentOutOfRangeException(nameof(backendType),
                                                      $"{backendType.Name} is not a descendent of {nameof(LanguageBackend)}.");
            }

            BackendType = backendType;

            // Calculate name (strip 'Backend' if present).
            Name = backendType.Name;
            if (Name.EndsWith("Backend", StringComparison.InvariantCultureIgnoreCase))
            {
                Name = Name.Substring(0, Name.Length - 7);
            }

            GraphicsBackend = graphicsBackend;

            ToolFeatures features = ToolFeatures.None;

            if (createBackend != null)
            {
                _createBackend = createBackend;
                features      |= ToolFeatures.Transpilation;
            }

            if (compileFunction != null)
            {
                _compileFunction = compileFunction;

                features |= ToolFeatures.Compilation;
            }

            // Don't allow creation of graphics devices on CI Servers.
            bool onCiServer = Environment.GetEnvironmentVariable("CI")?.ToLowerInvariant() == "true";

            if (!onCiServer &&
                createHeadless != null &&
                GraphicsDevice.IsBackendSupported(graphicsBackend))
            {
                try
                {
                    // Try to create a headless graphics device
                    using (createHeadless()) { }
                    _createHeadless = createHeadless;
                    features       |= ToolFeatures.HeadlessGraphicsDevice;
                }
                catch
                {
                }
            }

            // TODO For future expansion, will need to review signature of function.
            if (!onCiServer &&
                createWindowed != null &&
                GraphicsDevice.IsBackendSupported(graphicsBackend))
            {
                try
                {
                    // Try to create a headless graphics device
                    using (createWindowed()) { }
                    _createWindowed = createWindowed;
                    features       |= ToolFeatures.WindowedGraphicsDevice;
                }
                catch
                {
                }
            }

            Features = features;

            // Add to lookup dictionaries.
            _toolChainsByGraphicsBackend.Add(graphicsBackend, this);
            _toolChainsByBackendType.Add(backendType, this);
        }
예제 #6
0
        internal static TResult CompileWithRetry <TResult>(
            ImmutableArray <MetadataBlock> metadataBlocks,
            DiagnosticFormatter formatter,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage)
        {
            TResult compileResult;

            PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null;
            bool tryAgain;
            var  linqLibrary = EvaluationContextBase.SystemLinqIdentity;

            do
            {
                errorMessage = null;

                var context     = createContext(metadataBlocks, useReferencedModulesOnly: false);
                var diagnostics = DiagnosticBag.GetInstance();
                compileResult = compile(context, diagnostics);
                tryAgain      = false;
                if (diagnostics.HasAnyErrors())
                {
                    bool useReferencedModulesOnly;
                    ImmutableArray <AssemblyIdentity> missingAssemblyIdentities;
                    errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities(
                        diagnostics,
                        formatter,
                        preferredUICulture: null,
                        linqLibrary: linqLibrary,
                        useReferencedModulesOnly: out useReferencedModulesOnly,
                        missingAssemblyIdentities: out missingAssemblyIdentities);
                    // If there were LINQ-related errors, we'll initially add System.Linq (set above).
                    // If that doesn't work, we'll fall back to System.Core for subsequent retries.
                    linqLibrary = EvaluationContextBase.SystemCoreIdentity;

                    // Can we remove the `useReferencedModulesOnly` attempt if we're only using
                    // modules reachable from the current module? In short, can we avoid retrying?
                    if (useReferencedModulesOnly)
                    {
                        Debug.Assert(missingAssemblyIdentities.IsEmpty);
                        var otherContext     = createContext(metadataBlocks, useReferencedModulesOnly: true);
                        var otherDiagnostics = DiagnosticBag.GetInstance();
                        var otherResult      = compile(otherContext, otherDiagnostics);
                        if (!otherDiagnostics.HasAnyErrors())
                        {
                            errorMessage  = null;
                            compileResult = otherResult;
                        }
                        otherDiagnostics.Free();
                    }
                    else
                    {
                        if (!missingAssemblyIdentities.IsEmpty)
                        {
                            if (assembliesLoadedInRetryLoop == null)
                            {
                                assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance();
                            }
                            // If any identities failed to add (they were already in the list), then don't retry.
                            if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities))
                            {
                                tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks);
                            }
                        }
                    }
                }
                diagnostics.Free();
            } while (tryAgain);
            assembliesLoadedInRetryLoop?.Free();

            return(compileResult);
        }