Esempio n. 1
0
        /// <summary>
        /// Applies the transformation
        /// </summary>
        /// <returns>The transformed item.</returns>
        /// <param name="item">The item to visit.</param>
        public ASTItem Transform(ASTItem item)
        {
            var rs = item as AST.ReturnStatement;

            if (rs == null)
            {
                return(item);
            }

            if (rs.ReturnExpression is EmptyExpression)
            {
                return(item);
            }

            var stm = new ExpressionStatement()
            {
                Expression = new AST.AssignmentExpression()
                {
                    Left = new AST.MemberReferenceExpression()
                    {
                        Target           = Method.ReturnVariable,
                        Name             = Method.ReturnVariable.Name,
                        SourceExpression = rs.ReturnExpression.SourceExpression,
                        SourceResultType = Method.ReturnVariable.CecilType
                    },
                    Right            = rs.ReturnExpression,
                    SourceExpression = rs.ReturnExpression.SourceExpression,
                    SourceResultType = Method.ReturnVariable.CecilType,
                    Operator         = ICSharpCode.Decompiler.CSharp.Syntax.AssignmentOperatorType.Assign
                }
            };

            rs.PrependStatement(stm);
            stm.UpdateParents();

            rs.ReplaceWith(new ReturnStatement()
            {
                ReturnExpression = new EmptyExpression()
                {
                    SourceExpression = rs.ReturnExpression.SourceExpression,
                    SourceResultType = Method.ReturnVariable.CecilType.LoadType(typeof(void))
                },
            });

            return(stm);
        }
