Exemplo n.º 1
0
        /// <param name="sourceType">Type that already has custom modifiers.</param>
        /// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers.  May differ in object/dynamic.</param>
        /// <param name="refKind"><see cref="RefKind"/> of the parameter of which this is the type (or <see cref="RefKind.None"/> for a return type.</param>
        /// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param>
        /// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns>
        internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, RefKind refKind, AssemblySymbol containingAssembly)
        {
            Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions));

            // NOTE: overrides can differ by object/dynamic.  If they do, we'll need to tweak newType before
            // we can use it in place of this.Type.  We do so by computing the dynamic transform flags that
            // code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
            ImmutableArray <bool> flags           = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
            TypeSymbol            typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);

            TypeSymbol resultType;

            if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
            {
                // We also preserve tuple names, if present and different
                ImmutableArray <string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType);
                resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithDynamic, containingAssembly, names);
            }
            else
            {
                resultType = typeWithDynamic;
            }

            Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames));                            // Same custom modifiers as source type.
            Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic and tuple names as destination type.
            return(resultType);
        }
Exemplo n.º 2
0
        /// <param name="sourceType">Type that already has custom modifiers.</param>
        /// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers.  May differ in object/dynamic.</param>
        /// <param name="refKind"><see cref="RefKind"/> of the parameter of which this is the type (or <see cref="RefKind.None"/> for a return type.</param>
        /// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param>
        /// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns>
        internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, RefKind refKind, AssemblySymbol containingAssembly)
        {
            Debug.Assert(sourceType.Equals(destinationType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: true));

            if (sourceType.IsTupleType)
            {
                ImmutableArray <bool> flags      = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
                TypeSymbol            resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);

                Debug.Assert(resultType.Equals(sourceType, ignoreCustomModifiersAndArraySizesAndLowerBounds: false, ignoreDynamic: true)); // Same custom modifiers as source type.
                return(resultType);
            }
            else
            {
                // NOTE: overrides can differ by object/dynamic.  If they do, we'll need to tweak newType before
                // we can use it in place of this.Type.  We do so by computing the dynamic transform flags that
                // code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
                ImmutableArray <bool> flags      = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
                TypeSymbol            resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);

                Debug.Assert(resultType.Equals(sourceType, ignoreCustomModifiersAndArraySizesAndLowerBounds: false, ignoreDynamic: true));      // Same custom modifiers as source type.
                Debug.Assert(resultType.Equals(destinationType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: false)); // Same object/dynamic as destination type.
                return(resultType);
            }
        }
Exemplo n.º 3
0
        private static void GetConstants(
            ArrayBuilder <LocalSymbol> builder,
            MethodSymbol method,
            ImmutableArray <NamedLocalConstant> constants,
            MetadataDecoder metadataDecoder,
            ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap,
            SourceAssemblySymbol containingAssembly)
        {
            foreach (var constant in constants)
            {
                var info = metadataDecoder.GetLocalInfo(constant.Signature);
                Debug.Assert(!info.IsByRef);
                Debug.Assert(!info.IsPinned);
                var type = info.Type;

                ImmutableArray <bool> dynamicFlags;
                if (dynamicLocalConstantMap.TryGetValue(constant.Name, out dynamicFlags))
                {
                    type = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
                        type,
                        containingAssembly,
                        RefKind.None,
                        dynamicFlags);
                }

                var constantValue = ReinterpretConstantValue(constant.Value, type.SpecialType);
                builder.Add(new EELocalConstantSymbol(method, constant.Name, type, constantValue));
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Returns symbols for the locals emitted in the original method,
        /// based on the local signatures from the IL and the names and
        /// slots from the PDB. The actual locals are needed to ensure the
        /// local slots in the generated method match the original.
        /// </summary>
        private static void GetLocals(
            ArrayBuilder <LocalSymbol> builder,
            MethodSymbol method,
            ImmutableArray <string> names,
            ImmutableArray <LocalInfo <TypeSymbol> > localInfo,
            ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap,
            SourceAssemblySymbol containingAssembly)
        {
            if (localInfo.Length == 0)
            {
                // When debugging a .dmp without a heap, localInfo will be empty although
                // names may be non-empty if there is a PDB. Since there's no type info, the
                // locals are dropped. Note this means the local signature of any generated
                // method will not match the original signature, so new locals will overlap
                // original locals. That is ok since there is no live process for the debugger
                // to update (any modified values exist in the debugger only).
                return;
            }

            Debug.Assert(localInfo.Length >= names.Length);

            for (int i = 0; i < localInfo.Length; i++)
            {
                var name     = (i < names.Length) ? names[i] : null;
                var info     = localInfo[i];
                var isPinned = info.IsPinned;

                LocalDeclarationKind kind;
                RefKind    refKind;
                TypeSymbol type;
                if (info.IsByRef && isPinned)
                {
                    kind    = LocalDeclarationKind.FixedVariable;
                    refKind = RefKind.None;
                    type    = new PointerTypeSymbol(info.Type);
                }
                else
                {
                    kind    = LocalDeclarationKind.RegularVariable;
                    refKind = info.IsByRef ? RefKind.Ref : RefKind.None;
                    type    = info.Type;
                }

                ImmutableArray <bool> dynamicFlags;
                if (dynamicLocalMap.TryGetValue(i, out dynamicFlags))
                {
                    type = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
                        type,
                        containingAssembly,
                        refKind,
                        dynamicFlags);
                }

                // Custom modifiers can be dropped since binding ignores custom
                // modifiers from locals and since we only need to preserve
                // the type of the original local in the generated method.
                builder.Add(new EELocalSymbol(method, EELocalSymbol.NoLocations, name, i, kind, type, refKind, isPinned, isCompilerGenerated: false, canScheduleToStack: false));
            }
        }
