/// <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); }
/// <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)); }
/// <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)); }
/// <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); } } }
/// <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)); }
/// <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()); }