diff --git a/src/absil/il.fs b/src/absil/il.fs index 288f69474d5..ce8ee4065ef 100644 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -7,16 +7,19 @@ module Microsoft.FSharp.Compiler.AbstractIL.IL #nowarn "346" // The struct, record or union type 'IlxExtensionType' has an explicit implementation of 'Object.Equals'. ... -open Internal.Utilities -open Microsoft.FSharp.Compiler.AbstractIL -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics -open Microsoft.FSharp.Compiler.AbstractIL.Internal -open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library +open System open System.Collections open System.Collections.Generic open System.Collections.Concurrent open System.Runtime.CompilerServices open System.Reflection + +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler.AbstractIL.Internal +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library + +open Internal.Utilities let logging = false @@ -42,7 +45,7 @@ let _ = if logging then dprintn "* warning: Il.logging is on" let int_order = LanguagePrimitives.FastGenericComparer -let notlazy v = Lazy.CreateFromValue v +let notlazy v = Lazy<_>.CreateFromValue v /// A little ugly, but the idea is that if a data structure does not /// contain lazy values then we don't add laziness. So if the thing to map @@ -321,12 +324,12 @@ type PublicKey = [] type AssemblyRefData = - { assemRefName: string; - assemRefHash: byte[] option; - assemRefPublicKeyInfo: PublicKey option; - assemRefRetargetable: bool; - assemRefVersion: ILVersionInfo option; - assemRefLocale: Locale option; } + { assemRefName: string + assemRefHash: byte[] option + assemRefPublicKeyInfo: PublicKey option + assemRefRetargetable: bool + assemRefVersion: ILVersionInfo option + assemRefLocale: Locale option } /// Global state: table of all assembly references keyed by AssemblyRefData. let AssemblyRefUniqueStampGenerator = new UniqueStampGenerator() @@ -721,11 +724,11 @@ let mkILCallSig (cc,args,ret) = { ArgTypes=args; CallingConv=cc; ReturnType=ret} let mkILBoxedType (tspec:ILTypeSpec) = tspec.TypeRef.AsBoxedType tspec type ILMethodRef = - { mrefParent: ILTypeRef; - mrefCallconv: ILCallingConv; - mrefGenericArity: int; - mrefName: string; - mrefArgs: ILTypes; + { mrefParent: ILTypeRef + mrefCallconv: ILCallingConv + mrefGenericArity: int + mrefName: string + mrefArgs: ILTypes mrefReturn: ILType } member x.DeclaringTypeRef = x.mrefParent member x.CallingConv = x.mrefCallconv @@ -736,8 +739,10 @@ type ILMethodRef = member x.ReturnType = x.mrefReturn member x.CallingSignature = mkILCallSig (x.CallingConv,x.ArgTypes,x.ReturnType) + static member Create(a,b,c,d,e,f) = { mrefParent= a;mrefCallconv=b;mrefName=c;mrefGenericArity=d; mrefArgs=e;mrefReturn=f } + override x.ToString() = x.DeclaringTypeRef.ToString() + "::" + x.Name + "(...)" @@ -750,9 +755,9 @@ type ILFieldRef = [] type ILMethodSpec = - { mspecMethodRef: ILMethodRef; - mspecDeclaringType: ILType; - mspecMethodInst: ILGenericArgs; } + { mspecMethodRef: ILMethodRef + mspecDeclaringType: ILType + mspecMethodInst: ILGenericArgs } static member Create(a,b,c) = { mspecDeclaringType=a; mspecMethodRef =b; mspecMethodInst=c } member x.MethodRef = x.mspecMethodRef member x.DeclaringType=x.mspecDeclaringType @@ -764,16 +769,14 @@ type ILMethodSpec = member x.FormalReturnType = x.MethodRef.ReturnType override x.ToString() = x.MethodRef.ToString() + "(...)" - type ILFieldSpec = - { FieldRef: ILFieldRef; + { FieldRef: ILFieldRef DeclaringType: ILType } member x.FormalType = x.FieldRef.Type member x.Name = x.FieldRef.Name member x.DeclaringTypeRef = x.FieldRef.DeclaringTypeRef override x.ToString() = x.FieldRef.ToString() - // -------------------------------------------------------------------- // Debug info. // -------------------------------------------------------------------- @@ -844,16 +847,34 @@ type ILAttribElem = type ILAttributeNamedArg = (string * ILType * bool * ILAttribElem) type ILAttribute = - { Method: ILMethodSpec; + { Method: ILMethodSpec Data: byte[] Elements: ILAttribElem list} -[] -type ILAttributes(f: unit -> ILAttribute[]) = - let mutable array = InlineDelayInit<_>(f) - member x.AsArray = array.Value +[] +type ILAttributes(array : ILAttribute[]) = + member x.AsArray = array member x.AsList = x.AsArray |> Array.toList +[] +type ILAttributesStored = + /// Computed by ilread.fs based on metadata index + | Reader of (int32 -> ILAttribute[]) + /// Already computed + | Given of ILAttributes + member x.GetCustomAttrs metadataIndex = + match x with + | Reader f -> ILAttributes(f metadataIndex) + | Given attrs -> attrs + +let emptyILCustomAttrs = ILAttributes [| |] +let mkILCustomAttrsFromArray (attrs: ILAttribute[]) = if attrs.Length = 0 then emptyILCustomAttrs else ILAttributes attrs +let mkILCustomAttrs l = match l with [] -> emptyILCustomAttrs | _ -> mkILCustomAttrsFromArray (List.toArray l) + +let emptyILCustomAttrsStored = ILAttributesStored.Given emptyILCustomAttrs +let storeILCustomAttrs (attrs: ILAttributes) = if attrs.AsArray.Length = 0 then emptyILCustomAttrsStored else ILAttributesStored.Given attrs +let mkILCustomAttrsReader f = ILAttributesStored.Reader f + type ILCodeLabel = int // -------------------------------------------------------------------- @@ -1236,11 +1257,28 @@ type type ILSecurityDecl = | ILSecurityDecl of ILSecurityAction * byte[] -[] -type ILSecurityDecls = - | ILSecurityDecls of ILSecurityDecl list - | ILSecurityDeclsLazy of Lazy - member x.AsList = match x with ILSecurityDecls m -> m | ILSecurityDeclsLazy m -> m.Force() +[] +type ILSecurityDecls(array : ILSecurityDecl[]) = + member x.AsArray = array + member x.AsList = x.AsArray |> Array.toList + +[] +type ILSecurityDeclsStored = + /// Computed by ilread.fs based on metadata index + | Reader of (int32 -> ILSecurityDecl[]) + /// Already computed + | Given of ILSecurityDecls + member x.GetSecurityDecls metadataIndex = + match x with + | Reader f -> ILSecurityDecls(f metadataIndex) + | Given attrs -> attrs + +let emptyILSecurityDecls = ILSecurityDecls [| |] +let emptyILSecurityDeclsStored = ILSecurityDeclsStored.Given emptyILSecurityDecls +let mkILSecurityDecls l = match l with [] -> emptyILSecurityDecls | _ -> ILSecurityDecls (Array.ofList l) +let storeILSecurityDecls (x: ILSecurityDecls) = if x.AsArray.Length = 0 then emptyILSecurityDeclsStored else ILSecurityDeclsStored.Given x +let mkILSecurityDeclsReader f = ILSecurityDeclsStored.Reader f + [] type PInvokeCharBestFit = @@ -1272,33 +1310,37 @@ type PInvokeCharEncoding = [] type PInvokeMethod = - { Where: ILModuleRef; - Name: string; - CallingConv: PInvokeCallingConvention; - CharEncoding: PInvokeCharEncoding; - NoMangle: bool; - LastError: bool; - ThrowOnUnmappableChar: PInvokeThrowOnUnmappableChar; + { Where: ILModuleRef + Name: string + CallingConv: PInvokeCallingConvention + CharEncoding: PInvokeCharEncoding + NoMangle: bool + LastError: bool + ThrowOnUnmappableChar: PInvokeThrowOnUnmappableChar CharBestFit: PInvokeCharBestFit } [] type ILParameter = - { Name: string option; - Type: ILType; - Default: ILFieldInit option; - Marshal: ILNativeType option; - IsIn: bool; - IsOut: bool; - IsOptional: bool; - CustomAttrs: ILAttributes } + { Name: string option + Type: ILType + Default: ILFieldInit option + Marshal: ILNativeType option + IsIn: bool + IsOut: bool + IsOptional: bool + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex type ILParameters = list [] type ILReturn = - { Marshal: ILNativeType option; - Type: ILType; - CustomAttrs: ILAttributes } + { Marshal: ILNativeType option + Type: ILType + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex type ILOverridesSpec = | OverridesSpec of ILMethodRef * ILType @@ -1336,7 +1378,7 @@ type MethodCodeKind = | Native | Runtime -let mkMethBodyAux mb = ILLazyMethodBody (Lazy.CreateFromValue mb) +let mkMethBodyAux mb = ILLazyMethodBody (notlazy mb) let mkMethBodyLazyAux mb = ILLazyMethodBody mb let typesOfILParams (ps:ILParameters) : ILTypes = ps |> List.map (fun p -> p.Type) @@ -1352,10 +1394,12 @@ type ILGenericParameterDef = Constraints: ILTypes Variance: ILGenericVariance HasReferenceTypeConstraint: bool - CustomAttrs : ILAttributes HasNotNullableValueTypeConstraint: bool - HasDefaultConstructorConstraint: bool } + HasDefaultConstructorConstraint: bool + CustomAttrsStored : ILAttributesStored + MetadataIndex: int32 } + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex override x.ToString() = x.Name type ILGenericParameterDefs = ILGenericParameterDef list @@ -1381,9 +1425,18 @@ let convertMemberAccess (ilMemberAccess:ILMemberAccess) = let inline conditionalAdd condition flagToAdd source = if condition then source ||| flagToAdd else source &&& ~~~flagToAdd +let NoMetadataIdx = -1 + [] -type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: MethodImplAttributes, callingConv: ILCallingConv, parameters: ILParameters, ret: ILReturn, body: ILLazyMethodBody, securityDecls: ILSecurityDecls, isEntryPoint:bool, genericParams: ILGenericParameterDefs, customAttrs: ILAttributes) = - +type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: MethodImplAttributes, callingConv: ILCallingConv, + parameters: ILParameters, ret: ILReturn, body: ILLazyMethodBody, isEntryPoint:bool, genericParams: ILGenericParameterDefs, + securityDeclsStored: ILSecurityDeclsStored, customAttrsStored: ILAttributesStored, metadataIndex: int32) = + + new (name, attributes, implAttributes, callingConv, parameters, ret, body, isEntryPoint, genericParams, securityDecls, customAttrs) = + ILMethodDef(name, attributes, implAttributes, callingConv, parameters, ret, body, isEntryPoint, genericParams, + storeILSecurityDecls securityDecls, storeILCustomAttrs customAttrs, NoMetadataIdx) + + // The captured data - remember the object will be as large as the data captured by these members member __.Name = name member __.Attributes = attributes member __.ImplAttributes = implAttributes @@ -1391,10 +1444,11 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me member __.Parameters = parameters member __.Return = ret member __.Body = body - member __.SecurityDecls = securityDecls + member __.SecurityDeclsStored = securityDeclsStored member __.IsEntryPoint = isEntryPoint member __.GenericParams = genericParams - member __.CustomAttrs = customAttrs + member __.CustomAttrsStored = customAttrsStored + member __.MetadataIndex = metadataIndex member x.With (?name: string, ?attributes: MethodAttributes, ?implAttributes: MethodImplAttributes, ?callingConv: ILCallingConv, ?parameters: ILParameters, ?ret: ILReturn, ?body: ILLazyMethodBody, ?securityDecls: ILSecurityDecls, ?isEntryPoint:bool, ?genericParams: ILGenericParameterDefs, ?customAttrs: ILAttributes) = ILMethodDef (name = defaultArg name x.Name, @@ -1404,11 +1458,13 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me parameters = defaultArg parameters x.Parameters, ret = defaultArg ret x.Return, body = defaultArg body x.Body, - securityDecls = defaultArg securityDecls x.SecurityDecls, + securityDecls = (match securityDecls with None -> x.SecurityDecls | Some attrs -> attrs), isEntryPoint = defaultArg isEntryPoint x.IsEntryPoint, genericParams = defaultArg genericParams x.GenericParams, - customAttrs = defaultArg customAttrs x.CustomAttrs) + customAttrs=(match customAttrs with None -> x.CustomAttrs | Some attrs -> attrs)) + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs metadataIndex + member x.SecurityDecls = x.SecurityDeclsStored.GetSecurityDecls x.MetadataIndex member x.ParameterTypes = typesOfILParams x.Parameters member md.Code = @@ -1503,16 +1559,22 @@ type ILMethodDefs(f : (unit -> ILMethodDef[])) = member x.FindByNameAndArity (nm,arity) = x.FindByName nm |> List.filter (fun x -> List.length x.Parameters = arity) [] -type ILEventDef(eventType: ILType option, name: string, attributes: EventAttributes, addMethod: ILMethodRef, removeMethod: ILMethodRef, fireMethod: ILMethodRef option, otherMethods: ILMethodRef list, customAttrs: ILAttributes) = +type ILEventDef(eventType: ILType option, name: string, attributes: EventAttributes, addMethod: ILMethodRef, removeMethod: ILMethodRef, fireMethod: ILMethodRef option, otherMethods: ILMethodRef list, customAttrsStored: ILAttributesStored, metadataIndex: int32) = + + new (eventType, name, attributes, addMethod, removeMethod, fireMethod, otherMethods, customAttrs) = + ILEventDef(eventType, name, attributes, addMethod, removeMethod, fireMethod, otherMethods, storeILCustomAttrs customAttrs, NoMetadataIdx) + + member __.EventType = eventType + member __.Name = name + member __.Attributes = attributes + member __.AddMethod = addMethod + member __.RemoveMethod = removeMethod + member __.FireMethod = fireMethod + member __.OtherMethods = otherMethods + member __.CustomAttrsStored = customAttrsStored + member __.MetadataIndex = metadataIndex + member x.CustomAttrs = customAttrsStored.GetCustomAttrs x.MetadataIndex - member x.EventType = eventType - member x.Name = name - member x.Attributes = attributes - member x.AddMethod = addMethod - member x.RemoveMethod = removeMethod - member x.FireMethod = fireMethod - member x.OtherMethods = otherMethods - member x.CustomAttrs = customAttrs member x.With(?eventType, ?name, ?attributes, ?addMethod, ?removeMethod, ?fireMethod, ?otherMethods, ?customAttrs) = ILEventDef(eventType= defaultArg eventType x.EventType, name= defaultArg name x.Name, @@ -1521,9 +1583,11 @@ type ILEventDef(eventType: ILType option, name: string, attributes: EventAttribu removeMethod=defaultArg removeMethod x.RemoveMethod, fireMethod= defaultArg fireMethod x.FireMethod, otherMethods= defaultArg otherMethods x.OtherMethods, - customAttrs=defaultArg customAttrs x.CustomAttrs) + customAttrs=(match customAttrs with None -> x.CustomAttrs | Some attrs -> attrs)) + member x.IsSpecialName = (x.Attributes &&& EventAttributes.SpecialName) <> enum<_>(0) member x.IsRTSpecialName = (x.Attributes &&& EventAttributes.RTSpecialName) <> enum<_>(0) + override x.ToString() = "event " + x.Name (* Index table by name. *) @@ -1534,7 +1598,11 @@ type ILEventDefs = member x.LookupByName s = let (ILEvents t) = x in t.[s] [] -type ILPropertyDef(name: string, attributes: PropertyAttributes, setMethod: ILMethodRef option, getMethod: ILMethodRef option, callingConv: ILThisConvention, propertyType: ILType, init: ILFieldInit option, args: ILTypes, customAttrs: ILAttributes) = +type ILPropertyDef(name: string, attributes: PropertyAttributes, setMethod: ILMethodRef option, getMethod: ILMethodRef option, callingConv: ILThisConvention, propertyType: ILType, init: ILFieldInit option, args: ILTypes, customAttrsStored: ILAttributesStored, metadataIndex: int32) = + + new (name, attributes, setMethod, getMethod, callingConv, propertyType, init, args, customAttrs) = + ILPropertyDef(name, attributes, setMethod, getMethod, callingConv, propertyType, init, args, storeILCustomAttrs customAttrs, NoMetadataIdx) + member x.Name = name member x.Attributes = attributes member x.GetMethod = getMethod @@ -1543,7 +1611,10 @@ type ILPropertyDef(name: string, attributes: PropertyAttributes, setMethod: ILMe member x.PropertyType = propertyType member x.Init = init member x.Args = args - member x.CustomAttrs = customAttrs + member x.CustomAttrsStored = customAttrsStored + member x.CustomAttrs = customAttrsStored.GetCustomAttrs x.MetadataIndex + member x.MetadataIndex = metadataIndex + member x.With(?name, ?attributes, ?setMethod, ?getMethod, ?callingConv, ?propertyType, ?init, ?args, ?customAttrs) = ILPropertyDef(name=defaultArg name x.Name, attributes=defaultArg attributes x.Attributes, @@ -1553,7 +1624,8 @@ type ILPropertyDef(name: string, attributes: PropertyAttributes, setMethod: ILMe propertyType=defaultArg propertyType x.PropertyType, init=defaultArg init x.Init, args=defaultArg args x.Args, - customAttrs=defaultArg customAttrs x.CustomAttrs) + customAttrs=(match customAttrs with None -> x.CustomAttrs | Some attrs -> attrs)) + member x.IsSpecialName = (x.Attributes &&& PropertyAttributes.SpecialName) <> enum<_>(0) member x.IsRTSpecialName = (x.Attributes &&& PropertyAttributes.RTSpecialName) <> enum<_>(0) @@ -1576,8 +1648,10 @@ let convertFieldAccess (ilMemberAccess:ILMemberAccess) = | ILMemberAccess.Public -> FieldAttributes.Public [] -type ILFieldDef(name: string, fieldType: ILType, attributes: FieldAttributes, data: byte[] option, literalValue: ILFieldInit option, offset: int32 option, marshal: ILNativeType option, customAttrs: ILAttributes) = +type ILFieldDef(name: string, fieldType: ILType, attributes: FieldAttributes, data: byte[] option, literalValue: ILFieldInit option, offset: int32 option, marshal: ILNativeType option, customAttrsStored: ILAttributesStored, metadataIndex: int32) = + new (name, fieldType, attributes, data, literalValue, offset, marshal, customAttrs) = + ILFieldDef(name, fieldType, attributes, data, literalValue, offset, marshal, storeILCustomAttrs customAttrs, NoMetadataIdx) member __.Name=name member __.FieldType = fieldType member __.Attributes=attributes @@ -1585,7 +1659,9 @@ type ILFieldDef(name: string, fieldType: ILType, attributes: FieldAttributes, da member __.LiteralValue=literalValue member __.Offset=offset member __.Marshal=marshal - member __.CustomAttrs=customAttrs + member x.CustomAttrsStored = customAttrsStored + member x.CustomAttrs = customAttrsStored.GetCustomAttrs x.MetadataIndex + member x.MetadataIndex = metadataIndex member x.With(?name: string, ?fieldType: ILType, ?attributes: FieldAttributes, ?data: byte[] option, ?literalValue: ILFieldInit option, ?offset: int32 option, ?marshal: ILNativeType option, ?customAttrs: ILAttributes) = ILFieldDef(name=defaultArg name x.Name, @@ -1744,7 +1820,10 @@ let convertInitSemantics (init:ILTypeInit) = [] type ILTypeDef(name: string, attributes: TypeAttributes, layout: ILTypeDefLayout, implements: ILTypes, genericParams: ILGenericParameterDefs, extends: ILType option, methods: ILMethodDefs, nestedTypes: ILTypeDefs, fields: ILFieldDefs, methodImpls: ILMethodImplDefs, - events: ILEventDefs, properties: ILPropertyDefs, customAttrs: ILAttributes, securityDecls: ILSecurityDecls) = + events: ILEventDefs, properties: ILPropertyDefs, securityDeclsStored: ILSecurityDeclsStored, customAttrsStored: ILAttributesStored, metadataIndex: int32) = + + new (name, attributes, layout, implements, genericParams, extends, methods, nestedTypes, fields, methodImpls, events, properties, securityDecls, customAttrs) = + ILTypeDef (name, attributes, layout, implements, genericParams, extends, methods, nestedTypes, fields, methodImpls, events, properties, storeILSecurityDecls securityDecls, storeILCustomAttrs customAttrs, NoMetadataIdx) member __.Name = name member __.Attributes = attributes @@ -1754,12 +1833,14 @@ type ILTypeDef(name: string, attributes: TypeAttributes, layout: ILTypeDefLayout member __.Implements = implements member __.Extends = extends member __.Methods = methods - member __.SecurityDecls = securityDecls + member __.SecurityDeclsStored = securityDeclsStored member __.Fields = fields member __.MethodImpls = methodImpls member __.Events = events member __.Properties = properties - member __.CustomAttrs = customAttrs + member __.CustomAttrsStored = customAttrsStored + member __.MetadataIndex = metadataIndex + member x.With(?name, ?attributes, ?layout, ?implements, ?genericParams, ?extends, ?methods, ?nestedTypes, ?fields, ?methodImpls, ?events, ?properties, ?customAttrs, ?securityDecls) = ILTypeDef(name=defaultArg name x.Name, attributes=defaultArg attributes x.Attributes, @@ -1775,6 +1856,10 @@ type ILTypeDef(name: string, attributes: TypeAttributes, layout: ILTypeDefLayout events = defaultArg events x.Events, properties = defaultArg properties x.Properties, customAttrs = defaultArg customAttrs x.CustomAttrs) + + member x.CustomAttrs = customAttrsStored.GetCustomAttrs x.MetadataIndex + member x.SecurityDecls = x.SecurityDeclsStored.GetSecurityDecls x.MetadataIndex + member x.IsClass = (typeKindOfFlags x.Name x.Methods x.Fields x.Extends (int x.Attributes)) = ILTypeDefKind.Class member x.IsStruct = (typeKindOfFlags x.Name x.Methods x.Fields x.Extends (int x.Attributes)) = ILTypeDefKind.ValueType member x.IsInterface = (typeKindOfFlags x.Name x.Methods x.Fields x.Extends (int x.Attributes)) = ILTypeDefKind.Interface @@ -1802,38 +1887,68 @@ type ILTypeDef(name: string, attributes: TypeAttributes, layout: ILTypeDefLayout member x.WithSpecialName(condition) = x.With(attributes=(x.Attributes |> conditionalAdd condition TypeAttributes.SpecialName)) member x.WithInitSemantics(init) = x.With(attributes=(x.Attributes ||| convertInitSemantics init)) -and [] ILTypeDefs(f : unit -> (string list * string * ILAttributes * Lazy)[]) = +and [] ILTypeDefs(f : unit -> ILPreTypeDef[]) = let mutable array = InlineDelayInit<_>(f) let mutable dict = InlineDelayInit<_>(fun () -> - let arr = array.Value - let t = Dictionary<_,_>(HashIdentity.Structural) - for (nsp, nm, _attr, ltd) in arr do - let key = nsp, nm - t.[key] <- ltd - t) + let arr = array.Value + let t = Dictionary<_,_>(HashIdentity.Structural) + for pre in arr do + let key = pre.Namespace, pre.Name + t.[key] <- pre + t) - member x.AsArray = [| for (_,_,_,ltd) in array.Value -> ltd.Force() |] - member x.AsList = [ for (_,_,_,ltd) in array.Value -> ltd.Force() ] + member x.AsArray = [| for pre in array.Value -> pre.GetTypeDef() |] + member x.AsList = [ for pre in array.Value -> pre.GetTypeDef() ] interface IEnumerable with member x.GetEnumerator() = ((x :> IEnumerable).GetEnumerator() :> IEnumerator) interface IEnumerable with member x.GetEnumerator() = - (seq { for (_,_,_,ltd) in array.Value -> ltd.Force() }).GetEnumerator() + (seq { for pre in array.Value -> pre.GetTypeDef() }).GetEnumerator() - member x.AsArrayOfLazyTypeDefs = array.Value + member x.AsArrayOfPreTypeDefs = array.Value member x.FindByName nm = let ns,n = splitILTypeName nm - dict.Value.[(ns,n)].Force() + dict.Value.[(ns,n)].GetTypeDef() + +/// This is a memory-critical class. Very many of these objects get allocated and held to represent the contents of .NET assemblies. +and [] ILPreTypeDef(nameSpace: string list, name: string, metadataIndex: int32, storage: ILTypeDefStored) = + let mutable store : ILTypeDef = Unchecked.defaultof<_> + + member __.Namespace = nameSpace + member __.Name = name + member __.MetadataIndex = metadataIndex + + member x.GetTypeDef() = + match box store with + | null -> + match storage with + | ILTypeDefStored.Given td -> + store <- td + td + | ILTypeDefStored.Computed f -> + System.Threading.LazyInitializer.EnsureInitialized(&store, System.Func<_>(fun () -> f())) + | ILTypeDefStored.Reader f -> + System.Threading.LazyInitializer.EnsureInitialized(&store, System.Func<_>(fun () -> f x.MetadataIndex)) + | _ -> store + +and ILTypeDefStored = + | Given of ILTypeDef + | Reader of (int32 -> ILTypeDef) + | Computed of (unit -> ILTypeDef) + +let mkILTypeDefReader f = ILTypeDefStored.Reader f type ILNestedExportedType = - { Name: string; - Access: ILMemberAccess; - Nested: ILNestedExportedTypes; - CustomAttrs: ILAttributes } + { Name: string + Access: ILMemberAccess + Nested: ILNestedExportedTypes + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex and ILNestedExportedTypes = | ILNestedExportedTypes of Lazy> @@ -1841,13 +1956,15 @@ and ILNestedExportedTypes = and [] ILExportedTypeOrForwarder = - { ScopeRef: ILScopeRef; - Name: string; + { ScopeRef: ILScopeRef + Name: string Attributes: TypeAttributes - Nested: ILNestedExportedTypes; - CustomAttrs: ILAttributes } + Nested: ILNestedExportedTypes + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } member x.Access = typeAccessOfFlags (int x.Attributes) member x.IsForwarder = x.Attributes &&& enum(0x00200000) <> enum 0 + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex and ILExportedTypesAndForwarders = | ILExportedTypesAndForwarders of Lazy> @@ -1867,9 +1984,12 @@ type ILResourceLocation = type ILResource = { Name: string; - Location: ILResourceLocation; - Access: ILResourceAccess; - CustomAttrs: ILAttributes } + Location: ILResourceLocation + Access: ILResourceAccess + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + + /// Read the bytes from a resource local to an assembly member r.GetBytes() = match r.Location with | ILResourceLocation.LocalIn (file, start, len) -> @@ -1877,6 +1997,8 @@ type ILResource = | ILResourceLocation.LocalOut bytes -> bytes | _ -> failwith "GetBytes" + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex + type ILResources = | ILResources of ILResource list member x.AsList = let (ILResources ltab) = x in ltab @@ -1897,11 +2019,11 @@ type ILAssemblyLongevity = type ILAssemblyManifest = { Name: string AuxModuleHashAlgorithm: int32 - SecurityDecls: ILSecurityDecls + SecurityDeclsStored: ILSecurityDeclsStored PublicKey: byte[] option Version: ILVersionInfo option Locale: Locale option - CustomAttrs: ILAttributes + CustomAttrsStored: ILAttributesStored AssemblyLongevity: ILAssemblyLongevity DisableJitOptimizations: bool @@ -1913,7 +2035,10 @@ type ILAssemblyManifest = ExportedTypes: ILExportedTypesAndForwarders /// Records whether the entrypoint resides in another module. EntrypointElsewhere: ILModuleRef option + MetadataIndex: int32 } + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex + member x.SecurityDecls = x.SecurityDeclsStored.GetSecurityDecls x.MetadataIndex [] type ILNativeResource = @@ -1922,7 +2047,6 @@ type ILNativeResource = type ILModuleDef = { Manifest: ILAssemblyManifest option - CustomAttrs: ILAttributes Name: string TypeDefs: ILTypeDefs SubsystemVersion : int * int @@ -1942,6 +2066,8 @@ type ILModuleDef = MetadataVersion: string Resources: ILResources NativeResources: ILNativeResource list (* e.g. win32 resources *) + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } member x.ManifestOfAssembly = match x.Manifest with @@ -1951,6 +2077,7 @@ type ILModuleDef = member m.HasManifest = match m.Manifest with None -> false | _ -> true + member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex // -------------------------------------------------------------------- // Add fields and types to tables, with decent error messages @@ -2085,11 +2212,6 @@ let mkILFieldSpec (tref,ty) = { FieldRef= tref; DeclaringType=ty } let mkILFieldSpecInTy (typ:ILType,nm,fty) = mkILFieldSpec (mkILFieldRef (typ.TypeRef,nm,fty), typ) -let emptyILCustomAttrs = ILAttributes (fun () -> [| |]) - -let mkILCustomAttrsFromArray (l: ILAttribute[]) = if l.Length = 0 then emptyILCustomAttrs else ILAttributes (fun () -> l) -let mkILCustomAttrs l = l |> List.toArray |> mkILCustomAttrsFromArray -let mkILComputedCustomAttrs f = ILAttributes f let andTailness x y = match x with Tailcall when y -> Tailcall | _ -> Normalcall @@ -2125,20 +2247,17 @@ let nonBranchingInstrsToCode instrs : ILCode = // // -------------------------------------------------------------------- -let emptyILSecurityDecls = ILSecurityDecls.ILSecurityDecls [] -let mkILSecurityDecls l = match l with [] -> emptyILSecurityDecls | _ -> ILSecurityDecls.ILSecurityDecls l -let mkILLazySecurityDecls l = ILSecurityDecls.ILSecurityDeclsLazy l - let mkILTyvarTy tv = ILType.TypeVar tv let mkILSimpleTypar nm = - { Name=nm; + { Name=nm Constraints = [] - Variance=NonVariant; - HasReferenceTypeConstraint=false; - HasNotNullableValueTypeConstraint=false; - HasDefaultConstructorConstraint=false; - CustomAttrs = emptyILCustomAttrs } + Variance=NonVariant + HasReferenceTypeConstraint=false + HasNotNullableValueTypeConstraint=false + HasDefaultConstructorConstraint=false + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } let gparam_of_gactual (_ga:ILType) = mkILSimpleTypar "T" @@ -2162,13 +2281,17 @@ let mkRefForNestedILTypeDef scope (enc:ILTypeDef list,td:ILTypeDef) = // Operations on type tables. // -------------------------------------------------------------------- -let getName (ltd: Lazy) = - let td = Lazy.force ltd +let mkILPreTypeDef (td:ILTypeDef) = let ns,n = splitILTypeName td.Name - (ns,n,td.CustomAttrs,ltd) + ILPreTypeDef(ns, n, NoMetadataIdx, ILTypeDefStored.Given td) +let mkILPreTypeDefComputed (ns, n, f) = + ILPreTypeDef(ns, n, NoMetadataIdx, ILTypeDefStored.Computed f) +let mkILPreTypeDefRead (ns, n, idx, f) = + ILPreTypeDef(ns, n, idx, f) -let addILTypeDef td (tdefs: ILTypeDefs) = ILTypeDefs (fun () -> [| yield getName (notlazy td); yield! tdefs.AsArrayOfLazyTypeDefs |]) -let mkILTypeDefsFromArray l = ILTypeDefs (fun () -> Array.map (notlazy >> getName) l) + +let addILTypeDef td (tdefs: ILTypeDefs) = ILTypeDefs (fun () -> [| yield mkILPreTypeDef td; yield! tdefs.AsArrayOfPreTypeDefs |]) +let mkILTypeDefsFromArray (l: ILTypeDef[]) = ILTypeDefs (fun () -> Array.map mkILPreTypeDef l) let mkILTypeDefs l = mkILTypeDefsFromArray (Array.ofList l) let mkILTypeDefsComputed f = ILTypeDefs f let emptyILTypeDefs = mkILTypeDefsFromArray [| |] @@ -2476,21 +2599,23 @@ let instILType i t = instILTypeAux 0 i t // -------------------------------------------------------------------- let mkILParam (name,ty) : ILParameter = - { Name=name; - Default=None; - Marshal=None; - IsIn=false; - IsOut=false; - IsOptional=false; - Type=ty; - CustomAttrs=emptyILCustomAttrs } + { Name=name + Default=None + Marshal=None + IsIn=false + IsOut=false + IsOptional=false + Type=ty + CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } let mkILParamNamed (s,ty) = mkILParam (Some s,ty) let mkILParamAnon ty = mkILParam (None,ty) let mkILReturn ty : ILReturn = - { Marshal=None; - Type=ty; - CustomAttrs=emptyILCustomAttrs } + { Marshal=None + Type=ty + CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } let mkILLocal ty dbgInfo : ILLocal = { IsPinned=false; @@ -2592,7 +2717,7 @@ let mkILClassCtor impl = ret=mkILVoidReturn, isEntryPoint=false, securityDecls=emptyILSecurityDecls, - customAttrs = emptyILCustomAttrs, + customAttrs=emptyILCustomAttrs, body= mkMethBodyAux impl) // -------------------------------------------------------------------- @@ -2763,11 +2888,12 @@ let addNestedExportedTypeToTable (y: ILNestedExportedType) tab = Map.add y.Name y tab let mkTypeForwarder scopeRef name nested customAttrs access = - { ScopeRef=scopeRef; - Name=name; - Attributes=enum(0x00200000) ||| convertTypeAccessFlags access; - Nested=nested; - CustomAttrs=customAttrs; } + { ScopeRef=scopeRef + Name=name + Attributes=enum(0x00200000) ||| convertTypeAccessFlags access + Nested=nested + CustomAttrsStored=storeILCustomAttrs customAttrs + MetadataIndex = NoMetadataIdx } let mkILNestedExportedTypes l = ILNestedExportedTypes (notlazy (List.foldBack addNestedExportedTypeToTable l Map.empty)) @@ -2874,20 +3000,21 @@ let mkILSimpleModule assname modname dll subsystemVersion useHighEntropyVA tdefs let manifest = { Name=assname AuxModuleHashAlgorithm= match hashalg with | Some(alg) -> alg | _ -> 0x8004 // SHA1 - SecurityDecls=emptyILSecurityDecls + SecurityDeclsStored=emptyILSecurityDeclsStored PublicKey= None Version= None Locale=locale - CustomAttrs=emptyILCustomAttrs + CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs AssemblyLongevity=ILAssemblyLongevity.Unspecified DisableJitOptimizations = 0 <> (flags &&& 0x4000) JitTracking = (0 <> (flags &&& 0x8000)) // always turn these on IgnoreSymbolStoreSequencePoints = (0 <> (flags &&& 0x2000)) Retargetable = (0 <> (flags &&& 0x100)) ExportedTypes=exportedTypes - EntrypointElsewhere=None } + EntrypointElsewhere=None + MetadataIndex = NoMetadataIdx } { Manifest= Some manifest - CustomAttrs=emptyILCustomAttrs + CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs Name=modname NativeResources=[] TypeDefs=tdefs @@ -2906,6 +3033,7 @@ let mkILSimpleModule assname modname dll subsystemVersion useHighEntropyVA tdefs ImageBase=defaultImageBase MetadataVersion=metadataVersion Resources=mkILResources [] + MetadataIndex = NoMetadataIdx } @@ -3777,7 +3905,7 @@ and refs_of_modul s m = refs_of_resources s m.Resources Option.iter (refs_of_manifest s) m.Manifest -and refs_of_manifest s m = +and refs_of_manifest s (m: ILAssemblyManifest) = refs_of_custom_attrs s m.CustomAttrs refs_of_exported_types s m.ExportedTypes diff --git a/src/absil/il.fsi b/src/absil/il.fsi index a83be837f6a..33b077e1976 100644 --- a/src/absil/il.fsi +++ b/src/absil/il.fsi @@ -1,10 +1,8 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -/// The "unlinked" view of .NET metadata and code. Central to -/// to Abstract IL library +/// The "unlinked" view of .NET metadata and code. Central to the Abstract IL library module public Microsoft.FSharp.Compiler.AbstractIL.IL -open Internal.Utilities open System.Collections.Generic open System.Reflection @@ -16,49 +14,7 @@ type PrimaryAssembly = member Name: string -// ==================================================================== -// .NET binaries can be converted to the data structures below by using -// the functions in the "Ilread" module. -// -// Constituent types are listed in ascending order of complexity, -// all the way up to the type ILModuleDef, representing the read of an IL -// assembly (.dll or .exe), or part of a multi-module assembly. Types are -// often specified via a concrete representation for the type (e.g. a record), -// though some types are abstract. -// -// The second part of the file (after the definition of all the types) -// specifies a large set of utilities for building objects belonging to -// the types. You will only need to become familiar with these if you -// are transforming code or writing a code-generating compiler. -// -// Several other utilities are also defined in this file: -// 1. A code builder for turning linear sequences of instructions -// augmented with exception tables into the more structured -// format used for code. -// -// 2. The "typ_XYZ", "tspec_XYZ" and "mspec_XYZ" values which -// can be used to reference types in the "primary assembly (either System.Runtime or mscorlib)" assembly. -// -// 3. The "rescopeXYZ" functions which can be used to lift a piece of -// metadata from one assembly and transform it to a piece of metadata -// suitable for use from another assembly. The transformation adjusts -// references in the metadata to take into account the assembly -// where the metadata will now be located. -// -// 4. The "instantiateXYZ" utilities to replace type variables -// by types. These are associated with generics. -// -// 5. The "intern_XYZ" tables for reducing the memory used by -// generated constructs. -// -// 6. The "refs_of_XYZ" utilities for finding all the assemblies -// referenced by a module. -// -// 7. A somewhat obscure facility to allow new instructions and types -// to be added to the This is only used by ILX. -// ==================================================================== - -// Guids (Note: consider adjusting these to the System.Guid type) +/// Represents guids type ILGuid = byte[] [] @@ -104,10 +60,12 @@ type ILAssemblyRef = static member Create: name: string * hash: byte[] option * publicKey: PublicKey option * retargetable: bool * version: ILVersionInfo option * locale: string option -> ILAssemblyRef static member FromAssemblyName: System.Reflection.AssemblyName -> ILAssemblyRef member Name: string + /// The fully qualified name of the assembly reference, e.g. mscorlib, Version=1.0.3705 etc. member QualifiedName: string member Hash: byte[] option member PublicKey: PublicKey option + /// CLI says this indicates if the assembly can be retargeted (at runtime) to be from a different publisher. member Retargetable: bool member Version: ILVersionInfo option @@ -123,67 +81,7 @@ type ILModuleRef = interface System.IComparable // Scope references -// -// Scope references are the bits of metadata attached to type names -// that indicate where a type can be found. CIL has three -// kinds: local, module and assembly references: -// o Local: the type must reside in the same module as the scope reference -// o Module: the type must reside in the indicated module in the same -// assembly as the scope reference -// o Assembly: The type must reside in the indicated assembly. -// These have no implicit context. Assembly references can end up -// binding to the assembly containing the reference, i.e. -// may be self or mutually referential. -// -// Assembly reference may also resolve to type in an -// auxiliary module of an assembly when the assembly -// has an "exported types" (here called "classes elsewhere") table. -// -// We represent these references by values embedded within type -// references. These values are usually "shared" across the data -// structures for a module, i.e. one such value is created for each -// assembly or module reference, and this value is reused within each -// type object. -// -// Note that as with method references the term structure is not -// _linked_, i.e. a "ILScopeRef" is still a _reference_ to a scope, -// not the scope itself. Because the structure is not linked, -// the Abstract IL toolset does not require -// strongly connected inputs: you can manipulate an assembly -// without loading all its dependent assemblies. This is the primary -// difference between Abstract IL and Reflection, and it can be both -// a blessing and a curse depending on the kind of manipulation you -// wish to perform. -// -// Similarly, you can manipulate individual modules within -// an assembly without having the whole assembly loaded. (But note that -// most assemblies are single-module in any case). -// -// [ILScopeRef]'s _cannot_ be compared for equality in the way that -// might be expected, in these sense that two ILScopeRef's may -// resolve to the same assembly/module even though they are not equal. -// -// Aside: People have suggested normalizing all scope references -// so that this would be possible, and early versions of this -// toolkit did this. However, this meant that in order to load -// each module you had to tell the toolkit which assembly it belonged to. -// Furthermore, you had to know the exact resolved details of -// each assembly the module refers to. This is -// effectively like having a "fully-linked" view of the graph -// of assemblies, like that provided in the Ilbind module. This is really problematic for compile-time tools, -// as, for example, the policy for linking at the runtime-machine -// may actually alter the results of linking. If such compile-time -// assumptions are to be made then the tool built on top -// of the toolkit rather than the toolkit itself should -// make them. -// -// Scope references, type references, field references and method references -// can be "bound" to particular assemblies using the functions in "Ilbind". -// This simulates the resolution/binding process performed by a Common Language -// Runtime during execution. Various tests and derived operations -// can then be performed on the results of binding. -[] -[] +[] type ILScopeRef = /// A reference to the type in the current module | Local @@ -228,29 +126,31 @@ type ILThisConvention = [] type ILCallingConv = | Callconv of ILThisConvention * ILArgConvention + member IsInstance: bool member IsInstanceExplicit: bool member IsStatic: bool member ThisConv: ILThisConvention member BasicConv: ILArgConvention + static member Instance: ILCallingConv static member Static : ILCallingConv -/// Array shapes. For most purposes, including verification, the -/// rank is the only thing that matters. - +/// Array shapes. For most purposes the rank is the only thing that matters. type ILArrayBound = int32 option + +/// Lower-bound/size pairs type ILArrayBounds = ILArrayBound * ILArrayBound -[] type ILArrayShape = - | ILArrayShape of ILArrayBounds list // lobound/size pairs + | ILArrayShape of ILArrayBounds list + member Rank: int + /// Bounds for a single dimensional, zero based array static member SingleDimensional: ILArrayShape static member FromRank: int -> ILArrayShape -[] type ILBoxity = | AsObject | AsValue @@ -291,14 +191,6 @@ type ILTypeRef = interface System.IComparable /// Type specs and types. -/// -/// These are the types that appear syntactically in .NET binaries. -/// -/// Generic type definitions must be combined with -/// an instantiation to form a type. Throughout this file, -/// a "ref" refers to something that is uninstantiated, and -/// a "spec" to a ref that is combined with the relevant instantiations. - [] type ILTypeSpec = static member Create: typeRef:ILTypeRef * instantiation:ILGenericArgs -> ILTypeSpec @@ -317,22 +209,31 @@ type ILTypeSpec = and [] ILType = + /// Used only in return and pointer types. | Void + /// Array types | Array of ILArrayShape * ILType + /// Unboxed types, including builtin types. | Value of ILTypeSpec + /// Reference types. Also may be used for parents of members even if for members in value types. | Boxed of ILTypeSpec + /// Unmanaged pointers. Nb. the type is used by tools and for binding only, not by the verifier. | Ptr of ILType + /// Managed pointers. | Byref of ILType + /// ILCode pointers. | FunctionPointer of ILCallingSignature + /// Reference a generic arg. | TypeVar of uint16 + /// Custom modifiers. | Modified of /// True if modifier is "required". @@ -341,6 +242,7 @@ and ILTypeRef * /// The type being modified. ILType + member TypeSpec: ILTypeSpec member Boxity: ILBoxity member TypeRef: ILTypeRef @@ -357,22 +259,17 @@ and [] ReturnType: ILType } /// Actual generic parameters are always types. +and ILGenericArgs = ILType list +and ILTypes = ILType list -and ILGenericArgs = list -and ILTypes = list - -/// Formal identities of methods. Method refs refer to methods on -/// named types. In general you should work with ILMethodSpec objects -/// rather than MethodRef objects, because ILMethodSpec objects carry -/// information about how generic methods are instantiated. MethodRef -/// objects are only used at a few places in the Abstract IL syntax -/// and if analyzing or generating IL you will be unlikely to come across -/// these. - +/// Formal identities of methods. [] type ILMethodRef = + + /// Functional creation static member Create: enclosingTypeRef: ILTypeRef * callingConv: ILCallingConv * name: string * genericArity: int * argTypes: ILTypes * returnType: ILType -> ILMethodRef + member DeclaringTypeRef: ILTypeRef member CallingConv: ILCallingConv member Name: string @@ -383,8 +280,7 @@ type ILMethodRef = member CallingSignature: ILCallingSignature interface System.IComparable -/// Formal identities of fields. - +/// Formal identities of fields. [] type ILFieldRef = { DeclaringTypeRef: ILTypeRef @@ -392,21 +288,12 @@ type ILFieldRef = Type: ILType } /// The information at the callsite of a method -// -// A ILMethodSpec is everything given at the callsite (apart from whether the call is a tailcall and whether it is passing -// varargs - see the instruction set below). It is made up of: -// 1) a (possibly generic) ILMethodRef -// 2) a "usage type" that indicates the how the type containing the declaration is being used (as -// a value class, a boxed value class, an instantiated generic class or whatever - see below) -// 3) an instantiation in the case where the method is generic. -// -// In this unbound form of the metadata, the enclosing type may be ILType.Boxed even when the member is a member of a value type or -// enumeration. This is because the binary format of the metadata does not carry enough information in a MemberRefParent to determine -// from the binary alone whether the enclosing type is a value type or not. - [] type ILMethodSpec = + + /// Functional creation static member Create: ILType * ILMethodRef * ILGenericArgs -> ILMethodSpec + member MethodRef: ILMethodRef member DeclaringType: ILType member GenericArgs: ILGenericArgs @@ -417,20 +304,18 @@ type ILMethodSpec = member FormalReturnType: ILType interface System.IComparable - /// Field specs. The data given for a ldfld, stfld etc. instruction. [] type ILFieldSpec = { FieldRef: ILFieldRef DeclaringType: ILType } + member DeclaringTypeRef: ILTypeRef member Name: string member FormalType: ILType member ActualType: ILType -/// ILCode labels. In structured code each code label -/// refers to a basic block somewhere in the code of the method. - +/// ILCode labels. In structured code each code label refers to a basic block somewhere in the code of the method. type ILCodeLabel = int [] @@ -499,15 +384,8 @@ type ILComparisonInstr = | BI_brtrue /// The instruction set. -/// -/// In general we don't categorize instructions, as different -/// instruction groups are relevant for different types of operations. -/// However we do collect the branch and compare instructions together -/// because they all take an address, and the ILArithInstr ones because -/// none of them take any direct arguments. [] type ILInstr = - // Basic | AI_add | AI_add_ovf | AI_add_ovf_un @@ -641,11 +519,10 @@ type ILInstr = | I_cpblk of ILAlignment * ILVolatility | I_initblk of ILAlignment * ILVolatility - // EXTENSIONS, e.g. MS-ILX + // EXTENSIONS | EI_ilzero of ILType | EI_ldlen_multi of int32 * int32 - [] type ILExceptionClause = | Finally of (ILCodeLabel * ILCodeLabel) @@ -679,7 +556,6 @@ type ILCode = Locals: ILLocalDebugInfo list } /// Field Init - [] type ILFieldInit = | String of string @@ -746,7 +622,6 @@ type ILNativeVariant = /// Native Types, for marshalling to the native C interface. /// These are taken directly from the ILASM syntax, see ECMA Spec (Partition II, 7.4). - [] type ILNativeType = | Empty @@ -774,7 +649,8 @@ type ILNativeType = | UInt16 | UInt32 | UInt64 - | Array of ILNativeType option * (int32 * int32 option) option (* optional idx of parameter giving size plus optional additive i.e. num elems *) + /// optional idx of parameter giving size plus optional additive i.e. num elems + | Array of ILNativeType option * (int32 * int32 option) option | Int | UInt | Method @@ -788,7 +664,6 @@ type ILNativeType = | ANSIBSTR | VariantBool - /// Local variables [] type ILLocal = @@ -802,7 +677,6 @@ type ILLocals = list [] type ILMethodBody = { IsZeroInit: bool - /// strictly speaking should be a uint16 MaxStack: int32 NoInlining: bool AggressiveInlining: bool @@ -852,13 +726,16 @@ type ILAttribute = Data: byte[] Elements: ILAttribElem list} -[] +[] type ILAttributes = member AsArray: ILAttribute [] member AsList: ILAttribute list -/// Method parameters and return values. +/// Represents the efficiency-oriented storage of ILAttributes in another item. +[] +type ILAttributesStored +/// Method parameters and return values. [] type ILParameter = { Name: string option @@ -869,7 +746,9 @@ type ILParameter = IsIn: bool IsOut: bool IsOptional: bool - CustomAttrs: ILAttributes } + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + member CustomAttrs: ILAttributes type ILParameters = list @@ -880,10 +759,11 @@ val typesOfILParams: ILParameters -> ILType list type ILReturn = { Marshal: ILNativeType option Type: ILType - CustomAttrs: ILAttributes } + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + + member CustomAttrs: ILAttributes -/// Security ILSecurityDecls -/// Attached to various structures... [] type ILSecurityAction = | Request @@ -910,10 +790,14 @@ type ILSecurityDecl = /// Abstract type equivalent to ILSecurityDecl list - use helpers /// below to construct/destruct these. -[] +[] type ILSecurityDecls = member AsList: ILSecurityDecl list +/// Represents the efficiency-oriented storage of ILSecurityDecls in another item. +[] +type ILSecurityDeclsStored + /// PInvoke attributes. [] type PInvokeCallingConvention = @@ -955,18 +839,12 @@ type PInvokeMethod = CharBestFit: PInvokeCharBestFit } -/// [OverridesSpec] - refer to a method declaration in a superclass -/// or superinterface. Used for overriding/method impls. Includes -/// a type for the parent for the same reason that a method specs -/// includes the type of the enclosing type, i.e. the type -/// gives the "ILGenericArgs" at which the parent type is being used. - +/// [OverridesSpec] - refer to a method declaration in a superclass or interface. type ILOverridesSpec = | OverridesSpec of ILMethodRef * ILType member MethodRef: ILMethodRef member DeclaringType: ILType -// REVIEW: fold this into ILMethodDef. type ILMethodVirtualInfo = { IsFinal: bool IsNewSlot: bool @@ -981,24 +859,21 @@ type MethodKind = | NonVirtual | Virtual of ILMethodVirtualInfo -// REVIEW: fold this into ILMethodDef. [] type MethodBody = | IL of ILMethodBody - | PInvoke of PInvokeMethod (* platform invoke to native *) + | PInvoke of PInvokeMethod | Abstract | Native | NotAvailable -// REVIEW: fold this into ILMethodDef. [] type MethodCodeKind = | IL | Native | Runtime -/// Generic parameters. Formal generic parameter declarations -/// may include the bounds, if any, on the generic parameter. +/// Generic parameters. Formal generic parameter declarations may include the bounds, if any, on the generic parameter. type ILGenericParameterDef = { Name: string @@ -1011,13 +886,19 @@ type ILGenericParameterDef = /// Indicates the type argument must be a reference type. HasReferenceTypeConstraint: bool - CustomAttrs: ILAttributes - /// Indicates the type argument must be a value type, but not Nullable. HasNotNullableValueTypeConstraint: bool /// Indicates the type argument must have a public nullary constructor. - HasDefaultConstructorConstraint: bool } + HasDefaultConstructorConstraint: bool + + /// Do not use this + CustomAttrsStored: ILAttributesStored + + /// Do not use this + MetadataIndex: int32 } + + member CustomAttrs: ILAttributes type ILGenericParameterDefs = ILGenericParameterDef list @@ -1026,14 +907,18 @@ type ILLazyMethodBody = member Contents: MethodBody /// IL Method definitions. -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. [] type ILMethodDef = - /// Functional creation of a value - new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * parameters: ILParameters * ret: ILReturn * body: ILLazyMethodBody * securityDecls: ILSecurityDecls * isEntryPoint:bool * genericParams: ILGenericParameterDefs * customAttrs: ILAttributes -> ILMethodDef + /// Functional creation of a value, with delayed reading of some elements via a metadata index + new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * + parameters: ILParameters * ret: ILReturn * body: ILLazyMethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * + securityDeclsStored: ILSecurityDeclsStored * customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILMethodDef + + /// Functional creation of a value, immediate + new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * + parameters: ILParameters * ret: ILReturn * body: ILLazyMethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * + securityDecls: ILSecurityDecls * customAttrs: ILAttributes -> ILMethodDef member Name: string member Attributes: MethodAttributes @@ -1096,7 +981,9 @@ type ILMethodDef = member IsMustRun: bool /// Functional update of the value - member With: ?name: string * ?attributes: MethodAttributes * ?implAttributes: MethodImplAttributes * ?callingConv: ILCallingConv * ?parameters: ILParameters * ?ret: ILReturn * ?body: ILLazyMethodBody * ?securityDecls: ILSecurityDecls * ?isEntryPoint:bool * ?genericParams: ILGenericParameterDefs * ?customAttrs: ILAttributes -> ILMethodDef + member With: ?name: string * ?attributes: MethodAttributes * ?implAttributes: MethodImplAttributes * ?callingConv: ILCallingConv * + ?parameters: ILParameters * ?ret: ILReturn * ?body: ILLazyMethodBody * ?securityDecls: ILSecurityDecls * ?isEntryPoint:bool * + ?genericParams: ILGenericParameterDefs * ?customAttrs: ILAttributes -> ILMethodDef member WithSpecialName: ILMethodDef member WithHideBySig: unit -> ILMethodDef member WithHideBySig: bool -> ILMethodDef @@ -1115,9 +1002,6 @@ type ILMethodDef = /// Tables of methods. Logically equivalent to a list of methods but /// the table is kept in a form optimized for looking up methods by /// name and arity. -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. [] type ILMethodDefs = interface IEnumerable @@ -1126,14 +1010,18 @@ type ILMethodDefs = member FindByName: string -> ILMethodDef list /// Field definitions. -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. [] type ILFieldDef = - /// Functional creation of a value - new: name: string * fieldType: ILType * attributes: FieldAttributes * data: byte[] option * literalValue: ILFieldInit option * offset: int32 option * marshal: ILNativeType option * customAttrs: ILAttributes -> ILFieldDef + /// Functional creation of a value using delayed reading via a metadata index + new: name: string * fieldType: ILType * attributes: FieldAttributes * data: byte[] option * + literalValue: ILFieldInit option * offset: int32 option * marshal: ILNativeType option * + customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILFieldDef + + /// Functional creation of a value, immediate + new: name: string * fieldType: ILType * attributes: FieldAttributes * data: byte[] option * + literalValue: ILFieldInit option * offset: int32 option * marshal: ILNativeType option * + customAttrs: ILAttributes -> ILFieldDef member Name: string member FieldType: ILType @@ -1144,7 +1032,7 @@ type ILFieldDef = /// The explicit offset in bytes when explicit layout is used. member Offset: int32 option member Marshal: ILNativeType option - member CustomAttrs: ILAttributes + member CustomAttrs: ILAttributes member IsStatic: bool member IsSpecialName: bool member IsLiteral: bool @@ -1153,7 +1041,8 @@ type ILFieldDef = member Access: ILMemberAccess /// Functional update of the value - member With: ?name: string * ?fieldType: ILType * ?attributes: FieldAttributes * ?data: byte[] option * ?literalValue: ILFieldInit option * ?offset: int32 option * ?marshal: ILNativeType option * ?customAttrs: ILAttributes -> ILFieldDef + member With: ?name: string * ?fieldType: ILType * ?attributes: FieldAttributes * ?data: byte[] option * ?literalValue: ILFieldInit option * + ?offset: int32 option * ?marshal: ILNativeType option * ?customAttrs: ILAttributes -> ILFieldDef member WithAccess: ILMemberAccess -> ILFieldDef member WithInitOnly: bool -> ILFieldDef member WithStatic: bool -> ILFieldDef @@ -1162,23 +1051,26 @@ type ILFieldDef = member WithLiteralDefaultValue: ILFieldInit option -> ILFieldDef member WithFieldMarshal: ILNativeType option -> ILFieldDef -/// Tables of fields. Logically equivalent to a list of fields but -/// the table is kept in a form optimized for looking up fields by -/// name. +/// Tables of fields. Logically equivalent to a list of fields but the table is kept in +/// a form to allow efficient looking up fields by name. [] type ILFieldDefs = member AsList: ILFieldDef list member LookupByName: string -> ILFieldDef list /// Event definitions. -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. [] type ILEventDef = - /// Functional creation of a value - new: eventType: ILType option * name: string * attributes: EventAttributes * addMethod: ILMethodRef * removeMethod: ILMethodRef * fireMethod: ILMethodRef option * otherMethods: ILMethodRef list * customAttrs: ILAttributes -> ILEventDef + /// Functional creation of a value, using delayed reading via a metadata index, for ilread.fs + new: eventType: ILType option * name: string * attributes: EventAttributes * addMethod: ILMethodRef * + removeMethod: ILMethodRef * fireMethod: ILMethodRef option * otherMethods: ILMethodRef list * + customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILEventDef + + /// Functional creation of a value, immediate + new: eventType: ILType option * name: string * attributes: EventAttributes * addMethod: ILMethodRef * + removeMethod: ILMethodRef * fireMethod: ILMethodRef option * otherMethods: ILMethodRef list * + customAttrs: ILAttributes -> ILEventDef member EventType: ILType option member Name: string @@ -1192,29 +1084,29 @@ type ILEventDef = member IsRTSpecialName: bool /// Functional update of the value - member With: ?eventType: ILType option * ?name: string * ?attributes: EventAttributes * ?addMethod: ILMethodRef * ?removeMethod: ILMethodRef * ?fireMethod: ILMethodRef option * ?otherMethods: ILMethodRef list * ?customAttrs: ILAttributes -> ILEventDef + member With: ?eventType: ILType option * ?name: string * ?attributes: EventAttributes * ?addMethod: ILMethodRef * + ?removeMethod: ILMethodRef * ?fireMethod: ILMethodRef option * ?otherMethods: ILMethodRef list * + ?customAttrs: ILAttributes -> ILEventDef /// Table of those events in a type definition. -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. [] type ILEventDefs = member AsList: ILEventDef list member LookupByName: string -> ILEventDef list /// Property definitions -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. [] type ILPropertyDef = - /// Functional creation of a value - new: name: string * attributes: PropertyAttributes * setMethod: ILMethodRef option * getMethod: ILMethodRef option * callingConv: ILThisConvention * propertyType: ILType * init: ILFieldInit option * args: ILTypes * customAttrs: ILAttributes -> ILPropertyDef + /// Functional creation of a value, using delayed reading via a metadata index, for ilread.fs + new: name: string * attributes: PropertyAttributes * setMethod: ILMethodRef option * getMethod: ILMethodRef option * + callingConv: ILThisConvention * propertyType: ILType * init: ILFieldInit option * args: ILTypes * + customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILPropertyDef - /// Functional update of the value - member With: ?name: string * ?attributes: PropertyAttributes * ?setMethod: ILMethodRef option * ?getMethod: ILMethodRef option * ?callingConv: ILThisConvention * ?propertyType: ILType * ?init: ILFieldInit option * ?args: ILTypes * ?customAttrs: ILAttributes -> ILPropertyDef + /// Functional creation of a value, immediate + new: name: string * attributes: PropertyAttributes * setMethod: ILMethodRef option * getMethod: ILMethodRef option * + callingConv: ILThisConvention * propertyType: ILType * init: ILFieldInit option * args: ILTypes * + customAttrs: ILAttributes -> ILPropertyDef member Name: string member Attributes: PropertyAttributes @@ -1228,6 +1120,11 @@ type ILPropertyDef = member IsSpecialName: bool member IsRTSpecialName: bool + /// Functional update of the value + member With: ?name: string * ?attributes: PropertyAttributes * ?setMethod: ILMethodRef option * ?getMethod: ILMethodRef option * + ?callingConv: ILThisConvention * ?propertyType: ILType * ?init: ILFieldInit option * ?args: ILTypes * + ?customAttrs: ILAttributes -> ILPropertyDef + /// Table of properties in an IL type definition. [] [] @@ -1284,11 +1181,8 @@ type ILTypeDefKind = | Enum | Delegate -/// Tables of named type definitions. The types and table may contain on-demand -/// (lazy) computations, e.g. the actual reading of some aspects -/// of a type definition may be delayed. -[] -[] +/// Tables of named type definitions. +[] type ILTypeDefs = interface IEnumerable @@ -1297,7 +1191,7 @@ type ILTypeDefs = member AsList: ILTypeDef list /// Get some information about the type defs, but do not force the read of the type defs themselves. - member AsArrayOfLazyTypeDefs: (string list * string * ILAttributes * Lazy) array + member AsArrayOfPreTypeDefs: ILPreTypeDef[] /// Calls to FindByName will result in any laziness in the overall /// set of ILTypeDefs being read in in addition @@ -1306,19 +1200,18 @@ type ILTypeDefs = member FindByName: string -> ILTypeDef /// Represents IL Type Definitions. -/// -/// This type is immutable and record-like. We use a class to get control over the representation -/// used, which allows more efficient representation of the information. and [] ILTypeDef = - /// Create the contents + /// Functional creation of a value, using delayed reading via a metadata index, for ilread.fs new: name: string * attributes: TypeAttributes * layout: ILTypeDefLayout * implements: ILTypes * genericParams: ILGenericParameterDefs * extends: ILType option * methods: ILMethodDefs * nestedTypes: ILTypeDefs * fields: ILFieldDefs * methodImpls: ILMethodImplDefs * - events: ILEventDefs * properties: ILPropertyDefs * customAttrs: ILAttributes * securityDecls: ILSecurityDecls -> ILTypeDef + events: ILEventDefs * properties: ILPropertyDefs * securityDeclsStored: ILSecurityDeclsStored * customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILTypeDef - /// Update the contents - member With: ?name: string * ?attributes: TypeAttributes * ?layout: ILTypeDefLayout * ?implements: ILTypes * ?genericParams:ILGenericParameterDefs * ?extends:ILType option * ?methods:ILMethodDefs * ?nestedTypes:ILTypeDefs * ?fields: ILFieldDefs * ?methodImpls:ILMethodImplDefs * ?events:ILEventDefs * ?properties:ILPropertyDefs * ?customAttrs:ILAttributes * ?securityDecls: ILSecurityDecls -> ILTypeDef + /// Functional creation of a value, immediate + new: name: string * attributes: TypeAttributes * layout: ILTypeDefLayout * implements: ILTypes * genericParams: ILGenericParameterDefs * + extends: ILType option * methods: ILMethodDefs * nestedTypes: ILTypeDefs * fields: ILFieldDefs * methodImpls: ILMethodImplDefs * + events: ILEventDefs * properties: ILPropertyDefs * securityDecls: ILSecurityDecls * customAttrs: ILAttributes -> ILTypeDef member Name: string member Attributes: TypeAttributes @@ -1365,8 +1258,32 @@ and [] member WithSpecialName: bool -> ILTypeDef member WithInitSemantics: ILTypeInit -> ILTypeDef -[] -[] + /// Functional update + member With: ?name: string * ?attributes: TypeAttributes * ?layout: ILTypeDefLayout * ?implements: ILTypes * + ?genericParams:ILGenericParameterDefs * ?extends:ILType option * ?methods:ILMethodDefs * + ?nestedTypes:ILTypeDefs * ?fields: ILFieldDefs * ?methodImpls:ILMethodImplDefs * ?events:ILEventDefs * + ?properties:ILPropertyDefs * ?customAttrs:ILAttributes * ?securityDecls: ILSecurityDecls -> ILTypeDef + +/// Represents a prefix of information for ILTypeDef. +/// +/// The information is enough to perform name resolution for the F# compiler, probe attributes +/// for ExtensionAttribute etc. This is key to the on-demand exploration of .NET metadata. +/// This information has to be "Goldilocks" - not too much, not too little, just right. +and [] ILPreTypeDef = + member Namespace: string list + member Name: string + member MetadataIndex: int32 + /// Realise the actual full typedef + member GetTypeDef : unit -> ILTypeDef + +and [] ILTypeDefStored + +val mkILPreTypeDef : ILTypeDef -> ILPreTypeDef +val mkILPreTypeDefComputed : string list * string * (unit -> ILTypeDef) -> ILPreTypeDef +val mkILPreTypeDefRead : string list * string * int32 * ILTypeDefStored -> ILPreTypeDef +val mkILTypeDefReader: (int32 -> ILTypeDef) -> ILTypeDefStored + +[] type ILNestedExportedTypes = member AsList: ILNestedExportedType list @@ -1401,7 +1318,9 @@ and ILNestedExportedType = { Name: string Access: ILMemberAccess Nested: ILNestedExportedTypes - CustomAttrs: ILAttributes } + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } + member CustomAttrs: ILAttributes /// these are only found in the ILExportedTypesAndForwarders table in the manifest [] @@ -1411,9 +1330,11 @@ type ILExportedTypeOrForwarder = Name: string Attributes: TypeAttributes Nested: ILNestedExportedTypes - CustomAttrs: ILAttributes } + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } member Access: ILTypeDefAccess member IsForwarder: bool + member CustomAttrs: ILAttributes [] [] @@ -1447,11 +1368,14 @@ type ILResource = { Name: string Location: ILResourceLocation Access: ILResourceAccess - CustomAttrs: ILAttributes } + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } /// Read the bytes from a resource local to an assembly. Will fail for non-local resources. member GetBytes : unit -> byte[] + member CustomAttrs: ILAttributes + /// Table of resources in a module. [] [] @@ -1476,7 +1400,7 @@ type ILAssemblyManifest = /// cryptographic hashes: they are simple file hashes. The algorithm /// is normally 0x00008004 indicating the SHA1 hash algorithm. AuxModuleHashAlgorithm: int32 - SecurityDecls: ILSecurityDecls + SecurityDeclsStored: ILSecurityDeclsStored /// This is the public key used to sign this /// assembly (the signature itself is stored elsewhere: see the /// binary format, and may not have been written if delay signing @@ -1485,7 +1409,7 @@ type ILAssemblyManifest = PublicKey: byte[] option Version: ILVersionInfo option Locale: string option - CustomAttrs: ILAttributes + CustomAttrsStored: ILAttributesStored AssemblyLongevity: ILAssemblyLongevity DisableJitOptimizations: bool JitTracking: bool @@ -1496,7 +1420,11 @@ type ILAssemblyManifest = ExportedTypes: ILExportedTypesAndForwarders /// Records whether the entrypoint resides in another module. EntrypointElsewhere: ILModuleRef option + MetadataIndex: int32 } + member CustomAttrs: ILAttributes + member SecurityDecls: ILSecurityDecls + [] type ILNativeResource = @@ -1513,7 +1441,6 @@ type ILNativeResource = /// several auxiliary modules. type ILModuleDef = { Manifest: ILAssemblyManifest option - CustomAttrs: ILAttributes Name: string TypeDefs: ILTypeDefs SubsystemVersion: int * int @@ -1530,11 +1457,14 @@ type ILModuleDef = PhysicalAlignment: int32 ImageBase: int32 MetadataVersion: string - Resources: ILResources + Resources: ILResources /// e.g. win86 resources, as the exact contents of a .res or .obj file. Must be unlinked manually. - NativeResources: ILNativeResource list } + NativeResources: ILNativeResource list + CustomAttrsStored: ILAttributesStored + MetadataIndex: int32 } member ManifestOfAssembly: ILAssemblyManifest member HasManifest: bool + member CustomAttrs: ILAttributes /// Find the method definition corresponding to the given property or /// event operation. These are always in the same class as the property @@ -1571,8 +1501,8 @@ val splitILTypeNameWithPossibleStaticArguments: string -> string[] * string /// namespace is kept as a whole string, rather than split at dots. val splitTypeNameRight: string -> string option * string - val typeNameForGlobalFunctions: string + val isTypeNameForGlobalFunctions: string -> bool val ungenericizeTypeName: string -> string (* e.g. List`1 --> List *) @@ -1634,6 +1564,7 @@ val decodeILAttribData: /// Generate simple references to assemblies and modules. val mkSimpleAssRef: string -> ILAssemblyRef + val mkSimpleModRef: string -> ILModuleRef val mkILTyvarTy: uint16 -> ILType @@ -1693,14 +1624,14 @@ val mkILFieldSpecInTy: ILType * string * ILType -> ILFieldSpec val mkILCallSig: ILCallingConv * ILType list * ILType -> ILCallingSignature -/// Make generalized versions of possibly-generic types, -/// e.g. Given the ILTypeDef for List, return the type "List". +/// Make generalized versions of possibly-generic types, e.g. Given the ILTypeDef for List, return the type "List". val mkILFormalBoxedTy: ILTypeRef -> ILGenericParameterDef list -> ILType val mkILFormalNamedTy: ILBoxity -> ILTypeRef -> ILGenericParameterDef list -> ILType val mkILFormalTypars: ILType list -> ILGenericParameterDefs val mkILFormalGenericArgs: int -> ILGenericParameterDefs -> ILGenericArgsList val mkILSimpleTypar: string -> ILGenericParameterDef + /// Make custom attributes. val mkILCustomAttribMethRef: ILGlobals @@ -1830,12 +1761,14 @@ val mkILTypeForGlobalFunctions: ILScopeRef -> ILType /// Making tables of custom attributes, etc. val mkILCustomAttrs: ILAttribute list -> ILAttributes val mkILCustomAttrsFromArray: ILAttribute[] -> ILAttributes -val mkILComputedCustomAttrs: (unit -> ILAttribute[]) -> ILAttributes +val storeILCustomAttrs: ILAttributes -> ILAttributesStored +val mkILCustomAttrsReader: (int32 -> ILAttribute[]) -> ILAttributesStored val emptyILCustomAttrs: ILAttributes val mkILSecurityDecls: ILSecurityDecl list -> ILSecurityDecls -val mkILLazySecurityDecls: Lazy -> ILSecurityDecls val emptyILSecurityDecls: ILSecurityDecls +val storeILSecurityDecls: ILSecurityDecls -> ILSecurityDeclsStored +val mkILSecurityDeclsReader: (int32 -> ILSecurityDecl[]) -> ILSecurityDeclsStored val mkMethBodyAux: MethodBody -> ILLazyMethodBody val mkMethBodyLazyAux: Lazy -> ILLazyMethodBody @@ -1873,7 +1806,7 @@ val emptyILTypeDefs: ILTypeDefs /// /// Note that individual type definitions may contain further delays /// in their method, field and other tables. -val mkILTypeDefsComputed: (unit -> (string list * string * ILAttributes * Lazy) array) -> ILTypeDefs +val mkILTypeDefsComputed: (unit -> ILPreTypeDef[]) -> ILTypeDefs val addILTypeDef: ILTypeDef -> ILTypeDefs -> ILTypeDefs val mkTypeForwarder: ILScopeRef -> string -> ILNestedExportedTypes -> ILAttributes -> ILTypeDefAccess -> ILExportedTypeOrForwarder @@ -1905,6 +1838,7 @@ val mkRefToILField: ILTypeRef * ILFieldDef -> ILFieldRef val mkRefToILAssembly: ILAssemblyManifest -> ILAssemblyRef val mkRefToILModule: ILModuleDef -> ILModuleRef +val NoMetadataIdx: int32 // -------------------------------------------------------------------- // Rescoping. @@ -1927,15 +1861,19 @@ val mkRefToILModule: ILModuleDef -> ILModuleRef /// Rescoping. The first argument tells the function how to reference the original scope from /// the new scope. val rescopeILScopeRef: ILScopeRef -> ILScopeRef -> ILScopeRef + /// Rescoping. The first argument tells the function how to reference the original scope from /// the new scope. val rescopeILTypeSpec: ILScopeRef -> ILTypeSpec -> ILTypeSpec + /// Rescoping. The first argument tells the function how to reference the original scope from /// the new scope. val rescopeILType: ILScopeRef -> ILType -> ILType + /// Rescoping. The first argument tells the function how to reference the original scope from /// the new scope. val rescopeILMethodRef: ILScopeRef -> ILMethodRef -> ILMethodRef + /// Rescoping. The first argument tells the function how to reference the original scope from /// the new scope. val rescopeILFieldRef: ILScopeRef -> ILFieldRef -> ILFieldRef @@ -1943,26 +1881,14 @@ val rescopeILFieldRef: ILScopeRef -> ILFieldRef -> ILFieldRef /// Unscoping. Clears every scope information, use for looking up IL method references only. val unscopeILType: ILType -> ILType -//----------------------------------------------------------------------- -// The ILCode Builder utility. -//---------------------------------------------------------------------- - val buildILCode: string -> lab2pc: Dictionary -> instrs:ILInstr[] -> ILExceptionSpec list -> ILLocalDebugInfo list -> ILCode -// -------------------------------------------------------------------- -// The instantiation utilities. -// -------------------------------------------------------------------- - /// Instantiate type variables that occur within types and other items. val instILTypeAux: int -> ILGenericArgs -> ILType -> ILType /// Instantiate type variables that occur within types and other items. val instILType: ILGenericArgs -> ILType -> ILType -// -------------------------------------------------------------------- -// ECMA globals -// -------------------------------------------------------------------- - /// This is a 'vendor neutral' way of referencing mscorlib. val ecmaPublicKey: PublicKey @@ -2002,19 +1928,14 @@ val getTyOfILEnumInfo: ILEnumInfo -> ILType val computeILEnumInfo: string * ILFieldDefs -> ILEnumInfo - -// -------------------------------------------------------------------- -// For completeness. These do not occur in metadata but tools that -// care about the existence of properties and events in the metadata -// can benefit from them. -// -------------------------------------------------------------------- - +/// A utility type provided for completeness [] type ILEventRef = static member Create: ILTypeRef * string -> ILEventRef member DeclaringTypeRef: ILTypeRef member Name: string +/// A utility type provided for completeness [] type ILPropertyRef = static member Create: ILTypeRef * string -> ILPropertyRef diff --git a/src/absil/ilmorph.fs b/src/absil/ilmorph.fs index 4e8d4ed8c01..ad28e1736a2 100644 --- a/src/absil/ilmorph.fs +++ b/src/absil/ilmorph.fs @@ -200,8 +200,8 @@ let morphILTypesInILInstr ((factualty,fformalty)) i = | ILToken.ILField fr -> I_ldtoken (ILToken.ILField (conv_fspec fr)) | x -> x -let return_typ2typ ilg f (r:ILReturn) = {r with Type=f r.Type; CustomAttrs=cattrs_typ2typ ilg f r.CustomAttrs} -let param_typ2typ ilg f (p: ILParameter) = {p with Type=f p.Type; CustomAttrs=cattrs_typ2typ ilg f p.CustomAttrs} +let return_typ2typ ilg f (r:ILReturn) = {r with Type=f r.Type; CustomAttrsStored= storeILCustomAttrs (cattrs_typ2typ ilg f r.CustomAttrs)} +let param_typ2typ ilg f (p: ILParameter) = {p with Type=f p.Type; CustomAttrsStored= storeILCustomAttrs (cattrs_typ2typ ilg f p.CustomAttrs)} let morphILMethodDefs f (m:ILMethodDefs) = mkILMethods (List.map f m.AsList) let fdefs_fdef2fdef f (m:ILFieldDefs) = mkILFields (List.map f m.AsList) @@ -287,14 +287,14 @@ and tdefs_typ2typ_ilmbody2ilmbody_mdefs2mdefs ilg enc fs tdefs = // -------------------------------------------------------------------- let manifest_typ2typ ilg f (m : ILAssemblyManifest) = - { m with CustomAttrs = cattrs_typ2typ ilg f m.CustomAttrs } + { m with CustomAttrsStored = storeILCustomAttrs (cattrs_typ2typ ilg f m.CustomAttrs) } let morphILTypeInILModule_ilmbody2ilmbody_mdefs2mdefs ilg ((ftype: ILModuleDef -> (ILTypeDef list * ILTypeDef) option -> ILMethodDef option -> ILType -> ILType),fmdefs) m = let ftdefs = tdefs_typ2typ_ilmbody2ilmbody_mdefs2mdefs ilg [] (ftype m,fmdefs m) { m with TypeDefs=ftdefs m.TypeDefs; - CustomAttrs=cattrs_typ2typ ilg (ftype m None None) m.CustomAttrs; + CustomAttrsStored= storeILCustomAttrs (cattrs_typ2typ ilg (ftype m None None) m.CustomAttrs); Manifest=Option.map (manifest_typ2typ ilg (ftype m None None)) m.Manifest } let module_instr2instr_typ2typ ilg fs x = diff --git a/src/absil/ilprint.fs b/src/absil/ilprint.fs index 7b12d098dc2..723c7470074 100644 --- a/src/absil/ilprint.fs +++ b/src/absil/ilprint.fs @@ -1021,11 +1021,10 @@ let goutput_manifest env os m = output_sqstring os m.Name; output_string os " { \n"; output_string os ".hash algorithm "; output_i32 os m.AuxModuleHashAlgorithm; output_string os "\n"; - goutput_custom_attrs env os m.CustomAttrs; - goutput_security_decls env os m.SecurityDecls; - (output_option output_publickey) os m.PublicKey; - (output_option output_ver) os m.Version; - (output_option output_locale) os m.Locale; + goutput_custom_attrs env os m.CustomAttrs + (output_option output_publickey) os m.PublicKey + (output_option output_ver) os m.Version + (output_option output_locale) os m.Locale output_string os " } \n" diff --git a/src/absil/ilread.fs b/src/absil/ilread.fs index 5bfb5f60fc9..d9d66d2464d 100644 --- a/src/absil/ilread.fs +++ b/src/absil/ilread.fs @@ -1116,8 +1116,22 @@ type ILMetadataReader = seekReadTypeDefAsType : TypeDefAsTypIdx -> ILType seekReadMethodDefAsMethodData : int -> MethodData seekReadGenericParams : GenericParamsIdx -> ILGenericParameterDef list - seekReadFieldDefAsFieldSpec : int -> ILFieldSpec - } + seekReadFieldDefAsFieldSpec : int -> ILFieldSpec + customAttrsReader_Module : ILAttributesStored + customAttrsReader_Assembly : ILAttributesStored + customAttrsReader_TypeDef : ILAttributesStored + customAttrsReader_GenericParam: ILAttributesStored + customAttrsReader_FieldDef: ILAttributesStored + customAttrsReader_MethodDef: ILAttributesStored + customAttrsReader_ParamDef: ILAttributesStored + customAttrsReader_Event: ILAttributesStored + customAttrsReader_Property: ILAttributesStored + customAttrsReader_ManifestResource: ILAttributesStored + customAttrsReader_ExportedType: ILAttributesStored + securityDeclsReader_TypeDef : ILSecurityDeclsStored + securityDeclsReader_MethodDef : ILSecurityDeclsStored + securityDeclsReader_Assembly : ILSecurityDeclsStored + typeDefReader : ILTypeDefStored } let seekReadUInt16Adv mdv (addr: byref) = @@ -1601,7 +1615,8 @@ let rec seekReadModule (ctxt: ILMetadataReader) (pectxtEager: PEReader) pevEager { Manifest = if ctxt.getNumRows (TableNames.Assembly) > 0 then Some (seekReadAssemblyManifest ctxt pectxtEager 1) else None - CustomAttrs = seekReadCustomAttrs ctxt (TaggedIndex(hca_Module, idx)) + CustomAttrsStored = ctxt.customAttrsReader_Module + MetadataIndex = idx Name = ilModuleName NativeResources=nativeResources TypeDefs = mkILTypeDefsComputed (fun () -> seekReadTopTypeDefs ctxt) @@ -1628,11 +1643,12 @@ and seekReadAssemblyManifest (ctxt: ILMetadataReader) pectxt idx = let pubkey = readBlobHeapOption ctxt publicKeyIdx { Name= name AuxModuleHashAlgorithm=hash - SecurityDecls= seekReadSecurityDecls ctxt (TaggedIndex(hds_Assembly, idx)) + SecurityDeclsStored= ctxt.securityDeclsReader_Assembly PublicKey= pubkey Version= Some (v1, v2, v3, v4) Locale= readStringHeapOption ctxt localeIdx - CustomAttrs = seekReadCustomAttrs ctxt (TaggedIndex(hca_Assembly, idx)) + CustomAttrsStored = ctxt.customAttrsReader_Assembly + MetadataIndex = idx AssemblyLongevity= let masked = flags &&& 0x000e if masked = 0x0000 then ILAssemblyLongevity.Unspecified @@ -1733,22 +1749,24 @@ and seekReadTypeDefRowWithExtents ctxt (idx:int) = let info= seekReadTypeDefRow ctxt idx info, seekReadTypeDefRowExtents ctxt info idx -and seekReadTypeDef ctxt toponly (idx:int) = +and seekReadPreTypeDef ctxt toponly (idx:int) = let (flags, nameIdx, namespaceIdx, _, _, _) = seekReadTypeDefRow ctxt idx if toponly && not (isTopTypeDef flags) then None else let ns, n = readBlobHeapAsSplitTypeName ctxt (nameIdx, namespaceIdx) - let cas = seekReadCustomAttrs ctxt (TaggedIndex(hca_TypeDef, idx)) + // Return the ILPreTypeDef + Some (mkILPreTypeDefRead (ns, n, idx, ctxt.typeDefReader)) - let rest = - lazy +and typeDefReader ctxtH : ILTypeDefStored = + mkILTypeDefReader + (fun idx -> + let (ctxt: ILMetadataReader) = getHole ctxtH let mdv = ctxt.mdfile.GetView() - // Re-read so as not to save all these in the lazy closure - this suspension is the largest + // Re-read so as not to save all these in the lazy closure - this suspension ctxt.is the largest // heavily allocated one in all of AbsIL let ((flags, nameIdx, namespaceIdx, extendsIdx, fieldsIdx, methodsIdx) as info) = seekReadTypeDefRow ctxt idx let nm = readBlobHeapAsTypeName ctxt (nameIdx, namespaceIdx) - let cas = seekReadCustomAttrs ctxt (TaggedIndex(hca_TypeDef, idx)) let (endFieldsIdx, endMethodsIdx) = seekReadTypeDefRowExtents ctxt info idx let typars = seekReadGenericParams ctxt 0 (tomd_TypeDef, idx) let numtypars = typars.Length @@ -1759,7 +1777,6 @@ and seekReadTypeDef ctxt toponly (idx:int) = let fdefs = seekReadFields ctxt (numtypars, hasLayout) fieldsIdx endFieldsIdx let nested = seekReadNestedTypeDefs ctxt idx let impls = seekReadInterfaceImpls ctxt mdv numtypars idx - let sdecls = seekReadSecurityDecls ctxt (TaggedIndex(hds_TypeDef, idx)) let mimpls = seekReadMethodImpls ctxt numtypars idx let props = seekReadProperties ctxt numtypars idx let events = seekReadEvents ctxt numtypars idx @@ -1771,17 +1788,18 @@ and seekReadTypeDef ctxt toponly (idx:int) = implements = impls, extends = super, methods = mdefs, - securityDecls = sdecls, + securityDeclsStored = ctxt.securityDeclsReader_TypeDef, fields=fdefs, methodImpls=mimpls, events= events, properties=props, - customAttrs=cas) - Some (ns, n, cas, rest) + customAttrsStored=ctxt.customAttrsReader_TypeDef, + metadataIndex=idx) + ) and seekReadTopTypeDefs (ctxt: ILMetadataReader) = [| for i = 1 to ctxt.getNumRows TableNames.TypeDef do - match seekReadTypeDef ctxt true i with + match seekReadPreTypeDef ctxt true i with | None -> () | Some td -> yield td |] @@ -1789,7 +1807,7 @@ and seekReadNestedTypeDefs (ctxt: ILMetadataReader) tidx = mkILTypeDefsComputed (fun () -> let nestedIdxs = seekReadIndexedRows (ctxt.getNumRows TableNames.Nested, seekReadNestedRow ctxt, snd, simpleIndexCompare tidx, false, fst) [| for i in nestedIdxs do - match seekReadTypeDef ctxt false i with + match seekReadPreTypeDef ctxt false i with | None -> () | Some td -> yield td |]) @@ -1822,11 +1840,11 @@ and seekReadGenericParamsUncached ctxtH (GenericParamsIdx(numtypars, a, b)) = elif variance_flags = 0x0002 then ContraVariant else NonVariant let constraints = seekReadGenericParamConstraints ctxt mdv numtypars gpidx - let cas = seekReadCustomAttrs ctxt (TaggedIndex(hca_GenericParam, gpidx)) seq, {Name=readStringHeap ctxt nameIdx Constraints = constraints Variance=variance - CustomAttrs=cas + CustomAttrsStored = ctxt.customAttrsReader_GenericParam + MetadataIndex=gpidx HasReferenceTypeConstraint= (flags &&& 0x0004) <> 0 HasNotNullableValueTypeConstraint= (flags &&& 0x0008) <> 0 HasDefaultConstructorConstraint=(flags &&& 0x0010) <> 0 })) @@ -1980,8 +1998,9 @@ and seekReadField ctxt mdv (numtypars, hasLayout) (idx:int) = (if hasLayout && not isStatic then Some (seekReadIndexedRow (ctxt.getNumRows TableNames.FieldLayout, seekReadFieldLayoutRow ctxt mdv, snd, simpleIndexCompare idx, isSorted ctxt TableNames.FieldLayout, fst)) else None), - customAttrs=seekReadCustomAttrs ctxt (TaggedIndex(hca_FieldDef, idx) )) - + customAttrsStored=ctxt.customAttrsReader_FieldDef, + metadataIndex = idx) + and seekReadFields (ctxt: ILMetadataReader) (numtypars, hasLayout) fidx1 fidx2 = mkILFieldsLazy (lazy @@ -2356,30 +2375,20 @@ and seekReadMethod (ctxt: ILMetadataReader) mdv numtypars (idx:int) = ILMethodDef(name=nm, attributes = enum(flags), implAttributes= enum(implflags), - securityDecls=seekReadSecurityDecls ctxt (TaggedIndex(hds_MethodDef, idx)), + securityDeclsStored=ctxt.securityDeclsReader_MethodDef, isEntryPoint=isEntryPoint, genericParams=seekReadGenericParams ctxt numtypars (tomd_MethodDef, idx), - customAttrs=seekReadCustomAttrs ctxt (TaggedIndex(hca_MethodDef, idx)), parameters= ilParams, callingConv=cc, ret=ret, - body=body) + body=body, + customAttrsStored=ctxt.customAttrsReader_MethodDef, + metadataIndex=idx) and seekReadParams (ctxt: ILMetadataReader) mdv (retty, argtys) pidx1 pidx2 = - let retRes : ILReturn ref = ref { Marshal=None; Type=retty; CustomAttrs=emptyILCustomAttrs } - let paramsRes : ILParameter [] = - argtys - |> List.toArray - |> Array.map (fun ty -> - { Name=None - Default=None - Marshal=None - IsIn=false - IsOut=false - IsOptional=false - Type=ty - CustomAttrs=emptyILCustomAttrs }) + let retRes = ref (mkILReturn retty) + let paramsRes = argtys |> List.toArray |> Array.map mkILParamAnon for i = pidx1 to pidx2 - 1 do seekReadParamExtras ctxt mdv (retRes, paramsRes) i !retRes, List.ofArray paramsRes @@ -2390,11 +2399,11 @@ and seekReadParamExtras (ctxt: ILMetadataReader) mdv (retRes, paramsRes) (idx:i let hasMarshal = (flags &&& 0x2000) <> 0x0 let hasDefault = (flags &&& 0x1000) <> 0x0 let fmReader idx = seekReadIndexedRow (ctxt.getNumRows TableNames.FieldMarshal, seekReadFieldMarshalRow ctxt mdv, fst, hfmCompare idx, isSorted ctxt TableNames.FieldMarshal, (snd >> readBlobHeapAsNativeType ctxt)) - let cas = seekReadCustomAttrs ctxt (TaggedIndex(hca_ParamDef, idx)) if seq = 0 then retRes := { !retRes with Marshal=(if hasMarshal then Some (fmReader (TaggedIndex(hfm_ParamDef, idx))) else None) - CustomAttrs = cas } + CustomAttrsStored = ctxt.customAttrsReader_ParamDef + MetadataIndex = idx} elif seq > Array.length paramsRes then dprintn "bad seq num. for param" else paramsRes.[seq - 1] <- @@ -2405,7 +2414,8 @@ and seekReadParamExtras (ctxt: ILMetadataReader) mdv (retRes, paramsRes) (idx:i IsIn = ((inOutMasked &&& 0x0001) <> 0x0) IsOut = ((inOutMasked &&& 0x0002) <> 0x0) IsOptional = ((inOutMasked &&& 0x0010) <> 0x0) - CustomAttrs =cas } + CustomAttrsStored = ctxt.customAttrsReader_ParamDef + MetadataIndex = idx } and seekReadMethodImpls (ctxt: ILMetadataReader) numtypars tidx = mkILMethodImplsLazy @@ -2455,7 +2465,8 @@ and seekReadEvent ctxt mdv numtypars idx = removeMethod=seekReadMethodSemantics ctxt (0x0010, TaggedIndex(hs_Event, idx)), fireMethod=seekReadoptional_MethodSemantics ctxt (0x0020, TaggedIndex(hs_Event, idx)), otherMethods = seekReadMultipleMethodSemantics ctxt (0x0004, TaggedIndex(hs_Event, idx)), - customAttrs=seekReadCustomAttrs ctxt (TaggedIndex(hca_Event, idx))) + customAttrsStored=ctxt.customAttrsReader_Event, + metadataIndex = idx ) (* REVIEW: can substantially reduce numbers of EventMap and PropertyMap reads by first checking if the whole table mdv sorted according to ILTypeDef tokens and then doing a binary chop *) and seekReadEvents (ctxt: ILMetadataReader) numtypars tidx = @@ -2489,6 +2500,7 @@ and seekReadProperty ctxt mdv numtypars idx = match setter with | Some mref -> mref.CallingConv .ThisConv | None -> cc + ILPropertyDef(name=readStringHeap ctxt nameIdx, callingConv = cc2, attributes = enum(flags), @@ -2497,7 +2509,8 @@ and seekReadProperty ctxt mdv numtypars idx = propertyType=retty, init= (if (flags &&& 0x1000) = 0 then None else Some (seekReadConstant ctxt (TaggedIndex(hc_Property, idx)))), args=argtys, - customAttrs=seekReadCustomAttrs ctxt (TaggedIndex(hca_Property, idx))) + customAttrsStored=ctxt.customAttrsReader_Property, + metadataIndex = idx ) and seekReadProperties (ctxt: ILMetadataReader) numtypars tidx = mkILPropertiesLazy @@ -2516,12 +2529,13 @@ and seekReadProperties (ctxt: ILMetadataReader) numtypars tidx = yield seekReadProperty ctxt mdv numtypars i ]) -and seekReadCustomAttrs (ctxt: ILMetadataReader) idx = - mkILComputedCustomAttrs - (fun () -> +and customAttrsReader ctxtH tag : ILAttributesStored = + mkILCustomAttrsReader + (fun idx -> + let (ctxt: ILMetadataReader) = getHole ctxtH seekReadIndexedRows (ctxt.getNumRows TableNames.CustomAttribute, seekReadCustomAttributeRow ctxt, (fun (a, _, _) -> a), - hcaCompare idx, + hcaCompare (TaggedIndex(tag,idx)), isSorted ctxt TableNames.CustomAttribute, (fun (_, b, c) -> seekReadCustomAttr ctxt (b, c))) |> List.toArray) @@ -2538,16 +2552,18 @@ and seekReadCustomAttrUncached ctxtH (CustomAttrIdx (cat, idx, valIdx)) = | None -> Bytes.ofInt32Array [| |] Elements = [] } -and seekReadSecurityDecls (ctxt: ILMetadataReader) idx = - mkILLazySecurityDecls - (lazy +and securityDeclsReader ctxtH tag = + mkILSecurityDeclsReader + (fun idx -> + let (ctxt: ILMetadataReader) = getHole ctxtH let mdv = ctxt.mdfile.GetView() seekReadIndexedRows (ctxt.getNumRows TableNames.Permission, seekReadPermissionRow ctxt mdv, (fun (_, par, _) -> par), - hdsCompare idx, + hdsCompare (TaggedIndex(tag,idx)), isSorted ctxt TableNames.Permission, - (fun (act, _, ty) -> seekReadSecurityDecl ctxt (act, ty)))) + (fun (act, _, ty) -> seekReadSecurityDecl ctxt (act, ty))) + |> List.toArray) and seekReadSecurityDecl ctxt (act, ty) = ILSecurityDecl ((if List.memAssoc (int act) (Lazy.force ILSecurityActionRevMap) then List.assoc (int act) (Lazy.force ILSecurityActionRevMap) else failwith "unknown security action"), @@ -3209,8 +3225,8 @@ and seekReadManifestResources (ctxt: ILMetadataReader) (mdv: BinaryView) (pectxt { Name= readStringHeap ctxt nameIdx Location = location Access = (if (flags &&& 0x01) <> 0x0 then ILResourceAccess.Public else ILResourceAccess.Private) - CustomAttrs = seekReadCustomAttrs ctxt (TaggedIndex(hca_ManifestResource, i)) } - + CustomAttrsStored = ctxt.customAttrsReader_ManifestResource + MetadataIndex = i } yield r ] and seekReadNestedExportedTypes ctxt (exported: _ array) (nested: Lazy<_ array>) parentIdx = @@ -3224,7 +3240,8 @@ and seekReadNestedExportedTypes ctxt (exported: _ array) (nested: Lazy<_ array>) | ILTypeDefAccess.Nested n -> n | _ -> failwith "non-nested access for a nested type described as being in an auxiliary module") Nested = seekReadNestedExportedTypes ctxt exported nested i - CustomAttrs = seekReadCustomAttrs ctxt (TaggedIndex(hca_ExportedType, i)) } + CustomAttrsStored = ctxt.customAttrsReader_ExportedType + MetadataIndex = i } )) and seekReadTopExportedTypes (ctxt: ILMetadataReader) = @@ -3255,7 +3272,8 @@ and seekReadTopExportedTypes (ctxt: ILMetadataReader) = Name = readBlobHeapAsTypeName ctxt (nameIdx, namespaceIdx) Attributes = enum(flags) Nested = seekReadNestedExportedTypes ctxt exported nested i - CustomAttrs = seekReadCustomAttrs ctxt (TaggedIndex(hca_ExportedType, i)) } + CustomAttrsStored = ctxt.customAttrsReader_ExportedType + MetadataIndex = i } ]) #if !FX_NO_PDB_READER @@ -3623,6 +3641,21 @@ let openMetadataReader (fileName, mdfile: BinaryFile, metadataPhysLoc, peinfo, p seekReadMethodDefAsMethodData = cacheMethodDefAsMethodData (seekReadMethodDefAsMethodDataUncached ctxtH) seekReadGenericParams = cacheGenericParams (seekReadGenericParamsUncached ctxtH) seekReadFieldDefAsFieldSpec = cacheFieldDefAsFieldSpec (seekReadFieldDefAsFieldSpecUncached ctxtH) + customAttrsReader_Module = customAttrsReader ctxtH hca_Module + customAttrsReader_Assembly = customAttrsReader ctxtH hca_Assembly + customAttrsReader_TypeDef = customAttrsReader ctxtH hca_TypeDef + customAttrsReader_GenericParam= customAttrsReader ctxtH hca_GenericParam + customAttrsReader_FieldDef= customAttrsReader ctxtH hca_FieldDef + customAttrsReader_MethodDef= customAttrsReader ctxtH hca_MethodDef + customAttrsReader_ParamDef= customAttrsReader ctxtH hca_ParamDef + customAttrsReader_Event= customAttrsReader ctxtH hca_Event + customAttrsReader_Property= customAttrsReader ctxtH hca_Property + customAttrsReader_ManifestResource= customAttrsReader ctxtH hca_ManifestResource + customAttrsReader_ExportedType= customAttrsReader ctxtH hca_ExportedType + securityDeclsReader_TypeDef = securityDeclsReader ctxtH hds_TypeDef + securityDeclsReader_MethodDef = securityDeclsReader ctxtH hds_MethodDef + securityDeclsReader_Assembly = securityDeclsReader ctxtH hds_Assembly + typeDefReader = typeDefReader ctxtH guidsStreamPhysicalLoc = guidsStreamPhysicalLoc rowAddr=rowAddr rsBigness=rsBigness diff --git a/src/absil/ilreflect.fs b/src/absil/ilreflect.fs index 589c948a9bd..841c16bb98a 100644 --- a/src/absil/ilreflect.fs +++ b/src/absil/ilreflect.fs @@ -1431,7 +1431,7 @@ let buildGenParamsPass1b cenv emEnv (genArgs : Type array) (gps : ILGenericParam | _ -> failwith "buildGenParam: multiple base types" ); // set interface constraints (interfaces that instances of gp must meet) - gpB.SetInterfaceConstraints(Array.ofList interfaceTs); + gpB.SetInterfaceConstraints(Array.ofList interfaceTs) gp.CustomAttrs |> emitCustomAttrs cenv emEnv (wrapCustomAttr gpB.SetCustomAttribute) let flags = GenericParameterAttributes.None diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 24f9615222e..8ecde4fe139 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -3781,13 +3781,15 @@ let MakeILResource rname bytes = { Name = rname Location = ILResourceLocation.LocalOut bytes Access = ILResourceAccess.Public - CustomAttrs = emptyILCustomAttrs } + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } let PickleToResource inMem file g scope rname p x = { Name = rname Location = (let bytes = pickleObjWithDanglingCcus inMem file g scope p x in ILResourceLocation.LocalOut bytes) Access = ILResourceAccess.Public - CustomAttrs = emptyILCustomAttrs } + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } let GetSignatureData (file, ilScopeRef, ilModule, byteReader) : PickledDataWithReferences = unpickleObjWithDanglingCcus file ilScopeRef ilModule unpickleCcuInfo byteReader @@ -5205,11 +5207,11 @@ module private ScriptPreprocessClosure = let allRootDiagnostics = allRootDiagnostics |> List.filter (fst >> isRootRange) let result : LoadClosure = - { SourceFiles = List.groupByFirst sourceFiles - References = List.groupByFirst references + { SourceFiles = List.groupBy fst sourceFiles |> List.map (map2Of2 (List.map snd)) + References = List.groupBy fst references |> List.map (map2Of2 (List.map snd)) UnresolvedReferences = unresolvedReferences Inputs = sourceInputs - NoWarns = List.groupByFirst globalNoWarns + NoWarns = List.groupBy fst globalNoWarns |> List.map (map2Of2 (List.map snd)) OriginalLoadReferences = tcConfig.loadedSources ResolutionDiagnostics = resolutionDiagnostics AllRootFileDiagnostics = allRootDiagnostics @@ -5430,7 +5432,7 @@ let TypeCheckOneInputEventually let m = qualNameOfFile.Range TcOpenDecl tcSink tcGlobals amap m m tcEnv prefixPath - let res = (EmptyTopAttrs, [], tcEnv, tcEnv, tcState.tcsTcImplEnv, RootSigsAndImpls(rootSigs, rootImpls, allSigModulTyp, allImplementedSigModulTyp), tcState.tcsCcuType, createsGeneratedProvidedTypes) + let res = (EmptyTopAttrs, None, tcEnv, tcEnv, tcState.tcsTcImplEnv, RootSigsAndImpls(rootSigs, rootImpls, allSigModulTyp, allImplementedSigModulTyp), tcState.tcsCcuType, createsGeneratedProvidedTypes) return res | ParsedInput.ImplFile (ParsedImplFileInput(filename, _, qualNameOfFile, _, _, _, _) as file) -> @@ -5490,7 +5492,7 @@ let TypeCheckOneInputEventually if verbose then dprintf "done TypeCheckOneInputEventually...\n" let topSigsAndImpls = RootSigsAndImpls(rootSigs, rootImpls, allSigModulTyp, allImplementedSigModulTyp) - let res = (topAttrs, [implFile], tcEnvAtEnd, tcSigEnv, tcImplEnv, topSigsAndImpls, ccuType, createsGeneratedProvidedTypes) + let res = (topAttrs, Some implFile, tcEnvAtEnd, tcSigEnv, tcImplEnv, topSigsAndImpls, ccuType, createsGeneratedProvidedTypes) return res } return (tcEnvAtEnd, topAttrs, implFiles), @@ -5502,7 +5504,7 @@ let TypeCheckOneInputEventually tcsRootSigsAndImpls = topSigsAndImpls } with e -> errorRecovery e range0 - return (tcState.TcEnvFromSignatures, EmptyTopAttrs, []), tcState + return (tcState.TcEnvFromSignatures, EmptyTopAttrs, None), tcState } /// Typecheck a single file (or interactive entry into F# Interactive) @@ -5518,7 +5520,7 @@ let TypeCheckMultipleInputsFinish(results, tcState: TcState) = let tcEnvsAtEndFile, topAttrs, implFiles = List.unzip3 results let topAttrs = List.foldBack CombineTopAttrs topAttrs EmptyTopAttrs - let implFiles = List.concat implFiles + let implFiles = List.choose id implFiles // This is the environment required by fsi.exe when incrementally adding definitions let tcEnvAtEndOfLastFile = (match tcEnvsAtEndFile with h :: _ -> h | _ -> tcState.TcEnvFromSignatures) diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 22a9e176c63..d749739f18a 100755 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -724,10 +724,10 @@ val GetInitialTcState: /// Check one input, returned as an Eventually computation val TypeCheckOneInputEventually : checkForErrors:(unit -> bool) * TcConfig * TcImports * TcGlobals * Ast.LongIdent option * NameResolution.TcResultsSink * TcState * Ast.ParsedInput - -> Eventually<(TcEnv * TopAttribs * TypedImplFile list) * TcState> + -> Eventually<(TcEnv * TopAttribs * TypedImplFile option) * TcState> /// Finish the checking of multiple inputs -val TypeCheckMultipleInputsFinish: (TcEnv * TopAttribs * 'T list) list * TcState -> (TcEnv * TopAttribs * 'T list) * TcState +val TypeCheckMultipleInputsFinish: (TcEnv * TopAttribs * 'T option) list * TcState -> (TcEnv * TopAttribs * 'T list) * TcState /// Finish the checking of a closed set of inputs val TypeCheckClosedInputSetFinish: TypedImplFile list * TcState -> TcState * TypedImplFile list diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 90385b2c2ea..493b9c3c964 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3454,7 +3454,8 @@ and GenGenericParam cenv eenv (tp:Typar) = Constraints = subTypeConstraints Variance=NonVariant - CustomAttrs = mkILCustomAttrs (GenAttrs cenv eenv tp.Attribs) + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv tp.Attribs)) + MetadataIndex = NoMetadataIdx HasReferenceTypeConstraint=refTypeConstraint HasNotNullableValueTypeConstraint=notNullableValueTypeConstraint HasDefaultConstructorConstraint= defaultConstructorConstraint } @@ -3474,7 +3475,8 @@ and GenSlotParam m cenv eenv (TSlotParam(nm,ty,inFlag,outFlag,optionalFlag,attri IsIn=inFlag || inFlag2 IsOut=outFlag || outFlag2 IsOptional=optionalFlag || optionalFlag2 - CustomAttrs= mkILCustomAttrs (GenAttrs cenv eenv attribs) } + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attribs)) + MetadataIndex = NoMetadataIdx } and GenFormalSlotsig m cenv eenv (TSlotSig(_,typ,ctps,mtps,paraml,returnTy)) = let paraml = List.concat paraml @@ -5005,7 +5007,8 @@ and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) (implVal IsIn=inFlag IsOut=outFlag IsOptional=optionalFlag - CustomAttrs= mkILCustomAttrs (GenAttrs cenv eenv attribs) } + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attribs)) + MetadataIndex = NoMetadataIdx } param, takenNames) |> fst @@ -5014,7 +5017,8 @@ and GenReturnInfo cenv eenv ilRetTy (retInfo : ArgReprInfo) : ILReturn = let marshal,attrs = GenMarshal cenv retInfo.Attribs { Type=ilRetTy Marshal=marshal - CustomAttrs= mkILCustomAttrs (GenAttrs cenv eenv attrs) } + CustomAttrsStored= storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attrs)) + MetadataIndex = NoMetadataIdx } and GenPropertyForMethodDef compileAsInstance tref mdef (v:Val) (memberInfo:ValMemberInfo) ilArgTys ilPropTy ilAttrs compiledName = let name = match compiledName with | Some n -> n | _ -> v.PropertyName in (* chop "get_" *) diff --git a/src/fsharp/InternalCollections.fs b/src/fsharp/InternalCollections.fs index 51fedcd6f96..8713eef00ff 100755 --- a/src/fsharp/InternalCollections.fs +++ b/src/fsharp/InternalCollections.fs @@ -198,37 +198,3 @@ type internal MruCache<'Token, 'Key,'Value when 'Value : not struct>(keepStrongl member bc.Resize(tok, newKeepStrongly, ?newKeepMax) = cache.Resize(tok, newKeepStrongly, ?newKeepMax=newKeepMax) -/// List helpers -[] -type internal List = - /// Return a new list with one element for each unique 'Key. Multiple 'TValues are flattened. - /// The original order of the first instance of 'Key is preserved. - static member groupByFirst( l : ('Key * 'Value) list) : ('Key * 'Value list) list = - let nextIndex = ref 0 - let result = System.Collections.Generic.List<'Key * System.Collections.Generic.List<'Value>>() - let keyToIndex = Dictionary<'Key,int>(HashIdentity.Structural) - let indexOfKey(key) = - match keyToIndex.TryGetValue(key) with - | true, v -> v - | false, _ -> - keyToIndex.Add(key,!nextIndex) - nextIndex := !nextIndex + 1 - !nextIndex - 1 - - for kv in l do - let index = indexOfKey(fst kv) - if index>= result.Count then - let k,vs = fst kv,System.Collections.Generic.List<'Value>() - vs.Add(snd kv) - result.Add(k,vs) - else - let _,vs = result.[index] - vs.Add(snd kv) - - result |> Seq.map(fun (k,vs) -> k,vs |> List.ofSeq ) |> List.ofSeq - - /// Return each distinct item in the list using reference equality. - static member referenceDistinct( l : 'T list) : 'T list when 'T : not struct = - let set = System.Collections.Generic.Dictionary<'T,bool>(HashIdentity.Reference) - l |> List.iter(fun i->set.Add(i,true)) - set |> Seq.map(fun kv->kv.Key) |> List.ofSeq diff --git a/src/fsharp/InternalCollections.fsi b/src/fsharp/InternalCollections.fsi index 8e26bc95782..711fb91d848 100755 --- a/src/fsharp/InternalCollections.fsi +++ b/src/fsharp/InternalCollections.fsi @@ -75,10 +75,3 @@ namespace Internal.Utilities.Collections /// Resize member Resize : 'Token * keepStrongly: int * ?keepMax : int -> unit - [] - type internal List = - /// Return a new list with one element for each unique 'Key. Multiple 'TValues are flattened. - /// The original order of the first instance of 'Key is preserved. - static member groupByFirst : l:('Key * 'Value) list -> ('Key * 'Value list) list when 'Key : equality - /// Return each distinct item in the list using reference equality. - static member referenceDistinct : 'T list -> 'T list when 'T : not struct diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 279bb145fe9..09aa6e33504 100644 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -1470,6 +1470,10 @@ type TcSymbolUseData = Range: range } /// Represents container for all name resolutions that were met so far when typechecking some particular file +/// +/// This is a memory-critical data structure - allocations of this data structure and its immediate contents +/// is one of the highest memory long-lived data structures in typical uses of IDEs. Not many of these objects +/// are allocated (one per file), but they are large because the allUsesOfAllSymbols array is large. type TcSymbolUses(g, capturedNameResolutions : ResizeArray, formatSpecifierLocations: (range * int)[]) = // Make sure we only capture the information we really need to report symbol uses @@ -1516,7 +1520,7 @@ type TcResultsSinkImpl(g, ?source: string) = member this.GetSymbolUses() = TcSymbolUses(g, capturedNameResolutions, capturedFormatSpecifierLocations.ToArray()) - member this.OpenDeclarations = Seq.toList capturedOpenDeclarations + member this.GetOpenDeclarations() = capturedOpenDeclarations.ToArray() interface ITypecheckResultsSink with member sink.NotifyEnvWithScope(m,nenv,ad) = diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index 326c310c573..7af7a278c23 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -375,7 +375,7 @@ type internal TcResultsSinkImpl = member GetSymbolUses : unit -> TcSymbolUses /// Get all open declarations reported to the sink - member OpenDeclarations : OpenDeclaration list + member GetOpenDeclarations : unit -> OpenDeclaration[] interface ITypecheckResultsSink diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index bd28de3b30e..333a1d30a68 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -771,11 +771,12 @@ module MainModuleBuilder = let systemNumericsAssemblyRef = ILAssemblyRef.Create(refNumericsDllName, aref.Hash, aref.PublicKey, aref.Retargetable, aref.Version, aref.Locale) typesForwardedToSystemNumerics |> Seq.map (fun t -> - { ScopeRef = ILScopeRef.Assembly(systemNumericsAssemblyRef) - Name = t - Attributes = enum(0x00200000) ||| TypeAttributes.Public - Nested = mkILNestedExportedTypes List.empty - CustomAttrs = mkILCustomAttrs List.empty }) |> + { ScopeRef = ILScopeRef.Assembly(systemNumericsAssemblyRef) + Name = t + Attributes = enum(0x00200000) ||| TypeAttributes.Public + Nested = mkILNestedExportedTypes [] + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx }) |> Seq.toList | None -> [] @@ -860,7 +861,8 @@ module MainModuleBuilder = { Name=reflectedDefinitionResourceName Location = ILResourceLocation.LocalOut reflectedDefinitionBytes Access= ILResourceAccess.Public - CustomAttrs = emptyILCustomAttrs } + CustomAttrsStored = storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } reflectedDefinitionAttrs, reflectedDefinitionResource) |> List.unzip |> (fun (attrs, resource) -> List.concat attrs, resource) @@ -886,11 +888,11 @@ module MainModuleBuilder = | None -> tcVersion | Some v -> v Some { man with Version= Some ver - CustomAttrs = manifestAttrs + CustomAttrsStored = storeILCustomAttrs manifestAttrs DisableJitOptimizations=disableJitOptimizations JitTracking= tcConfig.jitTracking IgnoreSymbolStoreSequencePoints = tcConfig.ignoreSymbolStoreSequencePoints - SecurityDecls=secDecls } + SecurityDeclsStored=storeILSecurityDecls secDecls } let resources = mkILResources @@ -903,7 +905,8 @@ module MainModuleBuilder = yield { Name=name Location=ILResourceLocation.LocalOut bytes Access=pub - CustomAttrs=emptyILCustomAttrs } + CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } yield! reflectedDefinitionResources yield! intfDataResources @@ -913,7 +916,8 @@ module MainModuleBuilder = yield { Name=name Location=ILResourceLocation.File(ILModuleRef.Create(name=file, hasMetadata=false, hash=Some (sha1HashBytes (FileSystem.ReadAllBytesShim file))), 0) Access=pub - CustomAttrs=emptyILCustomAttrs } ] + CustomAttrsStored=storeILCustomAttrs emptyILCustomAttrs + MetadataIndex = NoMetadataIdx } ] let assemblyVersion = match tcConfig.version with @@ -1033,11 +1037,12 @@ module MainModuleBuilder = Is32Bit=(match tcConfig.platform with Some X86 -> true | _ -> false) Is64Bit=(match tcConfig.platform with Some AMD64 | Some IA64 -> true | _ -> false) Is32BitPreferred = if tcConfig.prefer32Bit && not tcConfig.target.IsExe then (error(Error(FSComp.SR.invalidPlatformTarget(), rangeCmdArgs))) else tcConfig.prefer32Bit - CustomAttrs= - mkILCustomAttrs + CustomAttrsStored= + storeILCustomAttrs + (mkILCustomAttrs [ if tcConfig.target = CompilerTarget.Module then yield! iattrs - yield! codegenResults.ilNetModuleAttrs ] + yield! codegenResults.ilNetModuleAttrs ]) NativeResources=nativeResources Manifest = manifest } @@ -1084,7 +1089,7 @@ module StaticLinker = [ for (_, depILModule) in dependentILModules do match depILModule.Manifest with | Some m -> - for ca in m.CustomAttrs.AsList do + for ca in m.CustomAttrs.AsArray do if ca.Method.MethodRef.DeclaringTypeRef.FullName = typeof.FullName then yield ca | _ -> () ] @@ -1141,8 +1146,8 @@ module StaticLinker = let ilxMainModule = { ilxMainModule with - Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrs = mkILCustomAttrs (m.CustomAttrs.AsList @ savedManifestAttrs) }) - CustomAttrs = mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsList ] + Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (m.CustomAttrs.AsList @ savedManifestAttrs)) }) + CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsArray ]) TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs) Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList) NativeResources = savedNativeResources } @@ -1194,7 +1199,7 @@ module StaticLinker = let meths = td.Methods.AsList |> List.map (fun md -> md.With(customAttrs = - mkILCustomAttrs (td.CustomAttrs.AsList |> List.filter (fun ilattr -> + mkILCustomAttrs (td.CustomAttrs.AsList |> List.filter (fun ilattr -> ilattr.Method.DeclaringType.TypeRef.FullName <> "System.Runtime.TargetedPatchingOptOutAttribute")))) |> mkILMethods let td = td.With(methods=meths) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 45800b80921..6b662c12af0 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1005,7 +1005,7 @@ type internal FsiDynamicCompiler { mainModule with Manifest = (let man = mainModule.ManifestOfAssembly - Some { man with CustomAttrs = mkILCustomAttrs codegenResults.ilAssemAttrs }); } + Some { man with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs codegenResults.ilAssemAttrs) }) } let ProcessInputs (ctok, errorLogger: ErrorLogger, istate: FsiDynamicCompilerState, inputs: ParsedInput list, showTypes: bool, isIncrementalFragment: bool, isInteractiveItExpr: bool, prefixPath: LongIdent) = let optEnv = istate.optEnv diff --git a/src/fsharp/import.fs b/src/fsharp/import.fs index f6f5648d8e4..41c27fd2891 100644 --- a/src/fsharp/import.fs +++ b/src/fsharp/import.fs @@ -473,8 +473,8 @@ and ImportILTypeDefList amap m (cpath:CompilationPath) enc items = let modty = lazy (ImportILTypeDefList amap m (cpath.NestedCompPath n Namespace) enc tgs) NewModuleOrNamespace (Some cpath) taccessPublic (mkSynId m n) XmlDoc.Empty [] (MaybeLazy.Lazy modty)) (fun (n,info:Lazy<_>) -> - let (scoref2,_,lazyTypeDef:Lazy) = info.Force() - ImportILTypeDef amap m scoref2 cpath enc n (lazyTypeDef.Force())) + let (scoref2,_,lazyTypeDef:ILPreTypeDef) = info.Force() + ImportILTypeDef amap m scoref2 cpath enc n (lazyTypeDef.GetTypeDef())) let kind = match enc with [] -> Namespace | _ -> ModuleOrType NewModuleOrNamespaceType kind entities [] @@ -483,8 +483,8 @@ and ImportILTypeDefList amap m (cpath:CompilationPath) enc items = /// and ImportILTypeDefs amap m scoref cpath enc (tdefs: ILTypeDefs) = // We be very careful not to force a read of the type defs here - tdefs.AsArrayOfLazyTypeDefs - |> Array.map (fun (ns,n,attrs,lazyTypeDef) -> (ns,(n,notlazy(scoref,attrs,lazyTypeDef)))) + tdefs.AsArrayOfPreTypeDefs + |> Array.map (fun pre -> (pre.Namespace,(pre.Name,notlazy(scoref,pre.MetadataIndex,pre)))) |> Array.toList |> ImportILTypeDefList amap m cpath enc @@ -502,19 +502,20 @@ let ImportILAssemblyExportedType amap m auxModLoader (scoref:ILScopeRef) (export if exportedType.IsForwarder then [] else + let ns,n = splitILTypeName exportedType.Name let info = lazy (match (try let modul = auxModLoader exportedType.ScopeRef - Some (lazy modul.TypeDefs.FindByName exportedType.Name) - with :? System.Collections.Generic.KeyNotFoundException -> None) + let ptd = mkILPreTypeDefComputed (ns, n, (fun () -> modul.TypeDefs.FindByName exportedType.Name)) + Some ptd + with :? KeyNotFoundException -> None) with | None -> error(Error(FSComp.SR.impReferenceToDllRequiredByAssembly(exportedType.ScopeRef.QualifiedName, scoref.QualifiedName, exportedType.Name),m)) - | Some lazyTypeDef -> - scoref,exportedType.CustomAttrs,lazyTypeDef) + | Some preTypeDef -> + scoref,-1,preTypeDef) - let ns,n = splitILTypeName exportedType.Name [ ImportILTypeDefList amap m (CompPath(scoref,[])) [] [(ns,(n,info))] ] /// Import the "exported types" table for multi-module assemblies. diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 10f63f5ac72..6f794fef9b8 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1025,13 +1025,24 @@ type TypeCheckAccumulator = tcGlobals:TcGlobals tcConfig:TcConfig tcEnvAtEndOfFile: TcEnv - tcResolutions: TcResolutions list - tcSymbolUses: TcSymbolUses list - tcOpenDeclarations: OpenDeclaration list + + /// Accumulated resolutions, last file first + tcResolutionsRev: TcResolutions list + + /// Accumulated symbol uses, last file first + tcSymbolUsesRev: TcSymbolUses list + + /// Accumulated 'open' declarations, last file first + tcOpenDeclarationsRev: OpenDeclaration[] list topAttribs:TopAttribs option - typedImplFiles:TypedImplFile list + + /// Result of checking most recent file, if any + lastestTypedImplFile:TypedImplFile option + tcDependencyFiles: string list - tcErrors:(PhasedDiagnostic * FSharpErrorSeverity) list } // errors=true, warnings=false + + /// Accumulated errors, last file first + tcErrorsRev:(PhasedDiagnostic * FSharpErrorSeverity)[] list } /// Global service state @@ -1099,14 +1110,26 @@ type PartialCheckResults = TcGlobals: TcGlobals TcConfig: TcConfig TcEnvAtEnd: TcEnv - Errors: (PhasedDiagnostic * FSharpErrorSeverity) list - TcResolutions: TcResolutions list - TcSymbolUses: TcSymbolUses list - TcOpenDeclarations: OpenDeclaration list + + /// Kept in a stack so that each incremental update shares storage with previous files + TcErrorsRev: (PhasedDiagnostic * FSharpErrorSeverity)[] list + + /// Kept in a stack so that each incremental update shares storage with previous files + TcResolutionsRev: TcResolutions list + + /// Kept in a stack so that each incremental update shares storage with previous files + TcSymbolUsesRev: TcSymbolUses list + + /// Kept in a stack so that each incremental update shares storage with previous files + TcOpenDeclarationsRev: OpenDeclaration[] list + TcDependencyFiles: string list TopAttribs: TopAttribs option - TimeStamp: System.DateTime - ImplementationFiles: TypedImplFile list } + TimeStamp: DateTime + LatestImplementationFile: TypedImplFile option } + + member x.TcErrors = Array.concat (List.rev x.TcErrorsRev) + member x.TcSymbolUses = List.rev x.TcSymbolUsesRev static member Create (tcAcc: TypeCheckAccumulator, timestamp) = { TcState = tcAcc.tcState @@ -1114,14 +1137,14 @@ type PartialCheckResults = TcGlobals = tcAcc.tcGlobals TcConfig = tcAcc.tcConfig TcEnvAtEnd = tcAcc.tcEnvAtEndOfFile - Errors = tcAcc.tcErrors - TcResolutions = tcAcc.tcResolutions - TcSymbolUses = tcAcc.tcSymbolUses - TcOpenDeclarations = tcAcc.tcOpenDeclarations + TcErrorsRev = tcAcc.tcErrorsRev + TcResolutionsRev = tcAcc.tcResolutionsRev + TcSymbolUsesRev = tcAcc.tcSymbolUsesRev + TcOpenDeclarationsRev = tcAcc.tcOpenDeclarationsRev TcDependencyFiles = tcAcc.tcDependencyFiles TopAttribs = tcAcc.topAttribs TimeStamp = timestamp - ImplementationFiles = tcAcc.typedImplFiles } + LatestImplementationFile = tcAcc.lastestTypedImplFile } [] @@ -1316,19 +1339,20 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput for (err, isError) in inp.MetaCommandDiagnostics do yield err, (if isError then FSharpErrorSeverity.Error else FSharpErrorSeverity.Warning) ] + let initialErrors = Array.append (Array.ofList loadClosureErrors) (errorLogger.GetErrors()) let tcAcc = { tcGlobals=tcGlobals tcImports=tcImports tcState=tcState tcConfig=tcConfig tcEnvAtEndOfFile=tcInitial - tcResolutions=[] - tcSymbolUses=[] - tcOpenDeclarations=[] + tcResolutionsRev=[] + tcSymbolUsesRev=[] + tcOpenDeclarationsRev=[] topAttribs=None - typedImplFiles=[] + lastestTypedImplFile=None tcDependencyFiles=basicDependencies - tcErrors = loadClosureErrors @ errorLogger.GetErrors() } + tcErrorsRev = [ initialErrors ] } return tcAcc } /// This is a build task function that gets placed into the build rules as the computation for a Vector.ScanLeft @@ -1347,9 +1371,9 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput ApplyMetaCommandsFromInputToTcConfig (tcConfig, input, Path.GetDirectoryName filename) |> ignore let sink = TcResultsSinkImpl(tcAcc.tcGlobals) - let hadParseErrors = not (List.isEmpty parseErrors) + let hadParseErrors = not (Array.isEmpty parseErrors) - let! (tcEnvAtEndOfFile, topAttribs, typedImplFiles), tcState = + let! (tcEnvAtEndOfFile, topAttribs, lastestTypedImplFile), tcState = TypeCheckOneInputEventually ((fun () -> hadParseErrors || errorLogger.ErrorCount > 0), tcConfig, tcAcc.tcImports, @@ -1359,7 +1383,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput tcAcc.tcState, input) /// Only keep the typed interface files when doing a "full" build for fsc.exe, otherwise just throw them away - let typedImplFiles = if keepAssemblyContents then typedImplFiles else [] + let lastestTypedImplFile = if keepAssemblyContents then lastestTypedImplFile else None let tcResolutions = if keepAllBackgroundResolutions then sink.GetResolutions() else TcResolutions.Empty let tcEnvAtEndOfFile = (if keepAllBackgroundResolutions then tcEnvAtEndOfFile else tcState.TcEnvFromImpls) let tcSymbolUses = sink.GetSymbolUses() @@ -1367,14 +1391,15 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput RequireCompilationThread ctok // Note: events get raised on the CompilationThread fileChecked.Trigger (filename) + let newErrors = Array.append parseErrors (capturingErrorLogger.GetErrors()) return {tcAcc with tcState=tcState tcEnvAtEndOfFile=tcEnvAtEndOfFile topAttribs=Some topAttribs - typedImplFiles=typedImplFiles - tcResolutions=tcAcc.tcResolutions @ [tcResolutions] - tcSymbolUses=tcAcc.tcSymbolUses @ [tcSymbolUses] - tcOpenDeclarations=tcAcc.tcOpenDeclarations @ sink.OpenDeclarations - tcErrors = tcAcc.tcErrors @ parseErrors @ capturingErrorLogger.GetErrors() + lastestTypedImplFile=lastestTypedImplFile + tcResolutionsRev=tcResolutions :: tcAcc.tcResolutionsRev + tcSymbolUsesRev=tcSymbolUses :: tcAcc.tcSymbolUsesRev + tcOpenDeclarationsRev = sink.GetOpenDeclarations() :: tcAcc.tcOpenDeclarationsRev + tcErrorsRev = newErrors :: tcAcc.tcErrorsRev tcDependencyFiles = filename :: tcAcc.tcDependencyFiles } } @@ -1413,7 +1438,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput // Finish the checking let (_tcEnvAtEndOfLastFile, topAttrs, mimpls), tcState = - let results = tcStates |> List.ofArray |> List.map (fun acc-> acc.tcEnvAtEndOfFile, defaultArg acc.topAttribs EmptyTopAttrs, acc.typedImplFiles) + let results = tcStates |> List.ofArray |> List.map (fun acc-> acc.tcEnvAtEndOfFile, defaultArg acc.topAttribs EmptyTopAttrs, acc.lastestTypedImplFile) TypeCheckMultipleInputsFinish (results, finalAcc.tcState) let ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = @@ -1469,7 +1494,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let finalAccWithErrors = { finalAcc with - tcErrors = finalAcc.tcErrors @ errorLogger.GetErrors() + tcErrorsRev = errorLogger.GetErrors() :: finalAcc.tcErrorsRev topAttribs = Some topAttrs } return ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt, finalAccWithErrors @@ -1823,10 +1848,10 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let errorSeverityOptions = builder.TcConfig.errorSeverityOptions let errorLogger = CompilationErrorLogger("IncrementalBuilderCreation", errorSeverityOptions) delayedLogger.CommitDelayedDiagnostics(errorLogger) - errorLogger.GetErrors() |> List.map (fun (d, severity) -> d, severity = FSharpErrorSeverity.Error) + errorLogger.GetErrors() |> Array.map (fun (d, severity) -> d, severity = FSharpErrorSeverity.Error) | _ -> - delayedLogger.Diagnostics - |> List.map (fun (d, isError) -> FSharpErrorInfo.CreateFromException(d, isError, range.Zero)) + Array.ofList delayedLogger.Diagnostics + |> Array.map (fun (d, isError) -> FSharpErrorInfo.CreateFromException(d, isError, range.Zero)) return builderOpt, diagnostics } diff --git a/src/fsharp/service/IncrementalBuild.fsi b/src/fsharp/service/IncrementalBuild.fsi index 73b3dc4be60..0f41ce10544 100755 --- a/src/fsharp/service/IncrementalBuild.fsi +++ b/src/fsharp/service/IncrementalBuild.fsi @@ -44,16 +44,16 @@ type internal PartialCheckResults = TcEnvAtEnd : TypeChecker.TcEnv /// Represents the collected errors from type checking - Errors : (PhasedDiagnostic * FSharpErrorSeverity) list + TcErrorsRev : (PhasedDiagnostic * FSharpErrorSeverity)[] list /// Represents the collected name resolutions from type checking - TcResolutions: TcResolutions list + TcResolutionsRev: TcResolutions list /// Represents the collected uses of symbols from type checking - TcSymbolUses: TcSymbolUses list + TcSymbolUsesRev: TcSymbolUses list /// Represents open declarations - TcOpenDeclarations: OpenDeclaration list + TcOpenDeclarationsRev: OpenDeclaration[] list TcDependencyFiles: string list @@ -62,8 +62,13 @@ type internal PartialCheckResults = TimeStamp: DateTime - /// Represents complete typechecked implementation files, including thier typechecked signatures if any. - ImplementationFiles: TypedImplFile list } + /// Represents latest complete typechecked implementation file, including its typechecked signature if any. + /// Empty for a signature file. + LatestImplementationFile: TypedImplFile option } + + member TcErrors: (PhasedDiagnostic * FSharpErrorSeverity)[] + + member TcSymbolUses: TcSymbolUses list /// Manages an incremental build graph for the build of an F# project [] @@ -151,9 +156,9 @@ type internal IncrementalBuilder = /// Await the untyped parse results for a particular slot in the vector of parse results. /// /// This may be a marginally long-running operation (parses are relatively quick, only one file needs to be parsed) - member GetParseResultsForFile : CompilationThreadToken * filename:string -> Cancellable + member GetParseResultsForFile : CompilationThreadToken * filename:string -> Cancellable - static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot -> Cancellable + static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot -> Cancellable /// Increment the usage count on the IncrementalBuilder by 1. This initial usage count is 0 so immediately after creation /// a call to KeepBuilderAlive should be made. The returns an IDisposable which will diff --git a/src/fsharp/service/ServiceAnalysis.fs b/src/fsharp/service/ServiceAnalysis.fs index b34fce79973..69624c252a1 100644 --- a/src/fsharp/service/ServiceAnalysis.fs +++ b/src/fsharp/service/ServiceAnalysis.fs @@ -76,10 +76,10 @@ module UnusedOpens = AppliedScope: range } /// Gets the open statements, their scopes and their resolutions - let getOpenStatements (openDeclarations: FSharpOpenDeclaration list) : OpenStatement list = + let getOpenStatements (openDeclarations: FSharpOpenDeclaration[]) : OpenStatement[] = openDeclarations - |> List.filter (fun x -> not x.IsOwnNamespace) - |> List.choose (fun openDecl -> + |> Array.filter (fun x -> not x.IsOwnNamespace) + |> Array.choose (fun openDecl -> match openDecl.LongId, openDecl.Range with | firstId :: _, Some range -> if firstId.idText = MangledGlobalName then @@ -191,7 +191,7 @@ module UnusedOpens = /// Async to allow cancellation. let filterOpenStatements symbolUses openStatements = async { - let! results = filterOpenStatementsIncremental symbolUses openStatements [] [] + let! results = filterOpenStatementsIncremental symbolUses (List.ofArray openStatements) [] [] return results |> List.map (fun os -> os.Range) } diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 615b8aecdff..f5f4a64025f 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -166,8 +166,8 @@ type TypeCheckInfo reactorOps : IReactorOperations, checkAlive : (unit -> bool), textSnapshotInfo:obj option, - implementationFiles: TypedImplFile list, - openDeclarations: OpenDeclaration list) = + implFileOpt: TypedImplFile option, + openDeclarations: OpenDeclaration[]) = let textSnapshotInfo = defaultArg textSnapshotInfo null let (|CNR|) (cnr:CapturedNameResolution) = @@ -1394,7 +1394,7 @@ type TypeCheckInfo /// The assembly being analyzed member __.ThisCcu = thisCcu - member __.ImplementationFiles = implementationFiles + member __.ImplementationFile = implFileOpt /// All open declarations in the file, including auto open modules member __.OpenDeclarations = openDeclarations @@ -1602,7 +1602,7 @@ module internal Parser = tcState: TcState, loadClosure: LoadClosure option, // These are the errors and warnings seen by the background compiler for the entire antecedent - backgroundDiagnostics: (PhasedDiagnostic * FSharpErrorSeverity) list, + backgroundDiagnostics: (PhasedDiagnostic * FSharpErrorSeverity)[], reactorOps: IReactorOperations, // Used by 'FSharpDeclarationListInfo' to check the IncrementalBuilder is still alive. checkAlive : (unit -> bool), @@ -1652,7 +1652,7 @@ module internal Parser = let hashLoadBackgroundDiagnostics, otherBackgroundDiagnostics = backgroundDiagnostics - |> List.partition (fun backgroundError -> + |> Array.partition (fun backgroundError -> hashLoadsInFile |> List.exists (fst >> sameFile (fileOfBackgroundError backgroundError))) @@ -1660,17 +1660,17 @@ module internal Parser = // Group errors and warnings by file name. let hashLoadBackgroundDiagnosticsGroupedByFileName = hashLoadBackgroundDiagnostics - |> List.map(fun err -> fileOfBackgroundError err,err) - |> List.groupByFirst // fileWithErrors, error list + |> Array.map(fun err -> fileOfBackgroundError err,err) + |> Array.groupBy fst // fileWithErrors, error list // Join the sets and report errors. // It is by-design that these messages are only present in the language service. A true build would report the errors at their // spots in the individual source files. for (fileOfHashLoad, rangesOfHashLoad) in hashLoadsInFile do - for errorGroupedByFileName in hashLoadBackgroundDiagnosticsGroupedByFileName do - if sameFile (fst errorGroupedByFileName) fileOfHashLoad then + for (file, errorGroupedByFileName) in hashLoadBackgroundDiagnosticsGroupedByFileName do + if sameFile file fileOfHashLoad then for rangeOfHashLoad in rangesOfHashLoad do // Handle the case of two #loads of the same file - let diagnostics = snd errorGroupedByFileName |> List.map(fun (pe,f)->pe.Exception,f) // Strip the build phase here. It will be replaced, in total, with TypeCheck + let diagnostics = errorGroupedByFileName |> Array.map(fun (_,(pe,f)) -> pe.Exception,f) // Strip the build phase here. It will be replaced, in total, with TypeCheck let errors = [ for (err,sev) in diagnostics do if sev = FSharpErrorSeverity.Error then yield err ] let warnings = [ for (err,sev) in diagnostics do if sev = FSharpErrorSeverity.Warning then yield err ] @@ -1729,25 +1729,25 @@ module internal Parser = let errors = errHandler.CollectedDiagnostics match tcEnvAtEndOpt with - | Some (tcEnvAtEnd, typedImplFiles, tcState) -> + | Some (tcEnvAtEnd, implFiles, tcState) -> let scope = TypeCheckInfo(tcConfig, tcGlobals, - tcState.PartialAssemblySignature, - tcState.Ccu, - tcImports, - tcEnvAtEnd.AccessRights, - //typedImplFiles, - projectFileName, - mainInputFileName, - sink.GetResolutions(), - sink.GetSymbolUses(), - tcEnvAtEnd.NameEnv, - loadClosure, - reactorOps, - checkAlive, - textSnapshotInfo, - typedImplFiles, - sink.OpenDeclarations) + tcState.PartialAssemblySignature, + tcState.Ccu, + tcImports, + tcEnvAtEnd.AccessRights, + //typedImplFiles, + projectFileName, + mainInputFileName, + sink.GetResolutions(), + sink.GetSymbolUses(), + tcEnvAtEnd.NameEnv, + loadClosure, + reactorOps, + checkAlive, + textSnapshotInfo, + List.tryHead implFiles, + sink.GetOpenDeclarations()) return errors, TypeCheckAborted.No scope | None -> return errors, TypeCheckAborted.Yes @@ -2094,25 +2094,26 @@ type FSharpCheckFileResults(filename: string, errors: FSharpErrorInfo[], scopeOp RequireCompilationThread ctok scope.IsRelativeNameResolvableFromSymbol(pos, plid, symbol)) - member info.ImplementationFiles = + member info.ImplementationFile = if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies" scopeOptX |> Option.map (fun scope -> let cenv = Impl.cenv(scope.TcGlobals, scope.ThisCcu, scope.TcImports) - [ for mimpl in scope.ImplementationFiles -> FSharpImplementationFileContents(cenv, mimpl)]) + scope.ImplementationFile |> Option.map (fun implFile -> FSharpImplementationFileContents(cenv, implFile))) + |> Option.defaultValue None member info.OpenDeclarations = scopeOptX |> Option.map (fun scope -> let cenv = Impl.cenv(scope.TcGlobals, scope.ThisCcu, scope.TcImports) - scope.OpenDeclarations |> List.map (fun x -> + scope.OpenDeclarations |> Array.map (fun x -> { LongId = x.LongId Range = x.Range Modules = x.Modules |> List.map (fun x -> FSharpEntity(cenv, x)) AppliedScope = x.AppliedScope IsOwnNamespace = x.IsOwnNamespace } : FSharpOpenDeclaration )) - |> Option.defaultValue [] + |> Option.defaultValue [| |] override info.ToString() = "FSharpCheckFileResults(" + filename + ")" @@ -2377,7 +2378,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC // /// Cache of builds keyed by options. let incrementalBuildersCache = - MruCache + MruCache (keepStrongly=projectCacheSize, keepMax=projectCacheSize, areSame = FSharpProjectOptions.AreSameForChecking, areSimilar = FSharpProjectOptions.UseSameProjectFileName, @@ -2436,7 +2437,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC static let mutable foregroundTypeCheckCount = 0 let MakeCheckFileResultsEmpty(filename, creationErrors) = - FSharpCheckFileResults (filename, Array.ofList creationErrors, None, [| |], None, reactorOps, keepAssemblyContents) + FSharpCheckFileResults (filename, creationErrors, None, [| |], None, reactorOps, keepAssemblyContents) let MakeCheckFileResults(filename, options:FSharpProjectOptions, builder, scope, dependencyFiles, creationErrors, parseErrors, tcErrors) = let errors = @@ -2488,7 +2489,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let! builderOpt, creationErrors, decrement = getOrCreateBuilderAndKeepAlive (ctok, options, userOpName) use _unwind = decrement match builderOpt with - | None -> return FSharpParseFileResults(List.toArray creationErrors, None, true, [| |]) + | None -> return FSharpParseFileResults(creationErrors, None, true, [| |]) | Some builder -> let! parseTreeOpt,_,_,parseErrors = builder.GetParseResultsForFile (ctok, filename) let errors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (builder.TcConfig.errorSeverityOptions, false, filename, parseErrors) |] @@ -2530,11 +2531,11 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC source: string, fileName: string, options: FSharpProjectOptions, - textSnapshotInfo : obj option, - fileVersion : int, - builder : IncrementalBuilder, - tcPrior : PartialCheckResults, - creationErrors : FSharpErrorInfo list, + textSnapshotInfo: obj option, + fileVersion: int, + builder: IncrementalBuilder, + tcPrior: PartialCheckResults, + creationErrors: FSharpErrorInfo[], userOpName: string) = async { @@ -2555,7 +2556,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let loadClosure = scriptClosureCacheLock.AcquireLock (fun ltok -> scriptClosureCache.TryGet (ltok, options)) let! tcErrors, tcFileResult = Parser.CheckOneFile(parseResults, source, fileName, options.ProjectFileName, tcPrior.TcConfig, tcPrior.TcGlobals, tcPrior.TcImports, - tcPrior.TcState, loadClosure, tcPrior.Errors, reactorOps, (fun () -> builder.IsAlive), textSnapshotInfo, userOpName) + tcPrior.TcState, loadClosure, tcPrior.TcErrors, reactorOps, (fun () -> builder.IsAlive), textSnapshotInfo, userOpName) let parsingOptions = FSharpParsingOptions.FromTcConfig(tcPrior.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules) let checkAnswer = MakeCheckFileAnswer(fileName, tcFileResult, options, builder, Array.ofList tcPrior.TcDependencyFiles, creationErrors, parseResults.Errors, tcErrors) bc.RecordTypeCheckFileInProjectResults(fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, source) @@ -2655,7 +2656,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC use _unwind = decrement match builderOpt with | None -> - let parseResults = FSharpParseFileResults(List.toArray creationErrors, None, true, [| |]) + let parseResults = FSharpParseFileResults(creationErrors, None, true, [| |]) return (parseResults, FSharpCheckFileAnswer.Aborted) | Some builder -> @@ -2688,7 +2689,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC use _unwind = decrement match builderOpt with | None -> - let parseResults = FSharpParseFileResults(Array.ofList creationErrors, None, true, [| |]) + let parseResults = FSharpParseFileResults(creationErrors, None, true, [| |]) let typedResults = MakeCheckFileResultsEmpty(filename, creationErrors) return (parseResults, typedResults) | Some builder -> @@ -2696,18 +2697,18 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let! tcProj = builder.GetCheckResultsAfterFileInProject (ctok, filename) let errorOptions = builder.TcConfig.errorSeverityOptions let untypedErrors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, false, filename, untypedErrors) |] - let tcErrors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, false, filename, tcProj.Errors) |] + let tcErrors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, false, filename, tcProj.TcErrors) |] let parseResults = FSharpParseFileResults(errors = untypedErrors, input = parseTreeOpt, parseHadErrors = false, dependencyFiles = builder.AllDependenciesDeprecated) let loadClosure = scriptClosureCacheLock.AcquireLock (fun ltok -> scriptClosureCache.TryGet (ltok, options) ) let scope = TypeCheckInfo(tcProj.TcConfig, tcProj.TcGlobals, tcProj.TcState.PartialAssemblySignature, tcProj.TcState.Ccu, tcProj.TcImports, tcProj.TcEnvAtEnd.AccessRights, options.ProjectFileName, filename, - List.last tcProj.TcResolutions, - List.last tcProj.TcSymbolUses, + List.head tcProj.TcResolutionsRev, + List.head tcProj.TcSymbolUsesRev, tcProj.TcEnvAtEnd.NameEnv, loadClosure, reactorOps, (fun () -> builder.IsAlive), None, - tcProj.ImplementationFiles, - tcProj.TcOpenDeclarations) + tcProj.LatestImplementationFile, + List.head tcProj.TcOpenDeclarationsRev) let typedResults = MakeCheckFileResults(filename, options, builder, scope, Array.ofList tcProj.TcDependencyFiles, creationErrors, parseResults.Errors, tcErrors) return (parseResults, typedResults) }) @@ -2730,12 +2731,12 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC use _unwind = decrement match builderOpt with | None -> - return FSharpCheckProjectResults (options.ProjectFileName, None, keepAssemblyContents, Array.ofList creationErrors, None, reactorOps) + return FSharpCheckProjectResults (options.ProjectFileName, None, keepAssemblyContents, creationErrors, None, reactorOps) | Some builder -> let! (tcProj, ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt) = builder.GetCheckResultsAndImplementationsForProject(ctok) let errorOptions = tcProj.TcConfig.errorSeverityOptions let fileName = TcGlobals.DummyFileNameForRangesWithoutASpecificLocation - let errors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, true, fileName, tcProj.Errors) |] + let errors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, true, fileName, tcProj.TcErrors) |] return FSharpCheckProjectResults (options.ProjectFileName, Some tcProj.TcConfig, keepAssemblyContents, errors, Some(tcProj.TcGlobals, tcProj.TcImports, tcProj.TcState.Ccu, tcProj.TcState.PartialAssemblySignature, tcProj.TcSymbolUses, tcProj.TopAttribs, tcAssemblyDataOpt, ilAssemRef, tcProj.TcEnvAtEnd.AccessRights, tcAssemblyExprOpt, Array.ofList tcProj.TcDependencyFiles), reactorOps) } @@ -3253,7 +3254,7 @@ type FsiInteractiveChecker(legacyReferenceResolver, reactorOps: IReactorOperatio let dependencyFiles = [| |] // interactions have no dependencies let parseResults = FSharpParseFileResults(parseErrors, parseTreeOpt, parseHadErrors = anyErrors, dependencyFiles = dependencyFiles) - let backgroundDiagnostics = [] + let backgroundDiagnostics = [| |] let reduceMemoryUsage = ReduceMemoryFlag.Yes let assumeDotNetFramework = true diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index 594f9a2da88..072d2813b84 100755 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -248,11 +248,11 @@ type public FSharpCheckFileResults = /// An optional string used for tracing compiler operations associated with this request. member IsRelativeNameResolvableFromSymbol: cursorPos : pos * plid : string list * symbol: FSharpSymbol * ?userOpName: string -> Async - /// Represents complete typechecked implementation files, including thier typechecked signatures if any. - member ImplementationFiles: FSharpImplementationFileContents list option + /// Represents complete typechecked implementation file, including its typechecked signatures if any. + member ImplementationFile: FSharpImplementationFileContents option /// Open declarations in the file, including auto open modules. - member OpenDeclarations: FSharpOpenDeclaration list + member OpenDeclarations: FSharpOpenDeclaration[] /// A handle to the results of CheckFileInProject. [] diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index a2997654b74..2e04170ad0a 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -157,7 +157,7 @@ type internal CompilationErrorLogger (debugName: string, options: FSharpErrorSev override x.ErrorCount = errorCount - member x.GetErrors() = List.ofSeq diagnostics + member x.GetErrors() = diagnostics.ToArray() /// This represents the global state established as each task function runs as part of the build. diff --git a/src/fsharp/symbols/SymbolHelpers.fsi b/src/fsharp/symbols/SymbolHelpers.fsi index 4e95e23a3bc..065c28335d4 100755 --- a/src/fsharp/symbols/SymbolHelpers.fsi +++ b/src/fsharp/symbols/SymbolHelpers.fsi @@ -188,7 +188,7 @@ type internal CompilationErrorLogger = new: debugName:string * options: FSharpErrorSeverityOptions -> CompilationErrorLogger /// Get the captured errors - member GetErrors: unit -> (PhasedDiagnostic * FSharpErrorSeverity) list + member GetErrors: unit -> (PhasedDiagnostic * FSharpErrorSeverity)[] /// This represents the global state established as each task function runs as part of the build. /// diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index d7eb1a801f6..8586fd2cd82 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5175,12 +5175,12 @@ type A(i:int) = | _ -> failwithf "Parsing aborted unexpectedly..." let declarations = - match fileCheckResults.ImplementationFiles with - | Some (implFile :: _) -> + match fileCheckResults.ImplementationFile with + | Some implFile -> match implFile.Declarations |> List.tryHead with | Some (FSharpImplementationFileDeclaration.Entity (_, subDecls)) -> subDecls | _ -> failwith "unexpected declaration" - | Some [] | None -> failwith "File check results does not contain any `ImplementationFile`s" + | None -> failwith "File check results does not contain any `ImplementationFile`s" match declarations |> List.tryHead with | Some (FSharpImplementationFileDeclaration.Entity(entity, [])) -> diff --git a/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs b/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs index 71d53fe406f..0b3f65d3627 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs @@ -22,7 +22,7 @@ and internal IProjectSite = abstract CompilationOptions : string[] /// The normalized '-r:' assembly references, without the '-r:' - abstract CompilationReferences : string [] + abstract CompilationReferences : string[] /// The '-o:' output bin path, without the '-o:' abstract CompilationBinOutputPath : string option