예제 #1
0
 private Expression?ShiftRightShiftLeft(BinaryExpression bin)
 {
     if (bin.Operator != Operator.Shl || !(bin.Right is Constant cRight))
     {
         return(null);
     }
     if (bin.Left is Identifier idLeft)
     {
         var innerExp = ctx.GetDefiningExpression(idLeft);
         if (innerExp is null)
         {
             return(null);
         }
         if (innerExp is BinaryExpression binInner &&
             (binInner.Operator == Operator.Shr || binInner.Operator == Operator.Sar) &&
             cmp.Equals(cRight, binInner.Right))
         {
             ctx.RemoveExpressionUse(idLeft);
             ctx.UseExpression(binInner.Left);
             var sig = FunctionType.Func(
                 new Identifier("", bin.DataType, null !),
                 new Identifier("x", binInner.Left.DataType, null !),
                 new Identifier("y", PrimitiveType.Int32, null !));
             var align = new IntrinsicProcedure(IntrinsicProcedure.Align, true, sig);
             return(m.Fn(align, binInner.Left, Constant.Int32(1 << cRight.ToInt32())));
         }
     }
     return(null);
 }
예제 #2
0
        public bool Match(MkSequence seq)
        {
            if (seq.Expressions.Length != 2)
            {
                return(false);   //$TODO: handle sequences of any length?
            }
            this.idHi = seq.Expressions[0] as Identifier;
            this.idLo = seq.Expressions[1] as Identifier;
            if (idHi == null || idLo == null)
            {
                return(false);
            }
            var defHi = ctx.GetDefiningExpression(idHi) as Slice;
            var defLo = ctx.GetDefiningExpression(idLo) as Slice;

            if (defHi == null || defLo == null)
            {
                return(false);
            }

            if (defHi.Expression != defLo.Expression)
            {
                return(false);
            }

            this.idOrig = defHi.Expression as Identifier;
            return(idOrig != null);
        }
예제 #3
0
        public bool Match(DepositBits dpb)
        {
            this.dpbUse = dpb;
            if (!dpb.Source.As(out idDef))
            {
                return(false);
            }
            var expDef = ctx.GetDefiningExpression(idDef);

            if (expDef == null)
            {
                return(false);
            }
            if (!expDef.As(out dpbDef))
            {
                return(false);
            }
            if (!dpbDef.Source.As(out idSrc))
            {
                return(false);
            }
            return
                (dpbDef.BitCount == dpbUse.BitCount &&
                 dpbDef.BitPosition == dpbUse.BitPosition);
        }
예제 #4
0
        public bool Match(DepositBits dpb)
        {
            this.dpbUse = dpb;
            if (!(dpb.Source is Identifier idDef))
            {
                return(false);
            }
            var expDef = ctx.GetDefiningExpression(idDef);

            if (expDef == null)
            {
                return(false);
            }
            if (!(expDef is DepositBits dpbDef))
            {
                return(false);
            }
            if (!(dpbDef.Source is Identifier idSrc))
            {
                return(false);
            }
            this.idDef  = idDef;
            this.dpbDef = dpbDef;
            this.idSrc  = idSrc;
            return(dpbDef.BitPosition == dpbUse.BitPosition);
        }
예제 #5
0
        public virtual Expression VisitCast(Cast cast)
        {
            var exp = cast.Expression.Accept(this);

            if (exp != Constant.Invalid)
            {
                var      ptCast = cast.DataType.ResolveAs <PrimitiveType>();
                Constant c      = exp as Constant;
                if (c != null && ptCast != null)
                {
                    PrimitiveType ptSrc = c.DataType as PrimitiveType;
                    if (ptSrc != null)
                    {
                        if (ptCast.Domain == Domain.Real)
                        {
                            if (ptSrc.Domain == Domain.Real &&
                                ptCast.Size < ptSrc.Size)
                            {
                                Changed = true;
                                return(ConstantReal.Create(ptCast, c.ToReal64()));
                            }
                        }
                        else if ((ptSrc.Domain & Domain.Integer) != 0)
                        {
                            Changed = true;
                            return(Constant.Create(ptCast, c.ToUInt64()));
                        }
                    }
                }
                Identifier  id;
                DepositBits dpb;
                if (exp.As(out id) && ctx.GetDefiningExpression(id).As(out dpb) && dpb.BitPosition == 0)
                {
                    // If we are casting the result of a DPB, and the deposited part is >=
                    // the size of the cast, then use deposited part directly.
                    int sizeDiff = dpb.InsertedBits.DataType.Size - cast.DataType.Size;
                    if (sizeDiff >= 0)
                    {
                        ctx.RemoveIdentifierUse(id);
                        ctx.UseExpression(dpb.InsertedBits);
                        Changed = true;
                        if (sizeDiff > 0)
                        {
                            return(new Cast(cast.DataType, dpb.InsertedBits));
                        }
                        else
                        {
                            return(dpb.InsertedBits);
                        }
                    }
                }
                cast = new Cast(cast.DataType, exp);
            }
            if (castCastRule.Match(cast))
            {
                Changed = true;
                return(castCastRule.Transform());
            }
            return(cast);
        }
