Skip to content

Commit 6a4ba7f

Browse files
KevinRansombaronfel
authored andcommitted
--standalone type forwarding (#7462)
* Add type forwarding to static linker * Type forward using simple matches when required * Fix native resource issue with emptry streams * reduce churn * Use typeref morpher
1 parent c6ee3d2 commit 6a4ba7f

1 file changed

Lines changed: 81 additions & 12 deletions

File tree

src/fsharp/fsc.fs

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ open FSharp.Compiler.AbstractIL.ILBinaryReader
3434
open FSharp.Compiler.AbstractIL.Internal
3535
open FSharp.Compiler.AbstractIL.Internal.Library
3636
open FSharp.Compiler.AbstractIL.Diagnostics
37-
open FSharp.Compiler.IlxGen
3837

38+
open FSharp.Compiler.IlxGen
3939
open FSharp.Compiler.AccessibilityLogic
4040
open FSharp.Compiler.AttributeChecking
4141
open FSharp.Compiler.Ast
@@ -1109,13 +1109,80 @@ module MainModuleBuilder =
11091109
//----------------------------------------------------------------------------
11101110

11111111
/// Optional static linking of all DLLs that depend on the F# Library, plus other specified DLLs
1112-
module StaticLinker =
1112+
module StaticLinker =
1113+
1114+
open FSharp.Compiler.AbstractIL
1115+
1116+
// Handles TypeForwarding for the generated IL model
1117+
type TypeForwarding (tcImports: TcImports) =
1118+
1119+
// Make a dictionary of ccus passed to the compiler will be looked up by qualified assembly name
1120+
let ccuThunksQualifiedName =
1121+
tcImports.GetCcusInDeclOrder()
1122+
|> List.filter(fun ccuThunk -> ccuThunk.QualifiedName |> Option.isSome)
1123+
|> List.map(fun ccuThunk -> ccuThunk.QualifiedName |> Option.defaultValue "Assembly Name Not Passed", ccuThunk)
1124+
|> dict
1125+
1126+
// If we can't type forward using exact assembly match, we need to rely on the loader (Policy, Configuration or the coreclr load heuristics), so use try simple name
1127+
let ccuThunksSimpleName =
1128+
tcImports.GetCcusInDeclOrder()
1129+
|> List.filter(fun ccuThunk -> not (String.IsNullOrEmpty(ccuThunk.AssemblyName)))
1130+
|> List.map(fun ccuThunk -> ccuThunk.AssemblyName, ccuThunk)
1131+
|> dict
1132+
1133+
let followTypeForwardForILTypeRef (tref:ILTypeRef) =
1134+
let typename =
1135+
let parts = tref.FullName.Split([|'.'|])
1136+
match parts.Length with
1137+
| 0 -> None
1138+
| 1 -> Some (Array.empty<string>, parts.[0])
1139+
| n -> Some (parts.[0..n-2], parts.[n-1])
1140+
1141+
let scoref = tref.Scope
1142+
match scoref with
1143+
| ILScopeRef.Assembly scope ->
1144+
match ccuThunksQualifiedName.TryGetValue(scope.QualifiedName) with
1145+
| true, ccu ->
1146+
match typename with
1147+
| Some (parts, name) ->
1148+
let forwarded = ccu.TryForward(parts, name)
1149+
let result =
1150+
match forwarded with
1151+
| Some fwd -> fwd.CompilationPath.ILScopeRef
1152+
| None -> scoref
1153+
result
1154+
| None -> scoref
1155+
| false, _ ->
1156+
// Couldn't find an assembly with the version so try using a simple name
1157+
match ccuThunksSimpleName.TryGetValue(scope.Name) with
1158+
| true, ccu ->
1159+
match typename with
1160+
| Some (parts, name) ->
1161+
let forwarded = ccu.TryForward(parts, name)
1162+
let result =
1163+
match forwarded with
1164+
| Some fwd -> fwd.CompilationPath.ILScopeRef
1165+
| None -> scoref
1166+
result
1167+
| None -> scoref
1168+
| false, _ -> scoref
1169+
| _ -> scoref
1170+
1171+
let typeForwardILTypeRef (tref: ILTypeRef) =
1172+
let scoref1 = tref.Scope
1173+
let scoref2 = followTypeForwardForILTypeRef tref
1174+
if scoref1 === scoref2 then tref
1175+
else ILTypeRef.Create (scoref2, tref.Enclosing, tref.Name)
1176+
1177+
member __.TypeForwardILTypeRef tref = typeForwardILTypeRef tref
1178+
11131179
let debugStaticLinking = condition "FSHARP_DEBUG_STATIC_LINKING"
11141180

1115-
let StaticLinkILModules (tcConfig, ilGlobals, ilxMainModule, dependentILModules: (CcuThunk option * ILModuleDef) list) =
1181+
let StaticLinkILModules (tcConfig:TcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules: (CcuThunk option * ILModuleDef) list) =
11161182
if isNil dependentILModules then
11171183
ilxMainModule, (fun x -> x)
11181184
else
1185+
let typeForwarding = new TypeForwarding(tcImports)
11191186

11201187
// Check no dependent assemblies use quotations
11211188
let dependentCcuUsingQuotations = dependentILModules |> List.tryPick (function (Some ccu, _) when ccu.UsesFSharp20PlusQuotations -> Some ccu | _ -> None)
@@ -1201,13 +1268,15 @@ module StaticLinker =
12011268
(mkILMethods (topTypeDefs |> List.collect (fun td -> td.Methods.AsList)),
12021269
mkILFields (topTypeDefs |> List.collect (fun td -> td.Fields.AsList)))
12031270

1204-
let ilxMainModule =
1205-
{ ilxMainModule with
1206-
Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (m.CustomAttrs.AsList @ savedManifestAttrs)) })
1207-
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsArray ])
1208-
TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs)
1209-
Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList)
1210-
NativeResources = savedNativeResources }
1271+
let ilxMainModule =
1272+
let main =
1273+
{ ilxMainModule with
1274+
Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (m.CustomAttrs.AsList @ savedManifestAttrs)) })
1275+
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsArray ])
1276+
TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs)
1277+
Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList)
1278+
NativeResources = savedNativeResources }
1279+
Morphs.morphILTypeRefsInILModuleMemoized ilGlobals typeForwarding.TypeForwardILTypeRef main
12111280

12121281
ilxMainModule, rewriteExternalRefsToLocalRefs
12131282

@@ -1578,8 +1647,8 @@ module StaticLinker =
15781647

15791648
// Glue all this stuff into ilxMainModule
15801649
let ilxMainModule, rewriteExternalRefsToLocalRefs =
1581-
StaticLinkILModules (tcConfig, ilGlobals, ilxMainModule, dependentILModules @ providerGeneratedILModules)
1582-
1650+
StaticLinkILModules (tcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules @ providerGeneratedILModules)
1651+
15831652
// Rewrite type and assembly references
15841653
let ilxMainModule =
15851654
let isMscorlib = ilGlobals.primaryAssemblyName = PrimaryAssembly.Mscorlib.Name

0 commit comments

Comments
 (0)