Przeglądaj źródła

Update to the latest IKVM.Reflection

Marek Safar 13 lat temu
rodzic
commit
d24f2bf83f

+ 8 - 1
mcs/class/IKVM.Reflection/AssemblyName.cs

@@ -334,7 +334,14 @@ namespace IKVM.Reflection
 			// HACK use the real AssemblyName to convert PublicKey to PublicKeyToken
 			StringBuilder sb = new StringBuilder("Foo, PublicKey=", 20 + publicKey.Length * 2);
 			AppendPublicKey(sb, publicKey);
-			return new System.Reflection.AssemblyName(sb.ToString()).GetPublicKeyToken();
+			string str = sb.ToString();
+			if (str == "Foo, PublicKey=00000000000000000400000000000000")
+			{
+				// MONOBUG workaround Mono 2.10 bug (fixed in 2.11)
+				// it does not return the correct public key token for the ECMA key
+				return new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 };
+			}
+			return new System.Reflection.AssemblyName(str).GetPublicKeyToken();
 		}
 
 		private static void AppendPublicKey(StringBuilder sb, byte[] publicKey)

+ 13 - 13
mcs/class/IKVM.Reflection/CustomModifiers.cs

@@ -32,14 +32,13 @@ namespace IKVM.Reflection
 {
 	public struct CustomModifiers : IEquatable<CustomModifiers>, IEnumerable<CustomModifiers.Entry>
 	{
-		private static readonly Type ModOpt = new MarkerType();
-		private static readonly Type ModReq = new MarkerType();
-		private static readonly Type Initial = ModOpt;
+		// note that FromReqOpt assumes that Initial == ModOpt
+		private static Type Initial { get { return MarkerType.ModOpt; } }
 		private readonly Type[] types;
 
 		internal CustomModifiers(List<CustomModifiersBuilder.Item> list)
 		{
-			bool required = Initial == ModReq;
+			bool required = Initial == MarkerType.ModReq;
 			int count = list.Count;
 			foreach (CustomModifiersBuilder.Item item in list)
 			{
@@ -50,14 +49,14 @@ namespace IKVM.Reflection
 				}
 			}
 			types = new Type[count];
-			required = Initial == ModReq;
+			required = Initial == MarkerType.ModReq;
 			int index = 0;
 			foreach (CustomModifiersBuilder.Item item in list)
 			{
 				if (item.required != required)
 				{
 					required = item.required;
-					types[index++] = required ? ModReq : ModOpt;
+					types[index++] = required ? MarkerType.ModReq : MarkerType.ModOpt;
 				}
 				types[index++] = item.type;
 			}
@@ -79,13 +78,13 @@ namespace IKVM.Reflection
 			{
 				this.types = types;
 				this.index = -1;
-				this.required = Initial == ModReq;
+				this.required = Initial == MarkerType.ModReq;
 			}
 
 			void System.Collections.IEnumerator.Reset()
 			{
 				this.index = -1;
-				this.required = Initial == ModReq;
+				this.required = Initial == MarkerType.ModReq;
 			}
 
 			public Entry Current
@@ -104,12 +103,12 @@ namespace IKVM.Reflection
 				{
 					return false;
 				}
-				else if (types[index] == ModOpt)
+				else if (types[index] == MarkerType.ModOpt)
 				{
 					required = false;
 					index++;
 				}
-				else if (types[index] == ModReq)
+				else if (types[index] == MarkerType.ModReq)
 				{
 					required = true;
 					index++;
@@ -247,7 +246,7 @@ namespace IKVM.Reflection
 			Type[] result = types;
 			for (int i = 0; i < types.Length; i++)
 			{
-				if (types[i] == ModOpt || types[i] == ModReq)
+				if (types[i] == MarkerType.ModOpt || types[i] == MarkerType.ModReq)
 				{
 					continue;
 				}
@@ -275,7 +274,7 @@ namespace IKVM.Reflection
 			Type mode = Initial;
 			do
 			{
-				Type cmod = br.ReadByte() == Signature.ELEMENT_TYPE_CMOD_REQD ? ModReq : ModOpt;
+				Type cmod = br.ReadByte() == Signature.ELEMENT_TYPE_CMOD_REQD ? MarkerType.ModReq : MarkerType.ModOpt;
 				if (mode != cmod)
 				{
 					mode = cmod;
@@ -304,6 +303,7 @@ namespace IKVM.Reflection
 			List<Type> list = null;
 			if (opt != null && opt.Length != 0)
 			{
+				Debug.Assert(Initial == MarkerType.ModOpt);
 				list = new List<Type>(opt);
 			}
 			if (req != null && req.Length != 0)
@@ -312,7 +312,7 @@ namespace IKVM.Reflection
 				{
 					list = new List<Type>();
 				}
-				list.Add(ModReq);
+				list.Add(MarkerType.ModReq);
 				list.AddRange(req);
 			}
 			if (list == null)

+ 40 - 88
mcs/class/IKVM.Reflection/Emit/ILGenerator.cs

@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2008-2011 Jeroen Frijters
+  Copyright (C) 2008-2012 Jeroen Frijters
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -116,43 +116,12 @@ namespace IKVM.Reflection.Emit
 		}
 	}
 
-	sealed class MarkerType : Type
-	{
-		public override Type BaseType
-		{
-			get { throw new InvalidOperationException(); }
-		}
-
-		public override TypeAttributes Attributes
-		{
-			get { throw new InvalidOperationException(); }
-		}
-
-		public override string Name
-		{
-			get { throw new InvalidOperationException(); }
-		}
-
-		public override string FullName
-		{
-			get { throw new InvalidOperationException(); }
-		}
-
-		public override Module Module
-		{
-			get { throw new InvalidOperationException(); }
-		}
-	}
-
 	public sealed class ILGenerator
 	{
-		private static readonly Type FAULT = new MarkerType();
-		private static readonly Type FINALLY = new MarkerType();
-		private static readonly Type FILTER = new MarkerType();
 		private readonly ModuleBuilder moduleBuilder;
 		private readonly ByteBuffer code;
-		private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
-		private List<CustomModifiers> localCustomModifiers;
+		private readonly SignatureHelper locals;
+		private int localsCount;
 		private readonly List<int> tokenFixups = new List<int>();
 		private readonly List<int> labels = new List<int>();
 		private readonly List<int> labelStackHeight = new List<int>();
@@ -183,7 +152,7 @@ namespace IKVM.Reflection.Emit
 			internal int tryLength;
 			internal int handlerOffset;
 			internal int handlerLength;
-			internal Type exceptionType;	// FINALLY = finally block, FILTER = handler with filter, FAULT = fault block
+			internal Type exceptionType;	// MarkerType.Finally = finally block, MarkerType.Filter = handler with filter, MarkerType.Fault = fault block
 			internal int filterOffset;
 
 			internal ExceptionBlock(int ordinal)
@@ -245,6 +214,7 @@ namespace IKVM.Reflection.Emit
 		{
 			this.code = new ByteBuffer(initialCapacity);
 			this.moduleBuilder = moduleBuilder;
+			this.locals = SignatureHelper.GetLocalVarSigHelper(moduleBuilder);
 			if (moduleBuilder.symbolWriter != null)
 			{
 				scope = new Scope(null);
@@ -305,7 +275,7 @@ namespace IKVM.Reflection.Emit
 			UpdateStack(1);
 			if (exceptionType == null)
 			{
-				if (block.exceptionType != FILTER || block.handlerOffset != 0)
+				if (block.exceptionType != MarkerType.Filter || block.handlerOffset != 0)
 				{
 					throw new ArgumentNullException("exceptionType");
 				}
@@ -330,7 +300,7 @@ namespace IKVM.Reflection.Emit
 					exceptionStack.Push(block);
 				}
 				block.exceptionType = exceptionType;
-				if (exceptionType == FILTER)
+				if (exceptionType == MarkerType.Filter)
 				{
 					block.filterOffset = code.Position;
 				}
@@ -354,17 +324,17 @@ namespace IKVM.Reflection.Emit
 
 		public void BeginExceptFilterBlock()
 		{
-			BeginCatchBlock(FILTER);
+			BeginCatchBlock(MarkerType.Filter);
 		}
 
 		public void BeginFaultBlock()
 		{
-			BeginFinallyFaultBlock(FAULT);
+			BeginFinallyFaultBlock(MarkerType.Fault);
 		}
 
 		public void BeginFinallyBlock()
 		{
-			BeginFinallyFaultBlock(FINALLY);
+			BeginFinallyFaultBlock(MarkerType.Finally);
 		}
 
 		private void BeginFinallyFaultBlock(Type type)
@@ -411,7 +381,7 @@ namespace IKVM.Reflection.Emit
 			ExceptionBlock block = exceptionStack.Pop();
 			if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1))
 			{
-				if (block.filterOffset != 0 || (block.exceptionType != FINALLY && block.exceptionType != FAULT))
+				if (block.filterOffset != 0 || (block.exceptionType != MarkerType.Finally && block.exceptionType != MarkerType.Fault))
 				{
 					Emit(OpCodes.Leave, block.labelEnd);
 				}
@@ -447,8 +417,8 @@ namespace IKVM.Reflection.Emit
 
 		public LocalBuilder DeclareLocal(Type localType, bool pinned)
 		{
-			LocalBuilder local = new LocalBuilder(localType, locals.Count, pinned);
-			locals.Add(local);
+			LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned);
+			locals.AddArgument(localType, pinned);
 			if (scope != null)
 			{
 				scope.locals.Add(local);
@@ -458,22 +428,13 @@ namespace IKVM.Reflection.Emit
 
 		public LocalBuilder __DeclareLocal(Type localType, bool pinned, CustomModifiers customModifiers)
 		{
-			if (!customModifiers.IsEmpty)
+			LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned);
+			locals.__AddArgument(localType, pinned, customModifiers);
+			if (scope != null)
 			{
-				if (localCustomModifiers == null)
-				{
-					localCustomModifiers = new List<CustomModifiers>();
-				}
-				// we lazily fill up the list (to sync with the locals list) and we don't need to
-				// make sure that the list has the same length as the locals list, because
-				// Signature.WriteLocalVarSig() can tolerate that.
-				while (localCustomModifiers.Count < locals.Count)
-				{
-					localCustomModifiers.Add(new CustomModifiers());
-				}
-				localCustomModifiers.Add(customModifiers);
+				scope.locals.Add(local);
 			}
-			return DeclareLocal(localType, pinned);
+			return local;
 		}
 
 		public Label DefineLabel()
@@ -781,7 +742,7 @@ namespace IKVM.Reflection.Emit
 		public void Emit(OpCode opc, string str)
 		{
 			Emit(opc);
-			code.Write(0x70000000 | moduleBuilder.UserStrings.Add(str));
+			code.Write(moduleBuilder.GetStringConstant(str).Token);
 		}
 
 		public void Emit(OpCode opc, Type type)
@@ -801,7 +762,7 @@ namespace IKVM.Reflection.Emit
 		{
 			Emit(opcode);
 			UpdateStack(opcode, signature.HasThis, signature.ReturnType, signature.ParameterCount);
-			code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(signature.GetSignature(moduleBuilder))));
+			code.Write(moduleBuilder.GetSignatureToken(signature).Token);
 		}
 
 		public void EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes)
@@ -819,20 +780,7 @@ namespace IKVM.Reflection.Emit
 			{
 				Emit(opc);
 				UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount + optionalParameterTypes.Length);
-				ByteBuffer sig = new ByteBuffer(16);
-				method.MethodSignature.WriteMethodRefSig(moduleBuilder, sig, optionalParameterTypes, customModifiers);
-				MemberRefTable.Record record = new MemberRefTable.Record();
-				if (method.Module == moduleBuilder)
-				{
-					record.Class = method.MetadataToken;
-				}
-				else
-				{
-					record.Class = moduleBuilder.GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
-				}
-				record.Name = moduleBuilder.Strings.Add(method.Name);
-				record.Signature = moduleBuilder.Blobs.Add(sig);
-				code.Write(0x0A000000 | moduleBuilder.MemberRef.FindOrAddRecord(record));
+				code.Write(moduleBuilder.__GetMethodToken(method, optionalParameterTypes, customModifiers).Token);
 			}
 		}
 