Exemplo n.º 5
0
        internal static PlaceholderLocalSymbol CreatePlaceholderLocal(
            TypeNameDecoder <PEModuleSymbol, TypeSymbol> typeNameDecoder,
            MethodSymbol containingMethod,
            Alias alias)
        {
            var typeName = alias.Type;

            Debug.Assert(typeName.Length > 0);

            var type = typeNameDecoder.GetTypeSymbolForSerializedType(typeName);

            Debug.Assert((object)type != null);

            var dynamicFlagsInfo = alias.CustomTypeInfo.ToDynamicFlagsCustomTypeInfo();

            if (dynamicFlagsInfo.Any())
            {
                var flagsBuilder = ArrayBuilder <bool> .GetInstance();

                dynamicFlagsInfo.CopyTo(flagsBuilder);
                var dynamicType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
                    type,
                    containingMethod.ContainingAssembly,
                    RefKind.None,
                    flagsBuilder.ToImmutableAndFree(),
                    checkLength: false);
                Debug.Assert(dynamicType != null);
                Debug.Assert(dynamicType != type);
                type = dynamicType;
            }

            var id = alias.FullName;

            switch (alias.Kind)
            {
            case AliasKind.Exception:
                return(new ExceptionLocalSymbol(containingMethod, id, type, ExpressionCompilerConstants.GetExceptionMethodName));

            case AliasKind.StowedException:
                return(new ExceptionLocalSymbol(containingMethod, id, type, ExpressionCompilerConstants.GetStowedExceptionMethodName));

            case AliasKind.ReturnValue:
            {
                int index;
                PseudoVariableUtilities.TryParseReturnValueIndex(id, out index);
                Debug.Assert(index >= 0);
                return(new ReturnValueLocalSymbol(containingMethod, id, type, index));
            }

            case AliasKind.ObjectId:
                return(new ObjectIdLocalSymbol(containingMethod, type, id, isWritable: false));

            case AliasKind.DeclaredLocal:
                return(new ObjectIdLocalSymbol(containingMethod, type, id, isWritable: true));

            default:
                throw ExceptionUtilities.UnexpectedValue(alias.Kind);
            }
        }
Exemplo n.º 6
0
 private TypeSymbol IncludeDynamicAndTupleElementNamesIfAny(
     TypeSymbol type,
     RefKind refKind,
     ImmutableArray <bool> dynamicFlagsOpt,
     ImmutableArray <string?> tupleElementNamesOpt)
 {
     if (!dynamicFlagsOpt.IsDefault)
     {
         type = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(type, _sourceAssembly, refKind, dynamicFlagsOpt, checkLength: false);
     }
     return(TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, tupleElementNamesOpt));
 }
