Merge pull request #69 from MichalStrehovsky/cctorsupport

Add support for running class constructors
This commit is contained in:
Michal Strehovský 2015-10-19 16:39:32 -07:00
Родитель 4fa5f2ab90 fb05bab838
Коммит 49072fb834
18 изменённых файлов: 400 добавлений и 40 удалений

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Debug = System.Diagnostics.Debug;
namespace System.Collections.Generic
{
@ -31,17 +32,25 @@ namespace System.Collections.Generic
public void Append(T[] newItems)
{
if (_items == null || (_count + newItems.Length) >= _items.Length)
var oldCount = _count;
ZeroExtend(newItems.Length);
Array.Copy(newItems, 0, _items, oldCount, newItems.Length);
}
public void ZeroExtend(int numItems)
{
Debug.Assert(numItems >= 0);
if (_items == null || (_count + numItems) >= _items.Length)
{
int newCount = 2 * _count + 1;
while ((_count + newItems.Length) >= newCount)
while ((_count + numItems) >= newCount)
{
newCount = 2 * newCount + 1;
}
Array.Resize(ref _items, newCount);
}
Array.Copy(newItems, 0, _items, _count, newItems.Length);
_count += newItems.Length;
_count += numItems;
}
public int Count

Просмотреть файл

@ -695,6 +695,14 @@ namespace Internal.TypeSystem
}
}
public override bool IsBeforeFieldInit
{
get
{
return _typeDef.IsBeforeFieldInit;
}
}
public override bool IsModuleType { get { return false; } }
}

Просмотреть файл

