예제 #1
0
        /// <summary>
        /// For a shared (canonical) instance method on a generic valuetype, gets a method that can be used to call the
        /// method given a boxed version of the generic valuetype as 'this' pointer.
        /// </summary>
        public MethodDesc GetSpecialUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk)
        {
            Debug.Assert(targetMethod.IsSharedByGenericInstantiations);
            Debug.Assert(!targetMethod.Signature.IsStatic);
            Debug.Assert(!targetMethod.HasInstantiation);

            TypeDesc owningType = targetMethod.OwningType;

            Debug.Assert(owningType.IsValueType);

            var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition();

            // Get a reference type that has the same layout as the boxed valuetype.
            var            typeKey             = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk);
            BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey);

            // Get a method on the reference type with the same signature as the target method (but different
            // calling convention, since 'this' will be a reference type).
            var targetMethodDefinition = targetMethod.GetTypicalMethodDefinition();
            var methodKey = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition);
            GenericUnboxingThunk thunkDefinition = _unboxingThunkHashtable.GetOrCreateValue(methodKey);

            // Find the thunk on the instantiated version of the reference type.
            Debug.Assert(owningType != owningTypeDefinition);
            InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation);

            MethodDesc thunk = GetMethodForInstantiatedType(thunkDefinition, boxedType);

            Debug.Assert(!thunk.HasInstantiation);

            return(thunk);
        }
예제 #2
0
        protected override bool ParseCilInstructionInternal(Instruction instruction,
                                                            ProgramState state)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Box:
                (var value, var type) = state.Pop();

                var boxedObjectType = new BoxedValueType(Tptr.PtrKind.Pk_pointer,
                                                         new Tstruct("System.Object"),
                                                         value,
                                                         type);

                // The value in question is boxed into a generic object, which we allocate.
                (var node, var boxedObjectVariable) = CreateObjectAllocationNode(
                    boxedObjectType, state);

                RegisterNode(state, node);

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

            default:
                return(false);
            }
        }
        public MethodDesc GetUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk)
        {
            TypeDesc owningType = targetMethod.OwningType;

            Debug.Assert(owningType.IsValueType);

            var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition();

            // Get a reference type that has the same layout as the boxed valuetype.
            var            typeKey             = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk);
            BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey);

            // Get a method on the reference type with the same signature as the target method (but different
            // calling convention, since 'this' will be a reference type).
            var           targetMethodDefinition = targetMethod.GetTypicalMethodDefinition();
            var           methodKey       = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition);
            UnboxingThunk thunkDefinition = _nonGenericUnboxingThunkHashtable.GetOrCreateValue(methodKey);

            // Find the thunk on the instantiated version of the reference type.
            if (owningType != owningTypeDefinition)
            {
                InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation);
                MethodDesc       thunk     = GetMethodForInstantiatedType(thunkDefinition, boxedType);
                //TODO: this might be triggered by a struct that implements an interface with a generic method
                Debug.Assert(!thunk.HasInstantiation);
                return(thunk);
            }
            else
            {
                //TODO: this might be triggered by a struct that implements an interface with a generic method
                Debug.Assert(!thunkDefinition.HasInstantiation);
                return(thunkDefinition);
            }
        }
예제 #4
0
            public UnboxingThunk(BoxedValueType owningType, MethodDesc targetMethod)
            {
                Debug.Assert(targetMethod.OwningType.IsValueType);
                Debug.Assert(!targetMethod.Signature.IsStatic);

                _owningType   = owningType;
                _targetMethod = targetMethod;
            }
예제 #5
0
            public GenericUnboxingThunk(BoxedValueType owningType, MethodDesc targetMethod)
            {
                Debug.Assert(targetMethod.OwningType.IsValueType);
                Debug.Assert(!targetMethod.Signature.IsStatic);

                _owningType        = owningType;
                _targetMethod      = targetMethod;
                _nakedTargetMethod = new ValueTypeInstanceMethodWithHiddenParameter(targetMethod);
            }
예제 #6
0
 public UnboxingThunkHashtableKey(MethodDesc targetMethod, BoxedValueType owningType)
 {
     TargetMethod = targetMethod;
     OwningType   = owningType;
 }
예제 #7
0
 public BoxedValueField(BoxedValueType owningType)
 {
     _owningType = owningType;
 }
예제 #8
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);
            }
        }