1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Collections.Generic;
18 using System.Dynamic.Utils;
20 using System.Reflection;
21 using System.Reflection.Emit;
22 using System.Security;
24 using System.Threading;
27 namespace Microsoft.Scripting.Ast.Compiler {
29 namespace System.Linq.Expressions.Compiler {
31 internal sealed class AssemblyGen {
32 private static AssemblyGen _assembly;
34 // Testing options. Only ever set in CLR2 build
35 // configurations, see SetSaveAssemblies
37 private static string _saveAssembliesPath;
38 private static bool _saveAssemblies;
41 private readonly AssemblyBuilder _myAssembly;
42 private readonly ModuleBuilder _myModule;
44 #if CLR2 && !SILVERLIGHT
45 private readonly string _outFileName; // can be null iff !SaveAndReloadAssemblies
46 private readonly string _outDir; // null means the current directory
50 private static AssemblyGen Assembly {
52 if (_assembly == null) {
53 Interlocked.CompareExchange(ref _assembly, new AssemblyGen(), null);
59 private AssemblyGen() {
60 var name = new AssemblyName("Snippets");
62 #if SILVERLIGHT // AssemblyBuilderAccess.RunAndSave, Environment.CurrentDirectory
63 _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
64 _myModule = _myAssembly.DefineDynamicModule(name.Name, false);
67 // mark the assembly transparent so that it works in partial trust:
68 var attributes = new[] {
69 new CustomAttributeBuilder(typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes), new object[0])
73 if (_saveAssemblies) {
74 string outDir = _saveAssembliesPath ?? Directory.GetCurrentDirectory();
76 outDir = Path.GetFullPath(outDir);
78 throw Error.InvalidOutputDir();
81 Path.Combine(outDir, name.Name + ".dll");
82 } catch (ArgumentException) {
83 throw Error.InvalidAsmNameOrExtension();
86 _outFileName = name.Name + ".dll";
88 _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, outDir,
89 null, null, null, null, false, attributes);
91 _myModule = _myAssembly.DefineDynamicModule(name.Name, _outFileName, false);
95 _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run, attributes);
96 _myModule = _myAssembly.DefineDynamicModule(name.Name, false);
99 _myAssembly.DefineVersionInfoResource();
103 private TypeBuilder DefineType(string name, Type parent, TypeAttributes attr) {
104 ContractUtils.RequiresNotNull(name, "name");
105 ContractUtils.RequiresNotNull(parent, "parent");
107 StringBuilder sb = new StringBuilder(name);
109 int index = Interlocked.Increment(ref _index);
113 // There is a bug in Reflection.Emit that leads to
114 // Unhandled Exception: System.Runtime.InteropServices.COMException (0x80131130): Record not found on lookup.
115 // if there is any of the characters []*&+,\ in the type name and a method defined on the type is called.
116 sb.Replace('+', '_').Replace('[', '_').Replace(']', '_').Replace('*', '_').Replace('&', '_').Replace(',', '_').Replace('\\', '_');
118 name = sb.ToString();
120 return _myModule.DefineType(name, attr, parent);
123 internal static TypeBuilder DefineDelegateType(string name) {
124 return Assembly.DefineType(
126 typeof(MulticastDelegate),
127 TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass
132 //Return the location of the saved assembly file.
133 //The file location is used by PE verification in Microsoft.Scripting.
134 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
135 internal string SaveAssembly() {
136 #if !SILVERLIGHT // AssemblyBuilder.Save
137 _myAssembly.Save(_outFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
138 return Path.Combine(_outDir, _outFileName);
144 // NOTE: this method is called through reflection from Microsoft.Scripting
145 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
146 internal static void SetSaveAssemblies(bool enable, string directory) {
147 _saveAssemblies = enable;
148 _saveAssembliesPath = directory;
151 // NOTE: this method is called through reflection from Microsoft.Scripting
152 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
153 internal static string[] SaveAssembliesToDisk() {
154 if (!_saveAssemblies) {
155 return new string[0];
158 var assemlyLocations = new List<string>();
160 // first save all assemblies to disk:
161 if (_assembly != null) {
162 string assemblyLocation = _assembly.SaveAssembly();
163 if (assemblyLocation != null) {
164 assemlyLocations.Add(assemblyLocation);
169 return assemlyLocations.ToArray();
174 internal static class SymbolGuids {
175 internal static readonly Guid DocumentType_Text =
176 new Guid(0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0, 0, 0xf8, 8, 0x49, 0xbd);