Esempio n. 1
0
        /// <summary>
        /// Loads the address of a field specified by the given metadata token.
        /// </summary>
        /// <param name="field">The field.</param>
        private void MakeLoadFieldAddress(FieldInfo field)
        {
            if (field == null)
            {
                throw Location.GetInvalidOperationException();
            }
            var parentType        = field.DeclaringType;
            var targetPointerType = Builder.CreatePointerType(
                Builder.CreateType(parentType),
                MemoryAddressSpace.Generic);
            var address = Block.Pop(
                targetPointerType,
                ConvertFlags.None);

            var typeInfo      = TypeContext.GetTypeInfo(field.FieldType);
            var parentInfo    = TypeContext.GetTypeInfo(parentType);
            int absoluteIndex = parentInfo.GetAbsoluteIndex(field);

            if (targetPointerType.ElementType.IsStructureType)
            {
                var structureType =
                    targetPointerType.ElementType.As <StructureType>(Location);
                absoluteIndex = structureType.RemapFieldIndex(absoluteIndex);
            }

            var fieldAddress = Builder.CreateLoadFieldAddress(
                Location,
                address,
                new FieldSpan(absoluteIndex, typeInfo.NumFlattendedFields));

            Block.Push(fieldAddress);
        }
Esempio n. 2
0
        /// <summary>
        /// Helper function to compute field refence for the specified field of a type.
        /// </summary>
        /// <param name="type">The type node.</param>
        /// <param name="field">The field.</param>
        /// <returns>The target field span.</returns>
        private FieldSpan ComputeFieldSpan(TypeNode type, FieldInfo field)
        {
            var typeInfo   = TypeContext.GetTypeInfo(field.FieldType);
            var parentInfo = TypeContext.GetTypeInfo(field.DeclaringType);
            var fieldIndex = parentInfo.GetAbsoluteIndex(field);

            if (type.IsStructureType)
            {
                var structureType = type.As <StructureType>(Location);
                fieldIndex = structureType.RemapFieldIndex(fieldIndex);
            }
            return(new FieldSpan(fieldIndex, typeInfo.NumFlattendedFields));
        }
Esempio n. 3
0
        /// <summary>
        /// Creates an instance of a managed <see cref="ImmutableArray{T}"/> value.
        /// </summary>
        /// <param name="location">The current location.</param>
        /// <param name="instance">The instance value.</param>
        /// <param name="managedType">The managed instance type.</param>
        /// <param name="managedElementType">
        /// The managed element type of the array.
        /// </param>
        /// <returns>The created value array.</returns>
        private ValueReference CreateImmutableArrayValue(
            Location location,
            object instance,
            Type managedType,
            Type managedElementType)
        {
            // Get the managed type information and extract the array instance
            var typeInfo      = TypeContext.GetTypeInfo(managedType);
            var arrayInstance = typeInfo.Fields[0].GetValue(instance);

            return(CreateArrayValue(
                       location,
                       arrayInstance as Array,
                       managedElementType,
                       force: true));
        }