@@ -848,12 +796,18 @@ namespace IKVM.Reflection.Emit
 
 		public void EmitCalli(OpCode opc, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
 		{
-			__EmitCalli(opc, moduleBuilder.universe.MakeStandAloneMethodSig(callingConvention, returnType, new CustomModifiers(), parameterTypes, null));
+			SignatureHelper sig = SignatureHelper.GetMethodSigHelper(moduleBuilder, callingConvention, returnType);
+			sig.AddArguments(parameterTypes, null, null);
+			Emit(opc, sig);
 		}
 
 		public void EmitCalli(OpCode opc, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
 		{
-			__EmitCalli(opc, moduleBuilder.universe.MakeStandAloneMethodSig(callingConvention, returnType, new CustomModifiers(), parameterTypes, optionalParameterTypes, null));
+			SignatureHelper sig = SignatureHelper.GetMethodSigHelper(moduleBuilder, callingConvention, returnType);
+			sig.AddArguments(parameterTypes, null, null);
+			sig.AddSentinel();
+			sig.AddArguments(optionalParameterTypes, null, null);
+			Emit(opc, sig);
 		}
 
 		public void __EmitCalli(OpCode opc, __StandAloneMethodSig sig)
@@ -969,7 +923,7 @@ namespace IKVM.Reflection.Emit
 			int localVarSigTok = 0;
 
 			int rva;
-			if (locals.Count == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64 && !fatHeader)
+			if (localsCount == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64 && !fatHeader)
 			{
 				rva = WriteTinyHeaderAndCode(bb);
 			}
@@ -1057,11 +1011,9 @@ namespace IKVM.Reflection.Emit
 			bb.Align(4);
 			int rva = bb.Position;
 
-			if (locals.Count != 0)
+			if (localsCount != 0)
 			{
-				ByteBuffer localVarSig = new ByteBuffer(locals.Count + 2);
-				Signature.WriteLocalVarSig(moduleBuilder, localVarSig, locals, localCustomModifiers);
-				localVarSigTok = 0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(localVarSig));
+				localVarSigTok = moduleBuilder.GetSignatureToken(locals).Token;
 			}
 
 			const byte CorILMethod_FatFormat = 0x03;
@@ -1119,15 +1071,15 @@ namespace IKVM.Reflection.Emit
 					bb.Write((short)(dataSize >> 8));
 					foreach (ExceptionBlock block in exceptions)
 					{
-						if (block.exceptionType == FAULT)
+						if (block.exceptionType == MarkerType.Fault)
 						{
 							bb.Write((int)COR_ILEXCEPTION_CLAUSE_FAULT);
 						}
-						else if (block.exceptionType == FILTER)
+						else if (block.exceptionType == MarkerType.Filter)
 						{
 							bb.Write((int)COR_ILEXCEPTION_CLAUSE_FILTER);
 						}
-						else if (block.exceptionType == FINALLY)
+						else if (block.exceptionType == MarkerType.Finally)
 						{
 							bb.Write((int)COR_ILEXCEPTION_CLAUSE_FINALLY);
 						}
@@ -1139,7 +1091,7 @@ namespace IKVM.Reflection.Emit
 						bb.Write(block.tryLength);
 						bb.Write(block.handlerOffset);
 						bb.Write(block.handlerLength);
-						if (block.exceptionType != FAULT && block.exceptionType != FILTER && block.exceptionType != FINALLY)
+						if (block.exceptionType != MarkerType.Fault && block.exceptionType != MarkerType.Filter && block.exceptionType != MarkerType.Finally)
 						{
 							bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
 						}
@@ -1156,15 +1108,15 @@ namespace IKVM.Reflection.Emit
 					bb.Write((short)0);
 					foreach (ExceptionBlock block in exceptions)
 					{
-						if (block.exceptionType == FAULT)
+						if (block.exceptionType == MarkerType.Fault)
 						{
 							bb.Write(COR_ILEXCEPTION_CLAUSE_FAULT);
 						}
-						else if (block.exceptionType == FILTER)
+						else if (block.exceptionType == MarkerType.Filter)
 						{
 							bb.Write(COR_ILEXCEPTION_CLAUSE_FILTER);
 						}
-						else if (block.exceptionType == FINALLY)
+						else if (block.exceptionType == MarkerType.Finally)
 						{
 							bb.Write(COR_ILEXCEPTION_CLAUSE_FINALLY);
 						}
@@ -1176,7 +1128,7 @@ namespace IKVM.Reflection.Emit
 						bb.Write((byte)block.tryLength);
 						bb.Write((short)block.handlerOffset);
 						bb.Write((byte)block.handlerLength);
-						if (block.exceptionType != FAULT && block.exceptionType != FILTER && block.exceptionType != FINALLY)
+						if (block.exceptionType != MarkerType.Fault && block.exceptionType != MarkerType.Filter && block.exceptionType != MarkerType.Finally)
 						{
 							bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType));
 						}

+ 35 - 0
mcs/class/IKVM.Reflection/Emit/ModuleBuilder.cs

@@ -584,6 +584,30 @@ namespace IKVM.Reflection.Emit
 			}
 		}
 
