~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/ikvmc/AotTypeWrapper.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2002-2009 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
 
 
25
using System;
 
26
using System.Collections.Generic;
 
27
using IKVM.Reflection;
 
28
using IKVM.Reflection.Emit;
 
29
using Type = IKVM.Reflection.Type;
 
30
using System.Diagnostics;
 
31
using System.Security;
 
32
using System.Security.Permissions;
 
33
using IKVM.Attributes;
 
34
 
 
35
namespace IKVM.Internal
 
36
{
 
37
        sealed class AotTypeWrapper : DynamicTypeWrapper
 
38
        {
 
39
                private FieldInfo ghostRefField;
 
40
                private MethodBuilder ghostIsInstanceMethod;
 
41
                private MethodBuilder ghostIsInstanceArrayMethod;
 
42
                private MethodBuilder ghostCastMethod;
 
43
                private MethodBuilder ghostCastArrayMethod;
 
44
                private TypeBuilder typeBuilderGhostInterface;
 
45
                private Annotation annotation;
 
46
                private Type enumType;
 
47
                private MethodWrapper[] replacedMethods;
 
48
                private WorkaroundBaseClass workaroundBaseClass;
 
49
 
 
50
                internal AotTypeWrapper(ClassFile f, CompilerClassLoader loader)
 
51
                        : base(f, loader)
 
52
                {
 
53
                }
 
54
 
 
55
                protected override Type GetBaseTypeForDefineType()
 
56
                {
 
57
                        TypeWrapper baseTypeWrapper = BaseTypeWrapper;
 
58
                        if (this.IsPublic && this.IsAbstract && baseTypeWrapper.IsPublic && baseTypeWrapper.IsAbstract)
 
59
                        {
 
60
                                // FXBUG
 
61
                                // if the current class widens access on an abstract base class method,
 
62
                                // we need to inject an artificial base class to workaround a C# compiler bug
 
63
                                List<MethodWrapper> methods = null;
 
64
                                foreach (MethodWrapper mw in GetMethods())
 
65
                                {
 
66
                                        if (!mw.IsStatic && mw.IsPublic)
 
67
                                        {
 
68
                                                MethodWrapper baseMethod = baseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
 
69
                                                if (baseMethod != null && baseMethod.IsAbstract && baseMethod.IsProtected)
 
70
                                                {
 
71
                                                        if (methods == null)
 
72
                                                        {
 
73
                                                                methods = new List<MethodWrapper>();
 
74
                                                        }
 
75
                                                        methods.Add(baseMethod);
 
76
                                                }
 
77
                                        }
 
78
                                }
 
79
                                if (methods != null)
 
80
                                {
 
81
                                        string name = "__WorkaroundBaseClass__." + Name;
 
82
                                        while (!classLoader.ReserveName(name))
 
83
                                        {
 
84
                                                name = "_" + name;
 
85
                                        }
 
86
                                        TypeWrapperFactory context = classLoader.GetTypeWrapperFactory();
 
87
                                        TypeBuilder typeBuilder = context.ModuleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Abstract, base.GetBaseTypeForDefineType());
 
88
                                        AttributeHelper.HideFromJava(typeBuilder);
 
89
                                        AttributeHelper.SetEditorBrowsableNever(typeBuilder);
 
90
                                        workaroundBaseClass = new WorkaroundBaseClass(this, typeBuilder, methods.ToArray());
 
91
                                        List<MethodWrapper> constructors = new List<MethodWrapper>();
 
92
                                        foreach (MethodWrapper mw in baseTypeWrapper.GetMethods())
 
93
                                        {
 
94
                                                if (ReferenceEquals(mw.Name, StringConstants.INIT) && mw.IsAccessibleFrom(baseTypeWrapper, this, this))
 
95
                                                {
 
96
                                                        constructors.Add(new ConstructorForwarder(context, typeBuilder, mw));
 
97
                                                }
 
98
                                        }
 
99
                                        replacedMethods = constructors.ToArray();
 
100
                                        return typeBuilder;
 
101
                                }
 
102
                        }
 
103
                        return base.GetBaseTypeForDefineType();
 
104
                }
 
105
 
 
106
                internal override void Finish()
 
107
                {
 
108
                        base.Finish();
 
109
                        if (workaroundBaseClass != null)
 
110
                        {
 
111
                                workaroundBaseClass.Finish();
 
112
                        }
 
113
                }
 
114
 
 
115
                private sealed class WorkaroundBaseClass
 
116
                {
 
117
                        private readonly AotTypeWrapper wrapper;
 
118
                        private readonly TypeBuilder typeBuilder;
 
119
                        private readonly MethodWrapper[] methods;
 
120
                        private MethodBuilder baseSerializationCtor;
 
121
 
 
122
                        internal WorkaroundBaseClass(AotTypeWrapper wrapper, TypeBuilder typeBuilder, MethodWrapper[] methods)
 
123
                        {
 
124
                                this.wrapper = wrapper;
 
125
                                this.typeBuilder = typeBuilder;
 
126
                                this.methods = methods;
 
127
                        }
 
128
 
 
129
                        internal MethodBuilder GetSerializationConstructor()
 
130
                        {
 
131
                                if (baseSerializationCtor == null)
 
132
                                {
 
133
                                        baseSerializationCtor = Serialization.AddAutomagicSerializationToWorkaroundBaseClass(typeBuilder, wrapper.BaseTypeWrapper.GetSerializationConstructor());
 
134
                                }
 
135
                                return baseSerializationCtor;
 
136
                        }
 
137
 
 
138
                        internal void Finish()
 
139
                        {
 
140
                                if (!typeBuilder.IsCreated())
 
141
                                {
 
142
                                        foreach (MethodWrapper mw in methods)
 
143
                                        {
 
144
                                                MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, mw.Name, MethodAttributes.FamORAssem | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.CheckAccessOnOverride);
 
145
                                                AttributeHelper.HideFromJava(mb);
 
146
                                                CodeEmitter ilgen = CodeEmitter.Create(mb);
 
147
                                                ilgen.EmitThrow("java.lang.AbstractMethodError");
 
148
                                                ilgen.DoEmit();
 
149
                                        }
 
150
                                        typeBuilder.CreateType();
 
151
                                }
 
152
                        }
 
153
                }
 
154
 
 
155
                private sealed class ConstructorForwarder : MethodWrapper
 
156
                {
 
157
                        private readonly TypeWrapperFactory context;
 
158
                        private readonly TypeBuilder typeBuilder;
 
159
                        private readonly MethodWrapper ctor;
 
160
                        private MethodBuilder constructorBuilder;
 
161
 
 
162
                        internal ConstructorForwarder(TypeWrapperFactory context, TypeBuilder typeBuilder, MethodWrapper ctor)
 
163
                                : base(ctor.DeclaringType, ctor.Name, ctor.Signature, null, null, null, ctor.Modifiers, MemberFlags.None)
 
164
                        {
 
165
                                this.context = context;
 
166
                                this.typeBuilder = typeBuilder;
 
167
                                this.ctor = ctor;
 
168
                        }
 
169
 
 
170
                        protected override void DoLinkMethod()
 
171
                        {
 
172
                                ctor.Link();
 
173
                                DefineMethodHelper dmh = ctor.GetDefineMethodHelper();
 
174
                                constructorBuilder = dmh.DefineConstructor(context, typeBuilder, MethodAttributes.PrivateScope);
 
175
                                AttributeHelper.HideFromJava(constructorBuilder);
 
176
                                CodeEmitter ilgen = CodeEmitter.Create(constructorBuilder);
 
177
                                ilgen.Emit(OpCodes.Ldarg_0);
 
178
                                for (int i = 1; i <= dmh.ParameterCount; i++)
 
179
                                {
 
180
                                        ilgen.EmitLdarg(i);
 
181
                                }
 
182
                                ctor.EmitCall(ilgen);
 
183
                                ilgen.Emit(OpCodes.Ret);
 
184
                                ilgen.DoEmit();
 
185
                        }
 
186
 
 
187
                        internal override void EmitCall(CodeEmitter ilgen)
 
188
                        {
 
189
                                ilgen.Emit(OpCodes.Call, constructorBuilder);
 
190
                        }
 
191
                }
 
