Example #1
0
 public DataType VisitStructure(StructureType s)
 {
     var str = new Reko.Core.Types.StructureType(null, 0, true);
     int offset = 0;
     foreach (var field in s.Fields)
     {
         var ft = field.Accept(this);
         str.Fields.Add(offset, ft);
         offset += ft.Size;
     }
     return str;
 }
Example #2
0
        /// <summary>
        /// Implements a partial ordering on data types, where
        /// primitives &lt; pointers &lt; arrays &lt; structs &lt; unions
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int Compare(DataType x, DataType y, int count)
        {
            if (count > 20)
            {
                throw new ApplicationException("Way too deep");                     //$BUG: discover why datatypes recurse so deep.
            }
            int prioX = x.Accept(this);
            int prioY = y.Accept(this);
            int dPrio = prioX - prioY;

            if (dPrio != 0)
            {
                return(dPrio);
            }

            if (x is VoidType)
            {
                return(0);
            }

            PrimitiveType ix = x as PrimitiveType;
            PrimitiveType iy = y as PrimitiveType;

            if (ix != null && iy != null)
            {
                return(ix.Compare(iy));
            }
            if (ix != null)
            {
                return(-1);
            }
            if (iy != null)
            {
                return(1);
            }

            if (x is EnumType || y is EnumType)
            {
                throw new NotImplementedException();
            }

            CodeType cx = x as CodeType;
            CodeType cy = y as CodeType;

            if (cx != null && cy != null)
            {
                return(0);
            }
            if (cx != null)
            {
                return(-1);
            }
            if (cy != null)
            {
                return(1);
            }

            TypeVariable tx = x as TypeVariable;
            TypeVariable ty = y as TypeVariable;

            if (tx != null && ty != null)
            {
                return(tx.Number - ty.Number);
            }

            TypeReference tr_x = x as TypeReference;
            TypeReference tr_y = y as TypeReference;

            if (tr_x != null && tr_y != null)
            {
                var d = StringComparer.InvariantCulture.Compare(tr_x.Name, tr_y.Name);
                if (d != 0)
                {
                    return(d);
                }
                return(Compare(tr_x.Referent, tr_y.Referent, ++count));
            }

            EquivalenceClass ex = x as EquivalenceClass;
            EquivalenceClass ey = y as EquivalenceClass;

            if (ex != null && ey != null)
            {
                return(ex.Number - ey.Number);
            }

            Pointer ptrX = x as Pointer;
            Pointer ptrY = y as Pointer;

            if (ptrX != null && ptrY != null)
            {
                return(Compare(ptrX.Pointee, ptrY.Pointee, ++count));
            }

            MemberPointer mX = x as MemberPointer;
            MemberPointer mY = y as MemberPointer;

            if (mX != null && mY != null)
            {
                int d = Compare(mX.BasePointer, mY.BasePointer, ++count);
                if (d != 0)
                {
                    return(d);
                }
                return(Compare(mX.Pointee, mY.Pointee, ++count));
            }

            StructureType sX = x as StructureType;
            StructureType sY = y as StructureType;

            if (sX != null && sY != null)
            {
                return(Compare(sX, sY, ++count));
            }

            UnionType ux = x as UnionType;
            UnionType uy = y as UnionType;

            if (ux != null && uy != null)
            {
                return(Compare(ux, uy, ++count));
            }
            ArrayType ax = x as ArrayType;
            ArrayType ay = y as ArrayType;

            if (ax != null && ay != null)
            {
                return(Compare(ax, ay, ++count));
            }

            StringType strX = x as StringType;
            StringType strY = y as StringType;

            if (strX != null && strY != null)
            {
                return(Compare(strX, strY, ++count));
            }

            FunctionType fnX = x as FunctionType;
            FunctionType fnY = y as FunctionType;

            if (fnX != null && fnY != null)
            {
                return(Compare(fnX, fnY, ++count));
            }
            throw new NotImplementedException(string.Format("NYI: comparison between {0} and {1}", x.GetType(), y.GetType()));
        }
Example #3
0
 public int VisitStructure(StructureType str)
 {
     return(Struct);
 }