+		// new in .NET 4.5
+		public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)
+		{
+			return __GetMethodToken(method, Util.ToArray(optionalParameterTypes), null);
+		}
+
+		public MethodToken __GetMethodToken(MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
+		{
+			ByteBuffer sig = new ByteBuffer(16);
+			method.MethodSignature.WriteMethodRefSig(this, sig, optionalParameterTypes, customModifiers);
+			MemberRefTable.Record record = new MemberRefTable.Record();
+			if (method.Module == this)
+			{
+				record.Class = method.MetadataToken;
+			}
+			else
+			{
+				record.Class = GetTypeTokenForMemberRef(method.DeclaringType ?? method.Module.GetModuleType());
+			}
+			record.Name = Strings.Add(method.Name);
+			record.Signature = Blobs.Add(sig);
+			return new MethodToken(0x0A000000 | MemberRef.FindOrAddRecord(record));
+		}
+
 		// when we refer to a method on a generic type definition in the IL stream,
 		// we need to use a MemberRef (even if the method is in the same module)
 		internal MethodToken GetMethodTokenForIL(MethodInfo method)
@@ -614,6 +638,17 @@ namespace IKVM.Reflection.Emit
 			}
 		}
 
+		// new in .NET 4.5
+		public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
+		{
+			return GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes);
+		}
+
+		public MethodToken __GetConstructorToken(ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
+		{
+			return __GetMethodToken(constructor.GetMethodInfo(), optionalParameterTypes, customModifiers);
+		}
+
 		internal int ImportMember(MethodBase member)
 		{
 			int token;

+ 193 - 109
mcs/class/IKVM.Reflection/Emit/SignatureHelper.cs

@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2008-2011 Jeroen Frijters
+  Copyright (C) 2008-2012 Jeroen Frijters
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -29,65 +29,168 @@ using IKVM.Reflection.Writer;
 
 namespace IKVM.Reflection.Emit
 {
-	public sealed class SignatureHelper
+	public abstract class SignatureHelper
 	{
-		private readonly ModuleBuilder module;
-		private readonly byte type;
-		private readonly List<Type> args = new List<Type>();
-		private readonly List<LocalBuilder> locals = new List<LocalBuilder>();
-		private readonly List<CustomModifiers> customModifiers = new List<CustomModifiers>();
-		private readonly List<Type> optionalArgs = new List<Type>();
-		private Type returnType;
-		private CustomModifiers returnTypeCustomModifiers;
-		private CallingConventions callingConvention;
-		private CallingConvention unmanagedCallConv;
-		private bool unmanaged;
-		private bool optional;
-
-		private SignatureHelper(ModuleBuilder module, byte type)
-		{
-			this.module = module;
+		protected readonly byte type;
+		protected ushort paramCount;
+
+		sealed class Lazy : SignatureHelper
+		{
+			private readonly List<Type> args = new List<Type>();
+
+			internal Lazy(byte type)
+				: base(type)
+			{
+			}
+
+			internal override Type ReturnType
+			{
+				get { return args[0]; }
+			}
+
+			public override byte[] GetSignature()
+			{
+				throw new NotSupportedException();
+			}
+
+			internal override ByteBuffer GetSignature(ModuleBuilder module)
+			{
+				ByteBuffer bb = new ByteBuffer(16);
+				Signature.WriteSignatureHelper(module, bb, type, paramCount, args);
+				return bb;
+			}
+
+			public override void AddSentinel()
+			{
+				args.Add(MarkerType.Sentinel);
+			}
+
+			public override void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers)
+			{
+				if (pinned)
+				{
+					args.Add(MarkerType.Pinned);
+				}
+				foreach (CustomModifiers.Entry mod in customModifiers)
+				{
+					args.Add(mod.IsRequired ? MarkerType.ModReq : MarkerType.ModOpt);
+					args.Add(mod.Type);
+				}
+				args.Add(argument);
+				paramCount++;
+			}
+		}
+
+		sealed class Eager : SignatureHelper
+		{
+			private readonly ModuleBuilder module;
+			private readonly ByteBuffer bb = new ByteBuffer(16);
+			private readonly Type returnType;
+
+			internal Eager(ModuleBuilder module, byte type, Type returnType)
+				: base(type)
+			{
+				this.module = module;
+				this.returnType = returnType;
+				bb.Write(type);
+				if (type != Signature.FIELD)
+				{
+					// space for parameterCount
+					bb.Write((byte)0);
+				}
+			}
+
+			internal override Type ReturnType
+			{
+				get { return returnType; }
+			}
+
+			public override byte[] GetSignature()
+			{
+				return GetSignature(null).ToArray();
+			}
+
+			internal override ByteBuffer GetSignature(ModuleBuilder module)
+			{
+				if (type != Signature.FIELD)
+				{
+					bb.Position = 1;
+					bb.Insert(MetadataWriter.GetCompressedIntLength(paramCount) - bb.GetCompressedIntLength());
+					bb.WriteCompressedInt(paramCount);
+				}
+				return bb;
+			}
+
+			public override void AddSentinel()
+			{
+				bb.Write(Signature.SENTINEL);
+			}
+
+			public override void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers)
+			{
+				if (pinned)
+				{
+					bb.Write(Signature.ELEMENT_TYPE_PINNED);
+				}
+				foreach (CustomModifiers.Entry mod in customModifiers)
+				{
+					bb.Write(mod.IsRequired ? Signature.ELEMENT_TYPE_CMOD_REQD : Signature.ELEMENT_TYPE_CMOD_OPT);
+					Signature.WriteTypeSpec(module, bb, mod.Type);
+				}
+				Signature.WriteTypeSpec(module, bb, argument ?? module.universe.System_Void);
+				paramCount++;
+			}
+		}
+
+		private SignatureHelper(byte type)
+		{
 			this.type = type;
 		}
 
 		internal bool HasThis
 		{
-			get { return (callingConvention & CallingConventions.HasThis) != 0; }
+			get { return (type & Signature.HASTHIS) != 0; }
 		}
 
-		internal Type ReturnType
+		internal abstract Type ReturnType
 		{
-			get { return returnType; }
+			get;
 		}
 
 		internal int ParameterCount
 		{
-			get { return args.Count + optionalArgs.Count; }
+			get { return paramCount; }
+		}
+
+		private static SignatureHelper Create(Module mod, byte type, Type returnType)
+		{
+			ModuleBuilder mb = mod as ModuleBuilder;
+			return mb == null
+				? (SignatureHelper)new Lazy(type)
+				: new Eager(mb, type, returnType);
 		}
 
 		public static SignatureHelper GetFieldSigHelper(Module mod)
 		{
-			return new SignatureHelper(mod as ModuleBuilder, Signature.FIELD);
+			return Create(mod, Signature.FIELD, null);
 		}
 
 		public static SignatureHelper GetLocalVarSigHelper()
 		{
-			return new SignatureHelper(null, Signature.LOCAL_SIG);
+			return new Lazy(Signature.LOCAL_SIG);
 		}
 
 		public static SignatureHelper GetLocalVarSigHelper(Module mod)
 		{
-			return new SignatureHelper(mod as ModuleBuilder, Signature.LOCAL_SIG);
+			return Create(mod, Signature.LOCAL_SIG, null);
 		}
 
 		public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
 		{
-			SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, Signature.PROPERTY);
-			sig.returnType = returnType;
-			foreach (Type type in parameterTypes)
-			{
-				sig.AddArgument(type);
-			}
+			SignatureHelper sig = Create(mod, Signature.PROPERTY, returnType);
+			sig.AddArgument(returnType);
+			sig.paramCount = 0;
+			sig.AddArguments(parameterTypes, null, null);
 			return sig;
 		}
 
@@ -98,10 +201,14 @@ namespace IKVM.Reflection.Emit
 
 		public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
 		{
-			SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, Signature.PROPERTY);
-			sig.callingConvention = callingConvention;
-			sig.returnType = returnType;
-			sig.returnTypeCustomModifiers = CustomModifiers.FromReqOpt(requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
+			byte type = Signature.PROPERTY;
+			if ((callingConvention & CallingConventions.HasThis) != 0)
+			{
+				type |= Signature.HASTHIS;
+			}
+			SignatureHelper sig = Create(mod, type, returnType);
+			sig.AddArgument(returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
+			sig.paramCount = 0;
 			sig.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
 			return sig;
 		}
@@ -118,78 +225,67 @@ namespace IKVM.Reflection.Emit
 
 		public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
 		{
-			SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
-			sig.returnType = returnType;
-			sig.unmanaged = true;
-			sig.unmanagedCallConv = unmanagedCallConv;
+			byte type;
+			switch (unmanagedCallConv)
+			{
+				case CallingConvention.Cdecl:
+					type = 0x01;	// C
+					break;
+				case CallingConvention.StdCall:
+				case CallingConvention.Winapi:
+					type = 0x02;	// STDCALL
+					break;
+				case CallingConvention.ThisCall:
+					type = 0x03;	// THISCALL
+					break;
+				case CallingConvention.FastCall:
+					type = 0x04;	// FASTCALL
+					break;
+				default:
+					throw new ArgumentOutOfRangeException("unmanagedCallConv");
+			}
+			SignatureHelper sig = Create(mod, type, returnType);
+			sig.AddArgument(returnType);
+			sig.paramCount = 0;
 			return sig;
 		}
 
 		public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
 		{
-			SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
-			sig.returnType = returnType;
-			sig.callingConvention = callingConvention;
-			return sig;
-		}
-
-		public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
-		{
-			SignatureHelper sig = new SignatureHelper(mod as ModuleBuilder, 0);
-			sig.returnType = returnType;
-			sig.callingConvention = CallingConventions.Standard;
-			foreach (Type type in parameterTypes)
+			byte type = 0;
+			if ((callingConvention & CallingConventions.HasThis) != 0)
 			{
-				sig.AddArgument(type);
+				type |= Signature.HASTHIS;
 			}
-			return sig;
-		}
-
-		public byte[] GetSignature()
-		{
-			if (module == null)
+			if ((callingConvention & CallingConventions.ExplicitThis) != 0)
 			{
-				throw new NotSupportedException();
+				type |= Signature.EXPLICITTHIS;
 			}
-			return GetSignature(module).ToArray();
-		}
-
-		internal ByteBuffer GetSignature(ModuleBuilder module)
-		{
-			ByteBuffer bb = new ByteBuffer(16);
-			switch (type)
+			if ((callingConvention & CallingConventions.VarArgs) != 0)
 			{
-				case 0:
-					if (unmanaged)
-					{
-						Signature.WriteStandAloneMethodSig(module, bb, module.universe.MakeStandAloneMethodSig(unmanagedCallConv, returnType, returnTypeCustomModifiers, args.ToArray(), customModifiers.ToArray()));
-					}
-					else
-					{
-						Signature.WriteStandAloneMethodSig(module, bb, module.universe.MakeStandAloneMethodSig(callingConvention, returnType, returnTypeCustomModifiers, args.ToArray(), optionalArgs.ToArray(), customModifiers.ToArray()));
-					}
-					break;
-				case Signature.FIELD:
-					FieldSignature.Create(args[0], customModifiers[0]).WriteSig(module, bb);
-					break;
-				case Signature.PROPERTY:
-					Signature.WritePropertySig(module, bb, callingConvention, returnType, returnTypeCustomModifiers, args.ToArray(), customModifiers.ToArray());
-					break;
-				case Signature.LOCAL_SIG:
-					Signature.WriteLocalVarSig(module, bb, locals, customModifiers);
-					break;
-				default:
-					throw new InvalidOperationException();
+				type |= Signature.VARARG;
 			}
-			return bb;
+			SignatureHelper sig = Create(mod, type, returnType);
+			sig.AddArgument(returnType);
+			sig.paramCount = 0;
+			return sig;
 		}
 
-		public void AddSentinel()
+		public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
 		{
-			optional = true;
-			callingConvention |= CallingConventions.VarArgs;
+			SignatureHelper sig = Create(mod, 0, returnType);
+			sig.AddArgument(returnType);
+			sig.paramCount = 0;
+			sig.AddArguments(parameterTypes, null, null);
+			return sig;
 		}
 
+		public abstract byte[] GetSignature();
+
+		internal abstract ByteBuffer GetSignature(ModuleBuilder module);
+
+		public abstract void AddSentinel();
+
 		public void AddArgument(Type clsArgument)
 		{
 			AddArgument(clsArgument, false);
@@ -205,28 +301,16 @@ namespace IKVM.Reflection.Emit
 			__AddArgument(argument, false, CustomModifiers.FromReqOpt(requiredCustomModifiers, optionalCustomModifiers));
 		}
 
-		public void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers)
-		{
-			if (type == Signature.LOCAL_SIG)
-			{
-				locals.Add(new LocalBuilder(argument, 0, pinned));
-			}
-			else if (optional)
-			{
-				this.optionalArgs.Add(argument);
-			}
-			else
-			{
-				this.args.Add(argument);
-			}
-			this.customModifiers.Add(customModifiers);
-		}
+		public abstract void __AddArgument(Type argument, bool pinned, CustomModifiers customModifiers);
 
 		public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
 		{
-			for (int i = 0; i < arguments.Length; i++)
+			if (arguments != null)
 			{
-				__AddArgument(arguments[i], false, CustomModifiers.FromReqOpt(requiredCustomModifiers[i], optionalCustomModifiers[i]));
+				for (int i = 0; i < arguments.Length; i++)
+				{
+					__AddArgument(arguments[i], false, CustomModifiers.FromReqOpt(Util.NullSafeElementAt(requiredCustomModifiers, i), Util.NullSafeElementAt(optionalCustomModifiers, i)));
+				}
 			}
 		}
 	}

+ 0 - 2
mcs/class/IKVM.Reflection/IKVM.Reflection.csproj

@@ -76,8 +76,6 @@
     <Compile Include="FieldSignature.cs" />
     <Compile Include="Fusion.cs" />
     <Compile Include="GenericWrappers.cs" />
-    <Compile Include="Impl\CryptoConvert.cs" />
-    <Compile Include="Impl\CryptoHack.cs" />
     <Compile Include="Impl\ITypeOwner.cs" />
     <Compile Include="Impl\MdbWriter.cs" />
     <Compile Include="Impl\PdbWriter.cs" />

+ 1 - 5
mcs/class/IKVM.Reflection/Impl/SymbolSupport.cs

@@ -51,16 +51,12 @@ namespace IKVM.Reflection.Impl
 
 	static class SymbolSupport
 	{
-#if !NO_SYMBOL_WRITER
-		private static readonly bool runningOnMono = System.Type.GetType("Mono.Runtime") != null;
-#endif
-
 		internal static ISymbolWriterImpl CreateSymbolWriterFor(ModuleBuilder moduleBuilder)
 		{
 #if NO_SYMBOL_WRITER
 			throw new NotSupportedException("IKVM.Reflection compiled with NO_SYMBOL_WRITER does not support writing debugging symbols.");
 #else
-			if (runningOnMono)
+			if (Universe.MonoRuntime)
 			{
 #if MONO
 				return new MdbWriter(moduleBuilder);

+ 37 - 53
mcs/class/IKVM.Reflection/Signature.cs

@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2009-2011 Jeroen Frijters
+  Copyright (C) 2009-2012 Jeroen Frijters
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -585,58 +585,6 @@ namespace IKVM.Reflection
 			}
 		}
 
-		internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals, IList<CustomModifiers> customModifiers)
-		{
-			bb.Write(LOCAL_SIG);
-			bb.WriteCompressedInt(locals.Count);
-			for (int i = 0; i < locals.Count; i++)
-			{
-				if (locals[i].IsPinned)
-				{
-					bb.Write(ELEMENT_TYPE_PINNED);
-				}
-				if (customModifiers != null && i < customModifiers.Count)
-				{
-					WriteCustomModifiers(module, bb, customModifiers[i]);
-				}
-				WriteType(module, bb, locals[i].LocalType);
-			}
-		}
-
-		internal static void WritePropertySig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention,
-			Type returnType, CustomModifiers returnTypeCustomModifiers,
-			Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers)
-		{
-			byte flags = PROPERTY;
-			if ((callingConvention & CallingConventions.HasThis) != 0)
-			{
-				flags |= HASTHIS;
-			}
-			if ((callingConvention & CallingConventions.ExplicitThis) != 0)
-			{
-				flags |= EXPLICITTHIS;
-			}
-			if ((callingConvention & CallingConventions.VarArgs) != 0)
-			{
-				flags |= VARARG;
-			}
-			bb.Write(flags);
-			bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
-			WriteCustomModifiers(module, bb, returnTypeCustomModifiers);
-			WriteType(module, bb, returnType);
-			if (parameterTypes != null)
-			{
-				for (int i = 0; i < parameterTypes.Length; i++)
-				{
-					if (parameterTypeCustomModifiers != null)
-					{
-						WriteCustomModifiers(module, bb, parameterTypeCustomModifiers[i]);
-					}
-					WriteType(module, bb, parameterTypes[i]);
-				}
-			}
-		}
-
 		internal static void WriteTypeSpec(ModuleBuilder module, ByteBuffer bb, Type type)
 		{
 			WriteType(module, bb, type);
@@ -693,5 +641,41 @@ namespace IKVM.Reflection
 			}
 			return expanded;
 		}