Esempio n. 4
0
        /// <summary>
        /// Loads the value of a field specified by the given metadata token.
        /// </summary>
        /// <param name="field">The field.</param>
        private void MakeLoadField(FieldInfo field)
        {
            if (field == null)
            {
                throw Location.GetInvalidOperationException();
            }

            var fieldValue = Block.Pop();

            if (fieldValue.Type.IsPointerType)
            {
                // Load field from address
                Block.Push(fieldValue);
                MakeLoadFieldAddress(field);
                var fieldAddress = Block.Pop();
                var fieldType    = Builder.CreateType(field.FieldType);
                Block.Push(CreateLoad(
                               fieldAddress,
                               fieldType,
                               field.FieldType.ToTargetUnsignedFlags()));
            }
            else
            {
                // Load field from value
                var typeInfo      = TypeContext.GetTypeInfo(field.FieldType);
                var parentInfo    = TypeContext.GetTypeInfo(field.DeclaringType);
                int absoluteIndex = parentInfo.GetAbsoluteIndex(field);

                // Check whether we have to get multiple elements
                var getField = Builder.CreateGetField(
                    Location,
                    fieldValue,
                    new FieldSpan(
                        absoluteIndex,
                        typeInfo.NumFlattendedFields));
                if (typeInfo.NumFlattendedFields == 1)
                {
                    Block.Push(LoadOntoEvaluationStack(
                                   getField,
                                   field.FieldType.ToTargetUnsignedFlags()));
                }
                else
                {
                    Block.Push(getField);
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Helper function to compute field refence for the specified field of a type.
        /// </summary>
        /// <param name="type">The type node.</param>
        /// <param name="field">The field.</param>
        /// <returns>The target field span.</returns>
        private FieldSpan ComputeFieldSpan(TypeNode type, FieldInfo field)
        {
            var typeInfo   = TypeContext.GetTypeInfo(field.FieldType);
            var parentInfo = TypeContext.GetTypeInfo(field.DeclaringType);
            var fieldIndex = parentInfo.GetAbsoluteIndex(field);

            if (type.IsStructureType)
            {
                var structureType = type.As <StructureType>(Location);
                fieldIndex = structureType.RemapFieldIndex(fieldIndex);
            }

            // Compute the actual span based on the intrinsic mapping of .Net arrays
            // to ILGPU structure values
            int span = typeInfo.NumFlattendedFields;

            if (typeInfo.ManagedType.IsArray)
            {
                span += typeInfo.ManagedType.GetArrayRank();
            }
            return(new FieldSpan(fieldIndex, span));
        }
Esempio n. 6
0
        /// <summary>
        /// Creates a new object value.
        /// </summary>
        /// <param name="location">The current location.</param>
        /// <param name="instance">The object value.</param>
        /// <returns>A reference to the requested value.</returns>
        public ValueReference CreateObjectValue(
            Location location,
            object instance)
        {
            if (instance == null)
            {
                throw location.GetArgumentNullException(nameof(instance));
            }

            var managedType = instance.GetType();

            if (managedType.IsILGPUPrimitiveType())
            {
                return(CreatePrimitiveValue(location, instance));
            }
            if (managedType.IsEnum)
            {
                return(CreateEnumValue(location, instance));
            }
            // Arrays requires a specific treatment
            if (managedType.IsArray)
            {
                return(CreateArrayValue(
                           location,
                           instance as Array,
                           managedType.GetElementType(),
                           force: false));
            }
            // Check whether this type is an immutable array which might require special
            if (managedType.IsImmutableArray(out var arrayElementType))
            {
                return(CreateImmutableArrayValue(
                           location,
                           instance,
                           managedType,
                           arrayElementType));
            }

            // Reject class types for now
            if (managedType.IsClass)
            {
                throw location.GetNotSupportedException(
                          ErrorMessages.NotSupportedClassType,
                          managedType);
            }

            // Get type information from the parent type context
            var typeInfo = TypeContext.GetTypeInfo(managedType);
            var type     = CreateType(managedType);

            if (!(type is StructureType structureType))
            {
                // This type has zero or one element and can be used without an
                // enclosing structure value
                return(typeInfo.NumFields > 0
                    ? CreateObjectValue(
                           location,
                           typeInfo.Fields[0].GetValue(instance))
                    : CreateNull(location, type));
            }
            var instanceBuilder = CreateStructure(location, structureType);

            for (int i = 0, e = typeInfo.NumFields; i < e; ++i)
            {
                var   field         = typeInfo.Fields[i];
                var   rawFieldValue = field.GetValue(instance);
                Value fieldValue    = CreateObjectValue(
                    location,
                    rawFieldValue);
                if (fieldValue.Type is StructureType nestedStructureType)
                {
                    // Extract all nested fields and insert them into the builder
                    foreach (var(_, access) in nestedStructureType)
                    {
                        instanceBuilder.Add(
                            CreateGetField(
                                location,
                                fieldValue,
                                access));
                    }
                }
                else
                {
                    instanceBuilder.Add(fieldValue);

                    // If the field value we just added is not the full size of the field,
                    // (e.g. it was the start of a fixed buffer) copy the remaining
                    // elements.
                    var fieldTypeInfo = typeInfo.GetFieldTypeInfo(i);
                    var initialBytes  = fieldValue.Type.Size;
                    var numBytes      = fieldTypeInfo.Size;
                    if (initialBytes < numBytes)
                    {
                        AddPaddingFields(
                            ref instanceBuilder,
                            location,
                            rawFieldValue,
                            initialBytes,
                            numBytes);
                    }
                }
            }
            return(instanceBuilder.Seal());
        }