192
 
 
193
                internal override bool IsGhost
 
194
                {
 
195
                        get
 
196
                        {
 
197
                                return classLoader.IsGhost(this);
 
198
                        }
 
199
                }
 
200
 
 
201
                internal override bool IsMapUnsafeException
 
202
                {
 
203
                        get
 
204
                        {
 
205
                                return classLoader.IsMapUnsafeException(this);
 
206
                        }
 
207
                }
 
208
 
 
209
                internal override Type TypeAsBaseType
 
210
                {
 
211
                        get
 
212
                        {
 
213
                                return typeBuilderGhostInterface != null ? typeBuilderGhostInterface : base.TypeAsBaseType;
 
214
                        }
 
215
                }
 
216
 
 
217
                internal void GetParameterNamesFromXml(string methodName, string methodSig, string[] parameterNames)
 
218
                {
 
219
                        IKVM.Internal.MapXml.Param[] parameters = classLoader.GetXmlMapParameters(Name, methodName, methodSig);
 
220
                        if(parameters != null)
 
221
                        {
 
222
                                for(int i = 0; i < parameters.Length; i++)
 
223
                                {
 
224
                                        if(parameters[i].Name != null)
 
225
                                        {
 
226
                                                parameterNames[i] = parameters[i].Name;
 
227
                                        }
 
228
                                }
 
229
                        }
 
230
                }
 
231
 
 
232
                internal void AddXmlMapParameterAttributes(MethodBuilder method, string className, string methodName, string methodSig, ref ParameterBuilder[] pbs)
 
233
                {
 
234
                        IKVM.Internal.MapXml.Param[] parameters = classLoader.GetXmlMapParameters(className, methodName, methodSig);
 
235
                        if(parameters != null)
 
236
                        {
 
237
                                if(pbs == null)
 
238
                                {
 
239
                                        // let's hope that the parameters array is the right length
 
240
                                        pbs = GetParameterBuilders(method, parameters.Length, null);
 
241
                                }
 
242
                                for(int i = 0; i < pbs.Length; i++)
 
243
                                {
 
244
                                        if(parameters[i].Attributes != null)
 
245
                                        {
 
246
                                                foreach(IKVM.Internal.MapXml.Attribute attr in parameters[i].Attributes)
 
247
                                                {
 
248
                                                        AttributeHelper.SetCustomAttribute(classLoader, pbs[i], attr);
 
249
                                                }
 
250
                                        }
 
251
                                }
 
252
                        }
 
253
                }
 
254
 
 
255
                private void AddParameterMetadata(MethodBuilder method, MethodWrapper mw)
 
256
                {
 
257
                        ParameterBuilder[] pbs;
 
258
                        if((mw.DeclaringType.IsPublic && (mw.IsPublic || mw.IsProtected)) || classLoader.EmitDebugInfo)
 
259
                        {
 
260
                                string[] parameterNames = new string[mw.GetParameters().Length];
 
261
                                GetParameterNamesFromXml(mw.Name, mw.Signature, parameterNames);
 
262
                                GetParameterNamesFromSig(mw.Signature, parameterNames);
 
263
                                pbs = GetParameterBuilders(method, parameterNames.Length, parameterNames);
 
264
                        }
 
265
                        else
 
266
                        {
 
267
                                pbs = GetParameterBuilders(method, mw.GetParameters().Length, null);
 
268
                        }
 
269
                        if((mw.Modifiers & Modifiers.VarArgs) != 0 && pbs.Length > 0)
 
270
                        {
 
271
                                AttributeHelper.SetParamArrayAttribute(pbs[pbs.Length - 1]);
 
272
                        }
 
273
                        AddXmlMapParameterAttributes(method, Name, mw.Name, mw.Signature, ref pbs);
 
274
                }
 
275
 
 
276
                protected override void AddMapXmlFields(ref FieldWrapper[] fields)
 
277
                {
 
278
                        Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses();
 
279
                        if(mapxml != null)
 
280
                        {
 
281
                                IKVM.Internal.MapXml.Class clazz;
 
282
                                if(mapxml.TryGetValue(this.Name, out clazz))
 
283
                                {
 
284
                                        if(clazz.Fields != null)
 
285
                                        {
 
286
                                                foreach(IKVM.Internal.MapXml.Field field in clazz.Fields)
 
287
                                                {
 
288
                                                        // are we adding a new field?
 
289
                                                        bool found = false;
 
290
                                                        foreach(FieldWrapper fw in fields)
 
291
                                                        {
 
292
                                                                if(fw.Name == field.Name && fw.Signature == field.Sig)
 
293
                                                                {
 
294
                                                                        found = true;
 
295
                                                                        break;
 
296
                                                                }
 
297
                                                        }
 
298
                                                        if(!found)
 
299
                                                        {
 
300
                                                                FieldWrapper[] newFields = new FieldWrapper[fields.Length + 1];
 
301
                                                                Array.Copy(fields, newFields, fields.Length);
 
302
                                                                fields = newFields;
 
303
                                                                fields[fields.Length - 1] = FieldWrapper.Create(this, null, null, field.Name, field.Sig, new ExModifiers((Modifiers)field.Modifiers, false));
 
304
                                                        }
 
305
                                                }
 
306
                                        }
 
307
                                }                               
 
308
                        }
 
309
                }
 
310
 
 
311
                protected override bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m)
 
312
                {
 
313
                        IKVM.Internal.MapXml.InstructionList prologue = classLoader.GetMethodPrologue(new MethodKey(f.Name, m.Name, m.Signature));
 
314
                        if(prologue != null)
 
315
                        {
 
316
                                prologue.Emit(classLoader, ilgen);
 
317
                        }
 
318
                        Dictionary<MethodKey, IKVM.Internal.MapXml.InstructionList> mapxml = classLoader.GetMapXmlMethodBodies();
 
319
                        if(mapxml != null)
 
320
                        {
 
321
                                IKVM.Internal.MapXml.InstructionList opcodes;
 
322
                                if(mapxml.TryGetValue(new MethodKey(f.Name, m.Name, m.Signature), out opcodes))
 
323
                                {
 
324
                                        opcodes.Emit(classLoader, ilgen);
 
325
                                        return true;
 
326
                                }
 
327
                        }
 
328
                        return false;
 
329
                }
 
330
 
 
331
                private void PublishAttributes(TypeBuilder typeBuilder, IKVM.Internal.MapXml.Class clazz)
 
332
                {
 
333
                        foreach(IKVM.Internal.MapXml.Attribute attr in clazz.Attributes)
 
334
                        {
 
335
                                AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, attr);
 
336
                        }
 
337
                }
 
338
 
 
339
                private static bool CheckPropertyArgs(Type[] args1, Type[] args2)
 
340
                {
 
341
                        if(args1.Length == args2.Length)
 
342
                        {
 
343
                                for(int i = 0; i < args1.Length; i++)
 
344
                                {
 
345
                                        if(args1[i] != args2[i])
 
346
                                        {
 
347
                                                return false;
 
348
                                        }
 
349
                                }
 
350
                                return true;
 
351
                        }
 
352
                        return false;
 
353
                }
 
354
 
 
355
                private static MethodAttributes GetPropertyMethodAttributes(MethodWrapper mw, bool final)
 
