コード例 #1
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Newarr:
                Typ arrayContentType;
                // The array is one-dimensional.
                if (instruction.Operand is TypeReference instructionType)
                {
                    arrayContentType = Typ.FromTypeReference(instructionType);
                }
                // Then the content type of the array is an array (it is multidimensional).
                else if (instruction.Operand is ArrayType instructionArrayType)
                {
                    // Creates a SIL representation of the array content type.
                    arrayContentType = CreateArrayType(
                        Typ.FromTypeReference(instructionArrayType.GetElementType()),
                        instructionArrayType.Rank, state);
                }
                else
                {
                    Log.WriteParserWarning(instruction.Operand, instruction, state);
                    return(false);
                }
                var arrayIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
                (var arrayLength, _) = state.Pop();

                var arrayLengthSizeofExp = new SizeofExpression(
                    new Tarray(arrayContentType),
                    SizeofExpression.SizeofExpressionKind.exact,
                    arrayLength);

                var arrayTypeWithPtr = new Tptr(Tptr.PtrKind.Pk_pointer,
                                                new Tarray(arrayContentType));

                var args = new List <Call.CallArg>
                {
                    new Call.CallArg(arrayLengthSizeofExp, arrayTypeWithPtr)
                };

                // Represents memory allocation.
                var callInstr = new Call(returnId: arrayIdentifier,
                                         returnType: arrayTypeWithPtr,
                                         functionExpression: new ConstExpression(
                                             ProcedureName.BuiltIn__new_array),
                                         args: args,
                                         flags: new Call.CallFlags(),
                                         location: state.CurrentLocation);
                var newNode = AddMethodBodyInstructionsToCfg(state, callInstr);
                state.PushExpr(new VarExpression(arrayIdentifier), arrayTypeWithPtr);
                state.PushInstruction(instruction.Next, newNode);
                return(true);

            default:
                return(false);
            }
        }
コード例 #2
0
        /// 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);
        }
コード例 #3
0
        /// <summary>
        /// Creates a <see cref="CfgNode"/> containing instructions for memory allocation as well
        /// as constructor invocation.
        /// </summary>
        /// <param name="type">The SIL type to be allocate memory for.</param>
        /// <param name="state">Current program state.</param>
        /// <returns>Node with the object allocation instructions, as well as the variable which
        /// represents the new object.</returns>
        protected static (CfgNode, VarExpression) CreateObjectAllocationNode(Tptr type,
                                                                             ProgramState state)
        {
            var typeName = type.StripPointer().ToString();

            var newObjectIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
            var newObjectVariable   = new VarExpression(newObjectIdentifier);
            var callFlags           = new Call.CallFlags(isVirtual: false,
                                                         noReturn: false,
                                                         isObjCBlock: false);
            var objectAllocationCall =
                new Call(newObjectIdentifier,
                         type,
                         new ConstExpression(ProcedureName.BuiltIn__new),
                         new List <Call.CallArg>
            {
                new Call.CallArg(
                    new SizeofExpression(
                        type.StripPointer(),
                        SizeofExpression.SizeofExpressionKind.exact),
                    type)
            },
                         callFlags,
                         state.CurrentLocation);

            var objectConstructorCall =
                new Call(state.GetIdentifier(Identifier.IdentKind.Normal),
                         new Tvoid(),
                         new ConstExpression(new ProcedureName(".ctor",
                                                               new List <string>(),
                                                               typeName,
                                                               "System.Void",
                                                               false)),
                         new List <Call.CallArg>
            {
                new Call.CallArg(newObjectVariable, type)
            },
                         callFlags,
                         state.CurrentLocation);

            var node = new StatementNode(state.CurrentLocation,
                                         StatementNode.StatementNodeKind.Call,
                                         state.ProcDesc,
                                         comment: $"System.Void {typeName}::.ctor()");

            node.Instructions.Add(objectAllocationCall);
            node.Instructions.Add(objectConstructorCall);

            return(node, newObjectVariable);
        }