예제 #6
0
        /// <summary>
        /// Try to find an original 32-bit segmented pointer that may have
        /// been SLICE'd to a segment and offset register.
        /// </summary>
        /// <param name="seg"></param>
        /// <param name="off"></param>
        /// <returns></returns>
        private Identifier?SlicedSegPointer(Identifier seg, Identifier off)
        {
            var defSeg = ctx.GetDefiningExpression(seg) as Slice;
            var defOff = ctx.GetDefiningExpression(off) as Slice;

            if (defSeg == null || defOff == null)
            {
                return(null);
            }
            if (defSeg.Expression == defOff.Expression)
            {
                return(defSeg.Expression as Identifier);
            }
            else
            {
                return(null);
            }
        }
예제 #7
0
        public bool Match(Expression ea)
        {
            //$REFACTOR: this is mutable shared state. Rewrite this to
            // use the (Expression newExpr, bool changed) pattern used
            // elsewhere in ExpressionSimplifier.
            this.binEaLeft  = null;
            this.binEaRight = null;
            this.idEa       = null;

            if (ea is BinaryExpression bin)
            {
                if (bin.Operator == Operator.IAdd || bin.Operator == Operator.ISub)
                {
                    if (bin.Left is Identifier idLeft)
                    {
                        this.defIndex = ctx.GetDefiningExpression(idLeft);
                        if (IsScaled(defIndex))
                        {
                            this.binEaLeft = bin;
                            return(true);
                        }
                    }
                    if (bin.Right is Identifier idRight)
                    {
                        this.defIndex = ctx.GetDefiningExpression(idRight);
                        if (IsScaled(defIndex))
                        {
                            this.binEaRight = bin;
                            return(true);
                        }
                    }
                }
            }
            else if (ea is Identifier id)
            {
                this.defIndex = ctx.GetDefiningExpression(id);
                if (IsScaled(defIndex))
                {
                    idEa = id;
                    return(true);
                }
            }
            return(false);
        }
예제 #8
0
 private bool IsSequence(Expression e, out MkSequence sequence)
 {
     if (e is Identifier id)
     {
         sequence = ctx.GetDefiningExpression(id) as MkSequence;
     }
     else
     {
         sequence = e as MkSequence;
     }
     return(sequence != null);
 }
예제 #9
0
 public bool Match(Expression ea)
 {
     if (ea is BinaryExpression bin)
     {
         if (bin.Operator == Operator.IAdd || bin.Operator == Operator.ISub)
         {
             if (bin.Left is Identifier idLeft)
             {
                 this.defIndex = ctx.GetDefiningExpression(idLeft);
                 if (IsScaled(defIndex))
                 {
                     this.binEaLeft = bin;
                     return(true);
                 }
             }
             if (bin.Right is Identifier idRight)
             {
                 this.defIndex = ctx.GetDefiningExpression(idRight);
                 if (IsScaled(defIndex))
                 {
                     this.binEaRight = bin;
                     return(true);
                 }
             }
         }
     }
     else if (ea is Identifier id)
     {
         this.defIndex = ctx.GetDefiningExpression(id);
         if (IsScaled(defIndex))
         {
             idEa = id;
             return(true);
         }
     }
     return(false);
 }
예제 #10
0
        private bool IsSequence(Expression e, out MkSequence sequence)
        {
            MkSequence?s;

            if (e is Identifier id)
            {
                s = ctx.GetDefiningExpression(id) as MkSequence;
            }
            else
            {
                s = e as MkSequence;
            }
            sequence = s !;
            return(s != null);
        }
