Exemple #1
0
        private static bool ReflectionEmitInternal(
            Compilation compilation,
            string expectedOutput,
            bool peImageRequested,
            out ImmutableArray <byte> peImage,
            bool refEmitSupported,
            bool fallback,
            bool collectEmittedAssembly,
            bool peVerify,
            TempRoot tempRoot)
        {
            peImage = default(ImmutableArray <byte>);

            var success = false;
            var compilationDependencies = new List <ModuleData>();
            var diagnostics             = new DiagnosticBag();

            HostedRuntimeEnvironment.EmitReferences(compilation, compilationDependencies, diagnostics);

            // allow warnings
            if (diagnostics.HasAnyErrors())
            {
                // this will throw if there are errors
                diagnostics.Verify();
            }

            bool doExecute = expectedOutput != null;

            string fileName;
            string fileNameExt;
            string fileDir;

            TempFile outputFile;
            AssemblyBuilderAccess access;

            if (peImageRequested)
            {
                access = doExecute ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Save;

                // Until HostedExecutionEnvironment supports ref emit, we need to generate a unique temp file.
                // Otherwise, the file will be held open the next time we Emit this same compilation (done in CompileAndVerify).
                outputFile = tempRoot.CreateFile("RefEmit_", ".dll");

                fileNameExt = Path.GetFileName(outputFile.Path);
                fileName    = Path.GetFileNameWithoutExtension(fileNameExt);
                fileDir     = Path.GetDirectoryName(outputFile.Path);
            }
            else
            {
                outputFile = null;

                fileName    = CommonTestBase.GetUniqueName();
                fileNameExt = fileName + ".dll";
                fileDir     = null;

                access = collectEmittedAssembly ? AssemblyBuilderAccess.RunAndCollect : AssemblyBuilderAccess.Run;
            }

            var             assemblyName = new AssemblyIdentity(fileName).ToAssemblyName();
            AssemblyBuilder abuilder     = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, access, fileDir);
            ModuleBuilder   mbuilder     = abuilder.DefineDynamicModule("Module", fileNameExt, emitSymbolInfo: false);

            using (var assemblyManager = new RuntimeAssemblyManager())
            {
                assemblyManager.AddModuleData(compilationDependencies);

                DiagnosticBag emitDiagnostics = DiagnosticBag.GetInstance();
                MethodInfo    entryPoint;

                byte[] compiledAssemblyImage;

                success = compilation.Emit(
                    moduleBuilder: mbuilder,
                    assemblyLoader: new AssemblyLoader(assemblyManager),
                    assemblySymbolMapper: null,
                    recoverOnError: !refEmitSupported && fallback,
                    diagnostics: emitDiagnostics,
                    cancellationToken: default(CancellationToken),
                    entryPoint: out entryPoint,
                    compiledAssemblyImage: out compiledAssemblyImage
                    );

                emitDiagnostics.Free();

                if (success && peImageRequested)
                {
                    if (fallback)
                    {
                        peImage = compiledAssemblyImage.AsImmutableOrNull();
                    }
                    else
                    {
                        abuilder.Save(fileNameExt);
                        peImage = CommonTestBase.ReadFromFile(outputFile.Path);
                    }
                }

                if (refEmitSupported)
                {
                    Assert.True(success, "Expected Ref.Emit success");
                    Assert.Null(compiledAssemblyImage);
                }
                else if (fallback)
                {
                    Assert.True(success, "Expected fallback to CCI");
                    Assert.NotNull(compiledAssemblyImage);
                }
                else
                {
                    Assert.False(success, "Expected emit failure but it succeeded");
                    Assert.Null(compiledAssemblyImage);
                }

                if (success)
                {
                    if (peVerify)
                    {
                        Assert.False(peImage.IsDefault);

                        // Saving AssemblyBuilder to disk changes its manifest module MVID.
                        Guid mvid;
                        using (var metadata = ModuleMetadata.CreateFromImage(peImage))
                        {
                            mvid = metadata.GetModuleVersionId();
                        }

                        assemblyManager.AddMainModuleMvid(mvid);
#if !(ARM)
                        Assert.Equal(String.Empty, CLRHelpers.PeVerify(peImage).Concat());
#endif
                    }

                    if (doExecute)
                    {
                        Assert.NotNull(entryPoint);
                        assemblyManager.AddMainModuleMvid(entryPoint.Module.ModuleVersionId);

                        Action main = GetEntryPointAction(entryPoint);
                        ConsoleOutput.AssertEqual(main, expectedOutput, "");
                    }
                }

                return(success);
            }
        }
 public AssemblyLoader(RuntimeAssemblyManager manager)
 {
     _manager = manager;
 }