Example #4
0
        private bool DoAreCompatible(DataType a, DataType b, int depth)
        {
            if (a == null || b == null)
            {
                return(false);
            }

            if (depth > 20)
            {
                throw new StackOverflowException("Way too deep");                     //$BUG: discover why datatypes recurse so deep.
            }
            PrimitiveType pa = a as PrimitiveType;
            PrimitiveType pb = b as PrimitiveType;

            if (pa != null && pb != null)
            {
                if (pa.Size != pb.Size)
                {
                    return(false);
                }
                return((pa.Domain & pb.Domain) != 0);
            }

            TypeReference tra = a as TypeReference;
            TypeReference trb = b as TypeReference;

            if (tra != null && trb != null)
            {
                return(tra == trb);
            }
            if (tra != null)
            {
                return(AreCompatible(tra.Referent, b, ++depth));
            }
            if (trb != null)
            {
                return(AreCompatible(a, trb.Referent, ++depth));
            }

            TypeVariable tva = a as TypeVariable;
            TypeVariable tvb = b as TypeVariable;

            if (tva != null && tvb != null)
            {
                return(tva.Number == tvb.Number);
            }

            EquivalenceClass eqA = a as EquivalenceClass;
            EquivalenceClass eqB = b as EquivalenceClass;

            if (eqA != null && eqB != null)
            {
                return(eqA.Number == eqB.Number);
            }

            Pointer ptrA = a as Pointer;
            Pointer ptrB = b as Pointer;

            if (ptrA != null)
            {
                return(IsCompatibleWithPointer(ptrA, b, ++depth));
            }
            if (ptrB != null)
            {
                return(IsCompatibleWithPointer(ptrB, a, ++depth));
            }

            MemberPointer mpA = a as MemberPointer;
            MemberPointer mpB = b as MemberPointer;

            if (mpA != null)
            {
                return(IsCompatibleWithMemberPointer(mpA, b, ++depth));
            }
            if (mpB != null)
            {
                return(IsCompatibleWithMemberPointer(mpB, a, ++depth));
            }

            StructureType sa = a as StructureType;
            StructureType sb = b as StructureType;

            if (sa != null && sb != null)
            {
                return(AreCompatible(sa, sb));
            }

            ArrayType aa = a as ArrayType;
            ArrayType ab = b as ArrayType;

            if (aa != null && ab != null)
            {
                return(AreCompatible(aa.ElementType, ab.ElementType, ++depth));
            }

            UnionType ua = a as UnionType;
            UnionType ub = b as UnionType;

            if (ua != null && ub != null)
            {
                return(true);
            }

            FunctionType fa = a as FunctionType;
            FunctionType fb = b as FunctionType;

            if (fa != null && fb != null)
            {
                return(fa.Parameters.Length == fb.Parameters.Length);
            }

            CodeType ca = a as CodeType;
            CodeType cb = a as CodeType;

            if (ca != null && cb != null)
            {
                return(true);
            }
            if (a is UnknownType unkA)
            {
                if (unkA.Size == 0 || a.Size == b.Size)
                {
                    return(true);
                }
            }
            if (b is UnknownType unkB)
            {
                if (unkB.Size == 0 || a.Size == b.Size)
                {
                    return(true);
                }
            }
            return(false);
        }
Example #5
0
        /// <summary>
        /// Unifies two structures by merging the fields in offset order.
        /// </summary>
        /// <remarks>
        /// Fields are taken from
        /// </remarks>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public DataType UnifyStructures(StructureType a, StructureType b)
        {
            int newSize = 0;

            if (a.Size != 0 && b.Size != 0)
            {
                if (a.Size != b.Size)
                {
                    return(MakeUnion(a, b));
                }
                else
                {
                    newSize = a.Size;
                }
            }
            else if (a.Size != 0)
            {
                newSize = a.Size;
            }
            else if (b.Size != 0)
            {
                newSize = b.Size;
            }

            string name = null;

            if (a.Name != null)
            {
                if (b.Name != null && a.Name != b.Name)
                {
                    return(MakeUnion(a, b));
                }
                else
                {
                    name = a.Name;
                }
            }
            else
            {
                name = b.Name;
            }

            StructureType mem = factory.CreateStructureType(name, newSize);

            mem.IsSegment = (a.IsSegment || b.IsSegment);

            IEnumerator <StructureField> ea = a.Fields.GetEnumerator();
            IEnumerator <StructureField> eb = b.Fields.GetEnumerator();
            StructureField fa = null;
            StructureField fb = null;

            for (;;)
            {
                if (fa == null && ea.MoveNext())
                {
                    fa = ea.Current;
                }
                if (fb == null && eb.MoveNext())
                {
                    fb = eb.Current;
                }

                if (fa == null || fb == null)
                {
                    break;
                }

                var nestedStructureUnifier = new NestedStructureUnifier(this);
                if (nestedStructureUnifier.Match(fa, fb))
                {
                    nestedStructureUnifier.Unify();
                    fa = nestedStructureUnifier.NextFieldA;
                    fb = nestedStructureUnifier.NextFieldB;
                }
                else if (fa.Offset < fb.Offset)
                {
                    mem.Fields.Add(fa.Clone());
                    fa = null;
                }
                else if (fa.Offset > fb.Offset)
                {
                    mem.Fields.Add(fb.Clone());
                    fb = null;
                }
                else
                {
                    var fieldType = Unify(fa.DataType, fb.DataType);
                    if (!TryMakeFieldName(fa, fb, out string fieldName))
                    {
                        throw new NotSupportedException(
                                  string.Format(
                                      "Failed to unify field '{0}' in structure '{1}' with field '{2}' in structure '{3}'.",
                                      fa.Name, a, fb.Name, b));
                    }
                    mem.Fields.Add(fa.Offset, fieldType, fieldName);
                    fa = null;
                    fb = null;
                }
            }
            if (fa != null)
            {
                mem.Fields.Add(fa);
                while (ea.MoveNext())
                {
                    StructureField f = ea.Current;
                    mem.Fields.Add(f.Clone());
                }
            }
            if (fb != null)
            {
                mem.Fields.Add(fb);
                while (eb.MoveNext())
                {
                    StructureField f = eb.Current;
                    mem.Fields.Add(f.Clone());
                }
            }
            mem.ForceStructure = a.ForceStructure | b.ForceStructure;
            return(mem);
        }
