コード例 #1
0
        private int GetSizeOfType(CheezType type)
        {
            if (type.GetSize() >= 0)
            {
                return(type.GetSize());
            }
            var path = new List <CheezType>();

            return(ComputeSizeAndAlignmentOfType(type, path).size);
        }
コード例 #2
0
        private (int size, int alignment) ComputeSizeAndAlignmentOfType(CheezType type, List <CheezType> path)
        {
            if (type.GetSize() >= 0)
            {
                return(type.GetSize(), type.GetAlignment());
            }

            if (path.Contains(type))
            {
                ReportError($"Failed to calculate size of type {type} because it has a circular dependency on its own size");
                return(0, 0);
            }

            path.Add(type);

            try
            {
                switch (type)
                {
                case TraitType s:
                {
                    //computetr(s.Declaration);
                    var alignment = 1;
                    var size      = 0;
                    for (int i = 0; i < s.Declaration.Members.Count; i++)
                    {
                        var m = s.Declaration.Members[i];

                        var(ms, ma) = ComputeSizeAndAlignmentOfType(m.Type, path);

                        m.Offset  = Utilities.GetNextAligned(size, ma);
                        alignment = Math.Max(alignment, ma);
                        size     += ms;
                        size      = Utilities.GetNextAligned(size, ma);
                    }

                    s.SetSizeAndAlignment(0, alignment);
                    return(0, alignment);
                }

                case StructType s:
                {
                    ComputeStructMemberSizes(s.Declaration);
                    var alignment = 1;
                    var size      = 0;
                    for (int i = 0; i < s.Declaration.Members.Count; i++)
                    {
                        var m = s.Declaration.Members[i];

                        var(ms, ma) = ComputeSizeAndAlignmentOfType(m.Type, path);

                        m.Offset  = Utilities.GetNextAligned(size, ma);
                        alignment = Math.Max(alignment, ma);
                        size     += ms;
                        size      = Utilities.GetNextAligned(size, ma);
                    }

                    if (s.Declaration.TryGetDirective("align", out var dir))
                    {
                        if (dir.Arguments.Count != 0 && dir.Arguments[0] is AstNumberExpr num)
                        {
                            var desired = ((NumberData)num.Value).ToUlong();
                            alignment = Math.Max(alignment, (int)desired);
                        }
                    }

                    size = Utilities.GetNextAligned(size, alignment);

                    s.SetSizeAndAlignment(size, alignment);
                    return(size, alignment);
                }

                case EnumType e:
                {
                    ComputeEnumMembers(e.Declaration);
                    // @todo: force compute member types
                    var tagSize  = 0;
                    var tagAlign = 1;
                    if (!e.Declaration.Untagged)
                    {
                        (tagSize, tagAlign) = ComputeSizeAndAlignmentOfType(e.Declaration.TagType, path);
                    }

                    var alignment = tagAlign;

                    var maxMemberSize = 0;

                    foreach (var m in e.Declaration.Members)
                    {
                        if (m.AssociatedType != null)
                        {
                            var(memberSize, _) = ComputeSizeAndAlignmentOfType(m.AssociatedType, path);
                            maxMemberSize      = Math.Max(maxMemberSize, memberSize);
                        }
                    }

                    var size = tagSize + maxMemberSize;
                    size = Utilities.GetNextAligned(size, alignment);

                    e.SetSizeAndAlignment(size, alignment);
                    return(size, alignment);
                }

                case TupleType t:
                {
                    var alignment = 1;
                    var size      = 0;
                    for (int i = 0; i < t.Members.Length; i++)
                    {
                        var m = t.Members[i];

                        var(ms, ma) = ComputeSizeAndAlignmentOfType(m.type, path);

                        alignment = Math.Max(alignment, ma);
                        size     += ms;
                        size      = Utilities.GetNextAligned(size, ma);
                    }

                    size = Utilities.GetNextAligned(size, alignment);

                    t.SetSizeAndAlignment(size, alignment);
                    return(size, alignment);
                }

                case ArrayType t:
                {
                    var(subSize, subAlign) = ComputeSizeAndAlignmentOfType(t.TargetType, path);

                    var size      = subSize * (int)((NumberData)t.Length).ToLong();
                    var alignment = subAlign;
                    t.SetSizeAndAlignment(size, alignment);
                    return(size, alignment);
                }

                case RangeType r:
                {
                    var(subSize, subAlign) = ComputeSizeAndAlignmentOfType(r.TargetType, path);
                    var size      = subSize * 2;
                    var alignment = subAlign;
                    r.SetSizeAndAlignment(size, alignment);
                    return(size, alignment);
                }

                case SumType _:
                    return(-1, 0);

                default:
                    ReportError("ERROR?");
                    return(-1, 0);
                }
            }
            finally
            {
                path.Remove(type);
            }
        }