예제 #11
0
        public virtual Expression VisitCast(Cast cast)
        {
            var exp = cast.Expression.Accept(this);

            if (exp == Constant.Invalid)
            {
                return(exp);
            }

            Constant c = exp as Constant;

            if (c != null)
            {
                PrimitiveType p = c.DataType as PrimitiveType;
                if (p != null && (p.Domain & Domain.Integer) != 0)
                {
                    //$REVIEW: this is fixed to 32 bits; need a general solution to it.
                    Changed = true;
                    return(Constant.Create(cast.DataType, c.ToUInt64()));
                }
            }
            Identifier  id;
            DepositBits dpb;

            if (exp.As(out id) && ctx.GetDefiningExpression(id).As(out dpb) && dpb.BitPosition == 0)
            {
                // If we are casting the result of a DPB, and the deposited part is >=
                // the size of the cast, then use deposited part directly.
                int sizeDiff = dpb.InsertedBits.DataType.Size - cast.DataType.Size;
                if (sizeDiff >= 0)
                {
                    ctx.RemoveIdentifierUse(id);
                    ctx.UseExpression(dpb.InsertedBits);
                    Changed = true;
                    if (sizeDiff > 0)
                    {
                        return(new Cast(cast.DataType, dpb.InsertedBits));
                    }
                    else
                    {
                        return(dpb.InsertedBits);
                    }
                }
            }
            return(new Cast(cast.DataType, exp));
        }
예제 #12
0
        public virtual Expression VisitCast(Cast cast)
        {
            var exp = cast.Expression.Accept(this);

            if (exp != Constant.Invalid)
            {
                var ptCast = cast.DataType.ResolveAs <PrimitiveType>();
                if (exp is Constant c && ptCast != null)
                {
                    if (c.DataType is PrimitiveType ptSrc)
                    {
                        if (ptCast.Domain == Domain.Real)
                        {
                            if (ptSrc.Domain == Domain.Real &&
                                ptCast.Size < ptSrc.Size)
                            {
                                Changed = true;
                                return(ConstantReal.Create(ptCast, c.ToReal64()));
                            }
                        }
                        else if ((ptSrc.Domain & Domain.Integer) != 0)
                        {
                            Changed = true;
                            return(Constant.Create(ptCast, c.ToUInt64()));
                        }
                    }
                }
                if (exp is Identifier id &&
                    ctx.GetDefiningExpression(id) is DepositBits dpb &&
                    dpb.BitPosition == 0)
                {
                    // If we are casting the result of a DPB, and the deposited part is >=
                    // the size of the cast, then use deposited part directly.
                    int sizeDiff = dpb.InsertedBits.DataType.Size - cast.DataType.Size;
                    if (sizeDiff >= 0)
                    {
                        ctx.RemoveIdentifierUse(id);
                        ctx.UseExpression(dpb.InsertedBits);
                        Changed = true;
                        if (sizeDiff > 0)
                        {
                            return(new Cast(cast.DataType, dpb.InsertedBits));
                        }
                        else
                        {
                            return(dpb.InsertedBits);
                        }
                    }
                }
                if (exp is ProcedureConstant pc && cast.DataType.BitSize == pc.DataType.BitSize)
                {
                    // (wordnn) procedure_const => procedure_const
                    return(pc);
                }
                if (exp.DataType.BitSize == cast.DataType.BitSize)
                {
                    // Redundant word-casts can be stripped.
                    var wordType = PrimitiveType.CreateWord(exp.DataType.BitSize);
                    if (wordType == cast.DataType)
                    {
                        return(exp);
                    }
                }
                cast = new Cast(cast.DataType, exp);
            }
            if (castCastRule.Match(cast))
            {
                Changed = true;
                return(castCastRule.Transform());
            }
            return(cast);
        }