+
+		internal static void WriteSignatureHelper(ModuleBuilder module, ByteBuffer bb, byte flags, ushort paramCount, List<Type> args)
+		{
+			bb.Write(flags);
+			if (flags != FIELD)
+			{
+				bb.WriteCompressedInt(paramCount);
+			}
+			foreach (Type type in args)
+			{
+				if (type == MarkerType.ModOpt)
+				{
+					bb.Write(ELEMENT_TYPE_CMOD_OPT);
+				}
+				else if (type == MarkerType.ModReq)
+				{
+					bb.Write(ELEMENT_TYPE_CMOD_REQD);
+				}
+				else if (type == MarkerType.Sentinel)
+				{
+					bb.Write(SENTINEL);
+				}
+				else if (type == MarkerType.Pinned)
+				{
+					bb.Write(ELEMENT_TYPE_PINNED);
+				}
+				else if (type == null)
+				{
+					bb.Write(ELEMENT_TYPE_VOID);
+				}
+				else
+				{
+					WriteType(module, bb, type);
+				}
+			}
+		}
 	}
 }

+ 23 - 2
mcs/class/IKVM.Reflection/StrongNameKeyPair.cs

@@ -38,6 +38,10 @@ namespace IKVM.Reflection
 			{
 				throw new ArgumentNullException("keyPairContainer");
 			}
+			if (Universe.MonoRuntime && Environment.OSVersion.Platform == PlatformID.Win32NT)
+			{
+				throw new NotSupportedException("IKVM.Reflection does not support key containers when running on Mono");
+			}
 			this.keyPairContainer = keyPairContainer;
 		}
 
@@ -70,6 +74,11 @@ namespace IKVM.Reflection
 		{
 			get
 			{
+				if (Universe.MonoRuntime)
+				{
+					// MONOBUG workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=5299
+					return MonoGetPublicKey();
+				}
 				using (RSACryptoServiceProvider rsa = CreateRSA())
 				{
 					byte[] cspBlob = rsa.ExportCspBlob(false);
@@ -100,9 +109,13 @@ namespace IKVM.Reflection
 				else
 				{
 					CspParameters parm = new CspParameters();
-					parm.Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey;
 					parm.KeyContainerName = keyPairContainer;
-					parm.KeyNumber = 2;	// Signature
+					// MONOBUG Mono doesn't like it when Flags or KeyNumber are set
+					if (!Universe.MonoRuntime)
+					{
+						parm.Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey;
+						parm.KeyNumber = 2;	// Signature
+					}
 					return new RSACryptoServiceProvider(parm);
 				}
 			}
@@ -111,5 +124,13 @@ namespace IKVM.Reflection
 				throw new ArgumentException("Unable to obtain public key for StrongNameKeyPair.");
 			}
 		}
