using System.Reflection;
using System.IO;
using System.Runtime.CompilerServices;
+using System.Reflection.Emit;
+using System.Security;
namespace Mono.CSharp
{
- public class ReflectionImporter : MetadataImporter
+#if STATIC
+ public class ReflectionImporter
{
- public ReflectionImporter (BuildinTypes buildin)
- : base ()
+ public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public TypeSpec ImportType (Type type)
+ {
+ throw new NotSupportedException ();
+ }
+ }
+#else
+ public sealed class ReflectionImporter : MetadataImporter
+ {
+ public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin)
+ : base (module)
+ {
+ Initialize (builtin);
+ }
+
+ public override void AddCompiledType (TypeBuilder builder, TypeSpec spec)
{
- Initialize (buildin);
}
protected override MemberKind DetermineKindFromBaseType (Type baseType)
return MemberKind.Class;
}
- protected override bool HasVolatileModifier (FieldInfo field)
+ protected override bool HasVolatileModifier (Type[] modifiers)
{
- var reqs = field.GetRequiredCustomModifiers ();
- if (reqs.Length > 0) {
- foreach (var t in reqs) {
- if (t == typeof (IsVolatile))
- return true;
- }
+ foreach (var t in modifiers) {
+ if (t == typeof (IsVolatile))
+ return true;
}
return false;
}
- void Initialize (BuildinTypes buildin)
+ public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
+ {
+ // It can be used more than once when importing same assembly
+ // into 2 or more global aliases
+ var definition = GetAssemblyDefinition (assembly);
+
+ //
+ // This part tries to simulate loading of top-level
+ // types only, any missing dependencies are ignores here.
+ // Full error report is reported later when the type is
+ // actually used
+ //
+ Type[] all_types;
+ try {
+ all_types = assembly.GetTypes ();
+ } catch (ReflectionTypeLoadException e) {
+ all_types = e.Types;
+ }
+
+ ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod);
+ }
+
+ public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
+ {
+ var module_definition = new ImportedModuleDefinition (module);
+ module_definition.ReadAttributes ();
+
+ Type[] all_types;
+ try {
+ all_types = module.GetTypes ();
+ } catch (ReflectionTypeLoadException e) {
+ all_types = e.Types;
+ }
+
+ ImportTypes (all_types, targetNamespace, false);
+
+ return module_definition;
+ }
+
+ void Initialize (BuiltinTypes builtin)
{
//
// Setup mapping for build-in types to avoid duplication of their definition
//
- buildin_types.Add (typeof (object), buildin.Object);
- buildin_types.Add (typeof (System.ValueType), buildin.ValueType);
- buildin_types.Add (typeof (System.Attribute), buildin.Attribute);
-
- buildin_types.Add (typeof (int), buildin.Int);
- buildin_types.Add (typeof (long), buildin.Long);
- buildin_types.Add (typeof (uint), buildin.UInt);
- buildin_types.Add (typeof (ulong), buildin.ULong);
- buildin_types.Add (typeof (byte), buildin.Byte);
- buildin_types.Add (typeof (sbyte), buildin.SByte);
- buildin_types.Add (typeof (short), buildin.Short);
- buildin_types.Add (typeof (ushort), buildin.UShort);
-
- buildin_types.Add (typeof (System.Collections.IEnumerator), buildin.IEnumerator);
- buildin_types.Add (typeof (System.Collections.IEnumerable), buildin.IEnumerable);
- buildin_types.Add (typeof (System.IDisposable), buildin.IDisposable);
-
- buildin_types.Add (typeof (char), buildin.Char);
- buildin_types.Add (typeof (string), buildin.String);
- buildin_types.Add (typeof (float), buildin.Float);
- buildin_types.Add (typeof (double), buildin.Double);
- buildin_types.Add (typeof (decimal), buildin.Decimal);
- buildin_types.Add (typeof (bool), buildin.Bool);
- buildin_types.Add (typeof (System.IntPtr), buildin.IntPtr);
- buildin_types.Add (typeof (System.UIntPtr), buildin.UIntPtr);
-
- buildin_types.Add (typeof (System.MulticastDelegate), buildin.MulticastDelegate);
- buildin_types.Add (typeof (System.Delegate), buildin.Delegate);
- buildin_types.Add (typeof (System.Enum), buildin.Enum);
- buildin_types.Add (typeof (System.Array), buildin.Array);
- buildin_types.Add (typeof (void), buildin.Void);
- buildin_types.Add (typeof (System.Type), buildin.Type);
- buildin_types.Add (typeof (System.Exception), buildin.Exception);
- buildin_types.Add (typeof (System.RuntimeFieldHandle), buildin.RuntimeFieldHandle);
- buildin_types.Add (typeof (System.RuntimeTypeHandle), buildin.RuntimeTypeHandle);
+ compiled_types.Add (typeof (object), builtin.Object);
+ compiled_types.Add (typeof (System.ValueType), builtin.ValueType);
+ compiled_types.Add (typeof (System.Attribute), builtin.Attribute);
+
+ compiled_types.Add (typeof (int), builtin.Int);
+ compiled_types.Add (typeof (long), builtin.Long);
+ compiled_types.Add (typeof (uint), builtin.UInt);
+ compiled_types.Add (typeof (ulong), builtin.ULong);
+ compiled_types.Add (typeof (byte), builtin.Byte);
+ compiled_types.Add (typeof (sbyte), builtin.SByte);
+ compiled_types.Add (typeof (short), builtin.Short);
+ compiled_types.Add (typeof (ushort), builtin.UShort);
+
+ compiled_types.Add (typeof (System.Collections.IEnumerator), builtin.IEnumerator);
+ compiled_types.Add (typeof (System.Collections.IEnumerable), builtin.IEnumerable);
+ compiled_types.Add (typeof (System.IDisposable), builtin.IDisposable);
+
+ compiled_types.Add (typeof (char), builtin.Char);
+ compiled_types.Add (typeof (string), builtin.String);
+ compiled_types.Add (typeof (float), builtin.Float);
+ compiled_types.Add (typeof (double), builtin.Double);
+ compiled_types.Add (typeof (decimal), builtin.Decimal);
+ compiled_types.Add (typeof (bool), builtin.Bool);
+ compiled_types.Add (typeof (System.IntPtr), builtin.IntPtr);
+ compiled_types.Add (typeof (System.UIntPtr), builtin.UIntPtr);
+
+ compiled_types.Add (typeof (System.MulticastDelegate), builtin.MulticastDelegate);
+ compiled_types.Add (typeof (System.Delegate), builtin.Delegate);
+ compiled_types.Add (typeof (System.Enum), builtin.Enum);
+ compiled_types.Add (typeof (System.Array), builtin.Array);
+ compiled_types.Add (typeof (void), builtin.Void);
+ compiled_types.Add (typeof (System.Type), builtin.Type);
+ compiled_types.Add (typeof (System.Exception), builtin.Exception);
+ compiled_types.Add (typeof (System.RuntimeFieldHandle), builtin.RuntimeFieldHandle);
+ compiled_types.Add (typeof (System.RuntimeTypeHandle), builtin.RuntimeTypeHandle);
}
}
- public class DynamicLoader
+ [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Explicit)]
+ struct SingleConverter
{
- readonly ReflectionImporter importer;
- readonly Report reporter;
+ [System.Runtime.InteropServices.FieldOffset (0)]
+ int i;
+ [System.Runtime.InteropServices.FieldOffset (0)]
+ float f;
- // A list of default references, they can fail to load as the user didn't not specify them
- string[] default_references;
+ public static int SingleToInt32Bits (float v)
+ {
+ SingleConverter c = new SingleConverter ();
+ c.f = v;
+ return c.i;
+ }
+ }
- List<string> paths;
+#endif
- public DynamicLoader (ReflectionImporter importer, CompilerContext compiler)
+ public class AssemblyDefinitionDynamic : AssemblyDefinition
+ {
+ //
+ // In-memory only assembly container
+ //
+ public AssemblyDefinitionDynamic (ModuleContainer module, string name)
+ : base (module, name)
{
- this.importer = importer;
- this.reporter = compiler.Report;
+ }
- default_references = GetDefaultReferences ();
+ //
+ // Assembly container with file output
+ //
+ public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName)
+ : base (module, name, fileName)
+ {
+ }
- paths = new List<string> ();
- paths.AddRange (RootContext.ReferencesLookupPaths);
- paths.Add (GetSystemDir ());
- paths.Add (Directory.GetCurrentDirectory ());
+ public Module IncludeModule (string moduleFile)
+ {
+ return builder_extra.AddModule (moduleFile);
}
- public ReflectionImporter Importer {
- get {
- return importer;
+#if !STATIC
+ public override ModuleBuilder CreateModuleBuilder ()
+ {
+ if (file_name == null)
+ return Builder.DefineDynamicModule (Name, false);
+
+ return base.CreateModuleBuilder ();
+ }
+#endif
+ //
+ // Initializes the code generator
+ //
+ public bool Create (AppDomain domain, AssemblyBuilderAccess access)
+ {
+#if STATIC
+ throw new NotSupportedException ();
+#else
+ ResolveAssemblySecurityAttributes ();
+ var an = CreateAssemblyName ();
+
+ Builder = file_name == null ?
+ domain.DefineDynamicAssembly (an, access) :
+ domain.DefineDynamicAssembly (an, access, Dirname (file_name));
+
+ module.Create (this, CreateModuleBuilder ());
+ builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler);
+ return true;
+#endif
+ }
+
+ static string Dirname (string name)
+ {
+ int pos = name.LastIndexOf ('/');
+
+ if (pos != -1)
+ return name.Substring (0, pos);
+
+ pos = name.LastIndexOf ('\\');
+ if (pos != -1)
+ return name.Substring (0, pos);
+
+ return ".";
+ }
+
+#if !STATIC
+ protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
+ {
+ try {
+ var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ var set_module_only = module_only.GetSetMethod (true);
+
+ set_module_only.Invoke (Builder, new object[] { true });
+ } catch {
+ base.SaveModule (pekind, machine);
}
+
+ Builder.Save (file_name, pekind, machine);
}
+#endif
+ }
- void Error6 (string name, string log)
+ //
+ // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
+ // compiler
+ //
+ class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension
+ {
+ static MethodInfo adder_method;
+ static MethodInfo add_permission;
+ static MethodInfo add_type_forwarder;
+ static MethodInfo win32_icon_define;
+ static FieldInfo assembly_version;
+ static FieldInfo assembly_algorithm;
+ static FieldInfo assembly_culture;
+ static FieldInfo assembly_flags;
+
+ AssemblyBuilder builder;
+
+ public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx)
+ : base (ctx)
{
- if (log != null && log.Length > 0)
- reporter.ExtraInformation (Location.Null, "Log:\n" + log + "\n(log related to previous ");
- reporter.Error (6, "cannot find metadata file `{0}'", name);
+ this.builder = ab;
}
- void Error9 (string type, string filename, string log)
+ public override Module AddModule (string module)
{
- if (log != null && log.Length > 0)
- reporter.ExtraInformation (Location.Null, "Log:\n" + log + "\n(log related to previous ");
- reporter.Error (9, "file `{0}' has invalid `{1}' metadata", filename, type);
+ try {
+ if (adder_method == null)
+ adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic);
+
+ return (Module) adder_method.Invoke (builder, new object[] { module });
+ } catch {
+ return base.AddModule (module);
+ }
}
- void BadAssembly (string filename, string log)
+ public override void AddPermissionRequests (PermissionSet[] permissions)
{
-/*
- MethodInfo adder_method = null; // AssemblyDefinition.AddModule_Method;
+ try {
+ if (add_permission == null)
+ add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
- if (adder_method != null) {
- AssemblyName an = new AssemblyName ();
- an.Name = ".temp";
- var ab = AppDomain.CurrentDomain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Run);
- try {
- object m = null;
- try {
- m = adder_method.Invoke (ab, new object [] { filename });
- } catch (TargetInvocationException ex) {
- throw ex.InnerException;
- }
+ add_permission.Invoke (builder, permissions);
+ } catch {
+ base.AddPermissionRequests (permissions);
+ }
+ }
- if (m != null) {
- Report.Error (1509, "Referenced file `{0}' is not an assembly. Consider using `-addmodule' option instead",
- Path.GetFileName (filename));
- return;
- }
- } catch (FileNotFoundException) {
- // did the file get deleted during compilation? who cares? swallow the exception
- } catch (BadImageFormatException) {
- // swallow exception
- } catch (FileLoadException) {
- // swallow exception
+ public override void AddTypeForwarder (TypeSpec type, Location loc)
+ {
+ try {
+ if (add_type_forwarder == null) {
+ add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance);
}
+
+ add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () });
+ } catch {
+ base.AddTypeForwarder (type, loc);
}
-*/
- Error9 ("assembly", filename, log);
}
- //
- // Returns the directory where the system assemblies are installed
- //
- static string GetSystemDir ()
+ public override void DefineWin32IconResource (string fileName)
{
- return Path.GetDirectoryName (typeof (object).Assembly.Location);
+ try {
+ if (win32_icon_define == null)
+ win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic);
+
+ win32_icon_define.Invoke (builder, new object[] { fileName });
+ } catch {
+ base.DefineWin32IconResource (fileName);
+ }
}
- string[] GetDefaultReferences ()
+ public override void SetAlgorithmId (uint value, Location loc)
{
- if (!RootContext.LoadDefaultReferences)
- return new string [0];
+ try {
+ if (assembly_algorithm == null)
+ assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
+ assembly_algorithm.SetValue (builder, value);
+ } catch {
+ base.SetAlgorithmId (value, loc);
+ }
+ }
+
+ public override void SetCulture (string culture, Location loc)
+ {
+ try {
+ if (assembly_culture == null)
+ assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
+
+ assembly_culture.SetValue (builder, culture);
+ } catch {
+ base.SetCulture (culture, loc);
+ }
+ }
+
+ public override void SetFlags (uint flags, Location loc)
+ {
+ try {
+ if (assembly_flags == null)
+ assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
+
+ assembly_flags.SetValue (builder, flags);
+ } catch {
+ base.SetFlags (flags, loc);
+ }
+ }
+
+ public override void SetVersion (Version version, Location loc)
+ {
+ try {
+ if (assembly_version == null)
+ assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
+
+ assembly_version.SetValue (builder, version.ToString (4));
+ } catch {
+ base.SetVersion (version, loc);
+ }
+ }
+ }
+
+ //
+ // Reflection based references loader
+ //
+ class DynamicLoader : AssemblyReferencesLoader<Assembly>
+ {
+ readonly ReflectionImporter importer;
+
+ public DynamicLoader (ReflectionImporter importer, CompilerContext compiler)
+ : base (compiler)
+ {
+ paths.Add (GetSystemDir ());
+
+ this.importer = importer;
+ }
+
+ public ReflectionImporter Importer {
+ get {
+ return importer;
+ }
+ }
+
+ protected override string[] GetDefaultReferences ()
+ {
//
// For now the "default config" is harcoded into the compiler
// we can move this outside later
default_references.Add ("System.Windows.Browser");
#endif
- if (RootContext.Version > LanguageVersion.ISO_2)
+ if (compiler.Settings.Version > LanguageVersion.ISO_2)
default_references.Add ("System.Core");
- if (RootContext.Version > LanguageVersion.V_3)
+ if (compiler.Settings.Version > LanguageVersion.V_3)
default_references.Add ("Microsoft.CSharp");
return default_references.ToArray ();
}
- public Assembly LoadAssemblyFile (string assembly, bool soft)
+ //
+ // Returns the directory where the system assemblies are installed
+ //
+ static string GetSystemDir ()
+ {
+ return Path.GetDirectoryName (typeof (object).Assembly.Location);
+ }
+
+ public override bool HasObjectType (Assembly assembly)
+ {
+ return assembly.GetType (compiler.BuiltinTypes.Object.FullName) != null;
+ }
+
+ public override Assembly LoadAssemblyFile (string assembly, bool isImplicitReference)
{
Assembly a = null;
- string total_log = "";
try {
try {
a = Assembly.Load (ass);
}
} catch (FileNotFoundException) {
- bool err = !soft;
+ bool err = !isImplicitReference;
foreach (string dir in paths) {
string full_path = Path.Combine (dir, assembly);
if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
a = Assembly.LoadFrom (full_path);
err = false;
break;
- } catch (FileNotFoundException ff) {
- if (soft)
- return a;
- total_log += ff.FusionLog;
+ } catch (FileNotFoundException) {
}
}
+
if (err) {
- Error6 (assembly, total_log);
+ Error_FileNotFound (assembly);
return a;
}
}
- } catch (BadImageFormatException f) {
- // .NET 2.0 throws this if we try to load a module without an assembly manifest ...
- BadAssembly (f.FileName, f.FusionLog);
- } catch (FileLoadException f) {
- // ... while .NET 1.1 throws this
- BadAssembly (f.FileName, f.FusionLog);
+ } catch (BadImageFormatException) {
+ Error_FileCorrupted (assembly);
}
return a;
}
- void LoadModule (AssemblyDefinition assembly, string module)
+ Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module)
{
string total_log = "";
try {
try {
- assembly.AddModule (module);
+ return assembly.IncludeModule (module);
} catch (FileNotFoundException) {
bool err = true;
foreach (string dir in paths) {
full_path += ".netmodule";
try {
- assembly.AddModule (full_path);
- err = false;
- break;
+ return assembly.IncludeModule (full_path);
} catch (FileNotFoundException ff) {
total_log += ff.FusionLog;
}
}
if (err) {
- Error6 (module, total_log);
- return;
+ Error_FileNotFound (module);
+ return null;
}
}
- } catch (BadImageFormatException f) {
- Error9 ("module", f.FileName, f.FusionLog);
- } catch (FileLoadException f) {
- Error9 ("module", f.FileName, f.FusionLog);
+ } catch (BadImageFormatException) {
+ Error_FileCorrupted (module);
}
+
+ return null;
}
- /// <summary>
- /// Loads all assemblies referenced on the command line
- /// </summary>
- public void LoadReferences (ModuleContainer module)
+ public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace)
{
- Assembly a;
- var loaded = new List<Tuple<RootNamespace, Assembly>> ();
-
- //
- // Load Core Library for default compilation
- //
- if (RootContext.StdLib) {
- a = LoadAssemblyFile ("mscorlib", false);
- if (a != null)
- loaded.Add (Tuple.Create (module.GlobalRootNamespace, a));
- }
-
- foreach (string r in default_references) {
- a = LoadAssemblyFile (r, true);
- if (a != null)
- loaded.Add (Tuple.Create (module.GlobalRootNamespace, a));
- }
-
- foreach (string r in RootContext.AssemblyReferences) {
- a = LoadAssemblyFile (r, false);
- if (a == null)
- continue;
-
- var key = Tuple.Create (module.GlobalRootNamespace, a);
- if (loaded.Contains (key))
- continue;
-
- loaded.Add (key);
- }
-
- foreach (var entry in RootContext.AssemblyReferencesAliases) {
- a = LoadAssemblyFile (entry.Item2, false);
- if (a == null)
- continue;
-
- var key = Tuple.Create (module.CreateRootNamespace (entry.Item1), a);
- if (loaded.Contains (key))
+ foreach (var moduleName in compiler.Settings.Modules) {
+ var m = LoadModuleFile (assembly, moduleName);
+ if (m == null)
continue;
- loaded.Add (key);
- }
-
- foreach (var entry in loaded) {
- importer.ImportAssembly (entry.Item2, entry.Item1);
+ var md = importer.ImportModule (m, targetNamespace);
+ assembly.AddModule (md);
}
}
- public void LoadModules (AssemblyDefinition assembly)
+ public override void LoadReferences (ModuleContainer module)
{
- if (RootContext.Modules.Count == 0)
+ Assembly corlib;
+ List<Tuple<RootNamespace, Assembly>> loaded;
+ base.LoadReferencesCore (module, out corlib, out loaded);
+
+ if (corlib == null)
return;
- foreach (var module in RootContext.Modules) {
- LoadModule (assembly, module);
+ importer.ImportAssembly (corlib, module.GlobalRootNamespace);
+ foreach (var entry in loaded) {
+ importer.ImportAssembly (entry.Item2, entry.Item1);
}
}
}