예제 #13
0
        public virtual Expression VisitConversion(Conversion conversion)
        {
            var exp = conversion.Expression.Accept(this);

            if (exp != Constant.Invalid)
            {
                var ptCvt = conversion.DataType.ResolveAs <PrimitiveType>();
                var ptSrc = conversion.SourceDataType.ResolveAs <PrimitiveType>();
                if (exp is Constant c && ptCvt != null)
                {
                    if (ptSrc != null)
                    {
                        if (ptCvt.Domain == Domain.Real)
                        {
                            if (ptSrc.Domain == Domain.Real)
                            {
                                if (ptCvt.Size < ptSrc.Size)
                                {
                                    // Real-to-real conversion.
                                    Changed = true;
                                    return(ConstantReal.Create(ptCvt, c.ToReal64()));
                                }
                            }
                            else if (ptSrc.IsWord)
                            {
                                // Raw bit pattern reinterpretation.
                                Changed = true;
                                return(CastRawBitsToReal(ptCvt, c));
                            }
                            else
                            {
                                // integer to real conversion
                                Changed = true;
                                return(ConstantReal.Create(ptCvt, c.ToInt64()));
                            }
                        }
                        else if ((ptSrc.Domain & Domain.Integer) != 0)
                        {
                            if (ptSrc != null)
                            {
                                if (ptSrc.Domain == Domain.SignedInt)
                                {
                                    Changed = true;
                                    return(Constant.Create(ptCvt, c.ToInt64()));
                                }
                                else if (ptSrc.Domain.HasFlag(Domain.SignedInt))
                                {
                                    Changed = true;
                                    return(Constant.Create(ptCvt, c.ToUInt64()));
                                }
                            }
                        }
                    }
                }
                if (exp is Identifier id &&
                    ctx.GetDefiningExpression(id) is MkSequence seq)
                {
                    // If we are casting a SEQ, and the corresponding element is >=
                    // the size of the cast, then use deposited part directly.
                    var lsbElem  = seq.Expressions[seq.Expressions.Length - 1];
                    int sizeDiff = lsbElem.DataType.Size - conversion.DataType.Size;
                    if (sizeDiff >= 0)
                    {
                        foreach (var elem in seq.Expressions)
                        {
                            ctx.RemoveExpressionUse(elem);
                        }
                        ctx.UseExpression(lsbElem);
                        Changed = true;
                        if (sizeDiff > 0)
                        {
                            return(new Conversion(lsbElem, lsbElem.DataType, conversion.DataType));
                        }
                        else
                        {
                            return(lsbElem);
                        }
                    }
                }
                if (exp is ProcedureConstant pc && conversion.DataType.BitSize == pc.DataType.BitSize)
                {
                    // (wordnn) procedure_const => procedure_const
                    return(pc);
                }
                if (exp.DataType.BitSize == conversion.DataType.BitSize)
                {
                    // Redundant word-casts can be stripped.
                    if (conversion.DataType.IsWord)
                    {
                        return(exp);
                    }
                }
                conversion = new Conversion(exp, exp.DataType, conversion.DataType);
            }
            if (convertConvertRule.Match(conversion))
            {
                Changed = true;
                return(convertConvertRule.Transform());
            }
            return(conversion);
        }
예제 #14
0
        public virtual Expression VisitCast(Cast cast)
        {
            var exp = cast.Expression.Accept(this);

            if (exp != Constant.Invalid)
            {
                var ptCast = cast.DataType.ResolveAs <PrimitiveType>();
                if (exp is Constant c && ptCast != null)
                {
                    if (c.DataType is PrimitiveType ptSrc)
                    {
                        if (ptCast.Domain == Domain.Real)
                        {
                            if (ptSrc.Domain == Domain.Real &&
                                ptCast.Size < ptSrc.Size)
                            {
                                Changed = true;
                                return(ConstantReal.Create(ptCast, c.ToReal64()));
                            }
                        }
                        else if ((ptSrc.Domain & Domain.Integer) != 0)
                        {
                            Changed = true;
                            return(Constant.Create(ptCast, c.ToUInt64()));
                        }
                    }
                }
                if (exp is Identifier id &&
                    ctx.GetDefiningExpression(id) is MkSequence seq)
                {
                    // If we are casting a SEQ, and the corresponding element is >=
                    // the size of the cast, then use deposited part directly.
                    var lsbElem  = seq.Expressions[seq.Expressions.Length - 1];
                    int sizeDiff = lsbElem.DataType.Size - cast.DataType.Size;
                    if (sizeDiff >= 0)
                    {
                        foreach (var elem in seq.Expressions)
                        {
                            ctx.RemoveExpressionUse(elem);
                        }
                        ctx.UseExpression(lsbElem);
                        Changed = true;
                        if (sizeDiff > 0)
                        {
                            return(new Cast(cast.DataType, lsbElem));
                        }
                        else
                        {
                            return(lsbElem);
                        }
                    }
                }
                if (exp is ProcedureConstant pc && cast.DataType.BitSize == pc.DataType.BitSize)
                {
                    // (wordnn) procedure_const => procedure_const
                    return(pc);
                }
                if (exp.DataType.BitSize == cast.DataType.BitSize)
                {
                    // Redundant word-casts can be stripped.
                    if (cast.DataType.IsWord())
                    {
                        return(exp);
                    }
                }
                cast = new Cast(cast.DataType, exp);
            }
            if (castCastRule.Match(cast))
            {
                Changed = true;
                return(castCastRule.Transform());
            }
            return(cast);
        }