356
                {
 
357
                        MethodAttributes attribs = MethodAttributes.HideBySig;
 
358
                        if(mw.IsStatic)
 
359
                        {
 
360
                                attribs |= MethodAttributes.Static;
 
361
                        }
 
362
                        else
 
363
                        {
 
364
                                // NOTE in order for IntelliSense to consider the property a "real" property,
 
365
                                // the getter and setter methods need to have substantially the same method attributes,
 
366
                                // so we may need to look at our peer to determine whether we should be final
 
367
                                // or not (and vice versa).
 
368
                                attribs |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride;
 
369
                                if(final)
 
370
                                {
 
371
                                        attribs |= MethodAttributes.Final;
 
372
                                }
 
373
                        }
 
374
                        // TODO what happens if accessibility doesn't match our peer?
 
375
                        if(mw.IsPublic)
 
376
                        {
 
377
                                attribs |= MethodAttributes.Public;
 
378
                        }
 
379
                        else if(mw.IsProtected)
 
380
                        {
 
381
                                attribs |= MethodAttributes.FamORAssem;
 
382
                        }
 
383
                        else if(mw.IsPrivate)
 
384
                        {
 
385
                                attribs |= MethodAttributes.Private;
 
386
                        }
 
387
                        else
 
388
                        {
 
389
                                attribs |= MethodAttributes.Assembly;
 
390
                        }
 
391
                        return attribs;
 
392
                }
 
393
 
 
394
                private void PublishProperties(TypeBuilder typeBuilder, IKVM.Internal.MapXml.Class clazz)
 
395
                {
 
396
                        foreach(IKVM.Internal.MapXml.Property prop in clazz.Properties)
 
397
                        {
 
398
                                TypeWrapper typeWrapper = GetClassLoader().RetTypeWrapperFromSigNoThrow(prop.Sig);
 
399
                                TypeWrapper[] propargs = GetClassLoader().ArgTypeWrapperListFromSigNoThrow(prop.Sig);
 
400
                                Type[] indexer = new Type[propargs.Length];
 
401
                                for(int i = 0; i < propargs.Length; i++)
 
402
                                {
 
403
                                        indexer[i] = propargs[i].TypeAsSignatureType;
 
404
                                }
 
405
                                PropertyBuilder propbuilder = typeBuilder.DefineProperty(prop.Name, PropertyAttributes.None, typeWrapper.TypeAsSignatureType, indexer);
 
406
                                AttributeHelper.HideFromJava(propbuilder);
 
407
                                if(prop.Attributes != null)
 
408
                                {
 
409
                                        foreach(IKVM.Internal.MapXml.Attribute attr in prop.Attributes)
 
410
                                        {
 
411
                                                AttributeHelper.SetCustomAttribute(classLoader, propbuilder, attr);
 
412
                                        }
 
413
                                }
 
414
                                MethodWrapper getter = null;
 
415
                                MethodWrapper setter = null;
 
416
                                if(prop.getter != null)
 
417
                                {
 
418
                                        getter = GetMethodWrapper(prop.getter.Name, prop.getter.Sig, true);
 
419
                                        if(getter == null)
 
420
                                        {
 
421
                                                Console.Error.WriteLine("Warning: getter not found for {0}::{1}", clazz.Name, prop.Name);
 
422
                                        }
 
423
                                }
 
424
                                if(prop.setter != null)
 
425
                                {
 
426
                                        setter = GetMethodWrapper(prop.setter.Name, prop.setter.Sig, true);
 
427
                                        if(setter == null)
 
428
                                        {
 
429
                                                Console.Error.WriteLine("Warning: setter not found for {0}::{1}", clazz.Name, prop.Name);
 
430
                                        }
 
431
                                }
 
432
                                bool final = (getter != null && getter.IsFinal) || (setter != null && setter.IsFinal);
 
433
                                if(getter != null)
 
434
                                {
 
435
                                        MethodWrapper mw = getter;
 
436
                                        if(!CheckPropertyArgs(mw.GetParametersForDefineMethod(), indexer) || mw.ReturnType != typeWrapper)
 
437
                                        {
 
438
                                                Console.Error.WriteLine("Warning: ignoring invalid property getter for {0}::{1}", clazz.Name, prop.Name);
 
439
                                        }
 
440
                                        else
 
441
                                        {
 
442
                                                MethodBuilder mb = mw.GetMethod() as MethodBuilder;
 
443
                                                if(mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final))
 
444
                                                {
 
445
                                                        mb = typeBuilder.DefineMethod("get_" + prop.Name, GetPropertyMethodAttributes(mw, final), typeWrapper.TypeAsSignatureType, indexer);
 
446
                                                        AttributeHelper.HideFromJava(mb);
 
447
                                                        CodeEmitter ilgen = CodeEmitter.Create(mb);
 
448
                                                        if(mw.IsStatic)
 
449
                                                        {
 
450
                                                                for(int i = 0; i < indexer.Length; i++)
 
451
                                                                {
 
452
                                                                        ilgen.EmitLdarg(i);
 
453
                                                                }
 
454
                                                                mw.EmitCall(ilgen);
 
455
                                                        }
 
456
                                                        else
 
457
                                                        {
 
458
                                                                ilgen.Emit(OpCodes.Ldarg_0);
 
459
                                                                for(int i = 0; i < indexer.Length; i++)
 
460
                                                                {
 
461
                                                                        ilgen.EmitLdarg(i + 1);
 
462
                                                                }
 
463
                                                                mw.EmitCallvirt(ilgen);
 
464
                                                        }
 
465
                                                        ilgen.Emit(OpCodes.Ret);
 
466
                                                        ilgen.DoEmit();
 
467
                                                }
 
468
                                                propbuilder.SetGetMethod(mb);
 
469
                                        }
 
470
                                }
 
471
                                if(setter != null)
 
472
                                {
 
473
                                        MethodWrapper mw = setter;
 
474
                                        Type[] args = new Type[indexer.Length + 1];
 
475
                                        indexer.CopyTo(args, 0);
 
476
                                        args[args.Length - 1] = typeWrapper.TypeAsSignatureType;
 
477
                                        if(!CheckPropertyArgs(args, mw.GetParametersForDefineMethod()))
 
478
                                        {
 
479
                                                Console.Error.WriteLine("Warning: ignoring invalid property setter for {0}::{1}", clazz.Name, prop.Name);
 
480
                                        }
 
481
                                        else
 
482
                                        {
 
483
                                                MethodBuilder mb = mw.GetMethod() as MethodBuilder;
 
484
                                                if(mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final))
 
485
                                                {
 
486
                                                        mb = typeBuilder.DefineMethod("set_" + prop.Name, GetPropertyMethodAttributes(mw, final), mw.ReturnTypeForDefineMethod, args);
 
487
                                                        AttributeHelper.HideFromJava(mb);
 
488
                                                        CodeEmitter ilgen = CodeEmitter.Create(mb);
 
489
                                                        if(mw.IsStatic)
 
490
                                                        {
 
491
                                                                for(int i = 0; i <= indexer.Length; i++)
 
492
                                                                {
 
493
                                                                        ilgen.EmitLdarg(i);
 
494
                                                                }
 
495
                                                                mw.EmitCall(ilgen);
 
496
                                                        }
 
497
                                                        else
 
498
                                                        {
 
499
                                                                ilgen.Emit(OpCodes.Ldarg_0);
 
500
                                                                for(int i = 0; i <= indexer.Length; i++)
 
501
                                                                {
 
502
                                                                        ilgen.EmitLdarg(i + 1);
 
503
                                                                }
 
504
                                                                mw.EmitCallvirt(ilgen);
 
505
                                                        }
 
506
                                                        ilgen.Emit(OpCodes.Ret);
 
507
                                                        ilgen.DoEmit();
 
508
                                                }
 
509
                                                propbuilder.SetSetMethod(mb);
 
510
                                        }
 
511
                                }
 
512
                        }
 
513
                }
 
514
 
 
515
                protected override bool IsPInvokeMethod(ClassFile.Method m)
 
