Extended map file support for ldtoken opcode to support loading method and field tokens.

This commit is contained in:
jfrijters 2011-07-11 07:32:40 +00:00
Родитель 939499a056
Коммит 141e584ee6
2 изменённых файлов: 160 добавлений и 1 удалений

Просмотреть файл

@ -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;
}
}
}