@ -157,6 +157,14 @@ namespace Internal.TypeSystem
return _typeDef.Context.GetMethodForInstantiatedType(typicalMethodDef, this);
}
public override MethodDesc GetStaticConstructor()
{
MethodDesc typicalCctor = _typeDef.GetStaticConstructor();
if (typicalCctor == null)
return null;
return _typeDef.Context.GetMethodForInstantiatedType(typicalCctor, this);
}
public override IEnumerable<FieldDesc> GetFields()
{
foreach (var fieldDef in _typeDef.GetFields())

Просмотреть файл

@ -5,12 +5,22 @@ namespace Internal.TypeSystem
{
public abstract partial class MetadataType : TypeDesc
{
public override bool HasStaticConstructor
{
get
{
return GetStaticConstructor() != null;
}
}
public abstract ClassLayoutMetadata GetClassLayout();
public abstract bool IsExplicitLayout { get; }
public abstract bool IsSequentialLayout { get; }
public abstract bool IsBeforeFieldInit { get; }
public abstract bool IsModuleType { get; }
}

Просмотреть файл

@ -251,6 +251,14 @@ namespace Internal.TypeSystem
}
}
public bool IsStaticConstructor
{
get
{
return this == this.OwningType.GetStaticConstructor();
}
}
public virtual string Name
{
get

Просмотреть файл

@ -336,6 +336,14 @@ namespace Internal.TypeSystem
}
}
public virtual bool HasStaticConstructor
{
get
{
return false;
}
}
public virtual IEnumerable<MethodDesc> GetMethods()
{
return MethodDesc.EmptyMethods;
@ -355,6 +363,11 @@ namespace Internal.TypeSystem
return null;
}
public virtual MethodDesc GetStaticConstructor()
{
return null;
}
public virtual IEnumerable<FieldDesc> GetFields()
{
return FieldDesc.EmptyFields;

Просмотреть файл

@ -248,6 +248,25 @@ namespace Internal.TypeSystem.Ecma
return null;
}
public override MethodDesc GetStaticConstructor()
{
var metadataReader = this.MetadataReader;
var stringComparer = metadataReader.StringComparer;
foreach (var handle in _typeDefinition.GetMethods())
{
var methodDefinition = metadataReader.GetMethodDefinition(handle);
if ((methodDefinition.Attributes & MethodAttributes.SpecialName) != 0 &&
stringComparer.Equals(methodDefinition.Name, ".cctor"))
{
MethodDesc method = (MethodDesc)this.Module.GetObject(handle);
return method;
}
}
return null;
}
public override IEnumerable<FieldDesc> GetFields()
{
foreach (var handle in _typeDefinition.GetFields())
@ -397,6 +416,14 @@ namespace Internal.TypeSystem.Ecma
}
}
public override bool IsBeforeFieldInit
{
get
{
return (_typeDefinition.Attributes & TypeAttributes.BeforeFieldInit) != 0;
}
}
public override bool IsModuleType
{
get

Просмотреть файл

@ -288,6 +288,18 @@ namespace ILToNative
Out.WriteLine("ret");
break;
case ReadyToRunHelperId.CCtorTrigger:
Out.Write("leaq __NonGCStaticBase_");
Out.Write(NameMangler.GetMangledTypeName((TypeDesc)helper.Target));
Out.WriteLine(" - 16(%rip), %rax");
Out.WriteLine("jmp *(%rax)");
// TODO: actually call into the managed helper that does a better job at this
// and won't call the same constructor twice...
break;
default:
throw new NotImplementedException();
}
@ -382,19 +394,63 @@ namespace ILToNative
if (type == null)
continue;
if (type.NonGCStaticFieldSize == 0 && !type.HasStaticConstructor)
continue;
// If the type has a class constructor, the GC statics section is prepended
// by System.Runtime.CompilerServices.StaticClassConstructionContext.
bool isAligned = false;
if (type.HasStaticConstructor && _registeredMethods.ContainsKey(type.GetStaticConstructor()))
{
int pointerSize = type.Context.Target.PointerSize;
// TODO: Assert that StaticClassConstructionContext type has the expected size and alignment
// (need to make it a well known type?)
int alignmentRequired = Math.Max(type.NonGCStaticFieldAlignment, pointerSize);
int classConstructionContextSize = 2 * pointerSize;
Out.Write(".align ");
Out.WriteLine(alignmentRequired);
// Prepend the context to the existing fields without messing up the alignment of those fields.
int classConstructorContextStorageSize = AlignmentHelper.AlignUp(classConstructionContextSize, alignmentRequired);
// Add padding before the context if alignment forces us to do so
if (classConstructorContextStorageSize - classConstructionContextSize > 0)
{
Out.Write(".rept ");
Out.WriteLine(classConstructorContextStorageSize - classConstructionContextSize);
}
isAligned = true;
var cctorMethod = type.GetStaticConstructor();
Out.Write(".quad ");
Out.WriteLine(NameMangler.GetMangledMethodName(cctorMethod));
Out.WriteLine(".quad 0");
}
Out.Write("__NonGCStaticBase_");
Out.Write(NameMangler.GetMangledTypeName(type));
Out.WriteLine(":");
if (type.NonGCStaticFieldSize > 0)
{
Out.Write(".align ");
Out.WriteLine(type.NonGCStaticFieldAlignment);
Out.Write("__NonGCStaticBase_");
Out.Write(NameMangler.GetMangledTypeName(type));
Out.WriteLine(":");
if (!isAligned)
{
Out.Write(".align ");
Out.WriteLine(type.NonGCStaticFieldAlignment);
}
Out.Write(".rept ");
Out.WriteLine(type.NonGCStaticFieldSize);
Out.WriteLine(".byte 0");
Out.WriteLine(".endr");
Out.WriteLine();
}
Out.WriteLine();
}
}

Просмотреть файл