516
                {
 
517
                        Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses();
 
518
                        if(mapxml != null)
 
519
                        {
 
520
                                IKVM.Internal.MapXml.Class clazz;
 
521
                                if(mapxml.TryGetValue(this.Name, out clazz) && clazz.Methods != null)
 
522
                                {
 
523
                                        foreach(IKVM.Internal.MapXml.Method method in clazz.Methods)
 
524
                                        {
 
525
                                                if(method.Name == m.Name && method.Sig == m.Signature)
 
526
                                                {
 
527
                                                        if(method.Attributes != null)
 
528
                                                        {
 
529
                                                                foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes)
 
530
                                                                {
 
531
                                                                        if(StaticCompiler.GetType(classLoader, attr.Type) == JVM.Import(typeof(System.Runtime.InteropServices.DllImportAttribute)))
 
532
                                                                        {
 
533
                                                                                return true;
 
534
                                                                        }
 
535
                                                                }
 
536
                                                        }
 
537
                                                        break;
 
538
                                                }
 
539
                                        }
 
540
                                }
 
541
                        }
 
542
                        return base.IsPInvokeMethod(m);
 
543
                }
 
544
 
 
545
                private static void MapModifiers(MapXml.MapModifiers mapmods, bool isConstructor, out bool setmodifiers, ref MethodAttributes attribs)
 
546
                {
 
547
                        setmodifiers = false;
 
548
                        Modifiers modifiers = (Modifiers)mapmods;
 
549
                        if((modifiers & Modifiers.Public) != 0)
 
550
                        {
 
551
                                attribs |= MethodAttributes.Public;
 
552
                        }
 
553
                        else if((modifiers & Modifiers.Protected) != 0)
 
554
                        {
 
555
                                attribs |= MethodAttributes.FamORAssem;
 
556
                        }
 
557
                        else if((modifiers & Modifiers.Private) != 0)
 
558
                        {
 
559
                                attribs |= MethodAttributes.Private;
 
560
                        }
 
561
                        else
 
562
                        {
 
563
                                attribs |= MethodAttributes.Assembly;
 
564
                        }
 
565
                        if((modifiers & Modifiers.Static) != 0)
 
566
                        {
 
567
                                attribs |= MethodAttributes.Static;
 
568
                                if((modifiers & Modifiers.Final) != 0)
 
569
                                {
 
570
                                        setmodifiers = true;
 
571
                                }
 
572
                        }
 
573
                        else if(!isConstructor)
 
574
                        {
 
575
                                // NOTE we're abusing the MethodAttributes.NewSlot and Modifiers.Final combination to mean non-virtual
 
576
                                if((modifiers & Modifiers.Final) != 0 && (attribs & MethodAttributes.NewSlot) != 0 && (attribs & MethodAttributes.Virtual) == 0)
 
577
                                {
 
578
                                        // remove NewSlot, because it doesn't make sense on a non-virtual method
 
579
                                        attribs &= ~MethodAttributes.NewSlot;
 
580
                                }
 
581
                                else
 
582
                                {
 
583
                                        attribs |= MethodAttributes.Virtual;
 
584
                                        if((modifiers & Modifiers.Final) != 0)
 
585
                                        {
 
586
                                                attribs |= MethodAttributes.Final;
 
587
                                        }
 
588
                                        else if((modifiers & Modifiers.Abstract) != 0)
 
589
                                        {
 
590
                                                attribs |= MethodAttributes.Abstract;
 
591
                                        }
 
592
                                }
 
593
                        }
 
594
                        if((modifiers & Modifiers.Synchronized) != 0)
 
595
                        {
 
596
                                throw new NotImplementedException();
 
597
                        }
 
598
                }
 
599
 
 
600
                private void MapSignature(string sig, out Type returnType, out Type[] parameterTypes)
 
601
                {
 
602
                        returnType = GetClassLoader().RetTypeWrapperFromSigNoThrow(sig).TypeAsSignatureType;
 
603
                        TypeWrapper[] parameterTypeWrappers = GetClassLoader().ArgTypeWrapperListFromSigNoThrow(sig);
 
604
                        parameterTypes = new Type[parameterTypeWrappers.Length];
 
605
                        for(int i = 0; i < parameterTypeWrappers.Length; i++)
 
606
                        {
 
607
                                parameterTypes[i] = parameterTypeWrappers[i].TypeAsSignatureType;
 
608
                        }
 
609
                }
 
610
 
 
611
                protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods)
 
612
                {
 
613
                        Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses();
 
614
                        if(mapxml != null)
 
615
                        {
 
616
                                IKVM.Internal.MapXml.Class clazz;
 
617
                                if(mapxml.TryGetValue(classFile.Name, out clazz))
 
618
                                {
 
619
                                        if(clazz.Attributes != null)
 
620
                                        {
 
621
                                                PublishAttributes(typeBuilder, clazz);
 
622
                                        }
 
623
                                        if(clazz.Properties != null)
 
624
                                        {
 
625
                                                PublishProperties(typeBuilder, clazz);
 
626
                                        }
 
627
                                        if(clazz.Fields != null)
 
628
                                        {
 
629
                                                foreach(IKVM.Internal.MapXml.Field field in clazz.Fields)
 
630
                                                {
 
631
                                                        if(field.Attributes != null)
 
632
                                                        {
 
633
                                                                foreach(FieldWrapper fw in fields)
 
634
                                                                {
 
635
                                                                        if(fw.Name == field.Name && fw.Signature == field.Sig)
 
636
                                                                        {
 
637
                                                                                FieldBuilder fb = fw.GetField() as FieldBuilder;
 
638
                                                                                if(fb != null)
 
639
                                                                                {
 
640
                                                                                        foreach(IKVM.Internal.MapXml.Attribute attr in field.Attributes)
 
641
                                                                                        {
 
642
                                                                                                AttributeHelper.SetCustomAttribute(classLoader, fb, attr);
 
643
                                                                                        }
 
644
                                                                                }
 
645
                                                                        }
 
646
                                                                }
 
647
                                                        }
 
648
                                                }
 
649
                                        }
 
650
                                        if(clazz.Constructors != null)
 
651
                                        {
 
652
                                                // HACK this isn't the right place to do this, but for now it suffices
 
653
                                                foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors)
 
654
                                                {
 
655
                                                        // are we adding a new constructor?
 
656
                                                        if(GetMethodWrapper(StringConstants.INIT, constructor.Sig, false) == null)
 
657
                                                        {
 
658
                                                                if(constructor.body == null)
 
659
                                                                {
 
660
                                                                        Console.Error.WriteLine("Error: Constructor {0}.<init>{1} in xml remap file doesn't have a body.", clazz.Name, constructor.Sig);
 
661
                                                                        continue;
 
662
                                                                }
 
663
                                                                bool setmodifiers = false;
 
664
                                                                MethodAttributes attribs = 0;
 
665
                                                                MapModifiers(constructor.Modifiers, true, out setmodifiers, ref attribs);
 
666
                                                                Type returnType;
 
667
                                                                Type[] parameterTypes;
 
668
                                                                MapSignature(constructor.Sig, out returnType, out parameterTypes);
 
669
                                                                MethodBuilder cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes);
 
670
                                                                if(setmodifiers)
 
671
                                                                {
 
672
                                                                        AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false);
 
673
                                                                }
 
674
                                                                CompilerClassLoader.AddDeclaredExceptions(cb, constructor.throws);
 
675
                                                                CodeEmitter ilgen = CodeEmitter.Create(cb);
 
676
                                                                constructor.Emit(classLoader, ilgen);
 
677
                                                                ilgen.DoEmit();
 
678
                                                                if(constructor.Attributes != null)
 
679
                                                                {
 
680
                                                                        foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes)
 
681
                                                                        {
 
682
                                                                                AttributeHelper.SetCustomAttribute(classLoader, cb, attr);
 
683
                                                                        }
 
684
                                                                }
 
685
                                                        }
 
686
                                                }
 
687
                                                foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors)
 
688
                                                {
 
689
                                                        if(constructor.Attributes != null)
 
690
                                                        {
 
691
                                                                foreach(MethodWrapper mw in methods)
 
692
                                                                {
 
693
                                                                        if(mw.Name == "<init>" && mw.Signature == constructor.Sig)
 
694
                                                                        {
 
695
                                                                                MethodBuilder mb = mw.GetMethod() as MethodBuilder;
 
696
                                                                                if(mb != null)
 
697
                                                                                {
 
698
                                                                                        foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes)
 
699
                                                                                        {
 
700
                                                                                                AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
 
701
                                                                                        }
 
702
                                                                                }
 
703
                                                                        }
 
704
                                                                }
 
705
                                                        }
 
