private MethodSignature HandleMethodSignature(Cts.MethodSignature signature) { List <ParameterTypeSignature> parameters; if (signature.Length > 0) { parameters = new List <ParameterTypeSignature>(signature.Length); for (int i = 0; i < signature.Length; i++) { parameters.Add(HandleParameterTypeSignature(signature[i])); } } else { parameters = null; } return(new MethodSignature { // TODO: CallingConvention GenericParameterCount = signature.GenericParameterCount, Parameters = parameters, ReturnType = new ReturnTypeSignature { // TODO: CustomModifiers Type = HandleType(signature.ReturnType) }, // TODO-NICE: VarArgParameters }); }
public static MethodIL EmitIL(MethodDesc target) { Debug.Assert(target.Name == "Call"); Debug.Assert(target.Signature.Length > 0 && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr)); ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); // Load all the arguments except the first one (IntPtr address) for (int i = 1; i < target.Signature.Length; i++) { codeStream.EmitLdArg(i); } // now load IntPtr address codeStream.EmitLdArg(0); // Create a signature for the calli by copying the signature of the containing method // while skipping the first argument MethodSignature template = target.Signature; TypeDesc returnType = template.ReturnType; TypeDesc[] parameters = new TypeDesc[template.Length - 1]; for (int i = 1; i < template.Length; i++) { parameters[i - 1] = template[i]; } var signature = new MethodSignature(template.Flags, 0, returnType, parameters); codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature)); codeStream.Emit(ILOpcode.ret); return emitter.Link(); }
public void TestMethodLookup() { MetadataType t = _testModule.GetType("GenericTypes", "GenericClass`1").MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32)); MethodSignature sig = new MethodSignature(MethodSignatureFlags.None, 0, t.Instantiation[0], new TypeDesc[0] { }); MethodDesc fooMethod = t.GetMethod("Foo", sig); Assert.NotNull(fooMethod); }
private MethodSignature InitializeSignature() { var metadataReader = MetadataReader; BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetMethodDefinition(_handle).Signature); EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader); var signature = parser.ParseMethodSignature(); return (_signature = signature); }
private bool IsBlocked(Cts.TypeDesc type) { switch (type.Category) { case Cts.TypeFlags.SzArray: case Cts.TypeFlags.Array: case Cts.TypeFlags.Pointer: case Cts.TypeFlags.ByRef: return(IsBlocked(((Cts.ParameterizedType)type).ParameterType)); case Cts.TypeFlags.SignatureMethodVariable: case Cts.TypeFlags.SignatureTypeVariable: return(false); case Cts.TypeFlags.FunctionPointer: { Cts.MethodSignature pointerSignature = ((Cts.FunctionPointerType)type).Signature; if (IsBlocked(pointerSignature.ReturnType)) { return(true); } for (int i = 0; i < pointerSignature.Length; i++) { if (IsBlocked(pointerSignature[i])) { return(true); } } return(false); } default: Debug.Assert(type.IsDefType); if (!type.IsTypeDefinition) { if (IsBlocked(type.GetTypeDefinition())) { return(true); } foreach (var arg in type.Instantiation) { if (IsBlocked(arg)) { return(true); } } return(false); } return(_policy.IsBlocked((Cts.MetadataType)type)); } }
/// <summary> /// Retrieves a method on <paramref name="type"/> that is well known to the compiler. /// Throws an exception if the method doesn't exist. /// </summary> public static MethodDesc GetKnownMethod(this TypeDesc type, string name, MethodSignature signature) { MethodDesc method = type.GetMethod(name, signature); if (method == null) { throw new InvalidOperationException(String.Format("Expected method '{0}' not found on type '{1}'", name, type)); } return method; }
private CallingConventions GetSignatureCallingConvention(Cts.MethodSignature signature) { CallingConventions callingConvention = CallingConventions.Standard; if ((signature.Flags & Cts.MethodSignatureFlags.Static) == 0) { callingConvention = CallingConventions.HasThis; } // TODO: additional calling convention flags like stdcall / cdecl etc. return(callingConvention); }
public static MethodIL EmitIL(MethodDesc target) { Debug.Assert(target.Name == "Call"); Debug.Assert(target.Signature.Length > 0 && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr)); ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); // Load all the arguments except the first one (IntPtr address) for (int i = 1; i < target.Signature.Length; i++) { codeStream.EmitLdArg(i); } // now load IntPtr address codeStream.EmitLdArg(0); // Create a signature for the calli by copying the signature of the containing method // while skipping the first argument MethodSignature template = target.Signature; TypeDesc returnType = template.ReturnType; TypeDesc[] parameters = new TypeDesc[template.Length - 1]; for (int i = 1; i < template.Length; i++) { parameters[i - 1] = template[i]; } var signature = new MethodSignature(template.Flags, 0, returnType, parameters); bool useTransformedCalli = true; if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) != 0) { // Fat function pointer only ever exist for managed targets. useTransformedCalli = false; } if (((MetadataType)target.OwningType).Name == "RawCalliHelper") { // RawCalliHelper doesn't need the transform. useTransformedCalli = false; } if (useTransformedCalli) EmitTransformedCalli(emitter, codeStream, signature); else codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature)); codeStream.Emit(ILOpcode.ret); return emitter.Link(target); }
public void TestVirtualDispatchOnGenericType() { // Verifies that virtual dispatch to a non-generic method on a generic instantiation works DefType objectType = _context.GetWellKnownType(WellKnownType.Object); MethodSignature toStringSig = new MethodSignature(MethodSignatureFlags.None, 0, _stringType, Array.Empty<TypeDesc>()); MethodDesc objectToString = objectType.GetMethod("ToString", toStringSig); Assert.NotNull(objectToString); MetadataType openTestType = _testModule.GetType("VirtualFunctionOverride", "SimpleGeneric`1"); InstantiatedType testInstance = openTestType.MakeInstantiatedType(new Instantiation(new TypeDesc[] { objectType })); MethodDesc targetOnInstance = testInstance.GetMethod("ToString", toStringSig); MethodDesc targetMethod = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(objectToString, testInstance); Assert.Equal(targetOnInstance, targetMethod); }
/// <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 constructorSignature = constructorMethod.Signature; // There's an extra (useless) Object as the first arg to match RyuJIT expectations. var parameters = new TypeDesc[constructorSignature.Length + 1]; parameters[0] = constructorMethod.Context.GetWellKnownType(WellKnownType.Object); for (int i = 0; i < constructorSignature.Length; i++) parameters[i + 1] = constructorSignature[i]; MethodSignature sig = new MethodSignature( MethodSignatureFlags.Static, 0, constructorMethod.OwningType, parameters); MethodDesc result = constructorMethod.OwningType.GetKnownMethod("Ctor", sig); return result; }
public static MethodIL EmitIL(MethodDesc target) { Debug.Assert(target.Name == "CompareExchange" || target.Name == "Exchange"); // // Find non-generic method to forward the generic method to. // int parameterCount = target.Signature.Length; Debug.Assert(parameterCount == 3 || parameterCount == 2); var objectType = target.Context.GetWellKnownType(WellKnownType.Object); var parameters = new TypeDesc[parameterCount]; parameters[0] = objectType.MakeByRefType(); for (int i = 1; i < parameters.Length; i++) parameters[i] = objectType; MethodSignature nonGenericSignature = new MethodSignature(MethodSignatureFlags.Static, 0, objectType, parameters); MethodDesc nonGenericMethod = target.OwningType.GetMethod(target.Name, nonGenericSignature); // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it". if (nonGenericMethod == null) throw new NotImplementedException(); // // Emit the forwarder // ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); // Reload all arguments for (int i = 0; i < parameterCount; i++) codeStream.EmitLdArg(i); codeStream.Emit(ILOpcode.call, emitter.NewToken(nonGenericMethod)); codeStream.Emit(ILOpcode.ret); return emitter.Link(); }
public void TestStandaloneSignatureGeneration() { var transformResult = MetadataTransform.Run(new SingleFileMetadataPolicy(), new[] { _systemModule }); var stringRecord = transformResult.GetTransformedTypeDefinition( (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.String)); var singleRecord = transformResult.GetTransformedTypeDefinition( (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Single)); var sig = new Cts.MethodSignature( 0, 0, _context.GetWellKnownType(Cts.WellKnownType.String), new[] { _context.GetWellKnownType(Cts.WellKnownType.Single) }); var sigRecord = transformResult.Transform.HandleMethodSignature(sig); // Verify the signature is connected to the existing transformResult world Assert.Same(stringRecord, sigRecord.ReturnType.Type); Assert.Equal(1, sigRecord.Parameters.Count); Assert.Same(singleRecord, sigRecord.Parameters[0].Type); }
public void TestStandaloneSignatureGeneration() { var transformResult = MetadataTransform.Run(new SingleFileMetadataPolicy(), new[] { _systemModule }); var stringRecord = transformResult.GetTransformedTypeDefinition( (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.String)); var singleRecord = transformResult.GetTransformedTypeDefinition( (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Single)); var sig = new Cts.MethodSignature( 0, 0, _context.GetWellKnownType(Cts.WellKnownType.String), new[] { _context.GetWellKnownType(Cts.WellKnownType.Single) }); var sigRecord = transformResult.Transform.HandleMethodSignature(sig); // Verify the signature is connected to the existing transformResult world Assert.Same(stringRecord, sigRecord.ReturnType); Assert.Equal(1, sigRecord.Parameters.Count); Assert.Same(singleRecord, sigRecord.Parameters[0]); }
public override MethodSignature HandleMethodSignature(Cts.MethodSignature signature) { // TODO: if Cts.MethodSignature implements Equals/GetHashCode, we could enable pooling here. var result = new MethodSignature { CallingConvention = GetSignatureCallingConvention(signature), GenericParameterCount = signature.GenericParameterCount, ReturnType = HandleType(signature.ReturnType), // TODO-NICE: VarArgParameters }; result.Parameters.Capacity = signature.Length; for (int i = 0; i < signature.Length; i++) { result.Parameters.Add(HandleType(signature[i])); } return(result); }
/// <summary> /// NEWOBJ operation on String type is actually a call to a static method that returs a String /// instance (i.e. there's an explict 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(MethodDesc constructorMethod) { Debug.Assert(constructorMethod.IsConstructor); Debug.Assert(constructorMethod.OwningType.IsString); // There's an extra (useless) Object as the first arg to match RyuJIT expectations. var parameters = new TypeDesc[constructorMethod.Signature.Length + 1]; parameters[0] = constructorMethod.Context.GetWellKnownType(WellKnownType.Object); for (int i = 0; i < constructorMethod.Signature.Length; i++) parameters[i + 1] = constructorMethod.Signature[i]; MethodSignature sig = new MethodSignature( MethodSignatureFlags.Static, 0, constructorMethod.OwningType, parameters); MethodDesc result = constructorMethod.OwningType.GetMethod("Ctor", sig); // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it". if (result == null) throw new NotImplementedException(); return result; }
public bool Equals(MethodSignature otherSignature) { // TODO: Generics, etc. if (this._flags != otherSignature._flags) return false; if (this._genericParameterCount != otherSignature._genericParameterCount) return false; if (this._returnType != otherSignature._returnType) return false; if (this._parameters.Length != otherSignature._parameters.Length) return false; for (int i = 0; i < this._parameters.Length; i++) { if (this._parameters[i] != otherSignature._parameters[i]) return false; } return true; }
public static MethodIL EmitIL(MethodDesc method) { if (!RequiresMarshalling(method)) return null; try { return new PInvokeMarshallingILEmitter(method).EmitIL(); } catch (NotSupportedException) { ILEmitter emitter = new ILEmitter(); string message = "Method '" + method.ToString() + "' requires non-trivial marshalling that is not yet supported by this compiler."; TypeSystemContext context = method.Context; MethodSignature ctorSignature = new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void), new TypeDesc[] { context.GetWellKnownType(WellKnownType.String) }); MethodDesc exceptionCtor = method.Context.GetWellKnownType(WellKnownType.Exception).GetKnownMethod(".ctor", ctorSignature); ILCodeStream codeStream = emitter.NewCodeStream(); codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(message)); codeStream.Emit(ILOpcode.newobj, emitter.NewToken(exceptionCtor)); codeStream.Emit(ILOpcode.throw_); codeStream.Emit(ILOpcode.ret); return emitter.Link(); } }
/// <summary> /// Gets calling conventions for a standalone ('calli') method signature. /// </summary> public static UnmanagedCallingConventions GetStandaloneMethodSignatureCallingConventions(this MethodSignature signature) { // If calling convention is anything but 'unmanaged', or there's no modifiers, we can bitcast to our enum and we're done. MethodSignatureFlags unmanagedCallconv = signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask; if (unmanagedCallconv != MethodSignatureFlags.UnmanagedCallingConvention) { Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)UnmanagedCallingConventions.Cdecl && (int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)UnmanagedCallingConventions.Stdcall && (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall); Debug.Assert(unmanagedCallconv != 0); return((UnmanagedCallingConventions)unmanagedCallconv); } // If calling convention is 'unmanaged', there might be more metadata in the custom modifiers. UnmanagedCallingConventions result = 0; if (signature.HasEmbeddedSignatureData) { foreach (EmbeddedSignatureData data in signature.GetEmbeddedSignatureData()) { if (data.kind != EmbeddedSignatureDataKind.OptionalCustomModifier) { continue; } // We only care about the modifiers for the return type. These will be at the start of // the signature, so will be first in the array of embedded signature data. if (data.index != MethodSignature.IndexOfCustomModifiersOnReturnType) { break; } if (data.type is not MetadataType mdType) { continue; } result = AccumulateCallingConventions(result, mdType); } } // If we haven't found a calling convention in the modifiers, the calling convention is 'unmanaged'. if ((result & UnmanagedCallingConventions.CallingConventionMask) == 0) { result |= GetPlatformDefaultUnmanagedCallingConvention(signature.Context); } return(result); }
public int Compare(MethodSignature x, MethodSignature y) { return(x.CompareTo(y, this)); }
public MissingMethodException(TypeDesc owningType, string methodName, MethodSignature signature) : this(ExceptionStringID.MissingField, Format.Method(owningType, methodName, signature)) { }
internal FunctionPointerType(MethodSignature signature) { _signature = signature; }
/// <summary> /// Gets a named method on the type. This method only looks at methods defined /// in type's metadata. The <paramref name="signature"/> parameter can be null. /// If signature is not specified and there are multiple matches, the first one /// is returned. Returns null if method not found. /// </summary> // TODO: Substitutions, generics, modopts, ... public virtual MethodDesc GetMethod(string name, MethodSignature signature) { foreach (var method in GetMethods()) { if (method.Name == name) { if (signature == null || signature.Equals(method.Signature)) return method; } } return null; }
public MethodSignatureBuilder(MethodSignature template) { _template = template; _flags = template._flags; _genericParameterCount = template._genericParameterCount; _returnType = template._returnType; _parameters = template._parameters; }
private bool Equals(MethodSignature otherSignature, bool allowCovariantReturn) { // TODO: Generics, etc. if (this._flags != otherSignature._flags) { return(false); } if (this._genericParameterCount != otherSignature._genericParameterCount) { return(false); } if (this._returnType != otherSignature._returnType) { if (!allowCovariantReturn) { return(false); } if (!otherSignature._returnType.IsCompatibleWith(this._returnType)) { return(false); } } if (this._parameters.Length != otherSignature._parameters.Length) { return(false); } for (int i = 0; i < this._parameters.Length; i++) { if (this._parameters[i] != otherSignature._parameters[i]) { return(false); } } if (this._embeddedSignatureData == null && otherSignature._embeddedSignatureData == null) { return(true); } if (this._embeddedSignatureData != null && otherSignature._embeddedSignatureData != null) { if (this._embeddedSignatureData.Length != otherSignature._embeddedSignatureData.Length) { return(false); } for (int i = 0; i < this._embeddedSignatureData.Length; i++) { if (this._embeddedSignatureData[i].index != otherSignature._embeddedSignatureData[i].index) { return(false); } if (this._embeddedSignatureData[i].kind != otherSignature._embeddedSignatureData[i].kind) { return(false); } if (this._embeddedSignatureData[i].type != otherSignature._embeddedSignatureData[i].type) { return(false); } } return(true); } return(false); }
public bool EqualsWithCovariantReturnType(MethodSignature otherSignature) { return(Equals(otherSignature, allowCovariantReturn: true)); }
/// <summary> /// Retrieves an existing <see cref="MethodSignature"/> record representing the specified signature /// in the metadata writer object model, or creates a new one. /// </summary> public abstract MethodSignature HandleMethodSignature(Cts.MethodSignature signature);
public FunctionPointerType GetFunctionPointerType(MethodSignature signature) { return(_functionPointerTypes.GetOrCreateValue(signature)); }
/// <summary> /// Gets a named method on the type. This method only looks at methods defined /// in type's metadata. The <paramref name="signature"/> parameter can be null. /// If signature is not specified and there are multiple matches, the first one /// is returned. Returns null if method not found. /// </summary> public MethodDesc GetMethod(string name, MethodSignature signature) { return(GetMethod(name, signature, default(Instantiation))); }
/// <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); }
public bool Equals(MethodSignature otherSignature) { return(Equals(otherSignature, allowCovariantReturn: false)); }
static public MethodDesc GetDefaultConstructor(this TypeDesc type) { // TODO: Do we want check for specialname/rtspecialname? Maybe add another overload on GetMethod? var sig = new MethodSignature(0, 0, type.Context.GetWellKnownType(WellKnownType.Void), Array.Empty<TypeDesc>()); return type.GetMethod(".ctor", sig); }
public ILImporter(Compilation compilation, CppWriter writer, MethodDesc method, MethodIL methodIL) { _compilation = compilation; _nodeFactory = _compilation.NodeFactory; _writer = writer; _method = method; _methodSignature = method.Signature; _typeSystemContext = method.Context; if (!_methodSignature.IsStatic) _thisType = method.OwningType; _methodIL = methodIL; _ilBytes = _methodIL.GetILBytes(); _locals = _methodIL.GetLocals(); var ilExceptionRegions = _methodIL.GetExceptionRegions(); _exceptionRegions = new ExceptionRegion[ilExceptionRegions.Length]; for (int i = 0; i < ilExceptionRegions.Length; i++) { _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] }; } }
public MethodSignature ToSignature() { if (_template == null || _flags != _template._flags || _genericParameterCount != _template._genericParameterCount || _returnType != _template._returnType || _parameters != _template._parameters) { _template = new MethodSignature(_flags, _genericParameterCount, _returnType, _parameters); } return _template; }
public void AppendCppMethodDeclaration(CppGenerationBuffer sb, MethodDesc method, bool implementation, string externalMethodName = null, MethodSignature methodSignature = null) { if (methodSignature == null) methodSignature = method.Signature; if (externalMethodName != null) { sb.Append("extern \"C\" "); } else { if (!implementation) { sb.Append("static "); } } sb.Append(GetCppSignatureTypeName(methodSignature.ReturnType)); sb.Append(" "); if (externalMethodName != null) { sb.Append(externalMethodName); } else { if (implementation) { sb.Append(GetCppMethodDeclarationName(method.OwningType, GetCppMethodName(method))); } else { sb.Append(GetCppMethodName(method)); } } sb.Append("("); bool hasThis = !methodSignature.IsStatic; int argCount = methodSignature.Length; if (hasThis) argCount++; List<string> parameterNames = null; if (method != null) { IEnumerable<string> parameters = GetParameterNamesForMethod(method); if (parameters != null) { parameterNames = new List<string>(parameters); if (parameterNames.Count != 0) { System.Diagnostics.Debug.Assert(parameterNames.Count == argCount); } else { parameterNames = null; } } } for (int i = 0; i < argCount; i++) { if (hasThis) { if (i == 0) { var thisType = method.OwningType; if (thisType.IsValueType) thisType = thisType.MakeByRefType(); sb.Append(GetCppSignatureTypeName(thisType)); } else { sb.Append(GetCppSignatureTypeName(methodSignature[i - 1])); } } else { sb.Append(GetCppSignatureTypeName(methodSignature[i])); } if (implementation) { sb.Append(" "); if (parameterNames != null) { sb.Append(SanitizeCppVarName(parameterNames[i])); } else { sb.Append("_a"); sb.Append(i.ToStringInvariant()); } } if (i != argCount - 1) sb.Append(", "); } sb.Append(")"); if (!implementation) sb.Append(";"); }
public ILToken NewToken(MethodSignature value) { return NewToken(value, 0x11000000); }
public SignatureEnumerator(MethodSignature signature) { _signature = signature; _index = -1; }
private void PassCallArguments(MethodSignature methodSignature, TypeDesc thisArgument) { int signatureLength = methodSignature.Length; int argumentsCount = (thisArgument != null) ? (signatureLength + 1) : signatureLength; int startingIndex = _stack.Top - argumentsCount; for (int i = 0; i < argumentsCount; i++) { var op = _stack[startingIndex + i]; int argIndex = signatureLength - (argumentsCount - i); TypeDesc argType; if (argIndex == -1) { argType = thisArgument; } else { argType = methodSignature[argIndex]; } AppendCastIfNecessary(argType, op); Append(op); if (i + 1 != argumentsCount) Append(", "); } _stack.PopN(argumentsCount); }
private void AppendSignaturePrefix(StringBuilder sb, MethodSignature signature) { if (!signature.IsStatic) sb.Append("instance "); this.TypeNameFormatter.AppendNameWithValueClassPrefix(sb, signature.ReturnType); }
internal void AppendSignatureTypeDef(CppGenerationBuffer sb, string name, MethodSignature methodSignature, TypeDesc thisArgument) { sb.AppendLine(); sb.Append("typedef "); sb.Append(GetCppSignatureTypeName(methodSignature.ReturnType)); sb.Append("(*"); sb.Append(name); sb.Append(")("); int argCount = methodSignature.Length; if (thisArgument != null) argCount++; for (int i = 0; i < argCount; i++) { if (thisArgument != null) { if (i == 0) { sb.Append(GetCppSignatureTypeName(thisArgument)); } else { sb.Append(GetCppSignatureTypeName(methodSignature[i - 1])); } } else { sb.Append(GetCppSignatureTypeName(methodSignature[i])); } if (i != argCount - 1) sb.Append(", "); } sb.Append(");"); }
private void AppendSignatureArgumentList(StringBuilder sb, MethodSignature signature) { for (int i = 0; i < signature.Length; i++) { if (i != 0) sb.Append(", "); this.TypeNameFormatter.AppendNameWithValueClassPrefix(sb, signature[i]); } }
private void Get_CORINFO_SIG_INFO(MethodSignature signature, out CORINFO_SIG_INFO sig) { sig.callConv = (CorInfoCallConv)0; if (!signature.IsStatic) sig.callConv |= CorInfoCallConv.CORINFO_CALLCONV_HASTHIS; TypeDesc returnType = signature.ReturnType; CorInfoType corInfoRetType = asCorInfoType(signature.ReturnType, out sig.retTypeClass); sig._retType = (byte)corInfoRetType; sig.retTypeSigClass = sig.retTypeClass; // The difference between the two is not relevant for ILCompiler sig.flags = 0; // used by IL stubs code sig.numArgs = (ushort)signature.Length; sig.args = (CORINFO_ARG_LIST_STRUCT_*)0; // CORINFO_ARG_LIST_STRUCT_ is argument index // TODO: Shared generic sig.sigInst.classInst = null; sig.sigInst.classInstCount = 0; sig.sigInst.methInst = null; sig.sigInst.methInstCount = 0; sig.pSig = (byte*)ObjectToHandle(signature); sig.cbSig = 0; // Not used by the JIT sig.scope = null; // Not used by the JIT sig.token = 0; // Not used by the JIT // TODO: Shared generic // if (ftn->RequiresInstArg()) // { // sig.callConv = (CorInfoCallConv)(sig.callConv | CORINFO_CALLCONV_PARAMTYPE); // } }
private void Get_CORINFO_SIG_INFO(MethodSignature signature, out CORINFO_SIG_INFO sig) { sig.callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask); if (!signature.IsStatic) sig.callConv |= CorInfoCallConv.CORINFO_CALLCONV_HASTHIS; TypeDesc returnType = signature.ReturnType; CorInfoType corInfoRetType = asCorInfoType(signature.ReturnType, out sig.retTypeClass); sig._retType = (byte)corInfoRetType; sig.retTypeSigClass = sig.retTypeClass; // The difference between the two is not relevant for ILCompiler sig.flags = 0; // used by IL stubs code sig.numArgs = (ushort)signature.Length; sig.args = (CORINFO_ARG_LIST_STRUCT_*)0; // CORINFO_ARG_LIST_STRUCT_ is argument index sig.sigInst.classInst = null; // Not used by the JIT sig.sigInst.classInstCount = 0; // Not used by the JIT sig.sigInst.methInst = null; // Not used by the JIT sig.sigInst.methInstCount = (uint)signature.GenericParameterCount; sig.pSig = (byte*)ObjectToHandle(signature); sig.cbSig = 0; // Not used by the JIT sig.scope = null; // Not used by the JIT sig.token = 0; // Not used by the JIT }
public override MethodIL EmitIL() { TypeDesc[] targetMethodParameters = new TypeDesc[Signature.Length + 1]; targetMethodParameters[0] = Context.GetWellKnownType(WellKnownType.Object); for (int i = 0; i < Signature.Length; i++) { targetMethodParameters[i + 1] = Signature[i]; } var targetMethodSignature = new MethodSignature( Signature.Flags | MethodSignatureFlags.Static, 0, Signature.ReturnType, targetMethodParameters); var emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); // Load the stored 'this' codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(HelperObjectField)); // 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(targetMethodSignature)); codeStream.Emit(ILOpcode.ret); return emitter.Link(this); }
public MethodIL EmitIL() { MethodSignature targetMethodSignature = _targetMethod.Signature; // We have 4 code streams: // - _marshallingCodeStream is used to convert each argument into a native type and // store that into the local // - callsiteSetupCodeStream is used to used to load each previously generated local // and call the actual target native method. // - _returnValueMarshallingCodeStream is used to convert the native return value // to managed one. // - _unmarshallingCodestream is used to propagate [out] native arguments values to // managed ones. _emitter = new ILEmitter(); _marshallingCodeStream = _emitter.NewCodeStream(); ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream(); _returnValueMarshallingCodeStream = _emitter.NewCodeStream(); _unmarshallingCodestream = _emitter.NewCodeStream(); TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length]; // // Parameter marshalling // // // Convert each argument to something we can pass to native and store it in a local. // Then load the local in the second code stream. // for (int i = 0; i < targetMethodSignature.Length; i++) { // TODO: throw if there's custom marshalling _marshallingCodeStream.EmitLdArg(i); TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]); nativeParameterTypes[i] = nativeType; ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType); _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp); callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp); } // // Return value marshalling // // TODO: throw if SetLastError is true // TODO: throw if there's custom marshalling TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType); MethodSignature nativeSig = new MethodSignature( targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, _importMetadata); // Call the native method callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod)); _unmarshallingCodestream.Emit(ILOpcode.ret); return _emitter.Link(); }
public static string Method(TypeDesc owningType, string methodName, MethodSignature signature) { StringBuilder sb = new StringBuilder(); if (signature != null) { sb.Append(ExceptionTypeNameFormatter.Instance.FormatName(signature.ReturnType)); sb.Append(' '); } sb.Append(ExceptionTypeNameFormatter.Instance.FormatName(owningType)); sb.Append('.'); sb.Append(methodName); if (signature != null) { sb.Append('('); for (int i = 0; i < signature.Length; i++) { if (i > 0) { sb.Append(", "); } sb.Append(ExceptionTypeNameFormatter.Instance.FormatName(signature[i])); } sb.Append(')'); } return sb.ToString(); }
public PInvokeTargetNativeMethod(TypeDesc owningType, MethodSignature signature, PInvokeMetadata methodMetadata) { _owningType = owningType; _signature = signature; _methodMetadata = methodMetadata; sequenceNumber = System.Threading.Interlocked.Increment(ref nativeMethodCounter); }
public static void ThrowMissingMethodException(TypeDesc owningType, string methodName, MethodSignature signature) { CoreLibThrow.ThrowMissingMethodException(ExceptionStringID.MissingMethod, Format.Method(owningType, methodName, signature)); }