CompiledMethod CompileBlock(Class host, Undo undo, Report Report) { #if STATIC throw new NotSupportedException(); #else string current_debug_name = "eval-" + count + ".dll"; ++count; AssemblyDefinitionDynamic assembly; AssemblyBuilderAccess access; if (Environment.GetEnvironmentVariable("SAVE") != null) { access = AssemblyBuilderAccess.RunAndSave; assembly = new AssemblyDefinitionDynamic(module, current_debug_name, current_debug_name); assembly.Importer = importer; } else { #if !NET_2_0 access = AssemblyBuilderAccess.RunAndCollect; #else access = AssemblyBuilderAccess.Run; #endif assembly = new AssemblyDefinitionDynamic(module, current_debug_name); } assembly.Create(AppDomain.CurrentDomain, access); Method expression_method; if (host != null) { var base_class_imported = importer.ImportType(prev_host ?? base_class); var baseclass_list = new List <FullNamedExpression> (1) { new TypeExpression(base_class_imported, host.Location) }; host.SetBaseTypes(baseclass_list); expression_method = (Method)host.Members[0]; if ((expression_method.ModFlags & Modifiers.ASYNC) != 0) { // // Host method is async. When WaitOnTask is set we wrap it with wait // // void AsyncWait (ref object $retval) { // $retval = Host(); // ((Task)$retval).Wait(); // When WaitOnTask is set // } // var p = new ParametersCompiled( new Parameter(new TypeExpression(module.Compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null) ); var method = new Method(host, new TypeExpression(module.Compiler.BuiltinTypes.Void, Location.Null), Modifiers.PUBLIC | Modifiers.STATIC, new MemberName("AsyncWait"), p, null); method.Block = new ToplevelBlock(method.Compiler, p, Location.Null); method.Block.AddStatement(new StatementExpression(new SimpleAssign( new SimpleName(p [0].Name, Location.Null), new Invocation(new SimpleName(expression_method.MemberName.Name, Location.Null), new Arguments(0)), Location.Null), Location.Null)); if (WaitOnTask) { var task = new Cast(expression_method.TypeExpression, new SimpleName(p [0].Name, Location.Null), Location.Null); method.Block.AddStatement(new StatementExpression(new Invocation( new MemberAccess(task, "Wait", Location.Null), new Arguments(0)), Location.Null)); } host.AddMember(method); expression_method = method; } host.CreateContainer(); host.DefineContainer(); host.Define(); } else { expression_method = null; } module.CreateContainer(); // Disable module and source file re-definition checks module.EnableRedefinition(); source_file.EnableRedefinition(); module.Define(); if (Report.Errors != 0) { if (undo != null) { undo.ExecuteUndo(); } return(null); } if (host != null) { host.PrepareEmit(); host.EmitContainer(); } module.EmitContainer(); if (Report.Errors != 0) { if (undo != null) { undo.ExecuteUndo(); } return(null); } module.CloseContainerEarlyForReflectionEmit(); module.CloseContainer(); if (host != null) { host.CloseContainer(); } if (access == AssemblyBuilderAccess.RunAndSave) { assembly.Save(); } if (host == null) { return(null); } // // Unlike Mono, .NET requires that the MethodInfo is fetched, it cant // work from MethodBuilders. Retarded, I know. // var tt = assembly.Builder.GetType(host.TypeBuilder.Name); prev_host = tt; var mi = tt.GetMethod(expression_method.MemberName.Name); // // We need to then go from FieldBuilder to FieldInfo // or reflection gets confused (it basically gets confused, and variables override each // other). // foreach (var member in host.Members) { var field = member as Field; if (field == null) { continue; } var fi = tt.GetField(field.Name); Tuple <FieldSpec, FieldInfo> old; // If a previous value was set, nullify it, so that we do // not leak memory if (fields.TryGetValue(field.Name, out old)) { if (old.Item1.MemberType.IsStruct) { // // TODO: Clear fields for structs // } else { try { old.Item2.SetValue(null, null); } catch { } } } Console.WriteLine("replacing fieldspec for " + field.Name); fields[field.Name] = Tuple.Create(field.Spec, fi); } return((CompiledMethod)System.Delegate.CreateDelegate(typeof(CompiledMethod), mi)); #endif }
public virtual void Emit() { if (Compiler.Settings.Target == Target.Module) { module_target_attrs = new AssemblyAttributesPlaceholder(module, name); module_target_attrs.CreateContainer(); module_target_attrs.DefineContainer(); module_target_attrs.Define(); module.AddCompilerGeneratedClass(module_target_attrs); } else if (added_modules != null) { ReadModulesAssemblyAttributes(); } if (Compiler.Settings.GenerateDebugInfo) { symbol_writer = new MonoSymbolFile(); } module.EmitContainer(); if (module.HasExtensionMethod) { var pa = module.PredefinedAttributes.Extension; if (pa.IsDefined) { SetCustomAttribute(pa.Constructor, AttributeEncoder.Empty); } } if (!IsSatelliteAssembly) { if (!wrap_non_exception_throws_custom) { PredefinedAttribute pa = module.PredefinedAttributes.RuntimeCompatibility; if (pa.IsDefined && pa.ResolveBuilder()) { var prop = module.PredefinedMembers.RuntimeCompatibilityWrapNonExceptionThrows.Get(); if (prop != null) { AttributeEncoder encoder = new AttributeEncoder(); encoder.EncodeNamedPropertyArgument(prop, new BoolLiteral(Compiler.BuiltinTypes, true, Location.Null)); SetCustomAttribute(pa.Constructor, encoder.ToArray()); } } } if (declarative_security != null) { #if STATIC foreach (var entry in declarative_security) { Builder.__AddDeclarativeSecurity(entry); } #else throw new NotSupportedException("Assembly-level security"); #endif } } CheckReferencesPublicToken(); SetEntryPoint(); }
CompiledMethod CompileBlock(Class host, Undo undo, Report Report) { #if STATIC throw new NotSupportedException(); #else string current_debug_name = "eval-" + count + ".dll"; ++count; AssemblyDefinitionDynamic assembly; AssemblyBuilderAccess access; if (Environment.GetEnvironmentVariable("SAVE") != null) { access = AssemblyBuilderAccess.RunAndSave; assembly = new AssemblyDefinitionDynamic(module, current_debug_name, current_debug_name); assembly.Importer = importer; } else { #if NET_4_0 access = AssemblyBuilderAccess.RunAndCollect; #else access = AssemblyBuilderAccess.Run; #endif assembly = new AssemblyDefinitionDynamic(module, current_debug_name); } assembly.Create(AppDomain.CurrentDomain, access); Method expression_method; if (host != null) { var base_class_imported = importer.ImportType(base_class); var baseclass_list = new List <FullNamedExpression> (1) { new TypeExpression(base_class_imported, host.Location) }; host.AddBasesForPart(baseclass_list); host.CreateContainer(); host.DefineContainer(); host.Define(); expression_method = (Method)host.Members[0]; } else { expression_method = null; } module.CreateContainer(); // Disable module and source file re-definition checks module.EnableRedefinition(); source_file.EnableRedefinition(); module.Define(); if (Report.Errors != 0) { if (undo != null) { undo.ExecuteUndo(); } return(null); } if (host != null) { host.EmitContainer(); } module.EmitContainer(); if (Report.Errors != 0) { if (undo != null) { undo.ExecuteUndo(); } return(null); } module.CloseContainer(); if (host != null) { host.CloseContainer(); } if (access == AssemblyBuilderAccess.RunAndSave) { assembly.Save(); } if (host == null) { return(null); } // // Unlike Mono, .NET requires that the MethodInfo is fetched, it cant // work from MethodBuilders. Retarded, I know. // var tt = assembly.Builder.GetType(host.TypeBuilder.Name); var mi = tt.GetMethod(expression_method.MemberName.Name); // // We need to then go from FieldBuilder to FieldInfo // or reflection gets confused (it basically gets confused, and variables override each // other). // foreach (var member in host.Members) { var field = member as Field; if (field == null) { continue; } var fi = tt.GetField(field.Name); Tuple <FieldSpec, FieldInfo> old; // If a previous value was set, nullify it, so that we do // not leak memory if (fields.TryGetValue(field.Name, out old)) { if (old.Item1.MemberType.IsStruct) { // // TODO: Clear fields for structs // } else { try { old.Item2.SetValue(null, null); } catch { } } } fields[field.Name] = Tuple.Create(field.Spec, fi); } return((CompiledMethod)System.Delegate.CreateDelegate(typeof(CompiledMethod), mi)); #endif }