示例#1
0
        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;
        }
示例#2
0
        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);
        }
示例#3
0
        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;
            }
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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;
            }
        }
示例#6
0
        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;
        }
示例#7
0
        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);
        }
示例#8
0
        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));
        }
示例#9
0
 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;
 }