/// <summary> /// NEWOBJ operation on String type is actually a call to a static method that returns a String /// instance (i.e. there's an explicit call to the runtime allocator from the static method body). /// This method returns the alloc+init helper corresponding to a given string constructor. /// </summary> public static MethodDesc GetStringInitializer(this MethodDesc constructorMethod) { Debug.Assert(constructorMethod.IsConstructor); Debug.Assert(constructorMethod.OwningType.IsString); var signatureBuilder = new MethodSignatureBuilder(constructorMethod.Signature); signatureBuilder.Flags = MethodSignatureFlags.Static; signatureBuilder.ReturnType = constructorMethod.OwningType; return constructorMethod.OwningType.GetKnownMethod("Ctor", signatureBuilder.ToSignature()); }
protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind) { MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(_signature); sigBuilder.ReturnType = Context.ConvertToCanon(_signature.ReturnType, kind); for (int i = 0; i < _signature.Length; i++) sigBuilder[i] = Context.ConvertToCanon(_signature[i], kind); MethodSignature canonSignature = sigBuilder.ToSignature(); if (canonSignature != _signature) return Context.GetFunctionPointerType(canonSignature); return this; }
public override TypeDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation) { MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(_signature); sigBuilder.ReturnType = _signature.ReturnType.InstantiateSignature(typeInstantiation, methodInstantiation); for (int i = 0; i < _signature.Length; i++) sigBuilder[i] = _signature[i].InstantiateSignature(typeInstantiation, methodInstantiation); MethodSignature instantiatedSignature = sigBuilder.ToSignature(); if (instantiatedSignature != _signature) return Context.GetFunctionPointerType(instantiatedSignature); return this; }
public override TypeDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation) { MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(_signature); sigBuilder.ReturnType = _signature.ReturnType.InstantiateSignature(typeInstantiation, methodInstantiation); for (int i = 0; i < _signature.Length; i++) { sigBuilder[i] = _signature[i].InstantiateSignature(typeInstantiation, methodInstantiation); } MethodSignature instantiatedSignature = sigBuilder.ToSignature(); if (instantiatedSignature != _signature) { return(Context.GetFunctionPointerType(instantiatedSignature)); } return(this); }
protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind) { MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(_signature); sigBuilder.ReturnType = Context.ConvertToCanon(_signature.ReturnType, kind); for (int i = 0; i < _signature.Length; i++) { sigBuilder[i] = Context.ConvertToCanon(_signature[i], kind); } MethodSignature canonSignature = sigBuilder.ToSignature(); if (canonSignature != _signature) { return(Context.GetFunctionPointerType(canonSignature)); } return(this); }
public override Object GetObject(int token) { Object o = _methodIL.GetObject(token); if (o is MethodDesc) { o = ((MethodDesc)o).InstantiateSignature(_typeInstantiation, _methodInstantiation); } else if (o is TypeDesc) { o = ((TypeDesc)o).InstantiateSignature(_typeInstantiation, _methodInstantiation); } else if (o is FieldDesc) { o = ((FieldDesc)o).InstantiateSignature(_typeInstantiation, _methodInstantiation); } else if (o is MethodSignature) { MethodSignature template = (MethodSignature)o; MethodSignatureBuilder builder = new MethodSignatureBuilder(template); builder.ReturnType = template.ReturnType.InstantiateSignature(_typeInstantiation, _methodInstantiation); for (int i = 0; i < template.Length; i++) builder[i] = template[i].InstantiateSignature(_typeInstantiation, _methodInstantiation); o = builder.ToSignature(); } return o; }
public override MethodIL EmitIL() { // Target has the same signature as the Invoke method, except it's static. MethodSignatureBuilder builder = new MethodSignatureBuilder(Signature); builder.Flags = Signature.Flags | MethodSignatureFlags.Static; var emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); // Load all arguments except 'this' for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Indirectly call the delegate target static method. codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(ExtraFunctionPointerOrDataField)); codeStream.Emit(ILOpcode.calli, emitter.NewToken(builder.ToSignature())); codeStream.Emit(ILOpcode.ret); return emitter.Link(this); }
/// <summary> /// Replace some of the types in a type's construction with a new set of types. This function does not /// support any situation where there is an instantiated generic that is not represented by an /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type. /// /// For instance, Given MyType<object, int[]>, /// an array of types to replace such as {int,object}, and /// an array of replacement types such as {string,__Canon}. /// The result shall be MyType<__Canon, string[]> /// /// This function cannot be used to replace MyType in the above example. /// </summary> public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes) { int directReplacementIndex = Array.IndexOf(typesToReplace, type); if (directReplacementIndex != -1) { return(replacementTypes[directReplacementIndex]); } if (type.HasInstantiation) { TypeDesc[] newInstantiation = null; Debug.Assert(type is InstantiatedType); int instantiationIndex = 0; for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++) { TypeDesc oldType = type.Instantiation[instantiationIndex]; TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if ((oldType != newType) || (newInstantiation != null)) { if (newInstantiation == null) { newInstantiation = new TypeDesc[type.Instantiation.Length]; for (int i = 0; i < instantiationIndex; i++) { newInstantiation[i] = type.Instantiation[i]; } } newInstantiation[instantiationIndex] = newType; } } if (newInstantiation != null) { return(type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation))); } } else if (type.IsParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; TypeDesc oldParameter = parameterizedType.ParameterType; TypeDesc newParameter = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if (oldParameter != newParameter) { if (type.IsArray) { ArrayType arrayType = (ArrayType)type; if (arrayType.IsSzArray) { return(type.Context.GetArrayType(newParameter)); } else { return(type.Context.GetArrayType(newParameter, arrayType.Rank)); } } else if (type.IsPointer) { return(type.Context.GetPointerType(newParameter)); } else if (type.IsByRef) { return(type.Context.GetByRefType(newParameter)); } Debug.Fail("Unknown form of type"); } } else if (type.IsFunctionPointer) { MethodSignature oldSig = ((FunctionPointerType)type).Signature; MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig); sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++) { sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); } MethodSignature newSig = sigBuilder.ToSignature(); if (newSig != oldSig) { return(type.Context.GetFunctionPointerType(newSig)); } } return(type); }
/// <summary> /// Replace some of the types in a type's construction with a new set of types. This function does not /// support any situation where there is an instantiated generic that is not represented by an /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type. /// /// For instance, Given MyType<object, int[]>, /// an array of types to replace such as {int,object}, and /// an array of replacement types such as {string,__Canon}. /// The result shall be MyType<__Canon, string[]> /// /// This function cannot be used to replace MyType in the above example. /// </summary> public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes) { int directReplacementIndex = Array.IndexOf(typesToReplace, type); if (directReplacementIndex != -1) return replacementTypes[directReplacementIndex]; if (type.HasInstantiation) { TypeDesc[] newInstantiation = null; Debug.Assert(type is InstantiatedType); int instantiationIndex = 0; for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++) { TypeDesc oldType = type.Instantiation[instantiationIndex]; TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if ((oldType != newType) || (newInstantiation != null)) { if (newInstantiation == null) { newInstantiation = new TypeDesc[type.Instantiation.Length]; for (int i = 0; i < instantiationIndex; i++) newInstantiation[i] = type.Instantiation[i]; } newInstantiation[instantiationIndex] = newType; } } if (newInstantiation != null) return type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation)); } else if (type.IsParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; TypeDesc oldParameter = parameterizedType.ParameterType; TypeDesc newParameter = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if (oldParameter != newParameter) { if (type.IsArray) { ArrayType arrayType = (ArrayType)type; if (arrayType.IsSzArray) return type.Context.GetArrayType(newParameter); else return type.Context.GetArrayType(newParameter, arrayType.Rank); } else if (type.IsPointer) { return type.Context.GetPointerType(newParameter); } else if (type.IsByRef) { return type.Context.GetByRefType(newParameter); } Debug.Fail("Unknown form of type"); } } else if (type.IsFunctionPointer) { MethodSignature oldSig = ((FunctionPointerType)type).Signature; MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig); sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++) sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); MethodSignature newSig = sigBuilder.ToSignature(); if (newSig != oldSig) return type.Context.GetFunctionPointerType(newSig); } return type; }