зеркало из https://github.com/mono/ikvm-fork.git
Extended map file support for ldtoken opcode to support loading method and field tokens.
This commit is contained in:
Родитель
939499a056
Коммит
141e584ee6
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче