diff options
author | jfrijters <jfrijters> | 2011-07-11 11:32:40 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2011-07-11 11:32:40 +0400 |
commit | 141e584ee62343bbfffa6b75dac9f25a4aaf5452 (patch) | |
tree | 880981eb7f520046be84967199391c3eb645202c /ikvmc | |
parent | 939499a05638bc6c690f46a14557907f955a84dd (diff) |
Extended map file support for ldtoken opcode to support loading method and field tokens.
Diffstat (limited to 'ikvmc')
-rw-r--r-- | ikvmc/CompilerClassLoader.cs | 8 | ||||
-rw-r--r-- | ikvmc/remapper.cs | 153 |
2 files changed, 160 insertions, 1 deletions
diff --git a/ikvmc/CompilerClassLoader.cs b/ikvmc/CompilerClassLoader.cs index 9f319c56..3ccd79f0 100644 --- a/ikvmc/CompilerClassLoader.cs +++ b/ikvmc/CompilerClassLoader.cs @@ -3405,6 +3405,8 @@ namespace IKVM.Internal StartErrors = 4000, UnableToCreateProxy = 4001, DuplicateProxy = 4002, + MapXmlUnableToResolveOpCode = 4003, + MapXmlError = 4004, } static class StaticCompiler @@ -3623,6 +3625,12 @@ namespace IKVM.Internal case Message.DuplicateProxy: msg = "duplicate proxy \"{0}\""; break; + case Message.MapXmlUnableToResolveOpCode: + msg = "unable to resolve opcode in remap file: {0}"; + break; + case Message.MapXmlError: + msg = "error in remap file: {0}"; + break; case Message.UnknownWarning: msg = "{0}"; break; diff --git a/ikvmc/remapper.cs b/ikvmc/remapper.cs index e121e66f..c21a8b0d 100644 --- a/ikvmc/remapper.cs +++ b/ikvmc/remapper.cs @@ -71,6 +71,38 @@ namespace IKVM.Internal.MapXml } internal abstract void Generate(CodeGenContext context, CodeEmitter ilgen); + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.Append('<'); + object[] attr = GetType().GetCustomAttributes(typeof(XmlTypeAttribute), false); + if (attr.Length == 1) + { + sb.Append(((XmlTypeAttribute)attr[0]).TypeName); + } + else + { + sb.Append(GetType().Name); + } + foreach (System.Reflection.FieldInfo field in GetType().GetFields()) + { + if (!field.IsStatic) + { + object value = field.GetValue(this); + if (value != null) + { + attr = field.GetCustomAttributes(typeof(XmlAttributeAttribute), false); + if (attr.Length == 1) + { + sb.AppendFormat(" {0}=\"{1}\"", ((XmlAttributeAttribute)attr[0]).AttributeName, value); + } + } + } + } + sb.Append(" />"); + return sb.ToString(); + } } [XmlType("ldstr")] @@ -1179,10 +1211,129 @@ namespace IKVM.Internal.MapXml { [XmlAttribute("type")] public string type; + [XmlAttribute("class")] + public string Class; + [XmlAttribute("method")] + public string Method; + [XmlAttribute("field")] + public string Field; + [XmlAttribute("sig")] + public string Sig; internal override void Generate(CodeGenContext context, CodeEmitter ilgen) { - ilgen.Emit(OpCodes.Ldtoken, StaticCompiler.GetTypeForMapXml(context.ClassLoader, type)); + if (!Validate()) + { + return; + } + + MemberInfo member = Resolve(context); + Type type = member as Type; + MethodInfo method = member as MethodInfo; + ConstructorInfo constructor = member as ConstructorInfo; + FieldInfo field = member as FieldInfo; + + if (type != null) + { + ilgen.Emit(OpCodes.Ldtoken, type); + } + else if (method != null) + { + ilgen.Emit(OpCodes.Ldtoken, method); + } + else if (constructor != null) + { + ilgen.Emit(OpCodes.Ldtoken, constructor); + } + else if (field != null) + { + ilgen.Emit(OpCodes.Ldtoken, field); + } + else + { + StaticCompiler.IssueMessage(Message.MapXmlUnableToResolveOpCode, ToString()); + } + } + + private bool Validate() + { + if (type != null && Class == null) + { + if (Method != null || Field != null || Sig != null) + { + StaticCompiler.IssueMessage(Message.MapXmlError, "not implemented: cannot use 'type' attribute with 'method' or 'field' attribute for ldtoken"); + return false; + } + return true; + } + else if (Class != null && type == null) + { + if (Method == null && Field == null) + { + if (Sig != null) + { + StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify 'sig' attribute without either 'method' or 'field' attribute for ldtoken"); + } + return true; + } + if (Method != null && Field != null) + { + StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify both 'method' and 'field' attribute for ldtoken"); + return false; + } + return true; + } + else + { + StaticCompiler.IssueMessage(Message.MapXmlError, "must specify either 'type' or 'class' attribute for ldtoken"); + return false; + } + } + + private MemberInfo Resolve(CodeGenContext context) + { + if (type != null) + { + if (Class != null || Method != null || Field != null || Sig != null) + { + throw new NotImplementedException(); + } + return StaticCompiler.GetTypeForMapXml(context.ClassLoader, type); + } + else if (Class != null) + { + TypeWrapper tw = context.ClassLoader.LoadClassByDottedNameFast(Class); + if (tw == null) + { + return null; + } + else if (Method != null) + { + MethodWrapper mw = tw.GetMethodWrapper(Method, Sig, false); + if (mw == null) + { + return null; + } + return mw.GetMethod(); + } + else if (Field != null) + { + FieldWrapper fw = tw.GetFieldWrapper(Field, Sig); + if (fw == null) + { + return null; + } + return fw.GetField(); + } + else + { + return tw.TypeAsBaseType; + } + } + else + { + return null; + } } } |