📄 codegen.cs
字号:
// public void EmitCapturedVariableInstance (LocalInfo li) { if (capture_context == null) throw new Exception ("Calling EmitCapturedContext when there is no capture_context"); capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod); } public void EmitParameter (string name) { capture_context.EmitParameter (this, name); } public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load) { capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load); } public void EmitAddressOfParameter (string name) { capture_context.EmitAddressOfParameter (this, name); } public Expression GetThis (Location loc) { This my_this; if (CurrentBlock != null) my_this = new This (CurrentBlock, loc); else my_this = new This (loc); if (!my_this.ResolveBase (this)) my_this = null; return my_this; } } public abstract class CommonAssemblyModulClass : Attributable { protected CommonAssemblyModulClass (): base (null) { } public void AddAttributes (ArrayList attrs) { if (OptAttributes == null) { OptAttributes = new Attributes (attrs); return; } OptAttributes.AddAttributes (attrs); } public virtual void Emit (TypeContainer tc) { if (OptAttributes == null) return; EmitContext ec = new EmitContext (tc, Mono.CSharp.Location.Null, null, null, 0, false); OptAttributes.Emit (ec, this); } protected Attribute ResolveAttribute (Type a_type) { if (OptAttributes == null) return null; // Ensure that we only have GlobalAttributes, since the Search below isn't safe with other types. if (!OptAttributes.CheckTargets (this)) return null; EmitContext temp_ec = new EmitContext (RootContext.Tree.Types, Mono.CSharp.Location.Null, null, null, 0, false); Attribute a = OptAttributes.Search (a_type, temp_ec); if (a != null) { a.Resolve (temp_ec); } return a; } } public class AssemblyClass : CommonAssemblyModulClass { // TODO: make it private and move all builder based methods here public AssemblyBuilder Builder; bool is_cls_compliant; bool wrap_non_exception_throws; public Attribute ClsCompliantAttribute; ListDictionary declarative_security; // Module is here just because of error messages static string[] attribute_targets = new string [] { "assembly", "module" }; public AssemblyClass (): base () { wrap_non_exception_throws = true; } public bool IsClsCompliant { get { return is_cls_compliant; } } public bool WrapNonExceptionThrows { get { return wrap_non_exception_throws; } } public override AttributeTargets AttributeTargets { get { return AttributeTargets.Assembly; } } public override bool IsClsCompliaceRequired(DeclSpace ds) { return is_cls_compliant; } public void Resolve () { ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type); if (ClsCompliantAttribute != null) { is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue (null); }#if NET_2_0 Attribute a = ResolveAttribute (TypeManager.runtime_compatibility_attr_type); if (a != null) { object val = a.GetPropertyValue ("WrapNonExceptionThrows"); if (val != null) wrap_non_exception_throws = (bool)val; }#endif } // fix bug #56621 private void SetPublicKey (AssemblyName an, byte[] strongNameBlob) { try { // check for possible ECMA key if (strongNameBlob.Length == 16) { // will be rejected if not "the" ECMA key an.SetPublicKey (strongNameBlob); } else { // take it, with or without, a private key RSA rsa = CryptoConvert.FromCapiKeyBlob (strongNameBlob); // and make sure we only feed the public part to Sys.Ref byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa); // AssemblyName.SetPublicKey requires an additional header byte[] publicKeyHeader = new byte [12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 }; byte[] encodedPublicKey = new byte [12 + publickey.Length]; Buffer.BlockCopy (publicKeyHeader, 0, encodedPublicKey, 0, 12); Buffer.BlockCopy (publickey, 0, encodedPublicKey, 12, publickey.Length); an.SetPublicKey (encodedPublicKey); } } catch (Exception) { Error_AssemblySigning ("The speficied file `" + RootContext.StrongNameKeyFile + "' is incorrectly encoded"); Environment.Exit (1); } } // TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way. public AssemblyName GetAssemblyName (string name, string output) { if (OptAttributes != null) { foreach (Attribute a in OptAttributes.Attrs) { // cannot rely on any resolve-based members before you call Resolve if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly") continue; // TODO: This code is buggy: comparing Attribute name without resolving is wrong. // However, this is invoked by CodeGen.Init, when none of the namespaces // are loaded yet. // TODO: Does not handle quoted attributes properly switch (a.Name) { case "AssemblyKeyFile": case "AssemblyKeyFileAttribute": case "System.Reflection.AssemblyKeyFileAttribute": if (RootContext.StrongNameKeyFile != null) { Report.SymbolRelatedToPreviousError (a.Location, a.Name); Report.Warning (1616, "Option `{0}' overrides attribute `{1}' given in a source file or added module", "keyfile", "System.Reflection.AssemblyKeyFileAttribute"); } else { string value = a.GetString (); if (value != String.Empty) RootContext.StrongNameKeyFile = value; } break; case "AssemblyKeyName": case "AssemblyKeyNameAttribute": case "System.Reflection.AssemblyKeyNameAttribute": if (RootContext.StrongNameKeyContainer != null) { Report.SymbolRelatedToPreviousError (a.Location, a.Name); Report.Warning (1616, "Option `{0}' overrides attribute `{1}' given in a source file or added module", "keycontainer", "System.Reflection.AssemblyKeyNameAttribute"); } else { string value = a.GetString (); if (value != String.Empty) RootContext.StrongNameKeyContainer = value; } break; case "AssemblyDelaySign": case "AssemblyDelaySignAttribute": case "System.Reflection.AssemblyDelaySignAttribute": RootContext.StrongNameDelaySign = a.GetBoolean (); break; } } } AssemblyName an = new AssemblyName (); an.Name = Path.GetFileNameWithoutExtension (name); // note: delay doesn't apply when using a key container if (RootContext.StrongNameKeyContainer != null) { an.KeyPair = new StrongNameKeyPair (RootContext.StrongNameKeyContainer); return an; } // strongname is optional if (RootContext.StrongNameKeyFile == null) return an; string AssemblyDir = Path.GetDirectoryName (output); // the StrongName key file may be relative to (a) the compiled // file or (b) to the output assembly. See bugzilla #55320 // http://bugzilla.ximian.com/show_bug.cgi?id=55320 // (a) relative to the compiled file string filename = Path.GetFullPath (RootContext.StrongNameKeyFile); bool exist = File.Exists (filename); if ((!exist) && (AssemblyDir != null) && (AssemblyDir != String.Empty)) { // (b) relative to the outputed assembly filename = Path.GetFullPath (Path.Combine (AssemblyDir, RootContext.StrongNameKeyFile)); exist = File.Exists (filename); } if (exist) { using (FileStream fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) { byte[] snkeypair = new byte [fs.Length]; fs.Read (snkeypair, 0, snkeypair.Length); if (RootContext.StrongNameDelaySign) { // delayed signing - DO NOT include private key SetPublicKey (an, snkeypair); } else { // no delay so we make sure we have the private key try { CryptoConvert.FromCapiPrivateKeyBlob (snkeypair); an.KeyPair = new StrongNameKeyPair (snkeypair); } catch (CryptographicException) { if (snkeypair.Length == 16) { // error # is different for ECMA key Report.Error (1606, "Could not sign the assembly. " + "ECMA key can only be used to delay-sign assemblies"); } else { Error_AssemblySigning ("The speficied file `" + RootContext.StrongNameKeyFile + "' does not have a private key"); } return null; } } } } else { Error_AssemblySigning ("The speficied file `" + RootContext.StrongNameKeyFile + "' does not exist"); return null; } return an; } void Error_AssemblySigning (string text) { Report.Error (1548, "Error during assembly signing. " + text); } public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder) { if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (true)) { if (declarative_security == null) declarative_security = new ListDictionary (); a.ExtractSecurityPermissionSet (declarative_security); return; } if (a.Type == TypeManager.assembly_culture_attribute_type) { string value = a.GetString (); if (value == null || value.Length == 0) return; if (RootContext.Target == Target.Exe) { a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty"); return; } } Builder.SetCustomAttribute (customBuilder); } public override void Emit (TypeContainer tc) { base.Emit (tc); if (declarative_security != null) { MethodInfo add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic); object builder_instance = Builder; try { // Microsoft runtime hacking if (add_permission == null) { Type assembly_builder = typeof (AssemblyBuilder).Assembly.GetType ("System.Reflection.Emit.AssemblyBuilderData"); add_permission = assembly_builder.GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo fi = typeof (AssemblyBuilder).GetField ("m_assemblyData", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); builder_instance = fi.GetValue (Builder); } object[] args = new object [] { declarative_security [SecurityAction.RequestMinimum], declarative_security [SecurityAction.RequestOptional], declarative_security [SecurityAction.RequestRefuse] }; add_permission.Invoke (builder_instance, args); } catch { Report.RuntimeMissingSupport (Location.Null, "assembly permission setting"); } }#if NET_2_0 if (!OptAttributes.Contains (TypeManager.runtime_compatibility_attr_type, null)) { ConstructorInfo ci = TypeManager.runtime_compatibility_attr_type.GetConstructor (TypeManager.NoTypes); PropertyInfo pi = TypeManager.runtime_compatibility_attr_type.GetProperty ("WrapNonExceptionThrows"); Builder.SetCustomAttribute (new CustomAttributeBuilder (ci, new object [0], new PropertyInfo [] { pi }, new object[] { true } )); }#endif } public override string[] ValidAttributeTargets { get { return attribute_targets; } } } public class ModuleClass : CommonAssemblyModulClass { // TODO: make it private and move all builder based methods here public ModuleBuilder Builder; bool m_module_is_unsafe; public CharSet DefaultCharSet = CharSet.Ansi; public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass; static string[] attribute_targets = new string [] { "module" }; public ModuleClass (bool is_unsafe) { m_module_is_unsafe = is_unsafe; } public override AttributeTargets AttributeTargets { get { return AttributeTargets.Module; } } public override bool IsClsCompliaceRequired(DeclSpace ds) { return CodeGen.Assembly.IsClsCompliant; } public override void Emit (TypeContainer tc) { base.Emit (tc); if (!m_module_is_unsafe) return; if (TypeManager.unverifiable_code_ctor == null) { Console.WriteLine ("Internal error ! Cannot set unverifiable code attribute."); return; } Builder.SetCustomAttribute (new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0])); } public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder) { if (a.Type == TypeManager.cls_compliant_attribute_type) { if (CodeGen.Assembly.ClsCompliantAttribute == null) { Report.Warning (3012, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking"); } else if (CodeGen.Assembly.IsClsCompliant != a.GetBoolean ()) { Report.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.GetSignatureForError ()); Report.Error (3017, a.Location, "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly"); return; } } Builder.SetCustomAttribute (customBuilder); } /// <summary> /// It is called very early therefore can resolve only predefined attributes /// </summary> public void ResolveAttributes () {#if NET_2_0 Attribute a = ResolveAttribute (TypeManager.default_charset_type); if (a != null) { DefaultCharSet = a.GetCharSetValue (); switch (DefaultCharSet) { case CharSet.Ansi: case CharSet.None: break; case CharSet.Auto: DefaultCharSetType = TypeAttributes.AutoClass; break; case CharSet.Unicode: DefaultCharSetType = TypeAttributes.UnicodeClass; break; default: Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid"); break; } }#endif } public override string[] ValidAttributeTargets { get { return attribute_targets; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -