X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FIKVM.Reflection%2FEmit%2FILGenerator.cs;h=7fddd7bcdb6f0edbfbeb7083f8a9c01d98db4c18;hb=3af50114d986e9ffcd1544aa7ff13f7472992687;hp=0f086b22f6e455ea7525e7d51d7b7c569d44e40a;hpb=95db77b7c5cabe65be02c6822796a9440dfd2fb1;p=mono.git diff --git a/mcs/class/IKVM.Reflection/Emit/ILGenerator.cs b/mcs/class/IKVM.Reflection/Emit/ILGenerator.cs index 0f086b22f6e..7fddd7bcdb6 100644 --- a/mcs/class/IKVM.Reflection/Emit/ILGenerator.cs +++ b/mcs/class/IKVM.Reflection/Emit/ILGenerator.cs @@ -1,5 +1,5 @@ /* - Copyright (C) 2008-2010 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 @@ -26,7 +26,6 @@ using System.Runtime.InteropServices; using System.Collections.Generic; using System.Diagnostics.SymbolStore; using System.Diagnostics; -using IKVM.Reflection.Metadata; using IKVM.Reflection.Writer; namespace IKVM.Reflection.Emit @@ -118,10 +117,10 @@ namespace IKVM.Reflection.Emit public sealed class ILGenerator { - private static readonly Type FAULT = new BakedType(null); // the type we use here doesn't matter, as long as it can never be used as a real exception type private readonly ModuleBuilder moduleBuilder; private readonly ByteBuffer code; - private readonly List locals = new List(); + private readonly SignatureHelper locals; + private int localsCount; private readonly List tokenFixups = new List(); private readonly List labels = new List(); private readonly List labelStackHeight = new List(); @@ -130,6 +129,7 @@ namespace IKVM.Reflection.Emit private readonly List exceptions = new List(); private readonly Stack exceptionStack = new Stack(); private ushort maxStack; + private bool fatHeader; private int stackHeight; private Scope scope; private byte exceptionBlockAssistanceMode = EBAM_COMPAT; @@ -151,7 +151,7 @@ namespace IKVM.Reflection.Emit internal int tryLength; internal int handlerOffset; internal int handlerLength; - internal Type exceptionType; // null = finally block or 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) @@ -166,33 +166,21 @@ namespace IKVM.Reflection.Emit { return 0; } - if (x.tryOffset >= y.handlerOffset && x.tryOffset + x.tryLength <= y.handlerOffset + y.handlerLength) - { - return -1; - } - if (y.tryOffset >= x.handlerOffset && y.tryOffset + y.tryLength <= x.handlerOffset + x.handlerLength) - { - return 1; - } - if (x.tryOffset == y.tryOffset && x.tryLength == y.tryLength) + else if (x.tryOffset == y.tryOffset && x.tryLength == y.tryLength) { return x.ordinal < y.ordinal ? -1 : 1; } - if (x.tryOffset + x.tryLength <= y.tryOffset) + else if (x.tryOffset >= y.tryOffset && x.handlerOffset + x.handlerLength <= y.handlerOffset + y.handlerLength) { return -1; } - if (y.tryOffset + y.tryLength <= x.tryOffset) + else if (y.tryOffset >= x.tryOffset && y.handlerOffset + y.handlerLength <= x.handlerOffset + x.handlerLength) { return 1; } - if (x.tryOffset > y.tryOffset || (x.tryOffset == y.tryOffset && x.tryLength < y.tryLength)) - { - return -1; - } else { - return 1; + return x.ordinal < y.ordinal ? -1 : 1; } } } @@ -225,17 +213,13 @@ 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); } } - private bool IsLabelReachable(Label label) - { - return labelStackHeight[label.Index] != -1; - } - // non-standard API public void __DisableExceptionBlockAssistance() { @@ -248,6 +232,24 @@ namespace IKVM.Reflection.Emit exceptionBlockAssistanceMode = EBAM_CLEVER; } + // non-standard API + public int __MaxStackSize + { + get { return maxStack; } + set + { + maxStack = (ushort)value; + fatHeader = true; + } + } + + // non-standard API + // returns -1 if the current position is currently unreachable + public int __StackHeight + { + get { return stackHeight; } + } + // new in .NET 4.0 public int ILOffset { @@ -270,24 +272,42 @@ namespace IKVM.Reflection.Emit } stackHeight = 0; UpdateStack(1); - if (block.tryLength == 0) + if (exceptionType == null) { - block.tryLength = code.Position - block.tryOffset; + if (block.exceptionType != MarkerType.Filter || block.handlerOffset != 0) + { + throw new ArgumentNullException("exceptionType"); + } + block.handlerOffset = code.Position; } - else if (exceptionType != null) + else { - block.handlerLength = code.Position - block.handlerOffset; - exceptionStack.Pop(); - ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); - newBlock.labelEnd = block.labelEnd; - newBlock.tryOffset = block.tryOffset; - newBlock.tryLength = block.tryLength; - block = newBlock; - exceptions.Add(block); - exceptionStack.Push(block); + if (block.tryLength == 0) + { + block.tryLength = code.Position - block.tryOffset; + } + else + { + block.handlerLength = code.Position - block.handlerOffset; + exceptionStack.Pop(); + ExceptionBlock newBlock = new ExceptionBlock(exceptions.Count); + newBlock.labelEnd = block.labelEnd; + newBlock.tryOffset = block.tryOffset; + newBlock.tryLength = block.tryLength; + block = newBlock; + exceptions.Add(block); + exceptionStack.Push(block); + } + block.exceptionType = exceptionType; + if (exceptionType == MarkerType.Filter) + { + block.filterOffset = code.Position; + } + else + { + block.handlerOffset = code.Position; + } } - block.handlerOffset = code.Position; - block.exceptionType = exceptionType; } public Label BeginExceptionBlock() @@ -303,25 +323,20 @@ namespace IKVM.Reflection.Emit public void BeginExceptFilterBlock() { - ExceptionBlock block = BeginFinallyFilterFaultBlock(); - block.filterOffset = code.Position; - UpdateStack(1); + BeginCatchBlock(MarkerType.Filter); } public void BeginFaultBlock() { - ExceptionBlock block = BeginFinallyFilterFaultBlock(); - block.handlerOffset = code.Position; - block.exceptionType = FAULT; + BeginFinallyFaultBlock(MarkerType.Fault); } public void BeginFinallyBlock() { - ExceptionBlock block = BeginFinallyFilterFaultBlock(); - block.handlerOffset = code.Position; + BeginFinallyFaultBlock(MarkerType.Finally); } - private ExceptionBlock BeginFinallyFilterFaultBlock() + private void BeginFinallyFaultBlock(Type type) { ExceptionBlock block = exceptionStack.Peek(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) @@ -355,8 +370,9 @@ namespace IKVM.Reflection.Emit exceptions.Add(block); exceptionStack.Push(block); } + block.handlerOffset = code.Position; + block.exceptionType = type; stackHeight = 0; - return block; } public void EndExceptionBlock() @@ -364,7 +380,7 @@ namespace IKVM.Reflection.Emit ExceptionBlock block = exceptionStack.Pop(); if (exceptionBlockAssistanceMode == EBAM_COMPAT || (exceptionBlockAssistanceMode == EBAM_CLEVER && stackHeight != -1)) { - if (block.filterOffset != 0 || (block.exceptionType != null && block.exceptionType != FAULT)) + if (block.filterOffset != 0 || (block.exceptionType != MarkerType.Finally && block.exceptionType != MarkerType.Fault)) { Emit(OpCodes.Leave, block.labelEnd); } @@ -400,8 +416,19 @@ 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); + } + return local; + } + + public LocalBuilder __DeclareLocal(Type localType, bool pinned, CustomModifiers customModifiers) + { + LocalBuilder local = new LocalBuilder(localType, localsCount++, pinned); + locals.__AddArgument(localType, pinned, customModifiers); if (scope != null) { scope.locals.Add(local); @@ -689,9 +716,9 @@ namespace IKVM.Reflection.Emit public void Emit(OpCode opc, MethodInfo method) { + UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount); Emit(opc); WriteToken(moduleBuilder.GetMethodTokenForIL(method)); - UpdateStack(opc, method.HasThis, method.ReturnType, method.ParameterCount); } public void Emit(OpCode opc, ConstructorInfo constructor) @@ -714,7 +741,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) @@ -734,10 +761,15 @@ 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) + { + __EmitCall(opc, method, optionalParameterTypes, null); + } + + public void __EmitCall(OpCode opc, MethodInfo method, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) { if (optionalParameterTypes == null || optionalParameterTypes.Length == 0) { @@ -747,20 +779,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); - 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); } } @@ -769,25 +788,42 @@ namespace IKVM.Reflection.Emit EmitCall(opc, constructor.GetMethodInfo(), optionalParameterTypes); } + public void __EmitCall(OpCode opc, ConstructorInfo constructor, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) + { + __EmitCall(opc, constructor.GetMethodInfo(), optionalParameterTypes, customModifiers); + } + public void EmitCalli(OpCode opc, CallingConvention callingConvention, Type returnType, Type[] parameterTypes) { - returnType = returnType ?? moduleBuilder.universe.System_Void; - Emit(opc); - UpdateStack(opc, false, returnType, parameterTypes.Length); - ByteBuffer sig = new ByteBuffer(16); - Signature.WriteStandAloneMethodSig(moduleBuilder, sig, callingConvention, returnType, parameterTypes); - code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(sig))); + 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) { - returnType = returnType ?? moduleBuilder.universe.System_Void; - optionalParameterTypes = optionalParameterTypes ?? Type.EmptyTypes; + 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) + { Emit(opc); - UpdateStack(opc, (callingConvention & CallingConventions.HasThis | CallingConventions.ExplicitThis) == CallingConventions.HasThis, returnType, parameterTypes.Length + optionalParameterTypes.Length); - ByteBuffer sig = new ByteBuffer(16); - Signature.WriteStandAloneMethodSig(moduleBuilder, sig, callingConvention, returnType, parameterTypes, optionalParameterTypes); - code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(sig))); + if (sig.IsUnmanaged) + { + UpdateStack(opc, false, sig.ReturnType, sig.ParameterCount); + } + else + { + CallingConventions callingConvention = sig.CallingConvention; + UpdateStack(opc, (callingConvention & CallingConventions.HasThis | CallingConventions.ExplicitThis) == CallingConventions.HasThis, sig.ReturnType, sig.ParameterCount); + } + ByteBuffer bb = new ByteBuffer(16); + Signature.WriteStandAloneMethodSig(moduleBuilder, bb, sig); + code.Write(0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(bb))); } public void EmitWriteLine(string text) @@ -886,7 +922,7 @@ namespace IKVM.Reflection.Emit int localVarSigTok = 0; int rva; - if (locals.Count == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64) + if (localsCount == 0 && exceptions.Count == 0 && maxStack <= 8 && code.Length < 64 && !fatHeader) { rva = WriteTinyHeaderAndCode(bb); } @@ -974,11 +1010,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); - localVarSigTok = 0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(localVarSig)); + localVarSigTok = moduleBuilder.GetSignatureToken(locals).Token; } const byte CorILMethod_FatFormat = 0x03; @@ -1036,27 +1070,27 @@ 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.filterOffset != 0) + else if (block.exceptionType == MarkerType.Filter) { bb.Write((int)COR_ILEXCEPTION_CLAUSE_FILTER); } - else if (block.exceptionType != null) + else if (block.exceptionType == MarkerType.Finally) { - bb.Write((int)COR_ILEXCEPTION_CLAUSE_EXCEPTION); + bb.Write((int)COR_ILEXCEPTION_CLAUSE_FINALLY); } else { - bb.Write((int)COR_ILEXCEPTION_CLAUSE_FINALLY); + bb.Write((int)COR_ILEXCEPTION_CLAUSE_EXCEPTION); } bb.Write(block.tryOffset); bb.Write(block.tryLength); bb.Write(block.handlerOffset); bb.Write(block.handlerLength); - if (block.exceptionType != null && block.exceptionType != FAULT) + if (block.exceptionType != MarkerType.Fault && block.exceptionType != MarkerType.Filter && block.exceptionType != MarkerType.Finally) { bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType)); } @@ -1073,27 +1107,27 @@ 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.filterOffset != 0) + else if (block.exceptionType == MarkerType.Filter) { bb.Write(COR_ILEXCEPTION_CLAUSE_FILTER); } - else if (block.exceptionType != null) + else if (block.exceptionType == MarkerType.Finally) { - bb.Write(COR_ILEXCEPTION_CLAUSE_EXCEPTION); + bb.Write(COR_ILEXCEPTION_CLAUSE_FINALLY); } else { - bb.Write(COR_ILEXCEPTION_CLAUSE_FINALLY); + bb.Write(COR_ILEXCEPTION_CLAUSE_EXCEPTION); } bb.Write((short)block.tryOffset); bb.Write((byte)block.tryLength); bb.Write((short)block.handlerOffset); bb.Write((byte)block.handlerLength); - if (block.exceptionType != null && block.exceptionType != FAULT) + if (block.exceptionType != MarkerType.Fault && block.exceptionType != MarkerType.Filter && block.exceptionType != MarkerType.Finally) { bb.Write(moduleBuilder.GetTypeTokenForMemberRef(block.exceptionType)); }