示例#1
0
        /// <summary>
        /// Returns a <see cref="Call"/> instruction denoting either the beginning or end of a
        /// program section guarded by a monitor, depending on whether the locked attribute is
        /// respectively set or deleted.
        /// </summary>
        /// <param name="setLockedAttribute"></param>
        /// <param name="paramCount"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private static Call CreateLockedAttributeCall(
            bool setLockedAttribute, int paramCount, ProgramState state)
        {
            var returnIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
            var callFlags        = new Call.CallFlags(isVirtual: false,
                                                      noReturn: false,
                                                      isObjCBlock: false);

            // There are up to two arguments (monitor object and a boolean indicating the result of
            // the attempt to acquire the lock, passed by reference), but the latter need only be
            // removed from the stack without being reflected in the translation.
            var arg      = state.PopMany(paramCount).First();
            var callArgs = new List <Call.CallArg> {
                new Call.CallArg(arg.Item1, arg.Item2)
            };

            return(setLockedAttribute ? new Call(returnIdentifier,
                                                 new Tvoid(),
                                                 new ConstExpression(
                                                     ProcedureName.BuiltIn__set_locked_attribute),
                                                 callArgs,
                                                 callFlags,
                                                 state.CurrentLocation)
                                     : new Call(returnIdentifier,
                                                new Tvoid(),
                                                new ConstExpression(
                                                    ProcedureName.
                                                    BuiltIn__delete_locked_attribute),
                                                callArgs,
                                                callFlags,
                                                state.CurrentLocation));
        }
        /// <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);
        }
示例#3
0
        /// <summary>
        /// Creates and returns a <see cref="Call"/> instruction indicating object memory
        /// allocation and the temporary identifier for the new object. Examples of CIL
        /// instructions for which this method is used include initobj and newobj.
        /// </summary>
        /// <param name="newObjectReference">The type to be allocated.</param>
        /// <param name="state">Current program state.</param>
        /// <returns>Instruction representing the memory allocation, as well as the identifier for
        /// the new object.</returns>
        protected static (Call, VarExpression) CreateMemoryAllocationCall(
            TypeReference newObjectReference, ProgramState state)
        {
            var type = Typ.FromTypeReference(newObjectReference);
            var newObjectIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
            var callFlags           = new Call.CallFlags(isVirtual: false,
                                                         noReturn: false,
                                                         isObjCBlock: false);
            var args = new List <Call.CallArg>
            {
                new Call.CallArg(new SizeofExpression(type.StripPointer(), "exact"), type)
            };

            return(new Call(newObjectIdentifier,
                            type,
                            new ConstExpression(ProcedureName.BuiltIn__new),
                            args,
                            callFlags,
                            state.CurrentLocation),
                   new VarExpression(newObjectIdentifier));
        }
示例#4
0
        /// <summary>
        /// Creates a method call returned via out parameter.
        /// </summary>
        /// <param name="state">Current program state.</param>
        /// <param name="isVirtual">True if method call is virtual, false otherwise.</param>
        /// <param name="calledMethod">The method being called.</param>
        /// <param name="returnType">The return type of the method being called.</param>
        /// <param name="returnVariable">Identifies the variable returned by the method.</param>
        /// <param name="callArgs">The method arguments.</param>
        /// <param name="methodCall">The Call SIL instruction.</param>
        /// <param name="isConstructorCall"><c>true</c> if the call is for a constructor,
        /// <c>false</c> otherwise.</param>
        protected static void CreateMethodCall(ProgramState state,
                                               bool isVirtual,
                                               MethodReference calledMethod,
                                               out TypeReference returnType,
                                               out Identifier returnVariable,
                                               out List <Call.CallArg> callArgs,
                                               out Call methodCall,
                                               bool isConstructorCall = false)
        {
            callArgs   = new List <Call.CallArg>();
            returnType = calledMethod.ReturnType;
            var paramCount = calledMethod.Parameters.Count;

            if (calledMethod.HasThis)
            {
                paramCount++;
            }
            if (isConstructorCall)
            {
                // In this case, the "this" argument of the constructor is located at the top of
                // the stack; we remove it and place it at the front of the argument list.
                (var thisExpr, var thisType) = state.Pop();
                callArgs.Add(new Call.CallArg(thisExpr, thisType));
                paramCount--;
            }
            var funcExp = new ConstExpression(new ProcedureName(calledMethod));

            callArgs.AddRange(state.PopMany(paramCount)
                              .Select(p => new Call.CallArg(p.Item1, p.Item2))
                              .ToList());
            var callFlags = new Call.CallFlags(isVirtual, false, false);

            returnVariable = state.GetIdentifier(Identifier.IdentKind.Normal);
            methodCall     = new Call(returnId: returnVariable,
                                      returnType: Typ.FromTypeReference(returnType),
                                      functionExpression: funcExp,
                                      args: callArgs,
                                      flags: callFlags,
                                      location: state.CurrentLocation);
        }
示例#5
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Box:
                (var value, var type) = state.Pop();

                var boxedValueIdentifier = state.GetIdentifier(Identifier.IdentKind.Normal);
                var boxedObjectVariable  = new VarExpression(boxedValueIdentifier);
                var boxedObjectType      = new BoxedValueType(Tptr.PtrKind.Pk_pointer,
                                                              new Tstruct("System.Object"),
                                                              value,
                                                              type);
                var callFlags = new Call.CallFlags(false, false, false);

                // The value in question is boxed into a generic object.
                var objectAllocationCall =
                    new Call(boxedValueIdentifier,
                             boxedObjectType,
                             new ConstExpression(ProcedureName.BuiltIn__new),
                             new List <Call.CallArg>
                {
                    new Call.CallArg(
                        new SizeofExpression(
                            boxedObjectType.StripPointer(), "exact"),
                        boxedObjectType)
                },
                             callFlags,
                             state.CurrentLocation);

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

                var node = new StatementNode(state.CurrentLocation,
                                             StatementNode.StatementNodeKind.Call,
                                             state.ProcDesc,
                                             comment: "System.Void System.Object::.ctor()");
                node.Instructions.Add(objectAllocationCall);
                node.Instructions.Add(objectConstructorCall);
                RegisterNode(state, node);

                state.PushExpr(boxedObjectVariable, boxedObjectType);
                state.PushInstruction(instruction.Next, node);
                state.AppendToPreviousNode = true;

                return(true);

            default:
                return(false);
            }
        }