Example #1
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            var fieldReference = instruction.Operand as FieldReference;
            // An object expression for an instance field and a class expression for a static
            // field.
            Expression fieldParentExpression;
            // The expression to set the field to.
            Expression expressionToStore;

            switch (instruction.OpCode.Code)
            {
            case Code.Stfld:
                (expressionToStore, _)     = state.Pop();
                (fieldParentExpression, _) = state.Pop();
                break;

            case Code.Stsfld:
                (expressionToStore, _) = state.Pop();
                fieldParentExpression  = new LvarExpression(
                    new GlobalVariable(fieldReference.DeclaringType.GetCompatibleFullName()));
                break;

            default:
                return(false);
            }
            var fieldStore = new Store(CreateFieldExpression(fieldParentExpression, fieldReference),
                                       expressionToStore,
                                       Typ.FromTypeReferenceNoPointer(fieldReference.DeclaringType),
                                       state.CurrentLocation);
            var node = AddMethodBodyInstructionsToCfg(state, fieldStore);

            state.PushInstruction(instruction.Next, node);
            return(true);
        }
        /// TODO: Need to add is_csharp to Pvar.ml to parse CatchVar accordingly.
        /// <summary>
        /// Helper method for creating a component of the entry block to exception-handling blocks,
        /// in which the thrown exception stored in the CatchVar is handled.
        /// </summary>
        /// <param name="state">The program state.</param>
        /// <param name="handler">The exception handler for which the node is being
        /// created.</param>
        /// <returns>The node in which the caught exception variable is loaded, as well as the
        /// synthetic exception variable created, if the handler is finally.</returns>
        private static (CfgNode, LvarExpression) CreateLoadCatchVarNode(ProgramState state,
                                                                        ExceptionHandler handler)
        {
            LvarExpression syntheticExceptionVariable = null;
            var            handlerStartLocation       = GetHandlerStartLocation(state, handler);
            var            exceptionIdentifier        = state.GetIdentifier(Identifier.IdentKind.Normal);
            var            exceptionType = new Tptr(Tptr.PtrKind.Pk_pointer, new Tstruct("System.Object"));

            var catchVarLoad = new Load(exceptionIdentifier,
                                        GetHandlerCatchVar(state, handler),
                                        exceptionType,
                                        handlerStartLocation);

            var node = new StatementNode(location: handlerStartLocation,
                                         kind: StatementNode.StatementNodeKind.MethodBody,
                                         proc: state.ProcDesc);

            node.Instructions.Add(catchVarLoad);
            switch (handler.HandlerType)
            {
            case ExceptionHandlerType.Catch:
                state.AppendToPreviousNode = true;
                break;

            case ExceptionHandlerType.Finally:
                // In this case, the exception catch variable is stored into a synthetic
                // variable we create here.
                syntheticExceptionVariable =
                    new LvarExpression(new LocalVariable(state.GetSyntheticVariableName(),
                                                         state.Method));
                var storeIntoSyntheticVariable = new Store(
                    syntheticExceptionVariable,
                    new VarExpression(exceptionIdentifier),
                    exceptionType,
                    handlerStartLocation);
                node.Instructions.Add(storeIntoSyntheticVariable);
                (var entryNode, _) = GetHandlerEntryNode(state, handler);
                var finallyBranchNode = CreateFinallyExceptionBranchNode(state, handler);
                entryNode.Successors.Add(finallyBranchNode);
                finallyBranchNode.Successors.Add(node);

                node.ExceptionNodes.Add(entryNode);

                state.FinallyExceptionalTranslation = true;
                state.PushInstruction(handler.HandlerStart, node);
                state.FinallyExceptionalTranslation = false;
                break;

            default:
                return(null, null);
            }
            state.Cfg.RegisterNode(node);
            return(node, syntheticExceptionVariable);
        }
        /// <summary>
        /// Creates an entry node for representing exceptional control flow into an exception
        /// handler; in it, the return value is nullified and the unwrap exception function is
        /// applied to it, which causes the exception to be stored in a catch variable.
        /// </summary>
        /// <param name="state">The state.</param>
        /// <param name="handler">The exception handler for which the node is being
        /// created.</param>
        /// <returns>The created entry node, as well as the identifier in which the exception is
        /// stored.</returns>
        private static (CfgNode, Identifier) CreateExceptionEntryNode(ProgramState state,
                                                                      ExceptionHandler handler)
        {
            var handlerStartLocation = GetHandlerStartLocation(state, handler);
            var returnIdentifier     = state.GetIdentifier(Identifier.IdentKind.Normal);
            var returnExpression     = new LvarExpression(
                new LocalVariable(Identifier.ReturnIdentifier, state.Method));
            var returnType = Typ.FromTypeReference(state.Method.ReturnType);

            var getReturnValue = new Load(returnIdentifier,
                                          returnExpression,
                                          returnType,
                                          handlerStartLocation);
            var deactivateException = new Store(returnExpression,
                                                new ConstExpression(
                                                    new IntRepresentation(0, false, true)),
                                                returnType,
                                                handlerStartLocation);

            var exceptionIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
            var unwrapReturnValue   = new Call(exceptionIdentifier,
                                               returnType,
                                               new ConstExpression(
                                                   ProcedureName.BuiltIn__unwrap_exception),
                                               new List <Call.CallArg>
            {
                new Call.CallArg(
                    new VarExpression(returnIdentifier),
                    returnType)
            },
                                               new Call.CallFlags(),
                                               handlerStartLocation);

            var node = new StatementNode(handlerStartLocation,
                                         StatementNode.StatementNodeKind.ExceptionHandler,
                                         state.ProcDesc);

            node.Instructions = new List <SilInstruction> {
                getReturnValue,
                deactivateException,
                unwrapReturnValue
            };
            state.Cfg.RegisterNode(node);
            return(node, exceptionIdentifier);
        }
        /// <summary>
        /// Creates a node for returning an exceptional value; does not register the node in the
        /// CFG.
        /// </summary>
        /// <param name="state">The state.</param>
        /// <param name="returnValue">The exceptional value to be returned.</param>
        /// <param name="location">The location.</param>
        /// <returns></returns>
        protected static CfgNode CreateExceptionReturnNode(ProgramState state,
                                                           Expression returnValue,
                                                           Location location)
        {
            var retType = state.Method.ReturnType.GetElementType();
            var retNode = new StatementNode(location,
                                            StatementNode.StatementNodeKind.ReturnStmt,
                                            state.ProcDesc);
            var returnVariable = new LvarExpression(new LocalVariable(Identifier.ReturnIdentifier,
                                                                      state.Method));
            var retInstr = new Store(returnVariable,
                                     new ExnExpression(returnValue),
                                     Typ.FromTypeReference(retType),
                                     location);

            retNode.Instructions.Add(retInstr);
            retNode.Successors = new List <CfgNode> {
                state.ProcDesc.ExitNode
            };
            return(retNode);
        }