コード例 #4
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Ldtoken:
                var    token = instruction.Operand;
                string runtimeHandleTypeString;

                if (token is TypeReference)
                {
                    runtimeHandleTypeString = "System.RuntimeTypeHandle";
                }
                else if (token is FieldReference)
                {
                    runtimeHandleTypeString = "System.RuntimeFieldHandle";
                }
                else if (token is MethodReference)
                {
                    runtimeHandleTypeString = "System.RuntimeMethodHandle";
                }
                else
                {
                    Log.WriteWarning($"Unexpected instruction operand {instruction.Operand}");
                    return(false);
                }
                var runtimeHandleType = new Tptr(Tptr.PtrKind.Pk_pointer,
                                                 new Tstruct(runtimeHandleTypeString));

                // In keeping with how we handle structs when translating Initobj, we
                // initialize an object in the SIL to represent the value type.
                (var node, var runtimeHandleVariable) = CreateObjectAllocationNode(
                    runtimeHandleType, state);

                RegisterNode(state, node);

                state.PushExpr(runtimeHandleVariable, runtimeHandleType);
                state.PushInstruction(instruction.Next, node);
                state.AppendToPreviousNode = true;
                return(true);

            default:
                return(false);
            }
        }
コード例 #5
0
        /// <summary>
        /// Creates a SIL array representation. Generates a SIL Tptr of Tarray around the input
        /// underlying type, with layers equal to the given <paramref name="dimensionCount"/>.
        /// </summary>
        /// <param name="arrayUnderlyingType">The type of the array's underlying elements (i.e. at
        /// the base dimension of the array). This typ must be encapsulated by a Tptr.</param>
        /// <param name="dimensionCount">Number of dimensions of the array. This must be greater
        /// than 0.</param>
        /// <param name="state">The program state.</param>
        /// <returns>SIL Tptr of Tarray for each dimension.</returns>
        /// <remarks>An example two-dimensional output with <paramref name="arrayUnderlyingType"/>
        /// object* would look like [[object*]*]*.</remarks>
        private Typ CreateArrayType(Typ arrayUnderlyingType,
                                    int dimensionCount,
                                    ProgramState state)
        {
            if (dimensionCount <= 0)
            {
                throw new ArgumentException(
                          state.GetStateDebugInformation(dimensionCount));
            }
            if (!(arrayUnderlyingType is Tptr))
            {
                throw new ArgumentException(
                          state.GetStateDebugInformation(arrayUnderlyingType));
            }
            var nextDimType = arrayUnderlyingType;

            for (var i = 0; i < dimensionCount; i++)
            {
                nextDimType = new Tptr(Tptr.PtrKind.Pk_pointer, new Tarray(nextDimType));
            }
            return(nextDimType);
        }
コード例 #6
0
        protected static CfgNode CreateFinallyExceptionExitNode(ProgramState state,
                                                                ExceptionHandler handler)
        {
            (_, var syntheticExceptionVariable) =
                GetHandlerCatchVarNode(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,
                                        syntheticExceptionVariable,
                                        exceptionType,
                                        GetHandlerEndLocation(state, handler));

            var exceptionReturnNode = CreateExceptionReturnNode(
                state,
                new VarExpression(exceptionIdentifier),
                GetHandlerEndLocation(state, handler));

            exceptionReturnNode.Instructions.Insert(0, catchVarLoad);
            state.Cfg.RegisterNode(exceptionReturnNode);
            state.PreviousNode.Successors.Add(exceptionReturnNode);
            return(exceptionReturnNode);
        }