@ -294,7 +294,7 @@ namespace ILToNative
if (!_options.IsCppCodeGen)
{
_nodeFactory = new NodeFactory(this._typeSystemContext.Target);
_nodeFactory = new NodeFactory(this._typeSystemContext);
NodeFactory.NameMangler = NameMangler;
var rootNode = _nodeFactory.MethodEntrypoint(_mainMethod);

Просмотреть файл

@ -49,8 +49,14 @@ namespace ILToNative
"RuntimeFieldHandle",
};
static readonly string[][] s_wellKnownEntrypointNames = new string[][] {
new string[] { "System.Runtime.CompilerServices", "CctorHelper", "CheckStaticClassConstruction" }
};
MetadataType[] _wellKnownTypes = new MetadataType[s_wellKnownTypeNames.Length];
MethodDesc[] _wellKnownEntrypoints = new MethodDesc[s_wellKnownEntrypointNames.Length];
EcmaModule _systemModule;
Dictionary<string, EcmaModule> _modules = new Dictionary<string, EcmaModule>(StringComparer.OrdinalIgnoreCase);
@ -93,6 +99,16 @@ namespace ILToNative
type.SetWellKnownType((WellKnownType)(typeIndex + 1));
_wellKnownTypes[typeIndex] = type;
}
// Initialize all well known entrypoints
for (int entrypointIndex = 0; entrypointIndex < _wellKnownEntrypoints.Length; entrypointIndex++)
{
MetadataType type = _systemModule.GetType(
s_wellKnownEntrypointNames[entrypointIndex][0],
s_wellKnownEntrypointNames[entrypointIndex][1]);
MethodDesc method = type.GetMethod(s_wellKnownEntrypointNames[entrypointIndex][2], null);
_wellKnownEntrypoints[entrypointIndex] = method;
}
}
public override MetadataType GetWellKnownType(WellKnownType wellKnownType)
@ -100,6 +116,11 @@ namespace ILToNative
return _wellKnownTypes[(int)wellKnownType - 1];
}
public MethodDesc GetWellKnownEntryPoint(WellKnownEntrypoint entryPoint)
{
return _wellKnownEntrypoints[(int)entryPoint - 1];
}
public override object ResolveAssembly(System.Reflection.AssemblyName name)
{
return GetModuleForSimpleName(name.Name);
@ -203,4 +224,10 @@ namespace ILToNative
}
}
}
public enum WellKnownEntrypoint
{
Unknown,
EnsureClassConstructorRun,
}
}

Просмотреть файл

@ -11,10 +11,12 @@ namespace ILToNative.DependencyAnalysis
public class NodeFactory
{
TargetDetails _target;
CompilerTypeSystemContext _context;
public NodeFactory(TargetDetails target)
public NodeFactory(CompilerTypeSystemContext context)
{
_target = target;
_target = context.Target;
_context = context;
CreateNodeCaches();
}
@ -141,6 +143,11 @@ namespace ILToNative.DependencyAnalysis
return _nonGCStatics.GetOrAdd(type);
}
public ISymbolNode TypeCctorContextSymbol(MetadataType type)
{
return _nonGCStatics.GetOrAdd(type).ClassConstructorContext;
}
private NodeCache<MetadataType, GCStaticsNode> _GCStatics;
public GCStaticsNode TypeGCStaticsSymbol(MetadataType type)
@ -206,6 +213,12 @@ namespace ILToNative.DependencyAnalysis
return _methodCode.GetOrAdd(method);
}
public ISymbolNode WellKnownEntrypoint(WellKnownEntrypoint entrypoint)
{
MethodDesc method = _context.GetWellKnownEntryPoint(entrypoint);
return MethodEntrypoint(method);
}
private NodeCache<MethodDesc, VirtualMethodUseNode> _virtMethods;
public DependencyNode VirtualMethodUse(MethodDesc decl)

Просмотреть файл

