private FieldInfo ResolveField(Cci.IFieldReference fieldRef) { var fieldDef = fieldRef.GetResolvedField(_context); if (fieldDef != null && IsLocal(fieldRef.GetContainingType(_context))) { return _fieldBuilders[fieldDef]; } FieldInfo result; if (_fieldRefs.TryGetValue(fieldRef, out result)) { return result; } Type declaringType = ResolveType(fieldRef.GetContainingType(_context)); Cci.ISpecializedFieldReference specializedRef = fieldRef.AsSpecializedFieldReference; if (specializedRef != null) { if (IsLocal(specializedRef.UnspecializedVersion.GetContainingType(_context))) { // declaring type is TypeBuilder or TypeBuilderInstantiation since it's defined in the module being built: FieldBuilder fieldBuilder = _fieldBuilders[(Cci.IFieldDefinition)specializedRef.UnspecializedVersion.AsDefinition(_context)]; result = TypeBuilder.GetField(declaringType, fieldBuilder); } else { FieldInfo unspecializedDefinition = ResolveField(specializedRef.UnspecializedVersion); result = new FieldRef(declaringType, fieldRef.Name, unspecializedDefinition.FieldType); } } else { GenericContext genericContext; if (declaringType.IsGenericTypeDefinition) { genericContext = new GenericContext(declaringType.GetGenericArguments(), Type.EmptyTypes); } else { genericContext = default(GenericContext); } // TODO: modifiers? Type fieldType = ResolveType(fieldRef.GetType(_context), genericContext); result = new FieldRef(declaringType, fieldRef.Name, fieldType); } _fieldRefs.Add(fieldRef, result); return result; }
private void MakeMethodParameters(MethodBase method, Cci.IMethodReference methodRef, out Type[] methodGenericParameters, out ParameterInfo[] parameters, out ParameterInfo returnParameter) { Type declaringType = method.DeclaringType; if (methodRef.IsGeneric && methodRef.AsGenericMethodInstanceReference == null) { // generic definition methodGenericParameters = MakeGenericParameters((MethodInfo)method, methodRef); } else { methodGenericParameters = Type.EmptyTypes; } Type[] typeGenericParameters; if (declaringType.IsGenericTypeDefinition) { typeGenericParameters = declaringType.GetGenericArguments(); } else { typeGenericParameters = Type.EmptyTypes; } GenericContext genericContext = methodGenericParameters.Length > 0 || typeGenericParameters.Length > 0 ? new GenericContext(typeGenericParameters, methodGenericParameters) : default(GenericContext); parameters = new ParameterInfo[methodRef.ParameterCount]; int i = 0; foreach (var parameter in methodRef.GetParameters(_context)) { parameters[i] = MakeParameterInfo(method, i + 1, parameter.GetType(_context), genericContext, parameter.CustomModifiers, parameter.IsByReference); i++; } returnParameter = MakeParameterInfo(method, 0, methodRef.GetType(_context), genericContext, methodRef.ReturnValueCustomModifiers, methodRef.ReturnValueIsByRef); }
private Type ResolveParameterType(Cci.IParameterTypeInformation parameter, GenericContext genericContext = default(GenericContext)) { var parameterType = ResolveType(parameter.GetType(_context), genericContext); if (parameter.IsByReference) { parameterType = parameterType.MakeByRefType(); } if (parameter.CustomModifiers.Any()) { Type[] reqMods, optMods; ResolveCustomModifiers(parameter.CustomModifiers, out reqMods, out optMods); return new ModifiedType(parameterType, reqMods, optMods); } else { return parameterType; } }
private void DefineParameter(MethodBuilder methodBuilder, ConstructorBuilder constructorBuilder, Cci.IParameterDefinition paramDef) { // No explicit param row is needed if param has no flags (other than optionally IN), // no name and no references to the param row, such as CustomAttribute, Constant, or FieldMarshall var attributes = paramDef.GetAttributes(_context); var defaultValue = paramDef.GetDefaultValue(_context); if (defaultValue != null || paramDef.IsOptional || paramDef.IsOut || paramDef.IsMarshalledExplicitly || attributes.Any() || paramDef.Name.Length > 0) { int index = paramDef is Cci.ReturnValueParameter ? 0 : paramDef.Index + 1; ParameterAttributes attrs = (ParameterAttributes)Cci.MetadataWriter.GetParameterFlags(paramDef); ParameterBuilder paramBuilder = (methodBuilder != null) ? methodBuilder.DefineParameter(index, attrs, paramDef.Name) : constructorBuilder.DefineParameter(index, attrs, paramDef.Name); if (defaultValue != null) { object rawValue = defaultValue.Value; if (rawValue == null) { var paramTypeRef = paramDef.GetType(_context); if (paramTypeRef.IsValueType) { SetParameterDefaultStructValue(paramBuilder); } else { paramBuilder.SetConstant(null); } } else { // TODO (tomat): Ref.Emit has too strict checks on the constant type. While it is ok to emit value, // e.g. of type Int16 for parameter of type Int32 to metadata, Ref.Emit checks if these types are Type.IsAssignableFrom. // To make this work we need to convert. // // We also need to support Nullable<T>. if (rawValue.GetType().IsPrimitive) { // parameter type has already been resolved once when defining the method, so just retrive it: Type paramType = ResolveType(paramDef.GetType(_context)); if (paramType.IsGenericType && paramType.GetGenericTypeDefinition() == typeof(Nullable<>)) { paramType = paramType.GetGenericArguments()[0]; } if (paramType.IsEnum) { // If emitting the enum, it isn't "created" as this stage so Enum.GetUnderlyingType() will throw // Otherwise, if the enum is already defined, we should use Enum.GetUnderlyingType() to get the correct type paramType = paramType is TypeBuilder ? paramType.UnderlyingSystemType : Enum.GetUnderlyingType(paramType); } rawValue = Convert.ChangeType(rawValue, paramType, System.Globalization.CultureInfo.InvariantCulture); } paramBuilder.SetConstant(rawValue); } } if (paramDef.IsMarshalledExplicitly) { // FieldMarshal var marshallingInformation = paramDef.MarshallingInformation; if (marshallingInformation != null) { paramBuilder.SetCustomAttribute(GetMarshalAsAttribute(marshallingInformation)); } else { Debug.Assert(!paramDef.MarshallingDescriptor.IsDefaultOrEmpty); // TODO: throw new NotImplementedException(); } } EmitCustomAttributes(paramBuilder, attributes); } }
private void GetReturnType(Cci.ISignature signature, out Type returnType, out Type[] reqMods, out Type[] optMods) { returnType = ResolveType(signature.GetType(_context)); if (signature.ReturnValueIsByRef) { returnType = returnType.MakeByRefType(); } // TODO (tomat, Dev12): this doesn't handle types constructed from modified types, we need Ref.Emit supporte for that: if (signature.ReturnValueCustomModifiers.Any()) { ResolveCustomModifiers(signature.ReturnValueCustomModifiers, out reqMods, out optMods); } else { reqMods = optMods = null; } }
private EventBuilder DefineEvent(TypeBuilder typeBuilder, Cci.IEventDefinition eventDef) { EventAttributes attrs = (EventAttributes)Cci.MetadataWriter.GetEventFlags(eventDef); Type type = ResolveType(eventDef.GetType(_context)); // Event, EventMap var eventBuilder = typeBuilder.DefineEvent(eventDef.Name, attrs, type); // MethodSemantics foreach (var accessor in eventDef.Accessors) { var accessorDef = (Cci.IMethodDefinition)accessor.AsDefinition(_context); var accessorBuilder = _methodBuilders[accessorDef]; if (accessor == eventDef.Adder) { eventBuilder.SetAddOnMethod(accessorBuilder); } else if (accessor == eventDef.Remover) { eventBuilder.SetRemoveOnMethod(accessorBuilder); } else if (accessor == eventDef.Caller) { eventBuilder.SetRaiseMethod(accessorBuilder); } else { eventBuilder.AddOtherMethod(accessorBuilder); } } return eventBuilder; }
private void DefineField(TypeBuilder typeBuilder, Cci.IFieldDefinition fieldDef) { FieldAttributes attrs = (FieldAttributes)Cci.MetadataWriter.GetFieldFlags(fieldDef); FieldBuilder fieldBuilder; if (!fieldDef.MappedData.IsDefault) { // TODO (tomat, Dev12): Unfortunately, Reflection.Emit doesn't allow us to directly set FieldRVA on arbitrary FieldBuilder. // Instead it creates the mapping types itself and provides APIs to define mapped fields. // So we use that API and ignore the mapping types provided by the compiler. // FieldRVA fieldBuilder = typeBuilder.DefineInitializedData(fieldDef.Name, fieldDef.MappedData.ToArray(), attrs); } else { // Field types that are value types need to be loaded before the declaring type. // If the field type is a nested type, e.g. A.B.C only the inner-most type needs to be loaded before the declaring type. Type type = ResolveType( fieldDef.GetType(_context), genericContext: default(GenericContext), dependentType: typeBuilder, valueTypeDependency: true); // TODO (tomat, Dev12): this doesn't handle types constructed from modified types, we need Ref.Emit support for that: Type[] reqMods = null, optMods = null; ModifiedType modified = type as ModifiedType; if (modified != null) { reqMods = modified.RequiredModifiers; optMods = modified.OptionalModifiers; type = modified.UnmodifiedType; } fieldBuilder = typeBuilder.DefineField(fieldDef.Name, type, reqMods, optMods, attrs); } // FieldLayout if (fieldDef.ContainingTypeDefinition.Layout == LayoutKind.Explicit && !fieldDef.IsStatic) { fieldBuilder.SetOffset((int)fieldDef.Offset); } // FieldMarshal if (fieldDef.IsMarshalledExplicitly) { var marshallingInformation = fieldDef.MarshallingInformation; if (marshallingInformation != null) { fieldBuilder.SetCustomAttribute(GetMarshalAsAttribute(marshallingInformation)); } else { Debug.Assert(!fieldDef.MarshallingDescriptor.IsDefaultOrEmpty); // TODO: throw new NotImplementedException(); } } _fieldBuilders.Add(fieldDef, fieldBuilder); }
private bool ReturnTypeMatches(Cci.IMethodReference methodRef, MethodBase method, GenericContext genericContext) { MethodInfo methodInfo = method as MethodInfo; if (methodInfo == null) { return true; } return methodInfo.ReturnType.IsEquivalentTo(ResolveType(methodRef.GetType(_context), genericContext)); }
private static CCI.TypeNode ResolveCCIType(CCI.AssemblyNode assembly, string ns, string nm) { var n = assembly.GetType(CCI.Identifier.For(ns), CCI.Identifier.For(nm)); if (n == null) throw new InvalidOperationException("unable to load well-known type"); return n; }