Exemplo n.º 7
0
        /// <param name="sourceType">Type that already has custom modifiers.</param>
        /// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers.  May differ in object/dynamic.</param>
        /// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param>
        /// <param name="nonNullTypesContext">The NonNullTypes context at the destination.</param>
        /// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns>
        internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, AssemblySymbol containingAssembly, INonNullTypesContext nonNullTypesContext)
        {
            Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(nonNullTypesContext != null);

            const RefKind refKind = RefKind.None;

            // NOTE: overrides can differ by object/dynamic.  If they do, we'll need to tweak newType before
            // we can use it in place of this.Type.  We do so by computing the dynamic transform flags that
            // code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
            // NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context
            ImmutableArray <bool> flags           = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
            TypeSymbol            typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);

            TypeSymbol resultType;

            if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
            {
                // We also preserve tuple names, if present and different
                ImmutableArray <string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType);
                resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithDynamic, names);
            }
            else
            {
                resultType = typeWithDynamic;
            }

            // Preserve nullable modifiers as well.
            // https://github.com/dotnet/roslyn/issues/30077: Is it reasonable to copy annotations from the source?
            // If the destination had some of those annotations but not all, then clearly the destination
            // was incorrect. Or if the destination is C#7, then the destination will advertise annotations
            // that the author did not write and did not validate.
            var flagsBuilder = ArrayBuilder <bool> .GetInstance();

            destinationType.AddNullableTransforms(flagsBuilder);
            int  position        = 0;
            int  length          = flagsBuilder.Count;
            bool transformResult = resultType.ApplyNullableTransforms(flagsBuilder.ToImmutableAndFree(), nonNullTypesContext, ref position, out resultType);

            Debug.Assert(transformResult && position == length);

            Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames)); // Same custom modifiers as source type.
            // Note: We would want to check nullability, but that would pull on NonNullTypes too early (ie. cause cycles).
            Debug.Assert(resultType.Equals(destinationType,
                                           TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic and tuple names as destination type.

            return(resultType);
        }
Exemplo n.º 8
0
        internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, AssemblySymbol containingAssembly)
        {
            Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions));

            const RefKind refKind = RefKind.None;

            // NOTE: overrides can differ by object/dynamic, tuple element names, etc.
            // If they do, we'll need to tweak destinationType before we can use it in place of sourceType.
            // NOTE: refKind is irrelevant here since we are just encoding/decoding the type.
            ImmutableArray <bool> flags      = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
            TypeSymbol            resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);

            if (!containingAssembly.RuntimeSupportsNumericIntPtr)
            {
                var builder = ArrayBuilder <bool> .GetInstance();

                CSharpCompilation.NativeIntegerTransformsEncoder.Encode(builder, destinationType);
                resultType = NativeIntegerTypeDecoder.TransformType(resultType, builder.ToImmutableAndFree());
            }

            if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreDynamic))
            {
                // We also preserve tuple names, if present and different
                ImmutableArray <string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType);
                resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(resultType, names);
            }

            // Preserve nullable modifiers as well.
            // https://github.com/dotnet/roslyn/issues/30077: Is it reasonable to copy annotations from the source?
            // If the destination had some of those annotations but not all, then clearly the destination
            // was incorrect. Or if the destination is C#7, then the destination will advertise annotations
            // that the author did not write and did not validate.
            var flagsBuilder = ArrayBuilder <byte> .GetInstance();

            destinationType.AddNullableTransforms(flagsBuilder);
            int  position        = 0;
            int  length          = flagsBuilder.Count;
            bool transformResult = resultType.ApplyNullableTransforms(defaultTransformFlag: 0, flagsBuilder.ToImmutableAndFree(), ref position, out resultType);

            Debug.Assert(transformResult && position == length);

            Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes | TypeCompareKind.IgnoreNativeIntegers)); // Same custom modifiers as source type.

            // Same object/dynamic, nullability, native integers, and tuple names as destination type.
            Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds));

            return(resultType);
        }
Exemplo n.º 9
0
        private static TypeSymbol DecodeDynamicTypes(TypeSymbol type, AssemblySymbol sourceAssembly, ReadOnlyCollection <byte> bytes)
        {
            var builder = ArrayBuilder <bool> .GetInstance();

            DynamicFlagsCustomTypeInfo.CopyTo(bytes, builder);
            var dynamicType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
                type,
                sourceAssembly,
                RefKind.None,
                builder.ToImmutableAndFree(),
                checkLength: false);

            Debug.Assert((object)dynamicType != null);
            Debug.Assert(dynamicType != type);
            return(dynamicType);
        }