Example #5
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Ret:
                var retType = state.Method.ReturnType.GetElementType();
                if (retType == state.Method.Module.TypeSystem.Void)
                {
                    state.PreviousNode.Successors.Add(state.ProcDesc.ExitNode);
                }
                else
                {
                    (var returnValue, _) = state.Pop();
                    Expression returnVariable = new LvarExpression(
                        new LocalVariable(Identifier.ReturnIdentifier,
                                          state.Method));
                    var retInstr = new Store(lvalue: returnVariable,
                                             rvalue: returnValue,
                                             type: Typ.FromTypeReference(retType),
                                             location: state.CurrentLocation);
                    var retNode = new StatementNode(state.CurrentLocation,
                                                    StatementNode.StatementNodeKind.ReturnStmt,
                                                    state.ProcDesc);
                    retNode.Instructions.Add(retInstr);
                    retNode.Successors = new List <CfgNode> {
                        state.ProcDesc.ExitNode
                    };
                    RegisterNode(state, retNode);
                }
                return(true);

            default:
                return(false);
            }
        }
Example #6
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Ret:
                Store retInstr;
                var   retType = state.Method.ReturnType.GetElementType();
                var   retNode = new StatementNode(state.CurrentLocation,
                                                  StatementNode.StatementNodeKind.ReturnStmt,
                                                  state.ProcDesc);
                if (retType == state.Method.Module.TypeSystem.Void)
                {
                    state.PreviousNode.Successors.Add(state.ProcDesc.ExitNode);
                }
                else
                {
                    (var returnValue, _) = state.Pop();
                    Expression returnVariable = new LvarExpression(
                        new LocalVariable(Identifier.ReturnIdentifier,
                                          state.Method));

                    if (returnValue is BinopExpression)
                    {
                        // We see that for the auto-generated method op_Inequality in records,
                        // an equality expression is pushed directly onto the stack and
                        // returned. However, return of an expression is not valid in the SIL --
                        // we must inline a variable store and load of the value prior to
                        // subsequently returning it.
                        var inlineReturn     = new LocalVariable("inlineReturn", state.Method);
                        var inlineIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);

                        var storeInlineReturn = new Store(new LvarExpression(inlineReturn),
                                                          returnValue,
                                                          Typ.FromTypeReference(retType),
                                                          state.CurrentLocation);
                        AddMethodBodyInstructionsToCfg(state, storeInlineReturn);

                        var loadInlineReturn = new Load(inlineIdentifier,
                                                        new LvarExpression(inlineReturn),
                                                        Typ.FromTypeReference(retType),
                                                        state.CurrentLocation);
                        AddMethodBodyInstructionsToCfg(state, loadInlineReturn);

                        retInstr = new Store(returnVariable,
                                             new VarExpression(inlineIdentifier),
                                             Typ.FromTypeReference(retType),
                                             state.CurrentLocation);
                    }
                    else
                    {
                        retInstr = new Store(returnVariable,
                                             returnValue,
                                             Typ.FromTypeReference(retType),
                                             state.CurrentLocation);
                    }
                    retNode.Instructions.Add(retInstr);
                    retNode.Successors = new List <CfgNode> {
                        state.ProcDesc.ExitNode
                    };
                    RegisterNode(state, retNode);
                }
                return(true);

            default:
                return(false);
            }
        }
