a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
436 lines
16 KiB
C#
436 lines
16 KiB
C#
//
|
|
// Mono.ILASM.ExternTable.cs
|
|
//
|
|
// Author(s):
|
|
// Jackson Harper (Jackson@LatitudeGeo.com)
|
|
//
|
|
// (C) 2003 Jackson Harper, All rights reserved
|
|
//
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Security;
|
|
using System.Globalization;
|
|
using PEAPI;
|
|
|
|
namespace Mono.ILASM {
|
|
|
|
public interface IScope {
|
|
ExternTypeRef GetTypeRef (string full_name, bool is_valuetype);
|
|
PEAPI.ClassRef GetType (string full_name, bool is_valuetype);
|
|
string FullName { get; }
|
|
}
|
|
|
|
public abstract class ExternRef : ICustomAttrTarget, IScope {
|
|
|
|
protected string name;
|
|
protected Hashtable class_table;
|
|
protected Hashtable typeref_table;
|
|
protected ArrayList customattr_list;
|
|
protected bool is_resolved;
|
|
|
|
public abstract void Resolve (CodeGen codegen);
|
|
public abstract PEAPI.IExternRef GetExternRef ();
|
|
|
|
public ExternRef (string name)
|
|
{
|
|
this.name = name;
|
|
typeref_table = new Hashtable ();
|
|
class_table = new Hashtable ();
|
|
}
|
|
|
|
public string Name {
|
|
get { return name; }
|
|
}
|
|
|
|
public virtual string FullName {
|
|
get { return name; }
|
|
}
|
|
|
|
public void AddCustomAttribute (CustomAttr customattr)
|
|
{
|
|
if (customattr_list == null)
|
|
customattr_list = new ArrayList ();
|
|
|
|
customattr_list.Add (customattr);
|
|
}
|
|
|
|
public ExternTypeRef GetTypeRef (string full_name, bool is_valuetype)
|
|
{
|
|
string first= full_name;
|
|
string rest = "";
|
|
int slash = full_name.IndexOf ('/');
|
|
if (slash > 0) {
|
|
first = full_name.Substring (0, slash);
|
|
rest = full_name.Substring (slash + 1);
|
|
}
|
|
|
|
ExternTypeRef type_ref = typeref_table [first] as ExternTypeRef;
|
|
|
|
if (type_ref != null) {
|
|
if (is_valuetype && rest == "")
|
|
type_ref.MakeValueClass ();
|
|
} else {
|
|
type_ref = new ExternTypeRef (this, first, is_valuetype);
|
|
typeref_table [first] = type_ref;
|
|
}
|
|
|
|
return (rest == "" ? type_ref : type_ref.GetTypeRef (rest, is_valuetype));
|
|
}
|
|
|
|
public PEAPI.ClassRef GetType (string full_name, bool is_valuetype)
|
|
{
|
|
PEAPI.ClassRef klass = class_table[full_name] as PEAPI.ClassRef;
|
|
|
|
if (klass != null)
|
|
return klass;
|
|
|
|
string name_space, name;
|
|
ExternTable.GetNameAndNamespace (full_name, out name_space, out name);
|
|
|
|
if (is_valuetype)
|
|
klass = (PEAPI.ClassRef) GetExternRef ().AddValueClass (name_space, name);
|
|
else
|
|
klass = (PEAPI.ClassRef) GetExternRef ().AddClass (name_space, name);
|
|
|
|
class_table [full_name] = klass;
|
|
return klass;
|
|
}
|
|
|
|
}
|
|
|
|
public class ExternModule : ExternRef {
|
|
|
|
public PEAPI.ModuleRef ModuleRef;
|
|
|
|
public ExternModule (string name) : base (name)
|
|
{
|
|
}
|
|
|
|
public override string FullName {
|
|
get {
|
|
//'name' field should not contain the [.module ]
|
|
//as its used for resolving
|
|
return String.Format ("[.module {0}]", name);
|
|
}
|
|
}
|
|
|
|
public override void Resolve (CodeGen codegen)
|
|
{
|
|
if (is_resolved)
|
|
return;
|
|
|
|
ModuleRef = codegen.PEFile.AddExternModule (name);
|
|
if (customattr_list != null)
|
|
foreach (CustomAttr customattr in customattr_list)
|
|
customattr.AddTo (codegen, ModuleRef);
|
|
|
|
is_resolved = true;
|
|
}
|
|
|
|
|
|
public override PEAPI.IExternRef GetExternRef ()
|
|
{
|
|
return ModuleRef;
|
|
}
|
|
}
|
|
|
|
public class ExternAssembly : ExternRef, IDeclSecurityTarget {
|
|
|
|
public PEAPI.AssemblyRef AssemblyRef;
|
|
|
|
private int major, minor, build, revision;
|
|
private byte [] public_key;
|
|
private byte [] public_key_token;
|
|
private string locale;
|
|
private byte [] hash;
|
|
private DeclSecurity decl_sec;
|
|
private AssemblyName asmb_name;
|
|
//flags
|
|
private PEAPI.AssemAttr attr;
|
|
|
|
public ExternAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr) : base (name)
|
|
{
|
|
this.name = name;
|
|
this.asmb_name = asmb_name;
|
|
this.attr = attr;
|
|
major = minor = build = revision = -1;
|
|
}
|
|
|
|
public override string FullName {
|
|
get {
|
|
//'name' field should not contain the []
|
|
//as its used for resolving
|
|
return String.Format ("[{0}]", name);
|
|
}
|
|
}
|
|
|
|
public AssemblyName AssemblyName {
|
|
get { return asmb_name; }
|
|
}
|
|
|
|
public DeclSecurity DeclSecurity {
|
|
get {
|
|
if (decl_sec == null)
|
|
decl_sec = new DeclSecurity ();
|
|
return decl_sec;
|
|
}
|
|
}
|
|
|
|
public override void Resolve (CodeGen code_gen)
|
|
{
|
|
if (is_resolved)
|
|
return;
|
|
|
|
AssemblyRef = code_gen.PEFile.AddExternAssembly (name);
|
|
AssemblyRef.AddAssemblyAttr (attr);
|
|
if (major != -1)
|
|
AssemblyRef.AddVersionInfo (major, minor, build, revision);
|
|
if (public_key != null)
|
|
AssemblyRef.AddKey (public_key);
|
|
if (public_key_token != null)
|
|
AssemblyRef.AddKeyToken (public_key_token);
|
|
if (locale != null)
|
|
AssemblyRef.AddCulture (locale);
|
|
if (hash != null)
|
|
AssemblyRef.AddHash (hash);
|
|
|
|
if (customattr_list != null)
|
|
foreach (CustomAttr customattr in customattr_list)
|
|
customattr.AddTo (code_gen, AssemblyRef);
|
|
|
|
if (decl_sec != null)
|
|
decl_sec.AddTo (code_gen, AssemblyRef);
|
|
|
|
class_table = new Hashtable ();
|
|
|
|
is_resolved = true;
|
|
}
|
|
|
|
public override PEAPI.IExternRef GetExternRef ()
|
|
{
|
|
return AssemblyRef;
|
|
}
|
|
|
|
public void SetVersion (int major, int minor, int build, int revision)
|
|
{
|
|
this.major = major;
|
|
this.minor = minor;
|
|
this.build = build;
|
|
this.revision = revision;
|
|
asmb_name.Version = new Version (major, minor, build, revision);
|
|
}
|
|
|
|
public void SetPublicKey (byte [] public_key)
|
|
{
|
|
this.public_key = public_key;
|
|
asmb_name.SetPublicKey (public_key);
|
|
}
|
|
|
|
public void SetPublicKeyToken (byte [] public_key_token)
|
|
{
|
|
this.public_key_token = public_key_token;
|
|
asmb_name.SetPublicKey (public_key);
|
|
}
|
|
|
|
public void SetLocale (string locale)
|
|
{
|
|
this.locale = locale;
|
|
//FIXME: is this correct?
|
|
asmb_name.CultureInfo = new CultureInfo (locale);
|
|
}
|
|
|
|
public void SetHash (byte [] hash)
|
|
{
|
|
this.hash = hash;
|
|
}
|
|
|
|
}
|
|
|
|
public class ExternClass
|
|
{
|
|
string fullName;
|
|
TypeAttr ta;
|
|
string assemblyReference;
|
|
|
|
public ExternClass (string fullName, TypeAttr ta, string assemblyReference)
|
|
{
|
|
this.fullName = fullName;
|
|
this.ta = ta;
|
|
this.assemblyReference = assemblyReference;
|
|
}
|
|
|
|
public void Resolve (CodeGen code_gen, ExternTable table)
|
|
{
|
|
var ar = table.GetAssemblyRef (assemblyReference);
|
|
if (ar != null) {
|
|
string ns = null;
|
|
string name = fullName;
|
|
|
|
int pos = name.LastIndexOf ('.');
|
|
if (pos > 0) {
|
|
ns = name.Substring (0, pos);
|
|
name = name.Substring (pos + 1);
|
|
}
|
|
|
|
code_gen.PEFile.AddExternClass (ns, name, ta, ar.AssemblyRef);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public class ExternTable {
|
|
|
|
Hashtable assembly_table;
|
|
Hashtable module_table;
|
|
List<ExternClass> class_table;
|
|
|
|
bool is_resolved;
|
|
|
|
public void AddCorlib ()
|
|
{
|
|
// Add mscorlib
|
|
string mscorlib_name = "mscorlib";
|
|
AssemblyName mscorlib = new AssemblyName ();
|
|
mscorlib.Name = mscorlib_name;
|
|
AddAssembly (mscorlib_name, mscorlib, 0);
|
|
|
|
// Also need to alias corlib, normally corlib and
|
|
// mscorlib are used interchangably
|
|
assembly_table["corlib"] = assembly_table["mscorlib"];
|
|
}
|
|
|
|
public ExternAssembly AddAssembly (string name, AssemblyName asmb_name, PEAPI.AssemAttr attr)
|
|
{
|
|
ExternAssembly ea = null;
|
|
|
|
if (assembly_table == null) {
|
|
assembly_table = new Hashtable ();
|
|
} else {
|
|
ea = assembly_table [name] as ExternAssembly;
|
|
if (ea != null)
|
|
return ea;
|
|
}
|
|
|
|
ea = new ExternAssembly (name, asmb_name, attr);
|
|
|
|
assembly_table [name] = ea;
|
|
|
|
return ea;
|
|
}
|
|
|
|
public ExternModule AddModule (string name)
|
|
{
|
|
ExternModule em = null;
|
|
|
|
if (module_table == null) {
|
|
module_table = new Hashtable ();
|
|
} else {
|
|
em = module_table [name] as ExternModule;
|
|
if (em != null)
|
|
return em;
|
|
}
|
|
|
|
em = new ExternModule (name);
|
|
|
|
module_table [name] = em;
|
|
|
|
return em;
|
|
}
|
|
|
|
public void AddClass (string name, TypeAttr ta, string assemblyReference)
|
|
{
|
|
if (class_table == null)
|
|
class_table = new List<ExternClass> ();
|
|
|
|
class_table.Add (new ExternClass (name, ta, assemblyReference));
|
|
}
|
|
|
|
public void Resolve (CodeGen code_gen)
|
|
{
|
|
if (is_resolved)
|
|
return;
|
|
|
|
if (assembly_table != null)
|
|
foreach (ExternAssembly ext in assembly_table.Values)
|
|
ext.Resolve (code_gen);
|
|
|
|
if (module_table != null)
|
|
foreach (ExternModule ext in module_table.Values)
|
|
ext.Resolve (code_gen);
|
|
|
|
if (class_table != null)
|
|
foreach (var entry in class_table)
|
|
entry.Resolve (code_gen, this);
|
|
|
|
is_resolved = true;
|
|
}
|
|
|
|
public ExternTypeRef GetTypeRef (string asmb_name, string full_name, bool is_valuetype)
|
|
{
|
|
ExternAssembly ext_asmb = null;
|
|
if (assembly_table == null && (asmb_name == "mscorlib" || asmb_name == "corlib")) {
|
|
/* AddCorlib if mscorlib is being referenced but
|
|
we haven't encountered a ".assembly 'name'" as yet. */
|
|
Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
|
|
AddCorlib ();
|
|
}
|
|
if (assembly_table != null)
|
|
ext_asmb = assembly_table[asmb_name] as ExternAssembly;
|
|
|
|
if (ext_asmb == null) {
|
|
System.Reflection.AssemblyName asmname = new System.Reflection.AssemblyName ();
|
|
asmname.Name = asmb_name;
|
|
|
|
Report.Warning (String.Format ("Reference to undeclared extern assembly '{0}', adding.", asmb_name));
|
|
ext_asmb = AddAssembly (asmb_name, asmname, 0);
|
|
}
|
|
|
|
return ext_asmb.GetTypeRef (full_name, is_valuetype);
|
|
}
|
|
|
|
public ExternTypeRef GetModuleTypeRef (string mod_name, string full_name, bool is_valuetype)
|
|
{
|
|
ExternModule mod = null;
|
|
if (module_table != null)
|
|
mod = module_table [mod_name] as ExternModule;
|
|
|
|
if (mod == null)
|
|
Report.Error ("Module " + mod_name + " not defined.");
|
|
|
|
return mod.GetTypeRef (full_name, is_valuetype);
|
|
}
|
|
|
|
public ExternAssembly GetAssemblyRef (string assembly_name)
|
|
{
|
|
ExternAssembly ass = null;
|
|
if (assembly_table != null)
|
|
ass = assembly_table [assembly_name] as ExternAssembly;
|
|
|
|
if (ass == null)
|
|
Report.Error ("Assembly " + assembly_name + " is not defined.");
|
|
|
|
return ass;
|
|
}
|
|
|
|
public static void GetNameAndNamespace (string full_name,
|
|
out string name_space, out string name) {
|
|
|
|
int last_dot = full_name.LastIndexOf ('.');
|
|
|
|
if (last_dot < 0) {
|
|
name_space = String.Empty;
|
|
name = full_name;
|
|
return;
|
|
}
|
|
|
|
name_space = full_name.Substring (0, last_dot);
|
|
name = full_name.Substring (last_dot + 1);
|
|
}
|
|
|
|
}
|
|
}
|
|
|