/// <summary>
        /// Computes a memory layout for a given type descriptor.
        /// </summary>
        /// <param name="td">type descriptor to layout</param>
        /// <param name="info">marshalling information</param>
        /// <returns>memory layout</returns>
        public static MemoryLayout Layout(TypeDescriptor td, IMarshalInfo info)
        {
            Type type = td.CILType;
            ISerializer ser = SLVSerializable.TryGetSerializer(type);
            if (ser != null)
            {
                object sample = td.GetSampleInstance();
                return CreatePrimLayout(ser.Serialize(sample).Size, td, info);
            }
            if (ser == null && td.HasIntrinsicTypeOverride)
                throw new InvalidOperationException("Type " + type.Name + " has intrinsic type override but no serializer");
            if (type.IsEnum)
            {
                return new EnumMemoryLayout(td, info);
            }
            if (type.IsArray)
            {
                td.AssertStatic();
                TypeDescriptor elemTd = td.Element0Type;
                MemoryLayout elemLayout = Layout(elemTd, info);
                ulong subStride = elemLayout.SizeInBits;
                if (subStride == 0)
                {
                    return new EmptyMemoryLayout(td)
                    {
                        Size = 0,
                        SizeInBits = 0
                    };
                }
                ulong[] strides = new ulong[type.GetArrayRank()];
                ulong elemsPerWord = (ulong)info.WordSize / elemLayout.SizeInBits;
                ulong wordsPerElem = elemLayout.Size;
                if (elemsPerWord > 1)
                {
                    if (info.UseArraySubWordAlignment)
                    {
                        if (info.UseArrayDimPow2Alignment)
                        {
                            elemsPerWord = MathExt.FloorPow2(elemsPerWord);
                            subStride = info.WordSize / elemsPerWord;
                        }
                    }
                    else
                    {
                        elemsPerWord = 1;
                    }
                }
                ulong dimSize = (ulong)(int)td.TypeParams.Last(); 
                ulong dimWords;
                if (elemsPerWord <= 1)
                {
                    subStride = 0;
                    if (info.UseArrayDimPow2Alignment)
                        wordsPerElem = MathExt.CeilPow2(wordsPerElem);
                    dimWords = wordsPerElem * dimSize;
                }
                else
                {
                    wordsPerElem = 0;
                    dimWords = (dimSize + elemsPerWord - 1) / elemsPerWord;
                }
                strides[strides.Length-1] = wordsPerElem;
                for (int i = strides.Length-2; i >= 0; i--)
                {
                    if (info.UseArrayDimPow2Alignment)
                        dimWords = MathExt.CeilPow2(dimWords);
                    strides[i] = dimWords;
                    dimSize = (ulong)(int)td.TypeParams[i];
                    dimWords *= dimSize;
                }
                return new ArrayMemoryLayout(td, info.WordSize, strides, subStride, (uint)elemsPerWord, (uint)wordsPerElem, elemLayout)
                {
                    Size = dimWords,
                    SizeInBits = dimWords * info.WordSize
                };
            }
            if (type.IsValueType && !type.IsPrimitive)
            {
                StructMemoryLayout ml = new StructMemoryLayout(td);
                FieldInfo[] fields = type.GetFields(
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                ulong offset = 0;
                foreach (FieldInfo field in fields)
                {
                    TypeDescriptor fieldTd = td.GetFieldType(field);
                    MemoryLayout fieldLayout = Layout(fieldTd, info);
                    FieldLocation fieldLoc = new FieldLocation(field, fieldLayout, offset);
                    ml.AddLocation(fieldLoc);
                    offset += fieldLayout.Size;
                }
                ml.Size = offset;
                ml.SizeInBits = offset * info.WordSize;
                return ml;
            }

            throw new InvalidOperationException("Unable to create data layout for type " + type.Name);
        }
Exemple #2
0
        /// <summary>
        /// Computes a memory layout for a given type descriptor.
        /// </summary>
        /// <param name="td">type descriptor to layout</param>
        /// <param name="info">marshalling information</param>
        /// <returns>memory layout</returns>
        public static MemoryLayout Layout(TypeDescriptor td, IMarshalInfo info)
        {
            Type        type = td.CILType;
            ISerializer ser  = SLVSerializable.TryGetSerializer(type);

            if (ser != null)
            {
                object sample = td.GetSampleInstance();
                return(CreatePrimLayout(ser.Serialize(sample).Size, td, info));
            }
            if (ser == null && td.HasIntrinsicTypeOverride)
            {
                throw new InvalidOperationException("Type " + type.Name + " has intrinsic type override but no serializer");
            }
            if (type.IsEnum)
            {
                return(new EnumMemoryLayout(td, info));
            }
            if (type.IsArray)
            {
                td.AssertStatic();
                TypeDescriptor elemTd     = td.Element0Type;
                MemoryLayout   elemLayout = Layout(elemTd, info);
                ulong          subStride  = elemLayout.SizeInBits;
                if (subStride == 0)
                {
                    return(new EmptyMemoryLayout(td)
                    {
                        Size = 0,
                        SizeInBits = 0
                    });
                }
                ulong[] strides      = new ulong[type.GetArrayRank()];
                ulong   elemsPerWord = (ulong)info.WordSize / elemLayout.SizeInBits;
                ulong   wordsPerElem = elemLayout.Size;
                if (elemsPerWord > 1)
                {
                    if (info.UseArraySubWordAlignment)
                    {
                        if (info.UseArrayDimPow2Alignment)
                        {
                            elemsPerWord = MathExt.FloorPow2(elemsPerWord);
                            subStride    = info.WordSize / elemsPerWord;
                        }
                    }
                    else
                    {
                        elemsPerWord = 1;
                    }
                }
                ulong dimSize = (ulong)(int)td.TypeParams.Last();
                ulong dimWords;
                if (elemsPerWord <= 1)
                {
                    subStride = 0;
                    if (info.UseArrayDimPow2Alignment)
                    {
                        wordsPerElem = MathExt.CeilPow2(wordsPerElem);
                    }
                    dimWords = wordsPerElem * dimSize;
                }
                else
                {
                    wordsPerElem = 0;
                    dimWords     = (dimSize + elemsPerWord - 1) / elemsPerWord;
                }
                strides[strides.Length - 1] = wordsPerElem;
                for (int i = strides.Length - 2; i >= 0; i--)
                {
                    if (info.UseArrayDimPow2Alignment)
                    {
                        dimWords = MathExt.CeilPow2(dimWords);
                    }
                    strides[i] = dimWords;
                    dimSize    = (ulong)(int)td.TypeParams[i];
                    dimWords  *= dimSize;
                }
                return(new ArrayMemoryLayout(td, info.WordSize, strides, subStride, (uint)elemsPerWord, (uint)wordsPerElem, elemLayout)
                {
                    Size = dimWords,
                    SizeInBits = dimWords * info.WordSize
                });
            }
            if (type.IsValueType && !type.IsPrimitive)
            {
                StructMemoryLayout ml     = new StructMemoryLayout(td);
                FieldInfo[]        fields = type.GetFields(
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                ulong offset = 0;
                foreach (FieldInfo field in fields)
                {
                    TypeDescriptor fieldTd     = td.GetFieldType(field);
                    MemoryLayout   fieldLayout = Layout(fieldTd, info);
                    FieldLocation  fieldLoc    = new FieldLocation(field, fieldLayout, offset);
                    ml.AddLocation(fieldLoc);
                    offset += fieldLayout.Size;
                }
                ml.Size       = offset;
                ml.SizeInBits = offset * info.WordSize;
                return(ml);
            }

            throw new InvalidOperationException("Unable to create data layout for type " + type.Name);
        }