Example #7
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            var field = instruction.Operand as FieldReference;
            // An object expression for an instance field and a class expression for a static
            // field.
            Expression fieldOwnerExpression;
            Typ        fieldType;

            switch (instruction.OpCode.Code)
            {
            case Code.Ldfld:
            case Code.Ldflda:
                (var objectExpression, var objectExpressionType) = state.Pop();
                // Handles the case in which the address of the owning object is on the stack.
                if (objectExpressionType is Address address)
                {
                    // The value at the address is the parent expression, matching how the
                    // field is initialized.
                    var addressValueIdentifier = state.GetIdentifier(
                        Identifier.IdentKind.Normal);
                    state.PreviousNode.Instructions.Add(
                        new Load(addressValueIdentifier,
                                 address.Value,
                                 Typ.FromTypeReferenceNoPointer(field.DeclaringType),
                                 state.CurrentLocation));
                    fieldOwnerExpression = new VarExpression(addressValueIdentifier);
                }
                // The expression represents the object itself.
                else
                {
                    fieldOwnerExpression = objectExpression;
                }
                break;

            case Code.Ldsfld:
            case Code.Ldsflda:
                fieldOwnerExpression = new LvarExpression(
                    new GlobalVariable(field.DeclaringType.GetCompatibleFullName()));
                break;

            default:
                return(false);
            }
            // An identifier to store the field expression.
            var fieldIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);

            fieldType = Typ.FromTypeReferenceNoPointer(field.FieldType);
            var fieldExpression = CreateFieldExpression(fieldOwnerExpression, field);

            if (instruction.OpCode.Code == Code.Ldfld || instruction.OpCode.Code == Code.Ldsfld)
            {
                state.PreviousNode.Instructions.Add(new Load(fieldIdentifier,
                                                             fieldExpression,
                                                             Typ.FromTypeReferenceNoPointer(
                                                                 field.DeclaringType),
                                                             state.CurrentLocation));
                state.AppendToPreviousNode = true;
                state.PushExpr(new VarExpression(fieldIdentifier), fieldType);
            }
            // Instruction is either Ldflda or Ldsflda.
            else
            {
                var fieldAddressVariableType =
                    new Address(Tptr.PtrKind.Pk_pointer,
                                Typ.FromTypeReferenceNoPointer(
                                    field.FieldType),
                                fieldExpression,
                                referenceKind: Address.ReferenceKind.Field);
                state.PushExpr(fieldExpression, fieldAddressVariableType);
            }
            state.PushInstruction(instruction.Next);
            return(true);
        }
        protected static void CreateCatchHandlerEntryBlock(ProgramState state,
                                                           ExceptionHandlerNode handlerNode,
                                                           CfgNode handlerEntryPredecessor,
                                                           Identifier exceptionIdentifier)
        {
            (var trueBranch, var falseBranch) = CreateExceptionTypeCheckBranchNodes(
                state, handlerNode.ExceptionHandler, exceptionIdentifier);
            handlerEntryPredecessor.Successors.Add(trueBranch);
            handlerEntryPredecessor.Successors.Add(falseBranch);

            if (!state.ExceptionHandlerToCatchVarNode.ContainsKey(handlerNode.ExceptionHandler))
            {
                state.ExceptionHandlerToCatchVarNode[handlerNode.ExceptionHandler] =
                    CreateLoadCatchVarNode(state, handlerNode.ExceptionHandler);
                // The CIL specification dictates that the exception object is on top of
                // the stack when the catch handler is entered; the first instruction of
                // the catch handler will handle the object pushed onto the stack.
                state.PushExpr(new VarExpression(exceptionIdentifier),
                               new Tptr(Tptr.PtrKind.Pk_pointer,
                                        new Tstruct("System.Object")));
                state.PushInstruction(
                    handlerNode.ExceptionHandler.HandlerStart,
                    state.ExceptionHandlerToCatchVarNode[handlerNode.ExceptionHandler].node);
            }
            (var loadCatchVarNode, _) = GetHandlerCatchVarNode(
                state, handlerNode.ExceptionHandler);
            trueBranch.Successors.Add(loadCatchVarNode);

            if (handlerNode.NextCatchBlock != null)
            {
                // Continues translation with catch handler's first instruction from
                // the handler's catch variable load node.
                CreateCatchHandlerEntryBlock(state,
                                             handlerNode.NextCatchBlock,
                                             falseBranch,
                                             exceptionIdentifier);
            }
            // Last catch handler of set; need to route control flow through the false
            // exception type-matching node.
            else
            {
                if (handlerNode.FinallyBlock != null)
                {
                    var finallyBranchNode = CreateFinallyExceptionBranchNode(
                        state, handlerNode.ExceptionHandler);
                    falseBranch.Successors
                    .Add(finallyBranchNode);
                    (var finallyLoadCatchVar, _) = GetHandlerCatchVarNode(
                        state, handlerNode.FinallyBlock);
                    finallyBranchNode.Successors.Add(finallyLoadCatchVar);
                }
                else
                {
                    var returnVariable = new LvarExpression(
                        new LocalVariable(Identifier.ReturnIdentifier, state.Method));
                    var retType  = state.Method.ReturnType.GetElementType();
                    var retInstr = new Store(
                        returnVariable,
                        new ExnExpression(new VarExpression(exceptionIdentifier)),
                        Typ.FromTypeReference(retType),
                        GetHandlerStartLocation(state,
                                                handlerNode.ExceptionHandler));
                    falseBranch.Instructions
                    .Add(retInstr);
                    falseBranch.Successors
                    .Add(state.ProcDesc.ExceptionSinkNode);
                }
            }
        }