private static FieldMemoryInfo[] GetFieldsMemoryInfo(ParsedStruct pdStruct, IDictionary <string, TypeMemoryInfo> typesMemInfo) { var fieldsMemInfo = new FieldMemoryInfo[pdStruct.Fields.Length]; for (var i = 0; i < fieldsMemInfo.Length; i++) { var pdField = pdStruct.Fields[i]; if (!typesMemInfo.TryGetValue(pdField.Type, out var memInfo)) { throw new Exception($"Unknown field type `{pdField.Type}` defined in the struct `{pdStruct.Name}`"); } fieldsMemInfo[i] = new FieldMemoryInfo(i, memInfo); } Array.Sort(fieldsMemInfo, (fieldA, fieldB) => { var(fieldIndexA, memInfoA) = fieldA; var(fieldIndexB, memInfoB) = fieldB; if (memInfoA.Alignment != memInfoB.Alignment) { return(memInfoB.Alignment.CompareTo(memInfoA.Alignment)); } return(fieldIndexA.CompareTo(fieldIndexB)); }); return(fieldsMemInfo); }
private static CodeGenStruct HandleStruct(ParsedStruct pdStruct, IDictionary <string, TypeMemoryInfo> typesMemInfo) { if (pdStruct.Fields.Length == 0) { throw new Exception($"Struct `{pdStruct.Name}` is zero-sized"); } var fieldsMemInfo = GetFieldsMemoryInfo(pdStruct, typesMemInfo); var offset = 0; var fields = new CodeGenField[pdStruct.Fields.Length]; for (var i = 0; i < fields.Length; i++) { var(pdFieldIndex, memInfo) = fieldsMemInfo[i]; var pdField = pdStruct.Fields[pdFieldIndex]; var defaultValue = memInfo.DefaultValueInfo.WithCustomDefaultValueIfPossible(pdField.DefaultValue); fields[i] = new CodeGenField(pdField.Type, pdField.Name, defaultValue, offset); offset += memInfo.Size; } var unalignedSize = fieldsMemInfo.Sum(fmi => fmi.TypeMemoryInfo.Size); var alignment = fieldsMemInfo.Max(fmi => fmi.TypeMemoryInfo.Alignment); var reminder = unalignedSize % alignment; var padding = reminder == 0 ? 0 : alignment - reminder; var size = unalignedSize + padding; var structDefaultValue = DefaultValueInfo.CallWriteDefaultMethod(); typesMemInfo.Add(pdStruct.Name, new TypeMemoryInfo(size, alignment, structDefaultValue)); return(new CodeGenStruct(pdStruct.Name, size, alignment, padding, fields)); }