Esempio n. 2
0
        public static Expression ConvertExpression(RenderState render, Method method, Expression s, VHDLType target, Mono.Cecil.TypeReference targetsource, bool fromCast)
        {
            var svhdl = render.VHDLType(s);

            // Deal with pesky integers that overflow the 32bit VHDL specs
            if (IsTooLargeIntegerLiteral(s, target))
            {
                svhdl = render.TypeScope.StdLogicVectorEquivalent(target);
            }

            // Already the real target type, just return it
            if (svhdl == target)
            {
                return(s);
            }

            // Stuff we do not care about
            if (!svhdl.IsStdLogicVector && !svhdl.IsUnsigned && !svhdl.IsSigned && svhdl.IsArray && target.IsArray && render.TypeScope.GetByName(svhdl.ElementName) == render.TypeScope.GetByName(target.ElementName))
            {
                return(s);
            }

            // Array lengths
            var targetlengthstr = string.IsNullOrWhiteSpace(target.Alias) ? target.Length.ToString() : target.Alias + "'length";

            if (target == VHDLTypes.SYSTEM_BOOL)
            {
                // Boolean to std_logic is fine
                if (string.Equals("STD_LOGIC", svhdl.Name, StringComparison.OrdinalIgnoreCase))
                {
                    return(s);
                }

                // Source is numeric, and output is bool
                if (svhdl.IsNumeric || svhdl.IsStdLogicVector)
                {
                    var zero = new PrimitiveExpression()
                    {
                        SourceExpression = s.SourceExpression,
                        SourceResultType = s.SourceResultType,
                        Value            = 0
                    };

                    var eval = new BinaryOperatorExpression()
                    {
                        Parent           = s.Parent,
                        Name             = s.Name,
                        SourceExpression = s.SourceExpression,
                        SourceResultType = s.SourceResultType.LoadType(typeof(bool)),
                        Left             = s,
                        Operator         = ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorType.InEquality,
                        Right            = zero
                    };

                    zero.Parent = eval;

                    s.ReplaceWith(eval);
                    s.Parent = eval;

                    return(eval);
                }
                else if (svhdl == VHDLTypes.BOOL)
                {
                    var truexp = new PrimitiveExpression()
                    {
                        Value            = true,
                        SourceExpression = s.SourceExpression,
                        SourceResultType = s.SourceResultType.LoadType(typeof(bool)),
                    };

                    var falseexp = new PrimitiveExpression()
                    {
                        Value            = false,
                        SourceExpression = s.SourceExpression,
                        SourceResultType = s.SourceResultType.LoadType(typeof(bool)),
                    };

                    var eval = new ConditionalExpression()
                    {
                        ConditionExpression = s,
                        TrueExpression      = truexp,
                        FalseExpression     = falseexp,
                        SourceExpression    = s.SourceExpression,
                        SourceResultType    = truexp.SourceResultType
                    };

                    truexp.Parent   = eval;
                    falseexp.Parent = eval;

                    s.ReplaceWith(eval);
                    s.Parent = eval;

                    return(eval);
                }
                else
                {
                    throw new Exception(string.Format("Unexpected conversion from {0} to {1}", svhdl, target));
                }
            }
            else if (svhdl == VHDLTypes.INTEGER && (target.IsStdLogicVector || target.IsNumeric))
            {
                if (target.IsSigned && target.IsNumeric)
                {
                    return(WrapExpression(render, s, string.Format("TO_SIGNED({0}, {1})", "{0}", targetlengthstr), target));
                }
                else if (target.IsUnsigned && target.IsNumeric)
                {
                    return(WrapExpression(render, s, string.Format("TO_UNSIGNED({0}, {1})", "{0}", targetlengthstr), target));
                }
                else if (target.IsStdLogicVector)
                {
                    return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR(TO_UNSIGNED({0}, {1}))", "{0}", targetlengthstr), target));
                }
                else
                {
                    throw new Exception(string.Format("Unexpected conversion from {0} to {1}", svhdl, target));
                }
            }
            else if (target.IsNumeric && !svhdl.IsEnum)
            {
                if (svhdl.IsStdLogicVector || svhdl.IsSigned || svhdl.IsUnsigned)
                {
                    var      str     = "{0}";
                    var      resized = false;
                    Variable tmpvar  = null;
                    if (target.Length != svhdl.Length)
                    {
                        if (svhdl.IsVHDLSigned)
                        {
                            // Resizing with signed is bad because we may chop the upper bit
                            resized = true;
                            str     = string.Format("SIGNED(resize(UNSIGNED({0}), {1}))", str, targetlengthstr);
                        }
                        else if (svhdl.IsVHDLUnsigned)
                        {
                            resized = true;
                            str     = string.Format("resize({0}, {1})", str, targetlengthstr);
                        }
                        else if (svhdl.IsSystemSigned)
                        {
                            // Resizing with signed is bad because we may chop the upper bit
                            str     = string.Format("SIGNED(resize(UNSIGNED({0}), {1}))", str, targetlengthstr);
                            svhdl   = render.TypeScope.NumericEquivalent(svhdl);
                            resized = true;
                        }
                        else if (svhdl.IsSystemUnsigned)
                        {
                            str     = string.Format("resize(UNSIGNED({0}), {1})", str, targetlengthstr);
                            svhdl   = render.TypeScope.NumericEquivalent(svhdl);
                            resized = true;
                        }

                        else if (target.Length > svhdl.Length)
                        {
                            // This must be a variable as bit concatenation is only allowed in assignment statements:
                            // http://stackoverflow.com/questions/209458/concatenating-bits-in-vhdl

                            tmpvar = render.RegisterTemporaryVariable(method, targetsource);
                            render.TypeLookup[tmpvar] = target;

                            var iexp = new IdentifierExpression()
                            {
                                Name             = tmpvar.Name,
                                Target           = tmpvar,
                                SourceExpression = s.SourceExpression,
                                SourceResultType = targetsource
                            };

                            string wstr;
                            if (render.Config.USE_EXPLICIT_CONCATENATION_OPERATOR)
                            {
                                wstr = string.Format("IEEE.STD_LOGIC_1164.\"&\"(\"{0}\", {1})", new string('0', target.Length - svhdl.Length), "{0}");
                            }
                            else
                            {
                                wstr = string.Format("\"{0}\" & {1}", new string('0', target.Length - svhdl.Length), "{0}");
                            }

                            s.ReplaceWith(iexp);

                            var asstm = new ExpressionStatement()
                            {
                                Expression = new AssignmentExpression()
                                {
                                    Left  = iexp.Clone(),
                                    Right = new CustomNodes.ConversionExpression()
                                    {
                                        Expression       = s,
                                        SourceExpression = s.SourceExpression,
                                        SourceResultType = targetsource,
                                        WrappingTemplate = wstr,
                                    },
                                    Operator         = ICSharpCode.Decompiler.CSharp.Syntax.AssignmentOperatorType.Assign,
                                    SourceExpression = s.SourceExpression,
                                    SourceResultType = targetsource
                                },
                            };

                            s.PrependStatement(asstm);
                            asstm.UpdateParents();

                            resized = true;

                            s = iexp;
                        }
                    }

                    if (svhdl.IsVHDLSigned != target.IsSigned || svhdl.IsVHDLUnsigned != target.IsUnsigned)
                    {
                        str = string.Format("{1}({0})", str, target.IsSigned ? "SIGNED" : "UNSIGNED");
                    }

                    if (target.Length != svhdl.Length && !resized)
                    {
                        str = string.Format("resize({0}, {1})", str, targetlengthstr);
                    }

                    return(WrapExpression(render, s, str, target));
                }


                /*if (svhdl.IsStdLogicVector && target.IsSigned)
                 *                      return new VHDLConvertedExpression(s, target, "SIGNED({0})");
                 *              else if (svhdl.IsStdLogicVector && target.IsUnsigned)
                 *                      return new VHDLConvertedExpression(s, target, "UNSIGNED({0})");
                 *              else*/
                throw new Exception(string.Format("Unexpected conversion from {0} to {1}", svhdl, target));
            }
            else if (target.IsStdLogicVector)
            {
                if (svhdl.IsNumeric)
                {
                    if (svhdl.Length == target.Length)
                    {
                        return(WrapExpression(render, s, "STD_LOGIC_VECTOR({0})", target));
                    }
                    else
                    {
                        if (!fromCast)
                        {
                            Console.WriteLine("WARN: Incompatible array lengths, from {0} to {1}", svhdl, target);
                        }
                        //throw new Exception(string.Format("Incompatible array lengths, from {0} to {1}", svhdl, target));

                        if (target.Length < svhdl.Length && svhdl.IsNumericSigned)
                        {
                            return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR(resize(UNSIGNED({0}), {1}))", "{0}", targetlengthstr), target));
                        }
                        else
                        {
                            return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR(resize({0}, {1}))", "{0}", targetlengthstr), target));
                        }
                    }
                }
                else if (svhdl.IsStdLogicVector)
                {
                    if (target.Length == svhdl.Length)
                    {
                        render.TypeLookup[s] = target;
                        return(s);
                    }

                    if (!fromCast)
                    {
                        Console.WriteLine("WARN: Incompatible array lengths, from {0} to {1}", svhdl, target);
                    }
                    //throw new Exception(string.Format("Incompatible array lengths, from {0} to {1}", svhdl, target));

                    if (target.Length < svhdl.Length)
                    {
                        // If the expression is a simple identifier, we can select bits from it
                        // otherwise we need to inject a variable with the expression
                        // and select the required bits from it
                        if (!(s is IdentifierExpression || s is MemberReferenceExpression || s is IndexerExpression))
                        {
                            var tmp = render.RegisterTemporaryVariable(method, s.SourceResultType);
                            render.TypeLookup[tmp] = svhdl;

                            var aleft = new IdentifierExpression()
                            {
                                Name             = tmp.Name,
                                Target           = tmp,
                                SourceExpression = s.SourceExpression,
                                SourceResultType = s.SourceResultType
                            };

                            var aexp = new AssignmentExpression()
                            {
                                Left             = aleft,
                                Right            = s,
                                SourceExpression = s.SourceExpression,
                                SourceResultType = s.SourceResultType
                            };

                            var astm = new ExpressionStatement()
                            {
                                Expression = aexp,
                                Parent     = method,
                            };

                            var iexp = new IdentifierExpression()
                            {
                                SourceExpression = s.SourceExpression,
                                SourceResultType = s.SourceResultType,
                                Target           = tmp
                            };

                            s.ReplaceWith(iexp);
                            s.PrependStatement(astm);
                            astm.UpdateParents();

                            return(WrapExpression(render, iexp, string.Format("{0}({1} downto 0)", "{0}", target.Length - 1), target));
                        }

                        return(WrapExpression(render, s, string.Format("{0}({1} downto 0)", "{0}", target.Length - 1), target));
                    }
                    else if (svhdl.IsSigned)
                    {
                        return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR(resize(SIGNED({0}), {1}))", "{0}", targetlengthstr), target));
                    }
                    else if (svhdl.IsUnsigned)
                    {
                        return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR(resize(UNSIGNED({0}), {1}))", "{0}", targetlengthstr), target));
                    }
                    else
                    {
                        var tmp = render.RegisterTemporaryVariable(method, targetsource);
                        render.TypeLookup[tmp] = target;

                        var iexp = new IdentifierExpression()
                        {
                            Name             = tmp.Name,
                            Target           = tmp,
                            SourceExpression = s.SourceExpression,
                            SourceResultType = targetsource
                        };

                        render.TypeLookup[iexp] = target;

                        string wexpr;
                        if (render.Config.USE_EXPLICIT_CONCATENATION_OPERATOR)
                        {
                            wexpr = string.Format("IEEE.STD_LOGIC_1164.\"&\"(\"{0}\", {1})", new string('0', target.Length - svhdl.Length), "{0}");
                        }
                        else
                        {
                            wexpr = string.Format("\"{0}\" & {1}", new string('0', target.Length - svhdl.Length), "{0}");
                        }

                        s.ReplaceWith(iexp);

                        var asstm = new ExpressionStatement();

                        s.PrependStatement(asstm);


                        var asexp = new AssignmentExpression()
                        {
                            Left     = iexp.Clone(),
                            Operator = ICSharpCode.Decompiler.CSharp.Syntax.AssignmentOperatorType.Assign,
                            Right    = new CustomNodes.ConversionExpression()
                            {
                                Expression       = s,
                                SourceExpression = s.SourceExpression,
                                SourceResultType = targetsource,
                                WrappingTemplate = wexpr
                            },
                            SourceExpression = s.SourceExpression,
                            SourceResultType = targetsource
                        };

                        render.TypeLookup[asexp.Left]  = target;
                        render.TypeLookup[asexp.Right] = target;
                        asexp.Left.SourceResultType    = targetsource;
                        asexp.Right.SourceResultType   = targetsource;
                        asstm.Expression = asexp;

                        asstm.UpdateParents();

                        return(iexp);
                    }
                }
                else if (svhdl.IsSigned || svhdl.IsUnsigned)
                {
                    if (target.Length == svhdl.Length)
                    {
                        return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR({0})", "{0}"), target));
                    }
                    else
                    {
                        return(WrapExpression(render, s, string.Format("STD_LOGIC_VECTOR(resize({0}, {1}))", "{0}", targetlengthstr), target));
                    }
                }
                else
                {
                    throw new Exception(string.Format("Unexpected conversion from {0} to {1}", svhdl.Name, target.Name));
                }
            }
            else if (target == VHDLTypes.INTEGER && (svhdl.IsStdLogicVector || svhdl.IsNumeric))
            {
                if (svhdl.IsNumeric)
                {
                    return(WrapExpression(render, s, "TO_INTEGER({0})", target));
                }

                if (svhdl.IsSigned)
                {
                    return(WrapExpression(render, s, "TO_INTEGER(SIGNED({0}))", target));
                }
                else
                {
                    return(WrapExpression(render, s, "TO_INTEGER(UNSIGNED({0}))", target));
                }
            }
            else if (target == VHDLTypes.INTEGER && (svhdl.IsSystemSigned || svhdl.IsSystemUnsigned))
            {
                return(WrapExpression(render, s, "TO_INTEGER({0})", target));
            }
            else if (target == VHDLTypes.BOOL && svhdl == VHDLTypes.SYSTEM_BOOL)
            {
                return(WrapInParenthesis(render, WrapExpression(render, s, "{0} = '1'", target)));
            }
            else if ((target.IsSigned || target.IsUnsigned) && svhdl.IsStdLogicVector)
            {
                if (target.Length == svhdl.Length)
                {
                    return(WrapExpression(render, s, string.Format("{1}({0})", "{0}", target.IsSigned ? "SIGNED" : "UNSIGNED"), target));
                }
                else
                {
                    return(WrapExpression(render, s, string.Format("resize({1}({0}), {2})", "{0}", target.IsSigned ? "SIGNED" : "UNSIGNED", targetlengthstr), target));
                }
            }
            else if ((target.IsSigned || target.IsUnsigned) && svhdl == VHDLTypes.INTEGER)
            {
                if (target.IsSigned)
                {
                    return(WrapExpression(render, s, string.Format("TO_SIGNED({0}, {1})", "{0}", target.Length), target));
                }
                else if (target.IsUnsigned)
                {
                    return(WrapExpression(render, s, string.Format("TO_UNSIGNED({0}, {1})", "{0}", target.Length), target));
                }
                else
                {
                    throw new Exception("Unexpected case");
                }
            }
            else if ((svhdl.IsSigned || svhdl.IsUnsigned) && (target.IsSigned || target.IsUnsigned))
            {
                if (target.Length == svhdl.Length)
                {
                    if (svhdl.IsSigned == target.IsSigned)
                    {
                        return(s);
                    }
                    else
                    {
                        return(WrapExpression(render, s, string.Format("{1}({0})", "{0}", target.IsSigned ? "SIGNED" : "UNSIGNED"), target));
                    }
                }
                else
                {
                    if (svhdl.IsSigned == target.IsSigned)
                    {
                        return(WrapExpression(render, s, string.Format("resize({0}, {1})", "{0}", targetlengthstr), target));
                    }
                    else if (svhdl.IsSigned && svhdl.Length > target.Length)
                    {
                        return(WrapExpression(render, s, string.Format("resize(UNSIGNED({0}), {1})", "{0}", targetlengthstr), target));
                    }
                    else
                    {
                        return(WrapExpression(render, s, string.Format("{2}(resize({0}, {1}))", "{0}", targetlengthstr, target.IsSigned ? "SIGNED" : "UNSIGNED"), target));
                    }
                }
            }
            else if (target.IsEnum && (svhdl.IsSigned || svhdl.IsUnsigned || svhdl == VHDLTypes.INTEGER))
            {
                if (target.IsIrregularEnum)
                {
                    return(WrapExpression(render, s, string.Format("fromValue_{1}({0})", svhdl == VHDLTypes.INTEGER ? "{0}" : "TO_INTEGER({0})", target.ToSafeVHDLName()), target));
                }
                else
                {
                    return(WrapExpression(render, s, string.Format("{1}'VAL({0})", svhdl == VHDLTypes.INTEGER ? "{0}" : "TO_INTEGER({0})", target.ToSafeVHDLName()), target));
                }
            }
            else if (svhdl.IsEnum && (target.IsSigned || target.IsUnsigned || target == VHDLTypes.INTEGER))
            {
                Expression wrapped;
                if (target.IsIrregularEnum)
                {
                    wrapped = WrapExpression(render, s, string.Format("toValue_{1}({0})", "{0}", svhdl.ToSafeVHDLName()), target);
                }
                else
                {
                    wrapped = WrapExpression(render, s, string.Format("{1}'POS({0})", "{0}", svhdl.ToSafeVHDLName()), target);
                }

                render.TypeLookup[wrapped] = VHDLTypes.INTEGER;

                if (target != VHDLTypes.INTEGER)
                {
                    wrapped = ConvertExpression(render, method, wrapped, target, targetsource, false);
                }

                return(wrapped);
            }
            else
            {
                throw new Exception(string.Format("Unexpected target type: {0} for source: {1}", target, svhdl));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Applies the transformation
        /// </summary>
        /// <returns>The transformed item.</returns>
        /// <param name="item">The item to visit.</param>
        public ASTItem Transform(ASTItem item)
        {
            var stm = item as AST.ForStatement;

            if (stm == null)
            {
                return(item);
            }

            if (m_processed.Contains(stm))
            {
                return(item);
            }
            m_processed.Add(stm);

            Tuple <int, int, int> loopedges = null;

            try
            {
                loopedges = stm.GetStaticForLoopValues();
            }
            catch
            {
                return(item);
            }

            var incr = loopedges.Item3;

            if (incr == 1)
            {
                return(item);
            }

            var tmp = State.RegisterTemporaryVariable(Method, stm.LoopIndex.CecilType);

            State.TypeLookup[tmp] = VHDLTypes.INTEGER;

            // Find the first expression, so we can inject the assignment before it
            var firstexp = stm.LoopBody.All().OfType <Expression>().First();

            // Replace all the references
            foreach (var x in stm.All().OfType <Expression>())
            {
                var target = x.GetTarget();
                if (target == stm.LoopIndex)
                {
                    x.SetTarget(tmp);
                }
            }

            var exp = firstexp.SourceExpression;

            // Inject the assignment
            var nstm = new ExpressionStatement()
            {
                Expression = new AssignmentExpression()
                {
                    Left = new IdentifierExpression()
                    {
                        Name             = tmp.Name,
                        Target           = tmp,
                        SourceExpression = exp,
                        SourceResultType = tmp.CecilType
                    },
                    Operator = ICSharpCode.Decompiler.CSharp.Syntax.AssignmentOperatorType.Assign,
                    Right    = new BinaryOperatorExpression()
                    {
                        Left = new IdentifierExpression()
                        {
                            Name             = stm.LoopIndex.Name,
                            Target           = stm.LoopIndex,
                            SourceExpression = exp,
                            SourceResultType = stm.LoopIndex.CecilType
                        },
                        Operator = ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorType.Multiply,
                        Right    = new PrimitiveExpression()
                        {
                            Value            = incr,
                            SourceResultType = tmp.CecilType,
                            SourceExpression = exp,
                        },
                        SourceExpression = exp,
                        SourceResultType = tmp.CecilType
                    },
                    SourceExpression = exp,
                    SourceResultType = tmp.CecilType
                }
            };

            nstm.UpdateParents();
            foreach (var x in nstm.All().OfType <Expression>())
            {
                State.TypeLookup[x] = VHDLTypes.INTEGER;
            }

            stm.LoopBody.PrependStatement(nstm);

            //Do not fix again
            stm.Increment = new AssignmentExpression(
                new IdentifierExpression(stm.LoopIndex),
                new BinaryOperatorExpression(
                    new IdentifierExpression(stm.LoopIndex),
                    ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorType.Add,
                    new PrimitiveExpression(1, tmp.CecilType)
                    )
            {
                SourceResultType = tmp.CecilType
            }
                )
            {
                Parent = stm, SourceResultType = tmp.CecilType
            };

            stm.Condition = new BinaryOperatorExpression(
                new IdentifierExpression(stm.LoopIndex),
                ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorType.LessThan,
                new PrimitiveExpression(loopedges.Item2 / loopedges.Item3, tmp.CecilType.Module.ImportReference(typeof(int)))
                )
            {
                Parent           = stm,
                SourceResultType = tmp.CecilType.Module.ImportReference(typeof(bool))
            };

            return(nstm);
        }
Esempio n. 4
0
        /// <summary>
        /// Applies the transformation
        /// </summary>
        /// <returns>The transformed item.</returns>
        /// <param name="el">The item to visit.</param>
        public ASTItem Transform(ASTItem el)
        {
            var uoe = el as UnaryOperatorExpression;

            if (uoe == null)
            {
                return(el);
            }

            var incr =
                new[] {
                ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.Increment,
                ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.Decrement,
                ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.PostIncrement,
                ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.PostDecrement
            }.Contains(uoe.Operator);

            if (!incr)
            {
                return(el);
            }


            var cnst = new PrimitiveExpression()
            {
                SourceExpression = uoe.SourceExpression,
                SourceResultType = uoe.SourceResultType.LoadType(typeof(int)),
                Value            = 1
            };

            State.TypeLookup[cnst] = VHDLTypes.INTEGER;

            var boe = new BinaryOperatorExpression()
            {
                Left             = uoe.Operand.Clone(),
                Right            = cnst,
                SourceExpression = uoe.SourceExpression,
                SourceResultType = uoe.SourceResultType,
                Operator         =
                    uoe.Operator == ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.Decrement
                    ||
                    uoe.Operator == ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.PostDecrement

                                   ? ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorType.Subtract
                                   : ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorType.Add
            };

            State.TypeLookup[boe] = State.VHDLType(uoe.Operand);

            // Prepare an assignment expresion
            var ase = new AssignmentExpression()
            {
                Left             = uoe.Operand.Clone(),
                Right            = boe,
                Operator         = ICSharpCode.Decompiler.CSharp.Syntax.AssignmentOperatorType.Assign,
                SourceExpression = uoe.SourceExpression,
                SourceResultType = uoe.SourceResultType
            };

            var exps = new ExpressionStatement()
            {
                Expression = ase,
            };

            exps.UpdateParents();

            if (uoe.Operator == ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.PostIncrement || uoe.Operator == ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorType.PostDecrement)
            {
                if (uoe.Parent is ExpressionStatement || uoe.Parent is ForStatement)
                {
                    // Simple "i++;" statements are replaced with i = i + 1
                    uoe.ReplaceWith(ase);
                    return(ase);
                }
                else
                {
                    // More complicated are split
                    uoe.AppendStatement(exps);

                    // Remove the operator now, as the assignment happens after
                    uoe.ReplaceWith(uoe.Operand);
                    return(exps);
                }
            }
            else
            {
                // If the left-hand-side is also the target, we can just replace
                // with the binary operator without needing a temporary variable
                if (uoe.Operand.GetTarget() != null && boe.Parent is AssignmentExpression && ((AssignmentExpression)boe.Parent).Left.GetTarget() == uoe.Operand.GetTarget())
                {
                    uoe.ReplaceWith(boe);
                    return(boe);
                }
                else
                {
                    // TODO: Can have more complex cases where
                    // the expression is use multiple times in the same statement and some need the updated version,
                    // others the non-updated version.
                    // To support this, we need to seek for references to the target
                    // and replace the references with the correct pre/post versions
                    uoe.PrependStatement(exps);
                    uoe.ReplaceWith(boe);
                    return(boe);
                }
            }
        }