+
+		[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+		private byte[] MonoGetPublicKey()
+		{
+			return keyPairArray != null
+				? new System.Reflection.StrongNameKeyPair(keyPairArray).PublicKey
+				: new System.Reflection.StrongNameKeyPair(keyPairContainer).PublicKey;
+		}
 	}
 }

+ 41 - 0
mcs/class/IKVM.Reflection/Type.cs

@@ -2837,4 +2837,45 @@ namespace IKVM.Reflection
 			return "<FunctionPtr>";
 		}
 	}
+
+	sealed class MarkerType : Type
+	{
+		// used by ILGenerator
+		internal static readonly Type Fault = new MarkerType();
+		internal static readonly Type Finally = new MarkerType();
+		internal static readonly Type Filter = new MarkerType();
+		// used by CustomModifiers and SignatureHelper
+		internal static readonly Type ModOpt = new MarkerType();
+		internal static readonly Type ModReq = new MarkerType();
+		// used by SignatureHelper
+		internal static readonly Type Sentinel = new MarkerType();
+		internal static readonly Type Pinned = new MarkerType();
+
+		private MarkerType() { }
+
+		public override Type BaseType
+		{
+			get { throw new InvalidOperationException(); }
+		}
+
+		public override TypeAttributes Attributes
+		{
+			get { throw new InvalidOperationException(); }
+		}
+
+		public override string Name
+		{
+			get { throw new InvalidOperationException(); }
+		}
+
+		public override string FullName
+		{
+			get { throw new InvalidOperationException(); }
+		}
+
+		public override Module Module
+		{
+			get { throw new InvalidOperationException(); }
+		}
+	}
 }