@ -2,21 +2,32 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Internal.TypeSystem;
using Debug = System.Diagnostics.Debug;
namespace ILToNative.DependencyAnalysis
{
/// <summary>
/// Represents a node with non-GC static data associated with a type, along
/// with it's class constructor context. The non-GC static data region shall be prefixed
/// with the class constructor context if the type has a class constructor that
/// needs to be triggered before the type members can be accessed.
/// </summary>
class NonGCStaticsNode : ObjectNode, ISymbolNode
{
MetadataType _type;
ISymbolNode _classConstructorContext;
public NonGCStaticsNode(MetadataType type)
{
_type = type;
if (HasClassConstructorContext)
{
_classConstructorContext = new ObjectAndOffsetSymbolNode(this, 0,
"__CCtorContext_" + NodeFactory.NameMangler.GetMangledTypeName(_type));
}
}
public override string GetName()
@ -32,14 +43,6 @@ namespace ILToNative.DependencyAnalysis
}
}
public override bool StaticDependenciesAreComputed
{
get
{
return true;
}
}
string ISymbolNode.MangledName
{
get
@ -52,17 +55,97 @@ namespace ILToNative.DependencyAnalysis
{
get
{
return 0;
if (!HasClassConstructorContext)
{
return 0;
}
else
{
// Prepend the context to the existing fields without messing up the alignment of those fields.
int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment, ClassConstructorContextAlignment);
int classConstructorContextStorageSize = AlignmentHelper.AlignUp(ClassConstructorContextSize, alignmentRequired);
return classConstructorContextStorageSize;
}
}
}
public bool HasClassConstructorContext
{
get
{
return _type.HasStaticConstructor;
}
}
public ISymbolNode ClassConstructorContext
{
get
{
Debug.Assert(HasClassConstructorContext);
return _classConstructorContext;
}
}
private int ClassConstructorContextSize
{
get
{
// TODO: Assert that StaticClassConstructionContext type has the expected size
// (need to make it a well known type?)
return _type.Context.Target.PointerSize * 2;
}
}
private int ClassConstructorContextAlignment
{
get
{
// TODO: Assert that StaticClassConstructionContext type has the expected alignment
// (need to make it a well known type?)
return _type.Context.Target.PointerSize;
}
}
public override bool StaticDependenciesAreComputed
{
get
{
return true;
}
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
{
ObjectData data = new ObjectData(new byte[_type.NonGCStaticFieldSize],
Array.Empty<Relocation>(),
_type.NonGCStaticFieldAlignment,
new ISymbolNode[] { this });
return data;
ObjectDataBuilder builder = new ObjectDataBuilder(factory);
// If the type has a class constructor, it's non-GC statics section is prefixed
// by System.Runtime.CompilerServices.StaticClassConstructionContext struct.
if (HasClassConstructorContext)
{
int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment, ClassConstructorContextAlignment);
builder.RequireAlignment(alignmentRequired);
Debug.Assert(((ISymbolNode)this).Offset >= ClassConstructorContextSize);
// Add padding before the context if alignment forces us to do so
builder.EmitZeros(((ISymbolNode)this).Offset - ClassConstructorContextSize);
// Emit the actual StaticClassConstructionContext
var cctorMethod = _type.GetStaticConstructor();
builder.EmitPointerReloc(factory.MethodEntrypoint(cctorMethod));
builder.EmitZeroPointer();
builder.DefinedSymbols.Add(_classConstructorContext);
}
else
{
builder.RequireAlignment(_type.NonGCStaticFieldAlignment);
}
builder.EmitZeros(_type.NonGCStaticFieldSize);
builder.DefinedSymbols.Add(this);
return builder.ToObjectData();
}
}
}

Просмотреть файл

@ -37,7 +37,7 @@ namespace ILToNative.DependencyAnalysis
public void RequireAlignment(int align)
{
Alignment = Math.Min(align, Alignment);
Alignment = Math.Max(align, Alignment);
}
public void RequirePointerAlignment()
@ -83,8 +83,12 @@ namespace ILToNative.DependencyAnalysis
public void EmitZeroPointer()
{
for (int i = 0; i < _target.PointerSize; i++)
EmitByte(0);
_data.ZeroExtend(_target.PointerSize);
}
public void EmitZeros(int numBytes)
{
_data.ZeroExtend(numBytes);
}
public void AddRelocAtOffset(ISymbolNode symbol, RelocType relocType, int offset, int instructionLength)

Просмотреть файл