Example #6
0
        private DataType UnifyInternal(DataType a, DataType b)
        {
            if (a == null)
            {
                return(b);
            }
            if (b == null)
            {
                return(a);
            }

            if (a == b)
            {
                return(a);
            }

            if (a is UnknownType)
            {
                if (a.Size == 0 || a.Size == b.Size)
                {
                    return(b);
                }
            }
            if (b is UnknownType)
            {
                if (b.Size == 0 || a.Size == b.Size)
                {
                    return(a);
                }
            }

            if (a is VoidType)
            {
                return(b);
            }
            if (b is VoidType)
            {
                return(a);
            }

            UnionType ua = a as UnionType;
            UnionType ub = b as UnionType;

            if (ua != null && ub != null)
            {
                UnionType u2 = UnifyUnions(ua, ub);
                return(u2.Simplify());
            }
            if (ua != null)
            {
                UnifyIntoUnion(ua, b);
                return(ua.Simplify());
            }
            if (ub != null)
            {
                UnifyIntoUnion(ub, a);
                return(ub.Simplify());
            }

            PrimitiveType pa = a as PrimitiveType;
            PrimitiveType pb = b as PrimitiveType;

            if (pa != null && pb != null)
            {
                if (pa == pb)
                {
                    return(pa);
                }

                return(UnifyPrimitives(pa, pb));
            }

            TypeVariable tA = a as TypeVariable;
            TypeVariable tB = b as TypeVariable;

            if (tA != null && tB != null)
            {
                return(UnifyTypeVariables(tA, tB));
            }

            TypeReference trA = a as TypeReference;
            TypeReference trB = b as TypeReference;

            if (trA != null && trB != null)
            {
                if (trA == trB)
                {
                    return(trA);
                }
                else
                {
                    return(MakeUnion(a, b));
                }
            }
            if (trA != null)
            {
                if (AreCompatible(trA.Referent, b))
                {
                    return(new TypeReference(trA.Name, UnifyInternal(trA.Referent, b)));
                }
            }
            if (trB != null)
            {
                if (AreCompatible(a, trB.Referent))
                {
                    return(new TypeReference(trB.Name, UnifyInternal(trB.Referent, a)));
                }
            }

            EquivalenceClass eqA = a as EquivalenceClass;
            EquivalenceClass eqB = b as EquivalenceClass;

            if (eqA != null && eqB != null)
            {
                if (eqA.Number == eqB.Number)
                {
                    return(eqA);
                }
                else
                {
                    return(MakeUnion(eqA, eqB));
                }
            }

            Pointer ptrA = a as Pointer;
            Pointer ptrB = b as Pointer;

            if (ptrA != null && ptrB != null)
            {
                DataType dt = UnifyInternal(ptrA.Pointee, ptrB.Pointee);
                return(new Pointer(dt, Math.Max(ptrA.BitSize, ptrB.BitSize)));
            }
            if (ptrA != null)
            {
                var dt = UnifyPointer(ptrA, b);
                if (dt != null)
                {
                    return(dt);
                }
            }
            if (ptrB != null)
            {
                var dt = UnifyPointer(ptrB, a);
                if (dt != null)
                {
                    return(dt);
                }
            }

            MemberPointer mpA = a as MemberPointer;
            MemberPointer mpB = b as MemberPointer;

            if (mpA != null && mpB != null)
            {
                DataType baseType = UnifyInternal(mpA.BasePointer, mpB.BasePointer);
                DataType pointee  = UnifyInternal(mpA.Pointee, mpB.Pointee);
                return(new MemberPointer(baseType, pointee, mpB.Size));
            }
            if (mpA != null)
            {
                var dt = UnifyMemberPointer(mpA, b);
                if (dt != null)
                {
                    return(dt);
                }
            }
            if (mpB != null)
            {
                var dt = UnifyMemberPointer(mpB, a);
                if (dt != null)
                {
                    return(dt);
                }
            }

            FunctionType funA = a as FunctionType;
            FunctionType funB = b as FunctionType;

            if (funA != null && funB != null)
            {
                return(UnifyFunctions(funA, funB));
            }
            if (funA != null && b is CodeType)
            {
                return(funA);
            }
            if (funB != null && a is CodeType)
            {
                return(funB);
            }

            ArrayType arrA = a as ArrayType;
            ArrayType arrB = b as ArrayType;

            if (arrA != null && arrB != null)
            {
                return(UnifyArrays(arrA, arrB));
            }
            if (arrA != null && arrA.ElementType.Size >= b.Size)
            {
                arrA.ElementType = Unify(arrA.ElementType, b);
                return(arrA);
            }
            if (arrB != null && arrB.ElementType.Size >= a.Size)
            {
                arrB.ElementType = Unify(arrB.ElementType, a);
                return(arrB);
            }

            StructureType strA = a as StructureType;
            StructureType strB = b as StructureType;

            if (strA != null && strB != null)
            {
                return(UnifyStructures(strA, strB));
            }
            if (strA != null && (strA.Size == 0 || strA.Size >= b.Size))
            {
                MergeIntoStructure(b, strA);
                return(strA);
            }
            if (strB != null && (strB.Size == 0 || strB.Size >= a.Size))
            {
                MergeIntoStructure(a, strB);
                return(strB);
            }
            if (strA != null || strB != null)
            {
                return(MakeUnion(a, b));
            }
            CodeType ca = a as CodeType;
            CodeType cb = b as CodeType;

            if (ca != null && cb != null)
            {
                return(ca);
            }
            if (tA != null)
            {
                return(UnifyTypeVariable(tA, b));
            }
            if (tB != null)
            {
                return(UnifyTypeVariable(tB, a));
            }
            return(MakeUnion(a, b));
        }
