/// <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)); }
/// <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); } } }
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); } }
/// <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); }