Beispiel #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);
        }
Beispiel #2
0
 /// <summary>
 /// Creates a field expression given an expression for the field's parent as well as the
 /// field reference.
 /// </summary>
 /// <param name="fieldParentExpression">An expression for the parent of the field;
 /// represents a class for a static field, and an instance of the class for an instance
 /// field.</param>
 /// <param name="fieldReference">A <see cref="FieldReference"/> which describes the field
 /// for which the expression is being created.</param>
 /// <returns>The <see cref="LfieldExpression"/> for the given field.</returns>
 protected static LfieldExpression CreateFieldExpression(Expression fieldParentExpression,
                                                         FieldReference fieldReference)
 {
     return(new LfieldExpression(fieldParentExpression,
                                 new FieldIdentifier(fieldReference.GetCompatibleFullName(),
                                                     Typ.FromTypeReferenceNoPointer(
                                                         fieldReference.FieldType)),
                                 Typ.FromTypeReferenceNoPointer(
                                     fieldReference.DeclaringType)));
 }
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            // Note that if unbox is applied on an object which is interprocedurally returned,
            // the object on the stack will not be a boxedValueType and unbox will fail. This
            // is a result of being unable to statically verify the type of the boxed object.
            case Code.Unbox:
            case Code.Unbox_Any:
                (_, var objType) = state.Pop();
                if (objType is BoxedValueType boxedValueType)
                {
                    var value     = boxedValueType.BoxedVal;
                    var valueType = boxedValueType.BoxedValType;
                    if (instruction.OpCode.Code == Code.Unbox)
                    {
                        state.PushExpr(value, new Address(Tptr.PtrKind.Pk_pointer,
                                                          valueType,
                                                          value));
                    }
                    else if (instruction.OpCode.Code == Code.Unbox_Any)
                    {
                        state.PushExpr(value, valueType);
                    }
                }
                else
                {
                    var type = instruction.Operand as TypeReference;
                    if (type != null)
                    {
                        var silType           = Typ.FromTypeReferenceNoPointer(type);
                        var defaultBoxedValue = GetDefaultBoxedValue(silType);
                        if (defaultBoxedValue != null)
                        {
                            state.PushExpr(defaultBoxedValue, silType);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
                state.PushInstruction(instruction.Next);
                return(true);

            default:
                return(false);
            }
        }
Beispiel #4
0
        private void InitializeStruct(VarExpression fieldParentVariable,
                                      TypeDefinition parentTypeDefinition,
                                      List <SilInstruction> structFieldInitializationInstructions,
                                      ProgramState state,
                                      HashSet <TypeDefinition> parentTypeDefinitions)
        {
            foreach (var fieldReference in parentTypeDefinition.Fields)
            {
                var fieldExpression = CreateFieldExpression(fieldParentVariable, fieldReference);

                var defaultValue = GetDefaultValue(fieldReference.FieldType);

                // Struct field; the default value must be recursively filled.
                if (fieldReference.FieldType is TypeDefinition fieldTypeDefinition &&
                    fieldTypeDefinition.BaseType != null &&
                    fieldTypeDefinition.BaseType.FullName == "System.ValueType")
                {
                    if (parentTypeDefinitions.Contains(fieldTypeDefinition))
                    {
                        throw new Exception("Unable to handle cyclical struct type " +
                                            $"{fieldTypeDefinition.FullName}");
                    }

                    // Allocates the struct field and stores it into the parent.
                    (var structFieldMemoryAllocationCall, var structFieldVariable) =
                        CreateMemoryAllocationCall(fieldTypeDefinition, state);
                    structFieldInitializationInstructions.Add(structFieldMemoryAllocationCall);
                    structFieldInitializationInstructions.Add(
                        new Store(fieldExpression,
                                  structFieldVariable,
                                  Typ.FromTypeReferenceNoPointer(fieldReference.DeclaringType),
                                  state.CurrentLocation));

                    // Add the field to the parent definitions before recursing; remove after
                    // recursive call returns.
                    parentTypeDefinitions.Add(fieldTypeDefinition);
                    // Recursively initializes the struct field.
                    InitializeStruct(structFieldVariable,
                                     fieldTypeDefinition,
                                     structFieldInitializationInstructions,
                                     state,
                                     parentTypeDefinitions);
                    parentTypeDefinitions.Remove(fieldTypeDefinition);
                }
Beispiel #5
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Isinst:
                (var objectExpression, var objectType) = state.Pop();
                var typeToCheck               = instruction.Operand as TypeReference;
                var returnIdentifier          = state.GetIdentifier(Identifier.IdentKind.Normal);
                var returnType                = new Tint(Tint.IntKind.IBool, true);
                var builtinFunctionExpression = new ConstExpression(
                    ProcedureName.BuiltIn__instanceof);
                var sizeofExpression = new SizeofExpression(
                    Typ.FromTypeReferenceNoPointer(typeToCheck),
                    SizeofExpression.SizeofExpressionKind.instof);
                var args = new List <Call.CallArg>
                {
                    new Call.CallArg(objectExpression, objectType),
                    new Call.CallArg(sizeofExpression, new Tvoid())
                };
                var callInstruction = new Call(
                    returnIdentifier,
                    returnType,
                    builtinFunctionExpression,
                    args,
                    new Call.CallFlags(),
                    state.CurrentLocation);
                var newNode = AddMethodBodyInstructionsToCfg(state, callInstruction);
                state.PushExpr(new VarExpression(returnIdentifier), returnType);
                state.PushInstruction(instruction.Next, newNode);
                return(true);

            default:
                return(false);
            }
        }
Beispiel #6
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 (CfgNode, CfgNode) CreateExceptionTypeCheckBranchNodes(
            ProgramState state, ExceptionHandler handler, Identifier exceptionIdentifier)
        {
            var handlerStartLocation = GetHandlerStartLocation(state, handler);
            var exceptionExpression  = new VarExpression(exceptionIdentifier);
            var isInstIdentifier     = state.GetIdentifier(Identifier.IdentKind.Normal);
            var isInstArgs           = new List <Call.CallArg>
            {
                new Call.CallArg(exceptionExpression,
                                 Typ.FromTypeReference(handler.CatchType)),
                new Call.CallArg(
                    new SizeofExpression(
                        Typ.FromTypeReferenceNoPointer(handler.CatchType),
                        SizeofExpression.SizeofExpressionKind.exact),
                    new Tvoid())
            };
            // We don't mark the function output as an isinst output, as there is no load or store
            // of it.
            var isInstCall = new Call(isInstIdentifier,
                                      new Tint(Tint.IntKind.IBool),
                                      new ConstExpression(ProcedureName.BuiltIn__instanceof),
                                      isInstArgs,
                                      new Call.CallFlags(),
                                      handlerStartLocation);

            var isInstOutputExpression = new VarExpression(isInstIdentifier);
            var pruneTrueInstruction   = new Prune(isInstOutputExpression,
                                                   true,
                                                   Prune.IfKind.Ik_switch,
                                                   handlerStartLocation);

            var pruneFalseInstruction = new Prune(new UnopExpression(UnopExpression.UnopKind.LNot,
                                                                     isInstOutputExpression,
                                                                     null),
                                                  false,
                                                  Prune.IfKind.Ik_switch,
                                                  handlerStartLocation);

            var setCatchVarInstruction = new Store(GetHandlerCatchVar(state, handler),
                                                   exceptionExpression,
                                                   Typ.FromTypeReference(state.Method.ReturnType),
                                                   handlerStartLocation);

            var pruneTrueNode = new PruneNode(handlerStartLocation,
                                              true,
                                              PruneNode.PruneNodeKind.ExceptionHandler,
                                              Prune.IfKind.Ik_switch,
                                              state.ProcDesc);

            var pruneFalseNode = new PruneNode(handlerStartLocation,
                                               false,
                                               PruneNode.PruneNodeKind.ExceptionHandler,
                                               Prune.IfKind.Ik_switch,
                                               state.ProcDesc);


            pruneTrueNode.Instructions.AddRange(new List <SilInstruction>
            {
                isInstCall, pruneTrueInstruction, setCatchVarInstruction
            });

            pruneFalseNode.Instructions.AddRange(new List <SilInstruction>
            {
                isInstCall, pruneFalseInstruction
            });
            pruneTrueNode.BlockEndOffset = state.MethodExceptionHandlers
                                           .GetBlockEndOffsetFromOffset(
                state.CurrentInstruction.Offset);
            pruneFalseNode.BlockEndOffset = state.MethodExceptionHandlers
                                            .GetBlockEndOffsetFromOffset(
                state.CurrentInstruction.Offset);
            state.Cfg.RegisterNode(pruneTrueNode);
            state.Cfg.RegisterNode(pruneFalseNode);
            return(pruneTrueNode, pruneFalseNode);
        }