Exemplo n.º 1
0
        /// <summary>
        /// <![CDATA[
        /// fixed(int* ptr = arr){ ... }    == becomes ===>
        ///
        /// pinned int[] pinnedTemp = arr;         // pinning managed ref
        /// int* ptr = pinnedTemp != null && pinnedTemp.Length != 0
        ///                (int*)&pinnedTemp[0]:   // unsafe cast to unmanaged ptr
        ///                0;
        ///   . . .
        ///   ]]>
        /// </summary>
        private BoundStatement InitializeFixedStatementArrayLocal(
            BoundLocalDeclaration localDecl,
            LocalSymbol localSymbol,
            BoundFixedLocalCollectionInitializer fixedInitializer,
            SyntheticBoundNodeFactory factory,
            out LocalSymbol pinnedTemp)
        {
            TypeSymbol      localType       = localSymbol.Type.TypeSymbol;
            BoundExpression initializerExpr = VisitExpression(fixedInitializer.Expression);
            TypeSymbol      initializerType = initializerExpr.Type;

            pinnedTemp = factory.SynthesizedLocal(initializerType, isPinned: true);
            TypeSymbol arrayType = pinnedTemp.Type.TypeSymbol;
            TypeSymbolWithAnnotations arrayElementType = arrayType.GetArrayElementType();

            // NOTE: we pin the array, not the pointer.
            Debug.Assert(pinnedTemp.IsPinned);
            Debug.Assert(!localSymbol.IsPinned);

            //(pinnedTemp = array)
            BoundExpression arrayTempInit = factory.AssignmentExpression(factory.Local(pinnedTemp), initializerExpr);

            //(pinnedTemp = array) != null
            BoundExpression notNullCheck = MakeNullCheck(factory.Syntax, arrayTempInit, BinaryOperatorKind.NotEqual);

            BoundExpression lengthCall;

            lengthCall = factory.ArrayLength(factory.Local(pinnedTemp));

            // NOTE: dev10 comment says ">", but code actually checks "!="
            //temp.Length != 0
            BoundExpression lengthCheck = factory.Binary(BinaryOperatorKind.Int32NotEqual, factory.SpecialType(SpecialType.System_Boolean), lengthCall, factory.Literal(0));

            //((temp = array) != null && temp.Length != 0)
            BoundExpression condition = factory.Binary(BinaryOperatorKind.LogicalBoolAnd, factory.SpecialType(SpecialType.System_Boolean), notNullCheck, lengthCheck);

            //temp[0]
            BoundExpression firstElement = factory.ArrayAccessFirstElement(factory.Local(pinnedTemp));

            // NOTE: this is a fixed statement address-of in that it's the initial value of the pointer.
            //&temp[0]
            BoundExpression firstElementAddress          = new BoundAddressOfOperator(factory.Syntax, firstElement, type: new PointerTypeSymbol(arrayElementType));
            BoundExpression convertedFirstElementAddress = factory.Convert(
                localType,
                firstElementAddress,
                fixedInitializer.ElementPointerTypeConversion);

            //loc = &temp[0]
            BoundExpression consequenceAssignment = factory.AssignmentExpression(factory.Local(localSymbol), convertedFirstElementAddress);

            //loc = null
            BoundExpression alternativeAssignment = factory.AssignmentExpression(factory.Local(localSymbol), factory.Null(localType));

            //(((temp = array) != null && temp.Length != 0) ? loc = &temp[0] : loc = null)
            BoundStatement localInit = factory.ExpressionStatement(
                new BoundConditionalOperator(factory.Syntax, false, condition, consequenceAssignment, alternativeAssignment, ConstantValue.NotAvailable, localType));

            return(InstrumentLocalDeclarationIfNecessary(localDecl, localSymbol, localInit));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Entry point to the array initialization.
        /// Assumes that we have newly created array on the stack.
        ///
        /// inits could be an array of values for a single dimensional array
        /// or an array (of array)+ of values for a multidimensional case
        ///
        /// in either case it is expected that number of leaf values will match number
        /// of elements in the array and nesting level should match the rank of the array.
        /// </summary>
        private void EmitArrayInitializers(TypeSymbol arrayType, BoundArrayInitialization inits)
        {
            var initExprs           = inits.Initializers;
            var initializationStyle = ShouldEmitBlockInitializer(arrayType.GetArrayElementType().TypeSymbol, initExprs);

            if (initializationStyle == ArrayInitializerStyle.Element)
            {
                this.EmitElementInitializers(arrayType, initExprs, true);
            }
            else
            {
                ImmutableArray <byte> data = this.GetRawData(initExprs);
                _builder.EmitArrayBlockInitializer(data, inits.Syntax, _diagnostics);

                if (initializationStyle == ArrayInitializerStyle.Mixed)
                {
                    EmitElementInitializers(arrayType, initExprs, false);
                }
            }
        }
Exemplo n.º 3
0
        private static bool ContainsNestedTypeOfUnconstructedGenericType(TypeSymbol type)
        {
            switch (type.TypeKind)
            {
            case TypeKind.Array:
                return(ContainsNestedTypeOfUnconstructedGenericType(type.GetArrayElementType().TypeSymbol));

            case TypeKind.Pointer:
                return(ContainsNestedTypeOfUnconstructedGenericType(((PointerTypeSymbol)type).PointedAtType.TypeSymbol));

            case TypeKind.Delegate:
            case TypeKind.Class:
            case TypeKind.Interface:
            case TypeKind.Struct:
            case TypeKind.Enum:
            case TypeKind.Error:
                NamedTypeSymbol namedType = (NamedTypeSymbol)type;
                if (IsNestedTypeOfUnconstructedGenericType(namedType))
                {
                    return(true);
                }

                foreach (TypeSymbolWithAnnotations typeArgument in namedType.TypeArgumentsNoUseSiteDiagnostics)
                {
                    if (ContainsNestedTypeOfUnconstructedGenericType(typeArgument.TypeSymbol))
                    {
                        return(true);
                    }
                }

                return(false);

            case TypeKind.TypeParameter:
                return(false);

            default:
                throw ExceptionUtilities.UnexpectedValue(type.TypeKind);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// This method finds an attribute by metadata name and signature. The algorithm for signature matching is similar to the one
        /// in Module.GetTargetAttributeSignatureIndex. Note, the signature matching is limited to primitive types
        /// and System.Type.  It will not match an arbitrary signature but it is sufficient to match the signatures of the current set of
        /// well known attributes.
        /// </summary>
        /// <param name="targetSymbol">The symbol which is the target of the attribute</param>
        /// <param name="description">The attribute to match.</param>
        internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description)
        {
            if (!IsTargetAttribute(description.NamespaceAndNestedType, description.Name))
            {
                return(-1);
            }

            var ctor = this.AttributeConstructor;

            // Ensure that the attribute data really has a constructor before comparing the signature.
            if ((object)ctor == null)
            {
                return(-1);
            }

            // Lazily loaded System.Type type symbol
            TypeSymbol lazySystemType = null;

            ImmutableArray <ParameterSymbol> parameters = ctor.Parameters;
            bool foundMatch = false;

            for (int i = 0; i < description.Signatures.Length; i++)
            {
                byte[] targetSignature = description.Signatures[i];
                if (targetSignature[0] != (byte)SignatureAttributes.Instance)
                {
                    continue;
                }

                byte parameterCount = targetSignature[1];
                if (parameterCount != parameters.Length)
                {
                    continue;
                }

                if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void)
                {
                    continue;
                }

                foundMatch = (targetSignature.Length == 3);
                int k = 0;
                for (int j = 3; j < targetSignature.Length; j++)
                {
                    if (k >= parameters.Length)
                    {
                        break;
                    }

                    TypeSymbol  parameterType = parameters[k].Type.TypeSymbol;
                    SpecialType specType      = parameterType.SpecialType;
                    byte        targetType    = targetSignature[j];

                    if (targetType == (byte)SignatureTypeCode.TypeHandle)
                    {
                        j++;

                        if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType)
                        {
                            foundMatch = false;
                            break;
                        }

                        var namedType = (NamedTypeSymbol)parameterType;
                        AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[j]];

                        // Compare name and containing symbol name. Uses HasNameQualifier
                        // extension method to avoid string allocations.
                        if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) ||
                            !namedType.HasNameQualifier(targetInfo.Namespace))
                        {
                            foundMatch = false;
                            break;
                        }

                        targetType = (byte)targetInfo.Underlying;

                        if (parameterType.IsEnumType())
                        {
                            specType = parameterType.GetEnumUnderlyingType().SpecialType;
                        }
                    }
                    else if (parameterType.IsArray())
                    {
                        specType = parameterType.GetArrayElementType().SpecialType;
                    }

                    switch (targetType)
                    {
                    case (byte)SignatureTypeCode.Boolean:
                        foundMatch = specType == SpecialType.System_Boolean;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Rune:
                        foundMatch = specType == SpecialType.System_Rune;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.SByte:
                        foundMatch = specType == SpecialType.System_Int8;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Byte:
                        foundMatch = specType == SpecialType.System_UInt8;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Int16:
                        foundMatch = specType == SpecialType.System_Int16;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt16:
                        foundMatch = specType == SpecialType.System_UInt16;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Int32:
                        foundMatch = specType == SpecialType.System_Int32;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt32:
                        foundMatch = specType == SpecialType.System_UInt32;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Int64:
                        foundMatch = specType == SpecialType.System_Int64;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt64:
                        foundMatch = specType == SpecialType.System_UInt64;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Single:
                        foundMatch = specType == SpecialType.System_Float32;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Double:
                        foundMatch = specType == SpecialType.System_Float64;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.String:
                        foundMatch = specType == SpecialType.System_String;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Object:
                        foundMatch = specType == SpecialType.System_Object;
                        k         += 1;
                        break;

                    case (byte)SerializationTypeCode.Type:
                        if ((object)lazySystemType == null)
                        {
                            lazySystemType = GetSystemType(targetSymbol);
                        }

                        foundMatch = TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything2);
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Array:
                        // Skip over and check the next byte
                        foundMatch = parameterType.IsArray();
                        break;

                    default:
                        return(-1);
                    }

                    if (!foundMatch)
                    {
                        break;
                    }
                }

                if (foundMatch)
                {
                    return(i);
                }
            }

            Debug.Assert(!foundMatch);
            return(-1);
        }
 private static bool IsInvariantArray(TypeSymbol type)
 {
     return(type.IsArray() && type.GetArrayElementType().TypeSymbol.IsSealed);
 }