26using System.Diagnostics;
48 public static new Call Read(XElement element)
50 var inst =
new Call();
60 public static void Load(Call inst, XElement element)
62 inst.Class = (string)element.Attribute(
"class");
63 inst.Type = (string)element.Attribute(
"type");
64 inst.Name = (string)element.Attribute(
"name");
65 inst.Sig = (string)element.Attribute(
"sig");
68 readonly OpCode opcode;
73 public Call() : this(OpCodes.Call)
82 protected Call(OpCode opcode)
87 public string Class {
get;
set; }
89 public string Type {
get;
set; }
91 public string Name {
get;
set; }
93 public string Sig {
get;
set; }
95 internal sealed override void Generate(CodeGenContext context,
CodeEmitter ilgen)
98 throw new MapXmlException(
"Missing name.");
102 Debug.Assert(
Class ==
null && Type !=
null);
104 var argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
105 var ci = context.ClassLoader.Context.Resolver.ResolveCoreType(Type).AsReflection().GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard, argTypes,
null);
108 throw new InvalidOperationException(
"Missing .ctor: " + Type +
"..ctor" + Sig);
110 ilgen.Emit(opcode, ci);
114 Debug.Assert(
Class ==
null ^ Type ==
null);
117 Debug.Assert(Sig !=
null);
118 var method = context.ClassLoader.LoadClassByName(
Class).GetMethod(
Name, Sig,
false);
121 throw new InvalidOperationException(
"method not found: " +
Class +
"." +
Name + Sig);
126 var argTypeWrappers = method.GetParameters();
127 for (
int i = 0; i < argTypeWrappers.Length; i++)
129 if (argTypeWrappers[i].IsGhost)
132 for (
int j = temps.Length - 1; j >= 0; j--)
137 tw = argTypeWrappers[j];
143 tw = method.DeclaringType;
147 tw = argTypeWrappers[j - 1];
152 tw.EmitConvStackTypeToSignatureType(ilgen,
null);
154 temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType);
155 ilgen.Emit(OpCodes.Stloc, temps[j]);
157 for (
int j = 0; j < temps.Length; j++)
159 ilgen.Emit(OpCodes.Ldloc, temps[j]);
164 if (opcode.Value == OpCodes.Call.Value)
166 method.EmitCall(ilgen);
168 else if (opcode.Value == OpCodes.Callvirt.Value)
170 method.EmitCallvirt(ilgen);
172 else if (opcode.Value == OpCodes.Newobj.Value)
174 method.EmitNewobj(ilgen);
179 ilgen.Emit(opcode, (MethodInfo)method.GetMethod());
185 if (Sig.StartsWith(
"("))
187 argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
191 argTypes = Reflection.Type.EmptyTypes;
195 string[] types = Sig.Split(
';');
196 argTypes =
new Type[types.Length];
197 for (
int i = 0; i < types.Length; i++)
199 argTypes[i] = context.ClassLoader.Context.Resolver.ResolveCoreType(types[i]).AsReflection();
203 var ti = context.ClassLoader.Context.Resolver.ResolveCoreType(Type).AsReflection();
206 throw new InvalidOperationException(
"Missing type: " + Type);
209 var mi = ti.GetMethod(
Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
null, argTypes,
null);
212 var ta = argTypes.Select(i => i.AssemblyQualifiedName).ToArray();
213 var m = ti.GetMethods().FirstOrDefault(i => i.Name ==
Name);
214 throw new InvalidOperationException(
"Missing method: " + ti.FullName +
"." +
Name + Sig + $
" -> ({string.Join(";
", ta)}). {(m != null ? string.Join(";
", m.GetParameters().Select(i => i.ParameterType.AssemblyQualifiedName)) : null)}");
217 ilgen.Emit(opcode, mi);
global::java.lang.Class Class
global::java.lang.invoke.LambdaForm.Name Name
IKVM.Runtime.ClassFile.Method.Instruction Instruction