Example #7
0
        public bool AreCompatible(DataType a, DataType b)
        {
            if (a == null || b == null)
            {
                return(false);
            }

            PrimitiveType pa = a as PrimitiveType;
            PrimitiveType pb = b as PrimitiveType;

            if (pa != null && pb != null)
            {
                if (pa.Size != pb.Size)
                {
                    return(false);
                }
                return((pa.Domain & pb.Domain) != 0);
            }

            TypeReference tra = a as TypeReference;
            TypeReference trb = b as TypeReference;

            if (tra != null && trb != null)
            {
                return(tra == trb);
            }
            if (tra != null)
            {
                return(AreCompatible(tra.Referent, b));
            }
            if (trb != null)
            {
                return(AreCompatible(a, trb.Referent));
            }

            TypeVariable tva = a as TypeVariable;
            TypeVariable tvb = b as TypeVariable;

            if (tva != null && tvb != null)
            {
                return(tva.Number == tvb.Number);
            }

            EquivalenceClass eqA = a as EquivalenceClass;
            EquivalenceClass eqB = b as EquivalenceClass;

            if (eqA != null && eqB != null)
            {
                return(eqA.Number == eqB.Number);
            }

            Pointer ptrA = a as Pointer;
            Pointer ptrB = b as Pointer;

            if (ptrA != null)
            {
                return(IsCompatibleWithPointer(ptrA, b));
            }
            if (ptrB != null)
            {
                return(IsCompatibleWithPointer(ptrB, a));
            }

            MemberPointer mpA = a as MemberPointer;
            MemberPointer mpB = b as MemberPointer;

            if (mpA != null)
            {
                return(IsCompatibleWithMemberPointer(mpA, b));
            }
            if (mpB != null)
            {
                return(IsCompatibleWithMemberPointer(mpB, a));
            }

            StructureType sa = a as StructureType;
            StructureType sb = b as StructureType;

            if (sa != null && sb != null)
            {
                return(AreCompatible(sa, sb));
            }

            ArrayType aa = a as ArrayType;
            ArrayType ab = b as ArrayType;

            if (aa != null && ab != null)
            {
                return(AreCompatible(aa.ElementType, ab.ElementType));
            }

            UnionType ua = a as UnionType;
            UnionType ub = b as UnionType;

            if (ua != null && ub != null)
            {
                return(true);
            }

            FunctionType fa = a as FunctionType;
            FunctionType fb = b as FunctionType;

            if (fa != null && fb != null)
            {
                return(fa.Parameters.Length == fb.Parameters.Length);
            }

            CodeType ca = a as CodeType;
            CodeType cb = a as CodeType;

            if (ca != null && cb != null)
            {
                return(true);
            }
            return(a is UnknownType || b is UnknownType);
        }