IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeImportByteCodeJavaType.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2015 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24
25using System;
26using System.Collections.Generic;
27
28using IKVM.Attributes;
30using IKVM.Reflection;
32using IKVM.Runtime;
34
35using Type = IKVM.Reflection.Type;
36
37namespace IKVM.Tools.Importer
38{
39
44 {
45
46 FieldInfo ghostRefField;
47 MethodBuilder ghostIsInstanceMethod;
48 MethodBuilder ghostIsInstanceArrayMethod;
49 MethodBuilder ghostCastMethod;
50 MethodBuilder ghostCastArrayMethod;
51 TypeBuilder typeBuilderGhostInterface;
52 Annotation annotation;
53 Type enumType;
54 RuntimeJavaMethod[] replacedMethods;
55
62 base(null, f, loader, null)
63 {
64
65 }
66
67 internal override void Finish()
68 {
69 base.Finish();
70 }
71
72 sealed class ConstructorForwarder : RuntimeJavaMethod
73 {
74
75 readonly RuntimeJavaTypeFactory context;
76 readonly TypeBuilder typeBuilder;
77 readonly RuntimeJavaMethod ctor;
78 MethodBuilder constructorBuilder;
79
86 internal ConstructorForwarder(RuntimeJavaTypeFactory context, TypeBuilder typeBuilder, RuntimeJavaMethod ctor) :
87 base(ctor.DeclaringType, ctor.Name, ctor.Signature, null, null, null, ctor.Modifiers, MemberFlags.None)
88 {
89 this.context = context;
90 this.typeBuilder = typeBuilder;
91 this.ctor = ctor;
92 }
93
94 protected override void DoLinkMethod()
95 {
96 ctor.Link();
97 DefineMethodHelper dmh = ctor.GetDefineMethodHelper();
98 constructorBuilder = dmh.DefineConstructor(context, typeBuilder, MethodAttributes.PrivateScope);
99 ctor.DeclaringType.Context.AttributeHelper.HideFromJava(constructorBuilder);
100 CodeEmitter ilgen = ctor.DeclaringType.Context.CodeEmitterFactory.Create(constructorBuilder);
101 ilgen.Emit(OpCodes.Ldarg_0);
102 for (int i = 1; i <= dmh.ParameterCount; i++)
103 {
104 ilgen.EmitLdarg(i);
105 }
106 ctor.EmitCall(ilgen);
107 ilgen.Emit(OpCodes.Ret);
108 ilgen.DoEmit();
109 }
110
111 internal override void EmitCall(CodeEmitter ilgen)
112 {
113 ilgen.Emit(OpCodes.Call, constructorBuilder);
114 }
115 }
116
117 internal override bool IsGhost => classLoader.IsGhost(this);
118
119 internal override bool IsMapUnsafeException => classLoader.IsMapUnsafeException(this);
120
121 internal override Type TypeAsBaseType => typeBuilderGhostInterface != null ? typeBuilderGhostInterface : base.TypeAsBaseType;
122
123 internal void GetParameterNamesFromXml(string methodName, string methodSig, string[] parameterNames)
124 {
125 var parameters = classLoader.GetXmlMapParameters(Name, methodName, methodSig);
126 if (parameters != null)
127 for (int i = 0; i < parameters.Length; i++)
128 if (parameters[i].Name != null)
129 parameterNames[i] = parameters[i].Name;
130 }
131
132 internal void AddXmlMapParameterAttributes(MethodBuilder method, string className, string methodName, string methodSig, ref ParameterBuilder[] parameterBuilders)
133 {
134 var parameters = classLoader.GetXmlMapParameters(className, methodName, methodSig);
135 if (parameters != null)
136 {
137 parameterBuilders ??= GetParameterBuilders(method, parameters.Length, null);
138 if (parameters.Length > parameterBuilders.Length)
139 throw new InvalidOperationException($"Number of parameters in map XML exceeds the number of parameters being built for '{className}:{methodName}' ({parameters.Length} > {parameterBuilders.Length}).");
140
141 for (int i = 0; i < parameters.Length; i++)
142 if (parameters[i].Attributes != null)
143 foreach (var attr in parameters[i].Attributes)
144 Context.AttributeHelper.SetCustomAttribute(classLoader, parameterBuilders[i], attr);
145 }
146 }
147
148 private void AddParameterMetadata(MethodBuilder method, RuntimeJavaMethod mw)
149 {
150 ParameterBuilder[] pbs;
151 if ((mw.DeclaringType.IsPublic && (mw.IsPublic || mw.IsProtected)) || classLoader.EmitSymbols)
152 {
153 string[] parameterNames = new string[mw.GetParameters().Length];
154 GetParameterNamesFromXml(mw.Name, mw.Signature, parameterNames);
155 GetParameterNamesFromSig(mw.Signature, parameterNames);
156 pbs = GetParameterBuilders(method, parameterNames.Length, parameterNames);
157 }
158 else
159 {
160 pbs = GetParameterBuilders(method, mw.GetParameters().Length, null);
161 }
162
163 if ((mw.Modifiers & Modifiers.VarArgs) != 0 && pbs.Length > 0)
164 Context.AttributeHelper.SetParamArrayAttribute(pbs[pbs.Length - 1]);
165
166 AddXmlMapParameterAttributes(method, Name, mw.Name, mw.Signature, ref pbs);
167 }
168
173 protected override void AddMapXmlFields(ref RuntimeJavaField[] fields)
174 {
175 var mapxml = classLoader.GetMapXmlClasses();
176 if (mapxml != null && mapxml.TryGetValue(Name, out var clazz) && clazz.Fields != null)
177 {
178 foreach (var field in clazz.Fields)
179 {
180 // are we adding a new field?
181 bool found = false;
182 foreach (var fw in fields)
183 {
184 if (fw.Name == field.Name && fw.Signature == field.Sig)
185 {
186 found = true;
187 break;
188 }
189 }
190
191 if (found == false)
192 fields = ArrayUtil.Concat(fields, RuntimeJavaField.Create(this, null, null, field.Name, field.Sig, new ExModifiers((Modifiers)field.Modifiers, false)));
193 }
194 }
195 }
196
198 {
199 var prologue = classLoader.GetMethodPrologue(new MethodKey(f.Name, m.Name, m.Signature));
200 if (prologue != null)
201 prologue.Emit(classLoader, ilgen);
202
203 var mapxml = classLoader.GetMapXmlMethodBodies();
204 if (mapxml != null && mapxml.TryGetValue(new MethodKey(f.Name, m.Name, m.Signature), out var opcodes))
205 {
206 opcodes.Emit(classLoader, ilgen);
207 return true;
208 }
209
210 return false;
211 }
212
213 void PublishAttributes(TypeBuilder typeBuilder, Class clazz)
214 {
215 foreach (var attr in clazz.Attributes)
216 Context.AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, attr);
217 }
218
225 static bool CheckPropertyArgs(Type[] args1, Type[] args2)
226 {
227 if (args1.Length == args2.Length)
228 {
229 for (int i = 0; i < args1.Length; i++)
230 if (args1[i] != args2[i])
231 return false;
232
233 return true;
234 }
235
236 return false;
237 }
238
239 static MethodAttributes GetPropertyMethodAttributes(RuntimeJavaMethod mw, bool final)
240 {
241 var attribs = MethodAttributes.HideBySig;
242 if (mw.IsStatic)
243 {
244 attribs |= MethodAttributes.Static;
245 }
246 else
247 {
248 // NOTE in order for IntelliSense to consider the property a "real" property,
249 // the getter and setter methods need to have substantially the same method attributes,
250 // so we may need to look at our peer to determine whether we should be final
251 // or not (and vice versa).
252 attribs |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride;
253 if (final)
254 attribs |= MethodAttributes.Final;
255 }
256
257 // TODO what happens if accessibility doesn't match our peer?
258 if (mw.IsPublic)
259 attribs |= MethodAttributes.Public;
260 else if (mw.IsProtected)
261 attribs |= MethodAttributes.FamORAssem;
262 else if (mw.IsPrivate)
263 attribs |= MethodAttributes.Private;
264 else
265 attribs |= MethodAttributes.Assembly;
266
267 return attribs;
268 }
269
270 private void PublishProperties(TypeBuilder typeBuilder, Class clazz)
271 {
272 foreach (var prop in clazz.Properties)
273 {
274 var typeWrapper = ClassLoader.RetTypeWrapperFromSig(prop.Sig, LoadMode.Link);
275 var propargs = ClassLoader.ArgJavaTypeListFromSig(prop.Sig, LoadMode.Link);
276 Type[] indexer = new Type[propargs.Length];
277 for (int i = 0; i < propargs.Length; i++)
278 {
279 indexer[i] = propargs[i].TypeAsSignatureType;
280 }
281 PropertyBuilder propbuilder = typeBuilder.DefineProperty(prop.Name, PropertyAttributes.None, typeWrapper.TypeAsSignatureType, indexer);
282 Context.AttributeHelper.HideFromJava(propbuilder);
283 if (prop.Attributes != null)
284 {
285 foreach (IKVM.Tools.Importer.MapXml.Attribute attr in prop.Attributes)
286 {
287 Context.AttributeHelper.SetCustomAttribute(classLoader, propbuilder, attr);
288 }
289 }
290
291 RuntimeJavaMethod getter = null;
292 RuntimeJavaMethod setter = null;
293 if (prop.Getter != null)
294 {
295 getter = GetMethod(prop.Getter.Name, prop.Getter.Sig, true);
296 if (getter == null)
297 {
298 Console.Error.WriteLine("Warning: getter not found for {0}::{1}", clazz.Name, prop.Name);
299 }
300 }
301
302 if (prop.Setter != null)
303 {
304 setter = GetMethod(prop.Setter.Name, prop.Setter.Sig, true);
305 if (setter == null)
306 Console.Error.WriteLine("Warning: setter not found for {0}::{1}", clazz.Name, prop.Name);
307 }
308
309 var final = (getter != null && getter.IsFinal) || (setter != null && setter.IsFinal);
310 if (getter != null)
311 {
312 var mw = getter;
313
314 if (!CheckPropertyArgs(mw.GetParametersForDefineMethod(), indexer) || mw.ReturnType != typeWrapper)
315 {
316 Console.Error.WriteLine("Warning: ignoring invalid property getter for {0}::{1}", clazz.Name, prop.Name);
317 }
318 else
319 {
320 var mb = mw.GetMethod() as MethodBuilder;
321 if (mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final))
322 {
323 mb = typeBuilder.DefineMethod("get_" + prop.Name, GetPropertyMethodAttributes(mw, final), typeWrapper.TypeAsSignatureType, indexer);
324 Context.AttributeHelper.HideFromJava(mb);
325 var ilgen = Context.CodeEmitterFactory.Create(mb);
326 if (mw.IsStatic)
327 {
328 for (int i = 0; i < indexer.Length; i++)
329 {
330 ilgen.EmitLdarg(i);
331 }
332 mw.EmitCall(ilgen);
333 }
334 else
335 {
336 ilgen.Emit(OpCodes.Ldarg_0);
337 for (int i = 0; i < indexer.Length; i++)
338 ilgen.EmitLdarg(i + 1);
339 mw.EmitCallvirt(ilgen);
340 }
341 ilgen.Emit(OpCodes.Ret);
342 ilgen.DoEmit();
343 }
344 propbuilder.SetGetMethod(mb);
345 }
346 }
347 if (setter != null)
348 {
349 var mw = setter;
350 var args = ArrayUtil.Concat(indexer, typeWrapper.TypeAsSignatureType);
351 if (!CheckPropertyArgs(args, mw.GetParametersForDefineMethod()))
352 {
353 Console.Error.WriteLine("Warning: ignoring invalid property setter for {0}::{1}", clazz.Name, prop.Name);
354 }
355 else
356 {
357 var mb = mw.GetMethod() as MethodBuilder;
358 if (mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final))
359 {
360 mb = typeBuilder.DefineMethod("set_" + prop.Name, GetPropertyMethodAttributes(mw, final), mw.ReturnTypeForDefineMethod, args);
361 Context.AttributeHelper.HideFromJava(mb);
362 var ilgen = Context.CodeEmitterFactory.Create(mb);
363 if (mw.IsStatic)
364 {
365 for (int i = 0; i <= indexer.Length; i++)
366 ilgen.EmitLdarg(i);
367 mw.EmitCall(ilgen);
368 }
369 else
370 {
371 ilgen.Emit(OpCodes.Ldarg_0);
372 for (int i = 0; i <= indexer.Length; i++)
373 ilgen.EmitLdarg(i + 1);
374 mw.EmitCallvirt(ilgen);
375 }
376 ilgen.Emit(OpCodes.Ret);
377 ilgen.DoEmit();
378 }
379
380 propbuilder.SetSetMethod(mb);
381 }
382 }
383 }
384 }
385
386 private static void MapModifiers(MapModifiers mapmods, bool isConstructor, out bool setmodifiers, ref MethodAttributes attribs, bool isNewSlot)
387 {
388 setmodifiers = false;
389 var modifiers = (Modifiers)mapmods;
390 if ((modifiers & Modifiers.Public) != 0)
391 {
392 attribs |= MethodAttributes.Public;
393 }
394 else if ((modifiers & Modifiers.Protected) != 0)
395 {
396 attribs |= MethodAttributes.FamORAssem;
397 }
398 else if ((modifiers & Modifiers.Private) != 0)
399 {
400 attribs |= MethodAttributes.Private;
401 }
402 else
403 {
404 attribs |= MethodAttributes.Assembly;
405 }
406
407 if ((modifiers & Modifiers.Static) != 0)
408 {
409 attribs |= MethodAttributes.Static;
410 if ((modifiers & Modifiers.Final) != 0)
411 {
412 setmodifiers = true;
413 }
414 }
415 else if (!isConstructor)
416 {
417 // NOTE we're abusing the MethodAttributes.NewSlot and Modifiers.Final combination to mean non-virtual
418 if ((modifiers & Modifiers.Final) != 0 && (attribs & MethodAttributes.NewSlot) != 0 && (attribs & MethodAttributes.Virtual) == 0)
419 {
420 // remove NewSlot, because it doesn't make sense on a non-virtual method
421 attribs &= ~MethodAttributes.NewSlot;
422 }
423 else if (((modifiers & (Modifiers.Public | Modifiers.Final)) == Modifiers.Final && isNewSlot && (attribs & MethodAttributes.Virtual) == 0))
424 {
425 // final method that doesn't need to be virtual
426 }
427 else
428 {
429 if ((modifiers & Modifiers.Private) == 0)
430 {
431 attribs |= MethodAttributes.Virtual;
432 }
433 if ((modifiers & Modifiers.Final) != 0)
434 {
435 attribs |= MethodAttributes.Final;
436 }
437 else if ((modifiers & Modifiers.Abstract) != 0)
438 {
439 attribs |= MethodAttributes.Abstract;
440 }
441 }
442 }
443
444 if ((modifiers & Modifiers.Synchronized) != 0)
445 {
446 throw new NotImplementedException();
447 }
448 }
449
450 private void MapSignature(string sig, out Type returnType, out Type[] parameterTypes)
451 {
452 returnType = ClassLoader.RetTypeWrapperFromSig(sig, LoadMode.Link).TypeAsSignatureType;
453 var parameterTypeWrappers = ClassLoader.ArgJavaTypeListFromSig(sig, LoadMode.Link);
454 parameterTypes = new Type[parameterTypeWrappers.Length];
455 for (int i = 0; i < parameterTypeWrappers.Length; i++)
456 {
457 parameterTypes[i] = parameterTypeWrappers[i].TypeAsSignatureType;
458 }
459 }
460
461 protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, RuntimeJavaField[] fields, RuntimeJavaMethod[] methods)
462 {
463 var mapxml = classLoader.GetMapXmlClasses();
464 if (mapxml != null)
465 {
466 if (mapxml.TryGetValue(classFile.Name, out var clazz))
467 {
468 if (clazz.Attributes != null)
469 PublishAttributes(typeBuilder, clazz);
470
471 if (clazz.Properties != null)
472 PublishProperties(typeBuilder, clazz);
473
474 if (clazz.Fields != null)
475 {
476 foreach (var field in clazz.Fields)
477 {
478 if (field.Attributes != null)
479 {
480 foreach (var fw in fields)
481 {
482 if (fw.Name == field.Name && fw.Signature == field.Sig)
483 {
484 var fb = fw.GetField() as FieldBuilder;
485 if (fb != null)
486 foreach (var attr in field.Attributes)
487 Context.AttributeHelper.SetCustomAttribute(classLoader, fb, attr);
488 }
489 }
490 }
491 }
492 }
493 if (clazz.Constructors != null)
494 {
495 // HACK this isn't the right place to do this, but for now it suffices
496 foreach (var constructor in clazz.Constructors)
497 {
498 // are we adding a new constructor?
499 if (GetMethod(StringConstants.INIT, constructor.Sig, false) == null)
500 {
501 if (constructor.Body == null)
502 {
503 Console.Error.WriteLine("Error: Constructor {0}.<init>{1} in xml remap file doesn't have a body.", clazz.Name, constructor.Sig);
504 continue;
505 }
506
507 MethodAttributes attribs = 0;
508 MapModifiers(constructor.Modifiers, true, out var setmodifiers, ref attribs, false);
509 MapSignature(constructor.Sig, out var returnType, out var parameterTypes);
510 var cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes);
511 if (setmodifiers)
512 Context.AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false);
513
514 ImportClassLoader.AddDeclaredExceptions(Context, cb, constructor.Throws);
515 var ilgen = Context.CodeEmitterFactory.Create(cb);
516 constructor.Emit(classLoader, ilgen);
517 ilgen.DoEmit();
518 if (constructor.Attributes != null)
519 foreach (var attr in constructor.Attributes)
520 Context.AttributeHelper.SetCustomAttribute(classLoader, cb, attr);
521 }
522 }
523
524 foreach (var constructor in clazz.Constructors)
525 {
526 if (constructor.Attributes != null)
527 {
528 foreach (var mw in methods)
529 {
530 if (mw.Name == "<init>" && mw.Signature == constructor.Sig)
531 {
532 var mb = mw.GetMethod() as MethodBuilder;
533 if (mb != null)
534 foreach (var attr in constructor.Attributes)
535 Context.AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
536 }
537 }
538 }
539 }
540 }
541 if (clazz.Methods != null)
542 {
543 // HACK this isn't the right place to do this, but for now it suffices
544 foreach (var method in clazz.Methods)
545 {
546 // are we adding a new method?
547 if (GetMethod(method.Name, method.Sig, false) == null)
548 {
549 var attribs = method.MethodAttributes;
550 MapModifiers(method.Modifiers, false, out var setmodifiers, ref attribs, BaseTypeWrapper == null || BaseTypeWrapper.GetMethod(method.Name, method.Sig, true) == null);
551 if (method.Body == null && (attribs & MethodAttributes.Abstract) == 0)
552 {
553 Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig);
554 continue;
555 }
556
557 MapSignature(method.Sig, out var returnType, out var parameterTypes);
558 var mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes);
559 if (setmodifiers)
560 {
561 Context.AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false);
562 }
563
564 if (method.Override != null)
565 {
566 var mw = ClassLoader.LoadClassByName(method.Override.Class).GetMethod(method.Override.Name, method.Sig, true);
567 mw.Link();
568 typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
569 }
570
571 ImportClassLoader.AddDeclaredExceptions(Context, mb, method.Throws);
572 if (method.Body != null)
573 {
574 CodeEmitter ilgen = Context.CodeEmitterFactory.Create(mb);
575 method.Emit(classLoader, ilgen);
576 ilgen.DoEmit();
577 }
578
579 if (method.Attributes != null)
580 foreach (var attr in method.Attributes)
581 Context.AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
582 }
583 }
584
585 foreach (IKVM.Tools.Importer.MapXml.Method method in clazz.Methods)
586 {
587 if (method.Attributes != null)
588 {
589 foreach (var mw in methods)
590 {
591 if (mw.Name == method.Name && mw.Signature == method.Sig)
592 {
593 MethodBuilder mb = mw.GetMethod() as MethodBuilder;
594 if (mb != null)
595 {
596 foreach (IKVM.Tools.Importer.MapXml.Attribute attr in method.Attributes)
597 {
598 Context.AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
599 }
600 }
601 }
602 }
603 }
604 }
605 }
606 if (clazz.Interfaces != null)
607 {
608 foreach (Implements iface in clazz.Interfaces)
609 {
610 var tw = ClassLoader.LoadClassByName(iface.Class);
611 // NOTE since this interface won't be part of the list in the ImplementAttribute,
612 // it won't be visible from Java that the type implements this interface.
613 typeBuilder.AddInterfaceImplementation(tw.TypeAsBaseType);
614 if (iface.Methods != null)
615 {
616 foreach (Method m in iface.Methods)
617 {
618 var mw = tw.GetMethod(m.Name, m.Sig, false);
619 if (mw == null)
620 throw new InvalidOperationException("Method " + m.Name + m.Sig + " not found in interface " + tw.Name);
621
622 mw.Link();
623 MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(this, typeBuilder, tw.Name + "/" + m.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.CheckAccessOnOverride);
624 Context.AttributeHelper.HideFromJava(mb);
625 typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
626 CodeEmitter ilgen = Context.CodeEmitterFactory.Create(mb);
627 m.Emit(classLoader, ilgen);
628 ilgen.DoEmit();
629 }
630 }
631 }
632 }
633 }
634 }
635 }
636
637 protected override MethodBuilder DefineGhostMethod(TypeBuilder typeBuilder, string name, MethodAttributes attribs, RuntimeJavaMethod mw)
638 {
639 if (typeBuilderGhostInterface != null && mw.IsVirtual)
640 {
641 var helper = mw.GetDefineMethodHelper();
642 var stub = helper.DefineMethod(this, typeBuilder, name, MethodAttributes.Public);
643 ((RuntimeGhostJavaMethod)mw).SetGhostMethod(stub);
644 return helper.DefineMethod(this, typeBuilderGhostInterface, name, attribs);
645 }
646
647 return null;
648 }
649
650 protected override void FinishGhost(TypeBuilder typeBuilder, RuntimeJavaMethod[] methods)
651 {
652 if (typeBuilderGhostInterface != null)
653 {
654 // TODO consider adding methods from base interface and java.lang.Object as well
655 for (int i = 0; i < methods.Length; i++)
656 {
657 // skip <clinit> and non-virtual interface methods introduced in Java 8
658 if (methods[i] is RuntimeGhostJavaMethod gmw)
659 {
660 var args = methods[i].GetParameters();
661 var stub = gmw.GetGhostMethod();
662 AddParameterMetadata(stub, methods[i]);
663 Context.AttributeHelper.SetModifiers(stub, methods[i].Modifiers, methods[i].IsInternal);
664 var ilgen = Context.CodeEmitterFactory.Create(stub);
665 var end = ilgen.DefineLabel();
666 var implementers = classLoader.GetGhostImplementers(this);
667 ilgen.Emit(OpCodes.Ldarg_0);
668 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
669 ilgen.Emit(OpCodes.Dup);
670 ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface);
671 var label = ilgen.DefineLabel();
672 ilgen.EmitBrfalse(label);
673 ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface);
674 for (int k = 0; k < args.Length; k++)
675 {
676 ilgen.EmitLdarg(k + 1);
677 }
678 ilgen.Emit(OpCodes.Callvirt, (MethodInfo)methods[i].GetMethod());
679 ilgen.EmitBr(end);
680 ilgen.MarkLabel(label);
681 for (int j = 0; j < implementers.Length; j++)
682 {
683 ilgen.Emit(OpCodes.Dup);
684 ilgen.Emit(OpCodes.Isinst, implementers[j].TypeAsTBD);
685 label = ilgen.DefineLabel();
686 ilgen.EmitBrfalse(label);
687 var mw = implementers[j].GetMethod(methods[i].Name, methods[i].Signature, true);
688 if (mw == null)
689 {
690 if (methods[i].IsAbstract)
691 {
692 // This should only happen for remapped types (defined in map.xml), because normally you'd get a miranda method.
693 throw new FatalCompilerErrorException(DiagnosticEvent.GhostInterfaceMethodMissing(implementers[j].Name, Name, methods[i].Name, methods[i].Signature));
694 }
695 // We're inheriting a default method
696 ilgen.Emit(OpCodes.Pop);
697 ilgen.Emit(OpCodes.Ldarg_0);
698 for (int k = 0; k < args.Length; k++)
699 {
700 ilgen.EmitLdarg(k + 1);
701 }
702 ilgen.Emit(OpCodes.Call, RuntimeDefaultInterfaceJavaMethod.GetImpl(methods[i]));
703 }
704 else
705 {
706 ilgen.Emit(OpCodes.Castclass, implementers[j].TypeAsTBD);
707 for (int k = 0; k < args.Length; k++)
708 {
709 ilgen.EmitLdarg(k + 1);
710 }
711 mw.EmitCallvirt(ilgen);
712 }
713 ilgen.EmitBr(end);
714 ilgen.MarkLabel(label);
715 }
716 // we need to do a null check (null fails all the isinst checks)
717 ilgen.EmitNullCheck();
718 ilgen.EmitThrow("java.lang.IncompatibleClassChangeError", Name);
719 ilgen.MarkLabel(end);
720 ilgen.Emit(OpCodes.Ret);
721 ilgen.DoEmit();
722 }
723 }
724
725 // HACK create a scope to enable reuse of "implementers" name
726 if (true)
727 {
728 MethodBuilder mb;
729 CodeEmitter ilgen;
730 CodeEmitterLocal local;
731 // add implicit conversions for all the ghost implementers
732 var implementers = classLoader.GetGhostImplementers(this);
733 for (int i = 0; i < implementers.Length; i++)
734 {
735 mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, TypeAsSignatureType, new Type[] { implementers[i].TypeAsSignatureType });
736 Context.AttributeHelper.HideFromJava(mb);
737 ilgen = Context.CodeEmitterFactory.Create(mb);
738 local = ilgen.DeclareLocal(TypeAsSignatureType);
739 ilgen.Emit(OpCodes.Ldloca, local);
740 ilgen.Emit(OpCodes.Ldarg_0);
741 ilgen.Emit(OpCodes.Stfld, ghostRefField);
742 ilgen.Emit(OpCodes.Ldloca, local);
743 ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType);
744 ilgen.Emit(OpCodes.Ret);
745 ilgen.DoEmit();
746 }
747 // Implement the "IsInstance" method
748 mb = ghostIsInstanceMethod;
749 Context.AttributeHelper.HideFromJava(mb);
750 ilgen = Context.CodeEmitterFactory.Create(mb);
751 CodeEmitterLabel end = ilgen.DefineLabel();
752 for (int i = 0; i < implementers.Length; i++)
753 {
754 ilgen.Emit(OpCodes.Ldarg_0);
755 ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD);
756 CodeEmitterLabel label = ilgen.DefineLabel();
757 ilgen.EmitBrfalse(label);
758 ilgen.Emit(OpCodes.Ldc_I4_1);
759 ilgen.EmitBr(end);
760 ilgen.MarkLabel(label);
761 }
762 ilgen.Emit(OpCodes.Ldarg_0);
763 ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface);
764 ilgen.Emit(OpCodes.Ldnull);
765 ilgen.Emit(OpCodes.Cgt_Un);
766 ilgen.MarkLabel(end);
767 ilgen.Emit(OpCodes.Ret);
768 ilgen.DoEmit();
769 // Implement the "IsInstanceArray" method
770 mb = ghostIsInstanceArrayMethod;
771 Context.AttributeHelper.HideFromJava(mb);
772 ilgen = Context.CodeEmitterFactory.Create(mb);
773 var localType = ilgen.DeclareLocal(Context.Types.Type);
774 var localRank = ilgen.DeclareLocal(Context.Types.Int32);
775 ilgen.Emit(OpCodes.Ldarg_0);
776 var skip = ilgen.DefineLabel();
777 ilgen.EmitBrtrue(skip);
778 ilgen.Emit(OpCodes.Ldc_I4_0);
779 ilgen.Emit(OpCodes.Ret);
780 ilgen.MarkLabel(skip);
781 ilgen.Emit(OpCodes.Ldarg_0);
782 ilgen.Emit(OpCodes.Call, Context.CompilerFactory.GetTypeMethod);
783 ilgen.Emit(OpCodes.Stloc, localType);
784 ilgen.Emit(OpCodes.Ldarg_1);
785 ilgen.Emit(OpCodes.Stloc, localRank);
786 skip = ilgen.DefineLabel();
787 ilgen.EmitBr(skip);
788 var iter = ilgen.DefineLabel();
789 ilgen.MarkLabel(iter);
790 ilgen.Emit(OpCodes.Ldloc, localType);
791 ilgen.Emit(OpCodes.Callvirt, Context.Types.Type.GetMethod("GetElementType"));
792 ilgen.Emit(OpCodes.Stloc, localType);
793 ilgen.Emit(OpCodes.Ldloc, localRank);
794 ilgen.Emit(OpCodes.Ldc_I4_1);
795 ilgen.Emit(OpCodes.Sub);
796 ilgen.Emit(OpCodes.Stloc, localRank);
797 ilgen.Emit(OpCodes.Ldloc, localRank);
798 var typecheck = ilgen.DefineLabel();
799 ilgen.EmitBrfalse(typecheck);
800 ilgen.MarkLabel(skip);
801 ilgen.Emit(OpCodes.Ldloc, localType);
802 ilgen.Emit(OpCodes.Callvirt, Context.Types.Type.GetMethod("get_IsArray"));
803 ilgen.EmitBrtrue(iter);
804 ilgen.Emit(OpCodes.Ldc_I4_0);
805 ilgen.Emit(OpCodes.Ret);
806 ilgen.MarkLabel(typecheck);
807 for (int i = 0; i < implementers.Length; i++)
808 {
809 ilgen.Emit(OpCodes.Ldtoken, implementers[i].TypeAsTBD);
810 ilgen.Emit(OpCodes.Call, Context.Types.Type.GetMethod("GetTypeFromHandle"));
811 ilgen.Emit(OpCodes.Ldloc, localType);
812 ilgen.Emit(OpCodes.Callvirt, Context.Types.Type.GetMethod("IsAssignableFrom"));
813 var label = ilgen.DefineLabel();
814 ilgen.EmitBrfalse(label);
815 ilgen.Emit(OpCodes.Ldc_I4_1);
816 ilgen.Emit(OpCodes.Ret);
817 ilgen.MarkLabel(label);
818 }
819 ilgen.Emit(OpCodes.Ldtoken, typeBuilderGhostInterface);
820 ilgen.Emit(OpCodes.Call, Context.Types.Type.GetMethod("GetTypeFromHandle"));
821 ilgen.Emit(OpCodes.Ldloc, localType);
822 ilgen.Emit(OpCodes.Callvirt, Context.Types.Type.GetMethod("IsAssignableFrom"));
823 skip = ilgen.DefineLabel();
824 ilgen.EmitBrfalse(skip);
825 ilgen.Emit(OpCodes.Ldc_I4_1);
826 ilgen.Emit(OpCodes.Ret);
827 ilgen.MarkLabel(skip);
828 ilgen.Emit(OpCodes.Ldarg_0);
829 ilgen.Emit(OpCodes.Ldtoken, typeBuilder);
830 ilgen.Emit(OpCodes.Ldarg_1);
831 ilgen.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType(typeof(IKVM.Runtime.GhostTag).FullName).AsReflection().GetMethod("IsGhostArrayInstance", BindingFlags.NonPublic | BindingFlags.Static));
832 ilgen.Emit(OpCodes.Ret);
833 ilgen.DoEmit();
834
835 // Implement the "Cast" method
836 mb = ghostCastMethod;
837 Context.AttributeHelper.HideFromJava(mb);
838 ilgen = Context.CodeEmitterFactory.Create(mb);
839 end = ilgen.DefineLabel();
840 for (int i = 0; i < implementers.Length; i++)
841 {
842 ilgen.Emit(OpCodes.Ldarg_0);
843 ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD);
844 ilgen.EmitBrtrue(end);
845 }
846 ilgen.Emit(OpCodes.Ldarg_0);
847 ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface);
848 ilgen.Emit(OpCodes.Pop);
849 ilgen.MarkLabel(end);
850 local = ilgen.DeclareLocal(TypeAsSignatureType);
851 ilgen.Emit(OpCodes.Ldloca, local);
852 ilgen.Emit(OpCodes.Ldarg_0);
853 ilgen.Emit(OpCodes.Stfld, ghostRefField);
854 ilgen.Emit(OpCodes.Ldloca, local);
855 ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType);
856 ilgen.Emit(OpCodes.Ret);
857 ilgen.DoEmit();
858 // Add "ToObject" methods
859 mb = typeBuilder.DefineMethod("ToObject", MethodAttributes.HideBySig | MethodAttributes.Public, Context.Types.Object, Type.EmptyTypes);
860 Context.AttributeHelper.HideFromJava(mb);
861 ilgen = Context.CodeEmitterFactory.Create(mb);
862 ilgen.Emit(OpCodes.Ldarg_0);
863 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
864 ilgen.Emit(OpCodes.Ret);
865 ilgen.DoEmit();
866
867 // Implement the "CastArray" method
868 // NOTE unlike "Cast" this doesn't return anything, it just throws a ClassCastException if the
869 // cast is unsuccessful. Also, because of the complexity of this test, we call IsInstanceArray
870 // instead of reimplementing the check here.
871 mb = ghostCastArrayMethod;
872 Context.AttributeHelper.HideFromJava(mb);
873 ilgen = Context.CodeEmitterFactory.Create(mb);
874 end = ilgen.DefineLabel();
875 ilgen.Emit(OpCodes.Ldarg_0);
876 ilgen.EmitBrfalse(end);
877 ilgen.Emit(OpCodes.Ldarg_0);
878 ilgen.Emit(OpCodes.Ldarg_1);
879 ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod);
880 ilgen.EmitBrtrue(end);
881 ilgen.Emit(OpCodes.Ldarg_0);
882 ilgen.Emit(OpCodes.Ldtoken, typeBuilder);
883 ilgen.Emit(OpCodes.Ldarg_1);
884 ilgen.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType(typeof(IKVM.Runtime.GhostTag).FullName).AsReflection().GetMethod("ThrowClassCastException", BindingFlags.NonPublic | BindingFlags.Static));
885 ilgen.MarkLabel(end);
886 ilgen.Emit(OpCodes.Ret);
887 ilgen.DoEmit();
888
889 // Implement the "Equals" method
890 mb = typeBuilder.DefineMethod("Equals", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Context.Types.Boolean, new Type[] { Context.Types.Object });
891 Context.AttributeHelper.HideFromJava(mb);
892 ilgen = Context.CodeEmitterFactory.Create(mb);
893 ilgen.Emit(OpCodes.Ldarg_0);
894 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
895 ilgen.Emit(OpCodes.Ldarg_1);
896 ilgen.Emit(OpCodes.Ceq);
897 ilgen.Emit(OpCodes.Ret);
898 ilgen.DoEmit();
899
900 // Implement the "GetHashCode" method
901 mb = typeBuilder.DefineMethod("GetHashCode", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Context.Types.Int32, Type.EmptyTypes);
902 Context.AttributeHelper.HideFromJava(mb);
903 ilgen = Context.CodeEmitterFactory.Create(mb);
904 ilgen.Emit(OpCodes.Ldarg_0);
905 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
906 ilgen.Emit(OpCodes.Callvirt, Context.Types.Object.GetMethod("GetHashCode"));
907 ilgen.Emit(OpCodes.Ret);
908 ilgen.DoEmit();
909
910 // Implement the "op_Equality" method
911 mb = typeBuilder.DefineMethod("op_Equality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Context.Types.Boolean, new Type[] { typeBuilder, typeBuilder });
912 Context.AttributeHelper.HideFromJava(mb);
913 ilgen = Context.CodeEmitterFactory.Create(mb);
914 ilgen.EmitLdarga(0);
915 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
916 ilgen.EmitLdarga(1);
917 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
918 ilgen.Emit(OpCodes.Ceq);
919 ilgen.Emit(OpCodes.Ret);
920 ilgen.DoEmit();
921
922 // Implement the "op_Inequality" method
923 mb = typeBuilder.DefineMethod("op_Inequality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Context.Types.Boolean, new Type[] { typeBuilder, typeBuilder });
924 Context.AttributeHelper.HideFromJava(mb);
925 ilgen = Context.CodeEmitterFactory.Create(mb);
926 ilgen.EmitLdarga(0);
927 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
928 ilgen.EmitLdarga(1);
929 ilgen.Emit(OpCodes.Ldfld, ghostRefField);
930 ilgen.Emit(OpCodes.Ceq);
931 ilgen.Emit(OpCodes.Ldc_I4_0);
932 ilgen.Emit(OpCodes.Ceq);
933 ilgen.Emit(OpCodes.Ret);
934 ilgen.DoEmit();
935 }
936 }
937 }
938
939 protected override void FinishGhostStep2()
940 {
941 typeBuilderGhostInterface?.CreateType();
942 }
943
944 protected override TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs)
945 {
946 typeAttribs &= ~(TypeAttributes.Interface | TypeAttributes.Abstract);
947 typeAttribs |= TypeAttributes.Class | TypeAttributes.Sealed;
948 TypeBuilder typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs, Context.Types.ValueType);
949 Context.AttributeHelper.SetGhostInterface(typeBuilder);
950 Context.AttributeHelper.SetModifiers(typeBuilder, Modifiers, IsInternal);
951 ghostRefField = typeBuilder.DefineField("__<ref>", Context.Types.Object, FieldAttributes.Public | FieldAttributes.SpecialName);
952 typeBuilderGhostInterface = typeBuilder.DefineNestedType("__Interface", TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.NestedPublic);
953 Context.AttributeHelper.HideFromJava(typeBuilderGhostInterface);
954 ghostIsInstanceMethod = typeBuilder.DefineMethod("IsInstance", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Context.Types.Boolean, new Type[] { Context.Types.Object });
955 ghostIsInstanceMethod.DefineParameter(1, ParameterAttributes.None, "obj");
956 ghostIsInstanceArrayMethod = typeBuilder.DefineMethod("IsInstanceArray", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Context.Types.Boolean, new Type[] { Context.Types.Object, Context.Types.Int32 });
957 ghostIsInstanceArrayMethod.DefineParameter(1, ParameterAttributes.None, "obj");
958 ghostIsInstanceArrayMethod.DefineParameter(2, ParameterAttributes.None, "rank");
959 ghostCastMethod = typeBuilder.DefineMethod("Cast", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeBuilder, new Type[] { Context.Types.Object });
960 ghostCastMethod.DefineParameter(1, ParameterAttributes.None, "obj");
961 ghostCastArrayMethod = typeBuilder.DefineMethod("CastArray", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Context.Types.Void, new Type[] { Context.Types.Object, Context.Types.Int32 });
962 ghostCastArrayMethod.DefineParameter(1, ParameterAttributes.None, "obj");
963 ghostCastArrayMethod.DefineParameter(2, ParameterAttributes.None, "rank");
964 return typeBuilder;
965 }
966
967 internal override FieldInfo GhostRefField => ghostRefField;
968
969 internal override void EmitCheckcast(CodeEmitter ilgen)
970 {
971 if (IsGhost)
972 {
973 ilgen.Emit(OpCodes.Dup);
974 ilgen.Emit(OpCodes.Call, ghostCastMethod);
975 ilgen.Emit(OpCodes.Pop);
976 }
977 else if (IsGhostArray)
978 {
979 ilgen.Emit(OpCodes.Dup);
980 RuntimeJavaType tw = this;
981 int rank = 0;
982 while (tw.IsArray)
983 {
984 rank++;
985 tw = tw.ElementTypeWrapper;
986 }
987 ilgen.EmitLdc_I4(rank);
988 ilgen.Emit(OpCodes.Call, ghostCastArrayMethod);
989 ilgen.Emit(OpCodes.Castclass, RuntimeArrayJavaType.MakeArrayType(Context.Types.Object, rank));
990 }
991 else
992 {
993 base.EmitCheckcast(ilgen);
994 }
995 }
996
997 internal override void EmitInstanceOf(CodeEmitter ilgen)
998 {
999 if (IsGhost)
1000 {
1001 ilgen.Emit(OpCodes.Call, ghostIsInstanceMethod);
1002 }
1003 else if (IsGhostArray)
1004 {
1005 ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod);
1006 }
1007 else
1008 {
1009 base.EmitInstanceOf(ilgen);
1010 }
1011 }
1012
1013 internal void SetAnnotation(Annotation annotation)
1014 {
1015 this.annotation = annotation;
1016 }
1017
1018 internal override Annotation Annotation => annotation;
1019
1020 internal void SetEnumType(Type enumType)
1021 {
1022 this.enumType = enumType;
1023 }
1024
1025 internal override Type EnumType => enumType;
1026
1027 sealed class ReplacedMethodWrapper : RuntimeJavaMethod
1028 {
1029
1030 readonly InstructionList code;
1031
1039 internal ReplacedMethodWrapper(RuntimeJavaType tw, string name, string sig, IKVM.Tools.Importer.MapXml.InstructionList code) :
1040 base(tw, name, sig, null, null, null, Modifiers.Public, MemberFlags.None)
1041 {
1042 this.code = code;
1043 }
1044
1050 internal ReplacedMethodWrapper(ClassFile.ConstantPoolItemMI cpi, IKVM.Tools.Importer.MapXml.InstructionList code) :
1051 base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None)
1052 {
1053 this.code = code;
1054 }
1055
1056 protected override void DoLinkMethod()
1057 {
1058
1059 }
1060
1061 private void DoEmit(CodeEmitter ilgen)
1062 {
1063 var context = new IKVM.Tools.Importer.MapXml.CodeGenContext(DeclaringType.ClassLoader);
1064 // we don't want the line numbers from map.xml, so we have our own emit loop
1065 for (int i = 0; i < code.Instructions.Length; i++)
1066 code.Instructions[i].Generate(context, ilgen);
1067 }
1068
1069 internal override void EmitCall(CodeEmitter ilgen)
1070 {
1071 DoEmit(ilgen);
1072 }
1073
1074 internal override void EmitCallvirt(CodeEmitter ilgen)
1075 {
1076 DoEmit(ilgen);
1077 }
1078
1079 internal override void EmitNewobj(CodeEmitter ilgen)
1080 {
1081 DoEmit(ilgen);
1082 }
1083
1084 }
1085
1086 internal override RuntimeJavaMethod[] GetReplacedMethodsFor(RuntimeJavaMethod mw)
1087 {
1088 var replacedMethods = ((ImportClassLoader)ClassLoader).GetReplacedMethodsFor(mw);
1089 var baseReplacedMethodWrappers = base.GetReplacedMethodsFor(mw);
1090 if (replacedMethods != null || baseReplacedMethodWrappers != null || this.replacedMethods != null)
1091 {
1092 var list = new List<RuntimeJavaMethod>();
1093
1094 if (replacedMethods != null)
1095 for (int i = 0; i < replacedMethods.Length; i++)
1096 list.Add(new ReplacedMethodWrapper(ClassLoader.LoadClassByName(replacedMethods[i].Class), replacedMethods[i].Name, replacedMethods[i].Sig, replacedMethods[i].Code));
1097
1098 if (baseReplacedMethodWrappers != null)
1099 list.AddRange(baseReplacedMethodWrappers);
1100
1101 if (this.replacedMethods != null)
1102 list.AddRange(this.replacedMethods);
1103
1104 return list.ToArray();
1105 }
1106
1107 return null;
1108 }
1109
1110 internal override bool IsFastClassLiteralSafe
1111 {
1112 get { return true; }
1113 }
1114
1115 internal RuntimeJavaMethod ReplaceMethodWrapper(RuntimeJavaMethod mw)
1116 {
1117 if (replacedMethods != null)
1118 foreach (var r in replacedMethods)
1119 if (mw.DeclaringType == r.DeclaringType && mw.Name == r.Name && mw.Signature == r.Signature)
1120 return r;
1121
1122 return mw;
1123 }
1124
1125 }
1126
1127}
global::java.lang.invoke.LambdaForm.Name Name
CodeEmitter Create(MethodBuilder mb)
Creates a new instance.
RuntimeContext Context
Gets the RuntimeContext that hosts this code emitter.
static ParameterBuilder[] GetParameterBuilders(MethodBuilder mb, int parameterCount, string[] parameterNames)
static void GetParameterNamesFromSig(string sig, string[] parameterNames)
AttributeHelper AttributeHelper
Gets the AttributeHelper associated with this instance of the runtime.
CodeEmitterFactory CodeEmitterFactory
Gets the CodeEmitterFactory associated with this instance of the runtime.
Types Types
Gets the Types associated with this instance of the runtime.
CompilerFactory CompilerFactory
Gets the CompilerFactory associated with this instance of the runtime.
ISymbolResolver Resolver
Gets the ISymbolResolver associated with this instance of the runtime.
Implementation of RuntimeClassLoader that emits loaded Java types to an AssemblyBuilder.
Implementation of RuntimeByteCodeJavaType that customizes output for the importer.
override bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m)
override TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs)
override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, RuntimeJavaField[] fields, RuntimeJavaMethod[] methods)
override void FinishGhost(TypeBuilder typeBuilder, RuntimeJavaMethod[] methods)
override MethodBuilder DefineGhostMethod(TypeBuilder typeBuilder, string name, MethodAttributes attribs, RuntimeJavaMethod mw)
override void AddMapXmlFields(ref RuntimeJavaField[] fields)
Applies fields from the map XML.
MemberFlags
Describes various options applied to a member.
record struct MethodKey(string ClassName, string MethodName, string MethodSig)
@ None
Emit no debugging information.
static DiagnosticEvent GhostInterfaceMethodMissing(string arg0, string arg1, string arg2, string arg3, Exception? exception=null, DiagnosticLocation location=default)
The 'GhostInterfaceMethodMissing' diagnostic.