+ 2 - 1
mcs/class/IKVM.Reflection/Universe.cs

@@ -87,6 +87,7 @@ namespace IKVM.Reflection
 
 	public sealed class Universe : IDisposable
 	{
+		internal static readonly bool MonoRuntime = System.Type.GetType("Mono.Runtime") != null;
 		private readonly Dictionary<Type, Type> canonicalizedTypes = new Dictionary<Type, Type>();
 		private readonly List<AssemblyReader> assemblies = new List<AssemblyReader>();
 		private readonly List<AssemblyBuilder> dynamicAssemblies = new List<AssemblyBuilder>();
@@ -171,7 +172,7 @@ namespace IKVM.Reflection
 			try
 			{
 				return Environment.OSVersion.Platform == PlatformID.Win32NT
-					&& System.Type.GetType("Mono.Runtime") == null
+					&& !MonoRuntime
 					&& Environment.GetEnvironmentVariable("IKVM_DISABLE_FUSION") == null;
 			}
 			catch (System.Security.SecurityException)

+ 7 - 0
mcs/class/IKVM.Reflection/Util.cs

@@ -120,6 +120,13 @@ namespace IKVM.Reflection
 			return array;
 		}
 
+		internal static T[] ToArray<T>(IEnumerable<T> values)
+		{
+			return values == null
+				? Empty<T>.Array
+				: new List<T>(values).ToArray();
+		}
+
 		// note that an empty array matches a null reference
 		internal static bool ArrayEquals(Type[] t1, Type[] t2)
 		{

+ 37 - 2
mcs/class/IKVM.Reflection/Writer/ByteBuffer.cs

@@ -62,6 +62,26 @@ namespace IKVM.Reflection.Writer
 			get { return Math.Max(pos, __length); }
 		}
 
