diff options
author | jfrijters <jfrijters> | 2011-12-01 13:47:21 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2011-12-01 13:47:21 +0400 |
commit | 8159a8d12c3db9a81774a7c7cb247f93346359ce (patch) | |
tree | fe556c5605013f8d0f7b8a51248852b369bca0e3 | |
parent | a1709bdbc80521975c606b1f73cd7cf619b6ec63 (diff) |
- Added custom modifier support in local variable signatures.
- Fixed SignatureHelper to support custom modifiers in method signatures.
-rw-r--r-- | reflect/CustomModifiers.cs | 19 | ||||
-rw-r--r-- | reflect/Emit/ILGenerator.cs | 23 | ||||
-rw-r--r-- | reflect/Emit/SignatureHelper.cs | 9 | ||||
-rw-r--r-- | reflect/LocalVariableInfo.cs | 11 | ||||
-rw-r--r-- | reflect/Signature.cs | 20 |
5 files changed, 66 insertions, 16 deletions
diff --git a/reflect/CustomModifiers.cs b/reflect/CustomModifiers.cs index e36029a2..499a120b 100644 --- a/reflect/CustomModifiers.cs +++ b/reflect/CustomModifiers.cs @@ -329,5 +329,24 @@ namespace IKVM.Reflection { return b == Signature.ELEMENT_TYPE_CMOD_OPT || b == Signature.ELEMENT_TYPE_CMOD_REQD; } + + internal static CustomModifiers Combine(CustomModifiers mods1, CustomModifiers mods2) + { + if (mods1.IsEmpty) + { + return mods2; + } + else if (mods2.IsEmpty) + { + return mods1; + } + else + { + Type[] combo = new Type[mods1.types.Length + mods2.types.Length]; + Array.Copy(mods1.types, combo, mods1.types.Length); + Array.Copy(mods2.types, 0, combo, mods1.types.Length, mods2.types.Length); + return new CustomModifiers(combo); + } + } } } diff --git a/reflect/Emit/ILGenerator.cs b/reflect/Emit/ILGenerator.cs index 437a4e3c..46c70918 100644 --- a/reflect/Emit/ILGenerator.cs +++ b/reflect/Emit/ILGenerator.cs @@ -152,6 +152,7 @@ namespace IKVM.Reflection.Emit private readonly ModuleBuilder moduleBuilder; private readonly ByteBuffer code; private readonly List<LocalBuilder> locals = new List<LocalBuilder>(); + private List<CustomModifiers> localCustomModifiers; private readonly List<int> tokenFixups = new List<int>(); private readonly List<int> labels = new List<int>(); private readonly List<int> labelStackHeight = new List<int>(); @@ -460,6 +461,26 @@ namespace IKVM.Reflection.Emit return local; } + public LocalBuilder __DeclareLocal(Type localType, bool pinned, CustomModifiers customModifiers) + { + if (!customModifiers.IsEmpty) + { + 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); + } + return DeclareLocal(localType, pinned); + } + public Label DefineLabel() { Label label = new Label(labels.Count); @@ -1034,7 +1055,7 @@ namespace IKVM.Reflection.Emit if (locals.Count != 0) { ByteBuffer localVarSig = new ByteBuffer(locals.Count + 2); - Signature.WriteLocalVarSig(moduleBuilder, localVarSig, locals); + Signature.WriteLocalVarSig(moduleBuilder, localVarSig, locals, localCustomModifiers); localVarSigTok = 0x11000000 | moduleBuilder.StandAloneSig.FindOrAddRecord(moduleBuilder.Blobs.Add(localVarSig)); } diff --git a/reflect/Emit/SignatureHelper.cs b/reflect/Emit/SignatureHelper.cs index 8162ef1e..b849371f 100644 --- a/reflect/Emit/SignatureHelper.cs +++ b/reflect/Emit/SignatureHelper.cs @@ -162,11 +162,11 @@ namespace IKVM.Reflection.Emit case 0: if (unmanaged) { - Signature.WriteStandAloneMethodSig(module, bb, __StandAloneMethodSig.Create(unmanagedCallConv, returnType, new CustomModifiers(), args.ToArray(), null)); + Signature.WriteStandAloneMethodSig(module, bb, __StandAloneMethodSig.Create(unmanagedCallConv, returnType, returnTypeCustomModifiers, args.ToArray(), customModifiers.ToArray())); } else { - Signature.WriteStandAloneMethodSig(module, bb, __StandAloneMethodSig.Create(callingConvention, returnType, new CustomModifiers(), args.ToArray(), optionalArgs.ToArray(), null)); + Signature.WriteStandAloneMethodSig(module, bb, __StandAloneMethodSig.Create(callingConvention, returnType, returnTypeCustomModifiers, args.ToArray(), optionalArgs.ToArray(), customModifiers.ToArray())); } break; case Signature.FIELD: @@ -176,7 +176,7 @@ namespace IKVM.Reflection.Emit Signature.WritePropertySig(module, bb, callingConvention, returnType, returnTypeCustomModifiers, args.ToArray(), customModifiers.ToArray()); break; case Signature.LOCAL_SIG: - Signature.WriteLocalVarSig(module, bb, locals); + Signature.WriteLocalVarSig(module, bb, locals, customModifiers); break; default: throw new InvalidOperationException(); @@ -209,7 +209,6 @@ namespace IKVM.Reflection.Emit { if (type == Signature.LOCAL_SIG) { - // TODO support custom modifiers in local sig locals.Add(new LocalBuilder(argument, 0, pinned)); } else if (optional) @@ -219,8 +218,8 @@ namespace IKVM.Reflection.Emit else { this.args.Add(argument); - this.customModifiers.Add(customModifiers); } + this.customModifiers.Add(customModifiers); } public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers) diff --git a/reflect/LocalVariableInfo.cs b/reflect/LocalVariableInfo.cs index 9575c4f5..e7f05678 100644 --- a/reflect/LocalVariableInfo.cs +++ b/reflect/LocalVariableInfo.cs @@ -1,5 +1,5 @@ /* - Copyright (C) 2009 Jeroen Frijters + Copyright (C) 2009-2011 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 @@ -30,12 +30,14 @@ namespace IKVM.Reflection private readonly int index; private readonly Type type; private readonly bool pinned; + private readonly CustomModifiers customModifiers; - internal LocalVariableInfo(int index, Type type, bool pinned) + internal LocalVariableInfo(int index, Type type, bool pinned, CustomModifiers customModifiers) { this.index = index; this.type = type; this.pinned = pinned; + this.customModifiers = customModifiers; } public bool IsPinned @@ -52,5 +54,10 @@ namespace IKVM.Reflection { get { return type; } } + + public CustomModifiers __GetCustomModifiers() + { + return customModifiers; + } } } diff --git a/reflect/Signature.cs b/reflect/Signature.cs index d4e0d2ad..ac93a3c3 100644 --- a/reflect/Signature.cs +++ b/reflect/Signature.cs @@ -259,20 +259,20 @@ namespace IKVM.Reflection if (br.PeekByte() == ELEMENT_TYPE_TYPEDBYREF) { br.ReadByte(); - list.Add(new LocalVariableInfo(i, module.universe.System_TypedReference, false)); + list.Add(new LocalVariableInfo(i, module.universe.System_TypedReference, false, new CustomModifiers())); } else { - CustomModifiers.Skip(br); + CustomModifiers mods1 = CustomModifiers.Read(module, br, context); bool pinned = false; if (br.PeekByte() == ELEMENT_TYPE_PINNED) { br.ReadByte(); pinned = true; } - CustomModifiers.Skip(br); + CustomModifiers mods2 = CustomModifiers.Read(module, br, context); Type type = ReadTypeOrByRef(module, br, context); - list.Add(new LocalVariableInfo(i, type, pinned)); + list.Add(new LocalVariableInfo(i, type, pinned, CustomModifiers.Combine(mods1, mods2))); } } } @@ -585,17 +585,21 @@ namespace IKVM.Reflection } } - internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals) + internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals, IList<CustomModifiers> customModifiers) { bb.Write(LOCAL_SIG); bb.WriteCompressedInt(locals.Count); - foreach (LocalBuilder local in locals) + for (int i = 0; i < locals.Count; i++) { - if (local.IsPinned) + if (locals[i].IsPinned) { bb.Write(ELEMENT_TYPE_PINNED); } - WriteType(module, bb, local.LocalType); + if (customModifiers != null && i < customModifiers.Count) + { + WriteCustomModifiers(module, bb, customModifiers[i]); + } + WriteType(module, bb, locals[i].LocalType); } } |