706
                                                }
 
707
                                        }
 
708
                                        if(clazz.Methods != null)
 
709
                                        {
 
710
                                                // HACK this isn't the right place to do this, but for now it suffices
 
711
                                                foreach(IKVM.Internal.MapXml.Method method in clazz.Methods)
 
712
                                                {
 
713
                                                        // are we adding a new method?
 
714
                                                        if(GetMethodWrapper(method.Name, method.Sig, false) == null)
 
715
                                                        {
 
716
                                                                if(method.body == null)
 
717
                                                                {
 
718
                                                                        Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig);
 
719
                                                                        continue;
 
720
                                                                }
 
721
                                                                bool setmodifiers = false;
 
722
                                                                MethodAttributes attribs = method.MethodAttributes;
 
723
                                                                MapModifiers(method.Modifiers, false, out setmodifiers, ref attribs);
 
724
                                                                Type returnType;
 
725
                                                                Type[] parameterTypes;
 
726
                                                                MapSignature(method.Sig, out returnType, out parameterTypes);
 
727
                                                                MethodBuilder mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes);
 
728
                                                                if(setmodifiers)
 
729
                                                                {
 
730
                                                                        AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false);
 
731
                                                                }
 
732
                                                                if(method.@override != null)
 
733
                                                                {
 
734
                                                                        MethodWrapper mw = GetClassLoader().LoadClassByDottedName(method.@override.Class).GetMethodWrapper(method.@override.Name, method.Sig, true);
 
735
                                                                        mw.Link();
 
736
                                                                        typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
 
737
                                                                }
 
738
                                                                CompilerClassLoader.AddDeclaredExceptions(mb, method.throws);
 
739
                                                                CodeEmitter ilgen = CodeEmitter.Create(mb);
 
740
                                                                method.Emit(classLoader, ilgen);
 
741
                                                                ilgen.DoEmit();
 
742
                                                                if(method.Attributes != null)
 
743
                                                                {
 
744
                                                                        foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes)
 
745
                                                                        {
 
746
                                                                                AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
 
747
                                                                        }
 
748
                                                                }
 
749
                                                        }
 
750
                                                }
 
751
                                                foreach(IKVM.Internal.MapXml.Method method in clazz.Methods)
 
752
                                                {
 
753
                                                        if(method.Attributes != null)
 
754
                                                        {
 
755
                                                                foreach(MethodWrapper mw in methods)
 
756
                                                                {
 
757
                                                                        if(mw.Name == method.Name && mw.Signature == method.Sig)
 
758
                                                                        {
 
759
                                                                                MethodBuilder mb = mw.GetMethod() as MethodBuilder;
 
760
                                                                                if(mb != null)
 
761
                                                                                {
 
762
                                                                                        foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes)
 
763
                                                                                        {
 
764
                                                                                                AttributeHelper.SetCustomAttribute(classLoader, mb, attr);
 
765
                                                                                        }
 
766
                                                                                }
 
767
                                                                        }
 
768
                                                                }
 
769
                                                        }
 
770
                                                }
 
771
                                        }
 
772
                                        if(clazz.Interfaces != null)
 
773
                                        {
 
774
                                                foreach(IKVM.Internal.MapXml.Interface iface in clazz.Interfaces)
 
775
                                                {
 
776
                                                        TypeWrapper tw = GetClassLoader().LoadClassByDottedName(iface.Name);
 
777
                                                        // NOTE since this interface won't be part of the list in the ImplementAttribute,
 
778
                                                        // it won't be visible from Java that the type implements this interface.
 
779
                                                        typeBuilder.AddInterfaceImplementation(tw.TypeAsBaseType);
 
780
                                                        if(iface.Methods != null)
 
781
                                                        {
 
782
                                                                foreach(IKVM.Internal.MapXml.Method m in iface.Methods)
 
783
                                                                {
 
784
                                                                        MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false);
 
785
                                                                        if(mw == null)
 
786
                                                                        {
 
787
                                                                                throw new InvalidOperationException("Method " + m.Name + m.Sig + " not found in interface " + tw.Name);
 
788
                                                                        }
 
789
                                                                        mw.Link();
 
790
                                                                        MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(this, typeBuilder, tw.Name + "/" + m.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.CheckAccessOnOverride);
 
791
                                                                        AttributeHelper.HideFromJava(mb);
 
792
                                                                        typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
 
793
                                                                        CodeEmitter ilgen = CodeEmitter.Create(mb);
 
794
                                                                        m.Emit(classLoader, ilgen);
 
795
                                                                        ilgen.DoEmit();
 
796
                                                                }
 
797
                                                        }
 
798
                                                }
 
799
                                        }
 
800
                                }
 
801
                        }
 
802
                }
 
803
 
 
804
                protected override MethodBuilder DefineGhostMethod(string name, MethodAttributes attribs, MethodWrapper mw)
 
805
                {
 
806
                        if(typeBuilderGhostInterface != null)
 
807
                        {
 
808
                                return mw.GetDefineMethodHelper().DefineMethod(this, typeBuilderGhostInterface, name, attribs);
 
809
                        }
 
810
                        return null;
 
811
                }
 
812
 
 
813
                protected override void FinishGhost(TypeBuilder typeBuilder, MethodWrapper[] methods)
 
814
                {
 
815
                        if(typeBuilderGhostInterface != null)
 
816
                        {
 
817
                                // TODO consider adding methods from base interface and java.lang.Object as well
 
818
                                for(int i = 0; i < methods.Length; i++)
 
819
                                {
 
820
                                        // skip <clinit>
 
821
                                        if(!methods[i].IsStatic)
 
822
                                        {
 
823
                                                TypeWrapper[] args = methods[i].GetParameters();
 
824
                                                MethodBuilder stub = methods[i].GetDefineMethodHelper().DefineMethod(this, typeBuilder, methods[i].Name, MethodAttributes.Public);
 
825
                                                AddParameterMetadata(stub, methods[i]);
 
826
                                                AttributeHelper.SetModifiers(stub, methods[i].Modifiers, methods[i].IsInternal);
 
827
                                                CodeEmitter ilgen = CodeEmitter.Create(stub);
 
828
                                                CodeEmitterLabel end = ilgen.DefineLabel();
 
829
                                                TypeWrapper[] implementers = classLoader.GetGhostImplementers(this);
 
830
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
831
                                                ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
832
                                                ilgen.Emit(OpCodes.Dup);
 
833
                                                ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface);
 
834
                                                CodeEmitterLabel label = ilgen.DefineLabel();
 
835
                                                ilgen.EmitBrfalse(label);
 
836
                                                ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface);
 
837
                                                for(int k = 0; k < args.Length; k++)
 
838
                                                {
 
839
                                                        ilgen.EmitLdarg(k + 1);
 
840
                                                }
 
841
                                                ilgen.Emit(OpCodes.Callvirt, (MethodInfo)methods[i].GetMethod());
 
842
                                                ilgen.EmitBr(end);
 
843
                                                ilgen.MarkLabel(label);
 
844
                                                for(int j = 0; j < implementers.Length; j++)
 
845
                                                {
 
846
                                                        ilgen.Emit(OpCodes.Dup);
 
847
                                                        ilgen.Emit(OpCodes.Isinst, implementers[j].TypeAsTBD);
 
848
                                                        label = ilgen.DefineLabel();
 
849
                                                        ilgen.EmitBrfalse(label);
 
850
                                                        ilgen.Emit(OpCodes.Castclass, implementers[j].TypeAsTBD);
 
851
                                                        for(int k = 0; k < args.Length; k++)
 
852
                                                        {
 
853
                                                                ilgen.EmitLdarg(k + 1);
 
854
                                                        }
 
855
                                                        MethodWrapper mw = implementers[j].GetMethodWrapper(methods[i].Name, methods[i].Signature, true);
 
856
                                                        mw.EmitCallvirt(ilgen);
 
857
                                                        ilgen.EmitBr(end);
 
858
                                                        ilgen.MarkLabel(label);
 
859
                                                }
 
860
                                                // we need to do a null check (null fails all the isinst checks)
 
861
                                                ilgen.EmitNullCheck();
 
862
                                                ilgen.EmitThrow("java.lang.IncompatibleClassChangeError", Name);
 
863
                                                ilgen.MarkLabel(end);
 
864
                                                ilgen.Emit(OpCodes.Ret);
 
865
                                                ilgen.DoEmit();
 
866
                                        }
 
867
                                }
 