@ -93,6 +93,11 @@ namespace ILToNative.DependencyAnalysis
encoder.EmitRET();
break;
case ReadyToRunHelperId.CCtorTrigger:
encoder.EmitLEAQ(Register.RCX, factory.TypeCctorContextSymbol((MetadataType)Helper.Target));
encoder.EmitJMP(factory.WellKnownEntrypoint(WellKnownEntrypoint.EnsureClassConstructorRun));
break;
default:
throw new NotImplementedException();
}

Просмотреть файл

@ -20,6 +20,7 @@ namespace ILToNative
CastClass,
GetNonGCStaticBase,
GetGCStaticBase,
CCtorTrigger,
}
public class ReadyToRunHelper : IEquatable<ReadyToRunHelper>
@ -57,6 +58,8 @@ namespace ILToNative
return "__GetNonGCStaticBase_" + _compilation.NameMangler.GetMangledTypeName((TypeDesc)this.Target);
case ReadyToRunHelperId.GetGCStaticBase:
return "__GetGCStaticBase_" + _compilation.NameMangler.GetMangledTypeName((TypeDesc)this.Target);
case ReadyToRunHelperId.CCtorTrigger:
return "__CCtorTrigger_" + _compilation.NameMangler.GetMangledTypeName((TypeDesc)this.Target);
default:
throw new NotImplementedException();
}

Просмотреть файл

@ -257,7 +257,7 @@ namespace Internal.JitInterface
[UnmanagedFunctionPointerAttribute(CallingConvention.ThisCall)]
delegate void _embedGenericHandle(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.Bool)]bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult);
[UnmanagedFunctionPointerAttribute(CallingConvention.ThisCall)]
delegate CORINFO_LOOKUP_KIND _getLocationOfThisType(IntPtr _this, CORINFO_METHOD_STRUCT_* context);
delegate void _getLocationOfThisType(IntPtr _this, CORINFO_LOOKUP_KIND* result, CORINFO_METHOD_STRUCT_* context);
[UnmanagedFunctionPointerAttribute(CallingConvention.ThisCall)]
delegate void* _getPInvokeUnmanagedTarget(IntPtr _this, CORINFO_METHOD_STRUCT_* method, ref void* ppIndirection);
[UnmanagedFunctionPointerAttribute(CallingConvention.ThisCall)]

Просмотреть файл

