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