868
                                // HACK create a scope to enable reuse of "implementers" name
 
869
                                if(true)
 
870
                                {
 
871
                                        MethodBuilder mb;
 
872
                                        CodeEmitter ilgen;
 
873
                                        CodeEmitterLocal local;
 
874
                                        // add implicit conversions for all the ghost implementers
 
875
                                        TypeWrapper[] implementers = classLoader.GetGhostImplementers(this);
 
876
                                        for(int i = 0; i < implementers.Length; i++)
 
877
                                        {
 
878
                                                mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, TypeAsSignatureType, new Type[] { implementers[i].TypeAsSignatureType });
 
879
                                                AttributeHelper.HideFromJava(mb);
 
880
                                                ilgen = CodeEmitter.Create(mb);
 
881
                                                local = ilgen.DeclareLocal(TypeAsSignatureType);
 
882
                                                ilgen.Emit(OpCodes.Ldloca, local);
 
883
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
884
                                                ilgen.Emit(OpCodes.Stfld, ghostRefField);
 
885
                                                ilgen.Emit(OpCodes.Ldloca, local);
 
886
                                                ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType);                 
 
887
                                                ilgen.Emit(OpCodes.Ret);
 
888
                                                ilgen.DoEmit();
 
889
                                        }
 
890
                                        // Implement the "IsInstance" method
 
891
                                        mb = ghostIsInstanceMethod;
 
892
                                        AttributeHelper.HideFromJava(mb);
 
893
                                        ilgen = CodeEmitter.Create(mb);
 
894
                                        CodeEmitterLabel end = ilgen.DefineLabel();
 
895
                                        for(int i = 0; i < implementers.Length; i++)
 
896
                                        {
 
897
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
898
                                                ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD);
 
899
                                                CodeEmitterLabel label = ilgen.DefineLabel();
 
900
                                                ilgen.EmitBrfalse(label);
 
901
                                                ilgen.Emit(OpCodes.Ldc_I4_1);
 
902
                                                ilgen.EmitBr(end);
 
903
                                                ilgen.MarkLabel(label);
 
904
                                        }
 
905
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
906
                                        ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface);
 
907
                                        ilgen.Emit(OpCodes.Ldnull);
 
908
                                        ilgen.Emit(OpCodes.Cgt_Un);
 
909
                                        ilgen.MarkLabel(end);
 
910
                                        ilgen.Emit(OpCodes.Ret);
 
911
                                        ilgen.DoEmit();
 
912
                                        // Implement the "IsInstanceArray" method
 
913
                                        mb = ghostIsInstanceArrayMethod;
 
914
                                        AttributeHelper.HideFromJava(mb);
 
915
                                        ilgen = CodeEmitter.Create(mb);
 
916
                                        CodeEmitterLocal localType = ilgen.DeclareLocal(Types.Type);
 
917
                                        CodeEmitterLocal localRank = ilgen.DeclareLocal(Types.Int32);
 
918
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
919
                                        CodeEmitterLabel skip = ilgen.DefineLabel();
 
920
                                        ilgen.EmitBrtrue(skip);
 
921
                                        ilgen.Emit(OpCodes.Ldc_I4_0);
 
922
                                        ilgen.Emit(OpCodes.Ret);
 
923
                                        ilgen.MarkLabel(skip);
 
924
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
925
                                        ilgen.Emit(OpCodes.Call, Compiler.getTypeMethod);
 
926
                                        ilgen.Emit(OpCodes.Stloc, localType);
 
927
                                        ilgen.Emit(OpCodes.Ldarg_1);
 
928
                                        ilgen.Emit(OpCodes.Stloc, localRank);
 
929
                                        skip = ilgen.DefineLabel();
 
930
                                        ilgen.EmitBr(skip);
 
931
                                        CodeEmitterLabel iter = ilgen.DefineLabel();
 
932
                                        ilgen.MarkLabel(iter);
 
933
                                        ilgen.Emit(OpCodes.Ldloc, localType);
 
934
                                        ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("GetElementType"));
 
935
                                        ilgen.Emit(OpCodes.Stloc, localType);
 
936
                                        ilgen.Emit(OpCodes.Ldloc, localRank);
 
937
                                        ilgen.Emit(OpCodes.Ldc_I4_1);
 
938
                                        ilgen.Emit(OpCodes.Sub);
 
939
                                        ilgen.Emit(OpCodes.Stloc, localRank);
 
940
                                        ilgen.Emit(OpCodes.Ldloc, localRank);
 
941
                                        CodeEmitterLabel typecheck = ilgen.DefineLabel();
 
942
                                        ilgen.EmitBrfalse(typecheck);
 
943
                                        ilgen.MarkLabel(skip);
 
944
                                        ilgen.Emit(OpCodes.Ldloc, localType);
 
945
                                        ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("get_IsArray"));
 
946
                                        ilgen.EmitBrtrue(iter);
 
947
                                        ilgen.Emit(OpCodes.Ldc_I4_0);
 
948
                                        ilgen.Emit(OpCodes.Ret);
 
949
                                        ilgen.MarkLabel(typecheck);
 
950
                                        for(int i = 0; i < implementers.Length; i++)
 
951
                                        {
 
952
                                                ilgen.Emit(OpCodes.Ldtoken, implementers[i].TypeAsTBD);
 
953
                                                ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle"));
 
954
                                                ilgen.Emit(OpCodes.Ldloc, localType);
 
955
                                                ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("IsAssignableFrom"));
 
956
                                                CodeEmitterLabel label = ilgen.DefineLabel();
 
957
                                                ilgen.EmitBrfalse(label);
 
958
                                                ilgen.Emit(OpCodes.Ldc_I4_1);
 
959
                                                ilgen.Emit(OpCodes.Ret);
 
960
                                                ilgen.MarkLabel(label);
 
961
                                        }
 
962
                                        ilgen.Emit(OpCodes.Ldtoken, typeBuilderGhostInterface);
 
963
                                        ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle"));
 
964
                                        ilgen.Emit(OpCodes.Ldloc, localType);
 
965
                                        ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("IsAssignableFrom"));
 
966
                                        skip = ilgen.DefineLabel();
 
967
                                        ilgen.EmitBrfalse(skip);
 
968
                                        ilgen.Emit(OpCodes.Ldc_I4_1);
 
969
                                        ilgen.Emit(OpCodes.Ret);
 
970
                                        ilgen.MarkLabel(skip);
 
971
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
972
                                        ilgen.Emit(OpCodes.Ldtoken, typeBuilder);
 
973
                                        ilgen.Emit(OpCodes.Ldarg_1);
 
974
                                        ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.GhostTag").GetMethod("IsGhostArrayInstance", BindingFlags.NonPublic | BindingFlags.Static));
 
975
                                        ilgen.Emit(OpCodes.Ret);
 
976
                                        ilgen.DoEmit();
 
977
                                                
 
978
                                        // Implement the "Cast" method
 
979
                                        mb = ghostCastMethod;
 
980
                                        AttributeHelper.HideFromJava(mb);
 
981
                                        ilgen = CodeEmitter.Create(mb);
 
982
                                        end = ilgen.DefineLabel();
 
983
                                        for(int i = 0; i < implementers.Length; i++)
 
984
                                        {
 
985
                                                ilgen.Emit(OpCodes.Ldarg_0);
 
986
                                                ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD);
 