+		// insert count bytes at the current position (without advancing the current position)
+		internal void Insert(int count)
+		{
+			if (count > 0)
+			{
+				int len = this.Length;
+				int free = buffer.Length - len;
+				if (free < count)
+				{
+					Grow(count - free);
+				}
+				Buffer.BlockCopy(buffer, pos, buffer, pos + count, len - pos);
+				__length = Math.Max(__length, pos) + count;
+			}
+			else if (count < 0)
+			{
+				throw new ArgumentOutOfRangeException("count");
+			}
+		}
+
 		private void Grow(int minGrow)
 		{
 			byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
@@ -84,6 +104,20 @@ namespace IKVM.Reflection.Writer
 			return buffer[pos];
 		}
 
+		// return the number of bytes that the compressed int at the current position takes
+		internal int GetCompressedIntLength()
+		{
+			switch (buffer[pos] & 0xC0)
+			{
+				default:
+					return 1;
+				case 0x80:
+					return 2;
+				case 0xC0:
+					return 4;
+			}
+		}
+
 		internal void Write(byte[] value)
 		{
 			if (pos + value.Length > buffer.Length)
@@ -259,8 +293,9 @@ namespace IKVM.Reflection.Writer
 
 		internal byte[] ToArray()
 		{
-			byte[] buf = new byte[pos];
-			Buffer.BlockCopy(buffer, 0, buf, 0, pos);
+			int len = this.Length;
+			byte[] buf = new byte[len];
+			Buffer.BlockCopy(buffer, 0, buf, 0, len);
 			return buf;
 		}
 

+ 0 - 2
mcs/class/IKVM.Reflection/reflect.build

@@ -77,8 +77,6 @@
                 <include name="Emit\SignatureHelper.cs" />
                 <include name="Emit\Tokens.cs" />
                 <include name="Emit\TypeBuilder.cs" />
-                <include name="Impl\CryptoConvert.cs" />
-                <include name="Impl\CryptoHack.cs" />
                 <include name="Impl\ITypeOwner.cs" />
                 <include name="Impl\MdbWriter.cs" />
                 <include name="Impl\PdbWriter.cs" />