예제 #1
0
 public CppTypeVisitorResult Visit(CppArrayType t, Qualifiers q)
 {
     // has inner type
     this.TypeBuilder.Append($"Array[]");
     this.DbgBuilder.Append(t.DbgDescription + " ");
     this.QualifierBuilder.Append(q.ToString("g") + " ");
     return(null);
 }
예제 #2
0
        // Add a field to the type. Returns the offset of the field in the type
        public int AddField(CppField field, int alignmentBytes = 0)
        {
            // Unions and enums always have an offset of zero
            // An empty struct has a Size (bits) of 8 so the first field must also be set to zero offset
            field.Offset = ComplexValueType == ComplexValueType.Struct ? (Fields.Any()? Size : 0) : 0;

            // If we just came out of a bitfield, move to the next byte if necessary
            if (field.BitfieldSize == 0 && field.Offset % 8 != 0)
            {
                field.Offset = (field.Offset / 8) * 8 + 8;
            }

            // A 2, 4 or 8-byte value etc. must be aligned on an equivalent boundary
            // The same goes for the first entry in a struct, union or array
            // This block searches depth-first for the first field or element in any child types to find the required alignment boundary
            // https://en.wikipedia.org/wiki/Data_structure_alignment
            if (field.BitfieldSize == 0)
            {
                var firstSimpleType = field.Type;
                var foundType       = false;
                while (!foundType)
                {
                    var simpleType = firstSimpleType switch {
                        CppAlias alias => alias.ElementType,
                        CppComplexType {
                            ComplexValueType : ComplexValueType.Struct
                        } complex => complex.Fields.FirstOrDefault().Value?.First().Type,
                        CppArrayType array => array.ElementType,
                        _ => firstSimpleType
                    };
                    if (simpleType == firstSimpleType)
                    {
                        foundType = true;
                    }
                    firstSimpleType = simpleType;
                }

                // Empty classes shall always have sizeof() >= 1 and alignment doesn't matter
                // Empty classes will be returned as null by the above code (complex? null conditional operator)
                // https://www.stroustrup.com/bs_faq2.html#sizeof-empty
                if (firstSimpleType != null)
                {
                    if (field.OffsetBytes % firstSimpleType.SizeBytes != 0)
                    {
                        field.Offset += (firstSimpleType.SizeBytes - field.OffsetBytes % firstSimpleType.SizeBytes) * 8;
                    }
                }
            }

            // Respect alignment directives
            if (alignmentBytes > 0 && field.OffsetBytes % alignmentBytes != 0)
            {
                field.Offset += (alignmentBytes - field.OffsetBytes % alignmentBytes) * 8;
            }

            if (field.Type.AlignmentBytes > 0 && field.OffsetBytes % field.Type.AlignmentBytes != 0)
            {
                field.Offset += (field.Type.AlignmentBytes - field.OffsetBytes % field.Type.AlignmentBytes) * 8;
            }

            if (Fields.ContainsKey(field.Offset))
            {
                Fields[field.Offset].Add(field);
            }
            else
            {
                Fields.Add(field.Offset, new List <CppField> {
                    field
                });
            }

            // Update type size. This lazy evaluation only works if there are no value type forward declarations in the type
            // Union size is the size of the largest element in the union
            if (ComplexValueType == ComplexValueType.Union)
            {
                if (field.Size > Size)
                {
                    Size = field.Size;
                }
            }

            // For structs we look for the last item and add the size; adding the sizes without offsets might fail because of alignment padding
            if (ComplexValueType == ComplexValueType.Struct)
            {
                Size = field.Offset + field.Size;
            }

            return(Size);
        }