987
                                                ilgen.EmitBrtrue(end);
 
988
                                        }
 
989
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
990
                                        ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface);
 
991
                                        ilgen.Emit(OpCodes.Pop);
 
992
                                        ilgen.MarkLabel(end);
 
993
                                        local = ilgen.DeclareLocal(TypeAsSignatureType);
 
994
                                        ilgen.Emit(OpCodes.Ldloca, local);
 
995
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
996
                                        ilgen.Emit(OpCodes.Stfld, ghostRefField);
 
997
                                        ilgen.Emit(OpCodes.Ldloca, local);
 
998
                                        ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType); 
 
999
                                        ilgen.Emit(OpCodes.Ret);
 
1000
                                        ilgen.DoEmit();
 
1001
                                        // Add "ToObject" methods
 
1002
                                        mb = typeBuilder.DefineMethod("ToObject", MethodAttributes.HideBySig | MethodAttributes.Public, Types.Object, Type.EmptyTypes);
 
1003
                                        AttributeHelper.HideFromJava(mb);
 
1004
                                        ilgen = CodeEmitter.Create(mb);
 
1005
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1006
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1007
                                        ilgen.Emit(OpCodes.Ret);
 
1008
                                        ilgen.DoEmit();
 
1009
 
 
1010
                                        // Implement the "CastArray" method
 
1011
                                        // NOTE unlike "Cast" this doesn't return anything, it just throws a ClassCastException if the
 
1012
                                        // cast is unsuccessful. Also, because of the complexity of this test, we call IsInstanceArray
 
1013
                                        // instead of reimplementing the check here.
 
1014
                                        mb = ghostCastArrayMethod;
 
1015
                                        AttributeHelper.HideFromJava(mb);
 
1016
                                        ilgen = CodeEmitter.Create(mb);
 
1017
                                        end = ilgen.DefineLabel();
 
1018
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1019
                                        ilgen.EmitBrfalse(end);
 
1020
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1021
                                        ilgen.Emit(OpCodes.Ldarg_1);
 
1022
                                        ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod);
 
1023
                                        ilgen.EmitBrtrue(end);
 
1024
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1025
                                        ilgen.Emit(OpCodes.Ldtoken, typeBuilder);
 
1026
                                        ilgen.Emit(OpCodes.Ldarg_1);
 
1027
                                        ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.GhostTag").GetMethod("ThrowClassCastException", BindingFlags.NonPublic | BindingFlags.Static));
 
1028
                                        ilgen.MarkLabel(end);
 
1029
                                        ilgen.Emit(OpCodes.Ret);
 
1030
                                        ilgen.DoEmit();
 
1031
 
 
1032
                                        // Implement the "Equals" method
 
1033
                                        mb = typeBuilder.DefineMethod("Equals", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Types.Boolean, new Type[] { Types.Object });
 
1034
                                        AttributeHelper.HideFromJava(mb);
 
1035
                                        ilgen = CodeEmitter.Create(mb);
 
1036
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1037
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1038
                                        ilgen.Emit(OpCodes.Ldarg_1);
 
1039
                                        ilgen.Emit(OpCodes.Ceq);
 
1040
                                        ilgen.Emit(OpCodes.Ret);
 
1041
                                        ilgen.DoEmit();
 
1042
 
 
1043
                                        // Implement the "GetHashCode" method
 
1044
                                        mb = typeBuilder.DefineMethod("GetHashCode", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Types.Int32, Type.EmptyTypes);
 
1045
                                        AttributeHelper.HideFromJava(mb);
 
1046
                                        ilgen = CodeEmitter.Create(mb);
 
1047
                                        ilgen.Emit(OpCodes.Ldarg_0);
 
1048
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1049
                                        ilgen.Emit(OpCodes.Callvirt, Types.Object.GetMethod("GetHashCode"));
 
1050
                                        ilgen.Emit(OpCodes.Ret);
 
1051
                                        ilgen.DoEmit();
 
1052
 
 
1053
                                        // Implement the "op_Equality" method
 
1054
                                        mb = typeBuilder.DefineMethod("op_Equality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Types.Boolean, new Type[] { typeBuilder, typeBuilder });
 
1055
                                        AttributeHelper.HideFromJava(mb);
 
1056
                                        ilgen = CodeEmitter.Create(mb);
 
1057
                                        ilgen.EmitLdarga(0);
 
1058
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1059
                                        ilgen.EmitLdarga(1);
 
1060
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1061
                                        ilgen.Emit(OpCodes.Ceq);
 
1062
                                        ilgen.Emit(OpCodes.Ret);
 
1063
                                        ilgen.DoEmit();
 
1064
 
 
1065
                                        // Implement the "op_Inequality" method
 
1066
                                        mb = typeBuilder.DefineMethod("op_Inequality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Types.Boolean, new Type[] { typeBuilder, typeBuilder });
 
1067
                                        AttributeHelper.HideFromJava(mb);
 
1068
                                        ilgen = CodeEmitter.Create(mb);
 
1069
                                        ilgen.EmitLdarga(0);
 
1070
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1071
                                        ilgen.EmitLdarga(1);
 
1072
                                        ilgen.Emit(OpCodes.Ldfld, ghostRefField);
 
1073
                                        ilgen.Emit(OpCodes.Ceq);
 
1074
                                        ilgen.Emit(OpCodes.Ldc_I4_0);
 
1075
                                        ilgen.Emit(OpCodes.Ceq);
 
1076
                                        ilgen.Emit(OpCodes.Ret);
 
1077
                                        ilgen.DoEmit();
 
1078
                                }
 
1079
                        }
 
1080
                }
 
1081
 
 
1082
                protected override void FinishGhostStep2()
 
1083
                {
 
1084
                        if(typeBuilderGhostInterface != null)
 
1085
                        {
 
1086
                                typeBuilderGhostInterface.CreateType();
 
1087
                        }
 
1088
                }
 
1089
 
 
1090
                protected override TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs)
 
1091
                {
 
1092
                        typeAttribs &= ~(TypeAttributes.Interface | TypeAttributes.Abstract);
 
1093
                        typeAttribs |= TypeAttributes.Class | TypeAttributes.Sealed;
 
1094
                        TypeBuilder typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs, Types.ValueType);
 
1095
                        AttributeHelper.SetGhostInterface(typeBuilder);
 
1096
                        AttributeHelper.SetModifiers(typeBuilder, Modifiers, IsInternal);
 
1097
                        ghostRefField = typeBuilder.DefineField("__<ref>", Types.Object, FieldAttributes.Public | FieldAttributes.SpecialName);
 
1098
                        typeBuilderGhostInterface = typeBuilder.DefineNestedType("__Interface", TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.NestedPublic);
 
1099
                        AttributeHelper.HideFromJava(typeBuilderGhostInterface);
 
1100
                        ghostIsInstanceMethod = typeBuilder.DefineMethod("IsInstance", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Types.Boolean, new Type[] { Types.Object });
 
1101
                        ghostIsInstanceMethod.DefineParameter(1, ParameterAttributes.None, "obj");
 
1102
                        ghostIsInstanceArrayMethod = typeBuilder.DefineMethod("IsInstanceArray", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Types.Boolean, new Type[] { Types.Object, Types.Int32 });
 
1103
                        ghostIsInstanceArrayMethod.DefineParameter(1, ParameterAttributes.None, "obj");
 
1104
                        ghostIsInstanceArrayMethod.DefineParameter(2, ParameterAttributes.None, "rank");
 
1105
                        ghostCastMethod = typeBuilder.DefineMethod("Cast", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeBuilder, new Type[] { Types.Object });
 
1106
                        ghostCastMethod.DefineParameter(1, ParameterAttributes.None, "obj");
 
1107
                        ghostCastArrayMethod = typeBuilder.DefineMethod("CastArray", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, Types.Void, new Type[] { Types.Object, Types.Int32 });
 
1108
                        ghostCastArrayMethod.DefineParameter(1, ParameterAttributes.None, "obj");
 