コード例 #7
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            Tptr   arrayTypeWithPtr;
            Tarray arrayTypeNoPtr;

            switch (instruction.OpCode.Code)
            {
            case Code.Ldelem_Any:
            case Code.Ldelem_I:
            case Code.Ldelem_I1:
            case Code.Ldelem_I2:
            case Code.Ldelem_I4:
            case Code.Ldelem_I8:
            case Code.Ldelem_R4:
            case Code.Ldelem_R8:
            case Code.Ldelem_Ref:
                (var arrayIndex, _)   = state.Pop();
                (var array, var type) = state.Pop();

                if (!(array is VarExpression arrayVar) || !(type.StripPointer() is Tarray))
                {
                    Log.WriteParserWarning(array, instruction, state);
                    return(false);
                }
                // Type is either Tarray or a Tptr with a Tarray type underlying it.
                if (type is Tarray)
                {
                    arrayTypeWithPtr = new Tptr(Tptr.PtrKind.Pk_pointer, type);
                    arrayTypeNoPtr   = (Tarray)type;
                }
                else if (type is Tptr)
                {
                    arrayTypeWithPtr = (Tptr)type;
                    arrayTypeNoPtr   = (Tarray)type.StripPointer();
                }
                else
                {
                    Log.WriteParserWarning(type, instruction, state);
                    return(false);
                }

                var derefArray     = CreateDereference(arrayVar, arrayTypeWithPtr, state);
                var tempIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
                var arrayIndexLoad = new Load(identifierAssignedTo: tempIdentifier,
                                              lvalue: new LindexExpression(
                                                  array, arrayIndex),
                                              type: arrayTypeNoPtr.ContentType,
                                              location: state.CurrentLocation);

                var newNode = AddMethodBodyInstructionsToCfg(state,
                                                             derefArray,
                                                             arrayIndexLoad);

                state.PushExpr(new VarExpression(tempIdentifier),
                               arrayTypeNoPtr.ContentType);
                state.AppendToPreviousNode = true;
                state.PushInstruction(instruction.Next, newNode);
                return(true);
            }
            return(false);
        }
コード例 #8
0
ファイル: LdcParser.cs プロジェクト: ScriptBox21/infersharp
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            ConstExpression constExp = null;
            Typ             type     = null;

            switch (instruction.OpCode.Code)
            {
            case Code.Ldc_I4_M1:
                (constExp, type) = MakeInt(-1);
                break;

            case Code.Ldc_I4:
                (constExp, type) = MakeInt((int)instruction.Operand);
                break;

            case Code.Ldc_I4_S:
                (constExp, type) = MakeInt((sbyte)instruction.Operand);
                break;

            case Code.Ldc_I4_0:
                (constExp, type) = MakeInt(0);
                break;

            case Code.Ldc_I4_1:
                (constExp, type) = MakeInt(1);
                break;

            case Code.Ldc_I4_2:
                (constExp, type) = MakeInt(2);
                break;

            case Code.Ldc_I4_3:
                (constExp, type) = MakeInt(3);
                break;

            case Code.Ldc_I4_4:
                (constExp, type) = MakeInt(4);
                break;

            case Code.Ldc_I4_5:
                (constExp, type) = MakeInt(5);
                break;

            case Code.Ldc_I4_6:
                (constExp, type) = MakeInt(6);
                break;

            case Code.Ldc_I4_7:
                (constExp, type) = MakeInt(7);
                break;

            case Code.Ldc_I4_8:
                (constExp, type) = MakeInt(8);
                break;

            case Code.Ldc_I8:
                (constExp, _) = MakeInt((long)instruction.Operand);
                type          = new Tint(Tint.IntKind.ILongLong);
                break;

            case Code.Ldc_R4:
                constExp = new ConstExpression((float)instruction.Operand);
                type     = new Tfloat(Tfloat.FloatKind.FFloat);
                break;

            case Code.Ldc_R8:
                constExp = new ConstExpression((double)instruction.Operand);
                type     = new Tfloat(Tfloat.FloatKind.FDouble);
                break;

            case Code.Ldstr:
                constExp = new ConstExpression((string)instruction.Operand);
                type     = new Tptr(Tptr.PtrKind.Pk_pointer, new Tstruct("System.String"));
                break;

            default:
                return(false);
            }

            state.PushExpr(constExp, type);
            state.PushInstruction(instruction.Next);

            return(true);
        }