Exemplo n.º 10
0
        private static void GetConstants(
            ArrayBuilder <LocalSymbol> builder,
            MethodSymbol method,
            ArrayBuilder <ISymUnmanagedScope> scopes,
            MetadataDecoder metadataDecoder,
            ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap,
            SourceAssemblySymbol containingAssembly)
        {
            foreach (var scope in scopes)
            {
                foreach (var constant in scope.GetConstants())
                {
                    string name      = constant.GetName();
                    object rawValue  = constant.GetValue();
                    var    signature = constant.GetSignature();

                    var info = metadataDecoder.GetLocalInfo(signature);
                    Debug.Assert(!info.IsByRef);
                    Debug.Assert(!info.IsPinned);
                    var type = info.Type;
                    if (type.IsErrorType())
                    {
                        continue;
                    }

                    var constantValue = PdbHelpers.GetConstantValue(type.EnumUnderlyingType(), rawValue);

                    ImmutableArray <bool> dynamicFlags;
                    if (dynamicLocalConstantMap != null && dynamicLocalConstantMap.TryGetValue(name, out dynamicFlags))
                    {
                        type = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
                            type,
                            containingAssembly,
                            RefKind.None,
                            dynamicFlags);
                    }

                    builder.Add(new EELocalConstantSymbol(method, name, type, constantValue));
                }
            }
        }
Exemplo n.º 11
0
 private TypeSymbol GetDynamicType(TypeSymbol type, RefKind refKind, ImmutableArray <bool> dynamicFlags)
 {
     return(DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(type, _sourceAssembly, refKind, dynamicFlags, checkLength: false));
 }
Exemplo n.º 12
0
        internal static LocalSymbol Create(
            TypeNameDecoder <PEModuleSymbol, TypeSymbol> typeNameDecoder,
            MethodSymbol containingMethod,
            AssemblySymbol sourceAssembly,
            Alias alias)
        {
            var typeName = alias.Type;

            Debug.Assert(typeName.Length > 0);

            var type = typeNameDecoder.GetTypeSymbolForSerializedType(typeName);

            Debug.Assert((object)type != null);

            ReadOnlyCollection <byte>   dynamicFlags;
            ReadOnlyCollection <string> tupleElementNames;

            CustomTypeInfo.Decode(alias.CustomTypeInfoId, alias.CustomTypeInfo, out dynamicFlags, out tupleElementNames);

            // Preserve tuple element names. See https://github.com/dotnet/roslyn/issues/13589.
            if (dynamicFlags != null)
            {
                var flagsBuilder = ArrayBuilder <bool> .GetInstance();

                DynamicFlagsCustomTypeInfo.CopyTo(dynamicFlags, flagsBuilder);
                var dynamicType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(
                    type,
                    sourceAssembly,
                    RefKind.None,
                    flagsBuilder.ToImmutableAndFree(),
                    checkLength: false);
                Debug.Assert(dynamicType != null);
                Debug.Assert(dynamicType != type);
                type = dynamicType;
            }

            var name        = alias.FullName;
            var displayName = alias.Name;

            switch (alias.Kind)
            {
            case DkmClrAliasKind.Exception:
                return(new ExceptionLocalSymbol(containingMethod, name, displayName, type, ExpressionCompilerConstants.GetExceptionMethodName));

            case DkmClrAliasKind.StowedException:
                return(new ExceptionLocalSymbol(containingMethod, name, displayName, type, ExpressionCompilerConstants.GetStowedExceptionMethodName));

            case DkmClrAliasKind.ReturnValue:
            {
                int index;
                PseudoVariableUtilities.TryParseReturnValueIndex(name, out index);
                Debug.Assert(index >= 0);
                return(new ReturnValueLocalSymbol(containingMethod, name, displayName, type, index));
            }

            case DkmClrAliasKind.ObjectId:
                return(new ObjectIdLocalSymbol(containingMethod, type, name, displayName, isWritable: false));

            case DkmClrAliasKind.Variable:
                return(new ObjectIdLocalSymbol(containingMethod, type, name, displayName, isWritable: true));

            default:
                throw ExceptionUtilities.UnexpectedValue(alias.Kind);
            }
        }