1109
                        ghostCastArrayMethod.DefineParameter(2, ParameterAttributes.None, "rank");
 
1110
                        return typeBuilder;
 
1111
                }
 
1112
 
 
1113
                internal override FieldInfo GhostRefField
 
1114
                {
 
1115
                        get
 
1116
                        {
 
1117
                                return ghostRefField;
 
1118
                        }
 
1119
                }
 
1120
 
 
1121
                internal override void EmitCheckcast(TypeWrapper context, CodeEmitter ilgen)
 
1122
                {
 
1123
                        if(IsGhost)
 
1124
                        {
 
1125
                                ilgen.Emit(OpCodes.Dup);
 
1126
                                ilgen.Emit(OpCodes.Call, ghostCastMethod);
 
1127
                                ilgen.Emit(OpCodes.Pop);
 
1128
                        }
 
1129
                        else if(IsGhostArray)
 
1130
                        {
 
1131
                                ilgen.Emit(OpCodes.Dup);
 
1132
                                TypeWrapper tw = this;
 
1133
                                int rank = 0;
 
1134
                                while(tw.IsArray)
 
1135
                                {
 
1136
                                        rank++;
 
1137
                                        tw = tw.ElementTypeWrapper;
 
1138
                                }
 
1139
                                ilgen.EmitLdc_I4(rank);
 
1140
                                ilgen.Emit(OpCodes.Call, ghostCastArrayMethod);
 
1141
                                ilgen.Emit(OpCodes.Castclass, ArrayTypeWrapper.MakeArrayType(Types.Object, rank));
 
1142
                        }
 
1143
                        else
 
1144
                        {
 
1145
                                base.EmitCheckcast(context, ilgen);
 
1146
                        }
 
1147
                }
 
1148
 
 
1149
                internal override void EmitInstanceOf(TypeWrapper context, CodeEmitter ilgen)
 
1150
                {
 
1151
                        if(IsGhost)
 
1152
                        {
 
1153
                                ilgen.Emit(OpCodes.Call, ghostIsInstanceMethod);
 
1154
                        }
 
1155
                        else if(IsGhostArray)
 
1156
                        {
 
1157
                                ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod);
 
1158
                        }
 
1159
                        else
 
1160
                        {
 
1161
                                base.EmitInstanceOf(context, ilgen);
 
1162
                        }
 
1163
                }
 
1164
 
 
1165
                internal void SetAnnotation(Annotation annotation)
 
1166
                {
 
1167
                        this.annotation = annotation;
 
1168
                }
 
1169
 
 
1170
                internal override Annotation Annotation
 
1171
                {
 
1172
                        get
 
1173
                        {
 
1174
                                return annotation;
 
1175
                        }
 
1176
                }
 
1177
 
 
1178
                internal void SetEnumType(Type enumType)
 
1179
                {
 
1180
                        this.enumType = enumType;
 
1181
                }
 
1182
 
 
1183
                internal override Type EnumType
 
1184
                {
 
1185
                        get
 
1186
                        {
 
1187
                                return enumType;
 
1188
                        }
 
1189
                }
 
1190
 
 
1191
                private sealed class ReplacedMethodWrapper : MethodWrapper
 
1192
                {
 
1193
                        private IKVM.Internal.MapXml.InstructionList code;
 
1194
 
 
1195
                        internal ReplacedMethodWrapper(TypeWrapper tw, string name, string sig, IKVM.Internal.MapXml.InstructionList code)
 
1196
                                : base(tw, name, sig, null, null, null, Modifiers.Public, MemberFlags.None)
 
1197
                        {
 
1198
                                this.code = code;
 
1199
                        }
 
1200
 
 
1201
                        internal ReplacedMethodWrapper(ClassFile.ConstantPoolItemMI cpi, IKVM.Internal.MapXml.InstructionList code)
 
1202
                                : base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None)
 
1203
                        {
 
1204
                                this.code = code;
 
1205
                        }
 
1206
 
 
1207
                        protected override void DoLinkMethod()
 
1208
                        {
 
1209
                        }
 
1210
 
 
1211
                        private void DoEmit(CodeEmitter ilgen)
 
1212
                        {
 
1213
                                IKVM.Internal.MapXml.CodeGenContext context = new IKVM.Internal.MapXml.CodeGenContext(this.DeclaringType.GetClassLoader());
 
1214
                                // we don't want the line numbers from map.xml, so we have our own emit loop
 
1215
                                for (int i = 0; i < code.invoke.Length; i++)
 
1216
                                {
 
1217
                                        code.invoke[i].Generate(context, ilgen);
 
1218
                                }
 
1219
                        }
 
1220
 
 
1221
                        internal override void EmitCall(CodeEmitter ilgen)
 
1222
                        {
 
1223
                                DoEmit(ilgen);
 
1224
                        }
 
1225
 
 
1226
                        internal override void EmitCallvirt(CodeEmitter ilgen)
 
1227
                        {
 
1228
                                DoEmit(ilgen);
 
1229
                        }
 
1230
 
 
1231
                        internal override void EmitNewobj(CodeEmitter ilgen)
 
1232
                        {
 
1233
                                DoEmit(ilgen);
 
1234
                        }
 
1235
                }
 
1236
 
 
1237
                internal override MethodWrapper[] GetReplacedMethodsFor(MethodWrapper mw)
 
1238
                {
 
1239
                        IKVM.Internal.MapXml.ReplaceMethodCall[] replacedMethods = ((CompilerClassLoader)GetClassLoader()).GetReplacedMethodsFor(mw);
 
1240
                        MethodWrapper[] baseReplacedMethodWrappers = base.GetReplacedMethodsFor(mw);
 
1241
                        if (replacedMethods != null || baseReplacedMethodWrappers != null || this.replacedMethods != null)
 
1242
                        {
 
1243
                                List<MethodWrapper> list = new List<MethodWrapper>();
 
1244
                                if (replacedMethods != null)
 
1245
                                {
 
1246
                                        for (int i = 0; i < replacedMethods.Length; i++)
 
1247
                                        {
 
1248
                                                list.Add(new ReplacedMethodWrapper(GetClassLoader().LoadClassByDottedName(replacedMethods[i].Class), replacedMethods[i].Name, replacedMethods[i].Sig, replacedMethods[i].code));
 
1249
                                        }
 
1250
                                }
 
1251
                                if (baseReplacedMethodWrappers != null)
 
1252
                                {
 
1253
                                        list.AddRange(baseReplacedMethodWrappers);
 
1254
                                }
 
1255
                                if (this.replacedMethods != null)
 
1256
                                {
 
1257
                                        list.AddRange(this.replacedMethods);
 
1258
                                }
 
1259
                                return list.ToArray();
 
1260
                        }
 
1261
                        return null;
 
1262
                }
 
1263
 
 
1264
                internal override bool IsFastClassLiteralSafe
 
1265
                {
 
1266
                        get { return true; }
 
1267
                }
 
1268
 
 
1269
                internal MethodWrapper ReplaceMethodWrapper(MethodWrapper mw)
 
1270
                {
 
1271
                        if (replacedMethods != null)
 
1272
                        {
 
1273
                                foreach (MethodWrapper r in replacedMethods)
 
1274
                                {
 
1275
                                        if (mw.DeclaringType == r.DeclaringType
 
1276
                                                && mw.Name == r.Name
 
1277
                                                && mw.Signature == r.Signature)
 
1278
                                        {
 
1279
                                                return r;
 
1280
                                        }
 
1281
                                }
 
1282
                        }
 
1283
                        return mw;
 
1284
                }
 
1285
 
 
1286
                internal override MethodBase GetBaseSerializationConstructor()
 
1287
                {
 
1288
                        if (workaroundBaseClass != null)
 
1289
                        {
 
1290
                                return workaroundBaseClass.GetSerializationConstructor();
 
1291
                        }
 
1292
                        else
 
1293
                        {
 
1294
                                return base.GetBaseSerializationConstructor();
 
1295
                        }
 
1296
                }
 
1297
        }
 
1298
}