@ -292,6 +292,30 @@ namespace Internal.JitInterface
return corInfoType;
}
MethodDesc methodFromContext(CORINFO_CONTEXT_STRUCT* contextStruct)
{
if (((ulong)contextStruct & (ulong)CorInfoContextFlags.CORINFO_CONTEXTFLAGS_MASK) == (ulong)CorInfoContextFlags.CORINFO_CONTEXTFLAGS_CLASS)
{
return null;
}
else
{
return HandleToObject((CORINFO_METHOD_STRUCT_*)((ulong)contextStruct & ~(ulong)CorInfoContextFlags.CORINFO_CONTEXTFLAGS_MASK));
}
}
TypeDesc typeFromContext(CORINFO_CONTEXT_STRUCT* contextStruct)
{
if (((ulong)contextStruct & (ulong)CorInfoContextFlags.CORINFO_CONTEXTFLAGS_MASK) == (ulong)CorInfoContextFlags.CORINFO_CONTEXTFLAGS_CLASS)
{
return HandleToObject((CORINFO_CLASS_STRUCT_*)((ulong)contextStruct & ~(ulong)CorInfoContextFlags.CORINFO_CONTEXTFLAGS_MASK));
}
else
{
return methodFromContext(contextStruct).OwningType;
}
}
uint getMethodAttribsInternal(MethodDesc method)
{
CorInfoFlag result = 0;
@ -808,6 +832,12 @@ namespace Internal.JitInterface
pLookup.addr = (void*)ObjectToHandle(_compilation.GetReadyToRunHelper(ReadyToRunHelperId.CastClass, type));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE:
{
var type = HandleToObject(pResolvedToken.hClass);
pLookup.addr = (void*)ObjectToHandle(_compilation.GetReadyToRunHelper(ReadyToRunHelperId.CCtorTrigger, type));
}
break;
default:
throw new NotImplementedException();
}
@ -818,8 +848,57 @@ namespace Internal.JitInterface
CorInfoInitClassResult initClass(IntPtr _this, CORINFO_FIELD_STRUCT_* field, CORINFO_METHOD_STRUCT_* method, CORINFO_CONTEXT_STRUCT* context, [MarshalAs(UnmanagedType.Bool)]bool speculative)
{
// TODO: Cctor triggers
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
FieldDesc fd = field == null ? null : HandleToObject(field);
Debug.Assert(fd == null || fd.IsStatic);
MethodDesc md = HandleToObject(method);
MetadataType typeToInit = (MetadataType)(fd != null ? fd.OwningType : typeFromContext(context));
if (!typeToInit.HasStaticConstructor)
{
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
}
if (typeToInit.IsModuleType)
{
// For both jitted and ngen code the global class is always considered initialized
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
}
if (fd == null)
{
if (typeToInit.IsBeforeFieldInit)
{
// We can wait for field accesses to run .cctor
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
}
// Run .cctor on statics & constructors
if (md.Signature.IsStatic)
{
// Except don't class construct on .cctor - it would be circular
if (md.IsStaticConstructor)
{
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
}
}
else if (!md.IsConstructor && !typeToInit.IsValueType)
{
// According to the spec, we should be able to do this optimization for both reference and valuetypes.
// To maintain backward compatibility, we are doing it for reference types only.
// For instance methods of types with precise-initialization
// semantics, we can assume that the .ctor triggerred the
// type initialization.
// This does not hold for NULL "this" object. However, the spec does
// not require that case to work.
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
}
}
// TODO: before giving up and asking to generate a helper call, check to see if this is some pattern we can
// prove doesn't need initclass anymore because we initialized it earlier.
return CorInfoInitClassResult.CORINFO_INITCLASS_USE_HELPER;
}
void classMustBeLoadedBeforeCodeIsRun(IntPtr _this, CORINFO_CLASS_STRUCT_* cls)
@ -1190,8 +1269,14 @@ namespace Internal.JitInterface
{ throw new NotImplementedException(); }
void embedGenericHandle(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.Bool)]bool fEmbedParent, ref CORINFO_GENERICHANDLE_RESULT pResult)
{ throw new NotImplementedException(); }
CORINFO_LOOKUP_KIND getLocationOfThisType(IntPtr _this, CORINFO_METHOD_STRUCT_* context)
{ throw new NotImplementedException(); }
void getLocationOfThisType(IntPtr _this, CORINFO_LOOKUP_KIND* result, CORINFO_METHOD_STRUCT_* context)
{
result->needsRuntimeLookup = false;
result->runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ;
// TODO: shared generics
}
void* getPInvokeUnmanagedTarget(IntPtr _this, CORINFO_METHOD_STRUCT_* method, ref void* ppIndirection)
{ throw new NotImplementedException(); }
void* getAddressOfPInvokeFixup(IntPtr _this, CORINFO_METHOD_STRUCT_* method, ref void* ppIndirection)

Просмотреть файл

@ -277,7 +277,8 @@ FUNCTIONS
CORINFO_METHOD_HANDLE embedMethodHandle(CORINFO_METHOD_HANDLE handle, void **ppIndirection);
CORINFO_FIELD_HANDLE embedFieldHandle(CORINFO_FIELD_HANDLE handle, void **ppIndirection);
void embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, BOOL fEmbedParent, CORINFO_GENERICHANDLE_RESULT * pResult);
CORINFO_LOOKUP_KIND getLocationOfThisType(CORINFO_METHOD_HANDLE context);
; WORKAROUND: CLR doesn't marshal the return struct right, so explicitly list the pointer to it as the first parameter
void getLocationOfThisType(CORINFO_LOOKUP_KIND * result, CORINFO_METHOD_HANDLE context);
void* getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void **ppIndirection);
void* getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method, void **ppIndirection);
LPVOID GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void ** ppIndirection);