@@ -549,6 +549,11 @@ structure Environment where
549549 -/
550550 private base : VisibilityMap Kernel.Environment
551551 /--
552+ Additional imported environment extension state for use in codegen. Access via
553+ `getModuleEntries (level := .ir)`.
554+ -/
555+ private irBaseExts : Array EnvExtensionState := base.private.extensions
556+ /--
552557 Additional imported environment extension state for use in the language server. This field is
553558 identical to `base.extensions` in other contexts. Access via
554559 `getModuleEntries (level := .server)`.
@@ -1484,6 +1489,8 @@ abbrev ImportM := ReaderT Lean.ImportM.Context IO
14841489inductive OLeanLevel where
14851490 /-- Information from exported contexts. -/
14861491 | exported
1492+ /-- Environment extension state for codegen. -/
1493+ | ir
14871494 /-- Environment extension state for the language server. -/
14881495 | server
14891496 /-- Private module data. -/
@@ -1571,12 +1578,15 @@ namespace PersistentEnvExtension
15711578/--
15721579Returns the data saved by `ext.exportEntriesFn` when `m` was elaborated. See docs on the function for
15731580details. When using the module system, `level` can be used to select the level of data to retrieve,
1574- but is limited to the maximum level actually imported: `exported ` on the cmdline and `server` in the
1581+ but is limited to the maximum level actually imported: `ir ` on the cmdline and `server` in the
15751582language server. Higher levels will return the data of the maximum imported level.
15761583-/
15771584def getModuleEntries {α β σ : Type } [Inhabited σ] (ext : PersistentEnvExtension α β σ)
15781585 (env : Environment) (m : ModuleIdx) (level := OLeanLevel.exported) : Array α :=
1579- let exts := if level = .exported then env.base.private.extensions else env.serverBaseExts
1586+ let exts := match level with
1587+ | .exported => env.base.private.extensions
1588+ | .ir => env.irBaseExts
1589+ | _ => env.serverBaseExts
15801590 -- safety: as in `getStateUnsafe`
15811591 unsafe (ext.toEnvExtension.getStateImpl exts).importedEntries[m]!
15821592
@@ -1715,6 +1725,7 @@ unsafe def Environment.freeRegions (env : Environment) : IO Unit :=
17151725
17161726def OLeanLevel.adjustFileName (base : System.FilePath) : OLeanLevel → System.FilePath
17171727 | .exported => base
1728+ | ir => base.addExtension "ir"
17181729 | .server => base.addExtension "server"
17191730 | .private => base.addExtension "private"
17201731
@@ -1754,6 +1765,7 @@ def writeModule (env : Environment) (fname : System.FilePath) : IO Unit := do
17541765 return (level.adjustFileName fname, (← mkModuleData env level))
17551766 saveModuleDataParts env.mainModule #[
17561767 (← mkPart .exported),
1768+ (← mkPart .ir),
17571769 (← mkPart .server),
17581770 (← mkPart .private)]
17591771 else
@@ -1839,21 +1851,33 @@ private structure ImportedModule extends EffectiveImport where
18391851 /-- All loaded incremental compacted regions. -/
18401852 parts : Array (ModuleData × CompactedRegion)
18411853
1842- /-- The main module data that will eventually be used to construct the kernel environment. -/
1843- private def ImportedModule.mainModule? (self : ImportedModule) : Option ModuleData := do
1844- let (baseMod, _) ← self.parts[0 ]?
1845- self.parts[if baseMod.isModule && self.importAll then 2 else 0 ]?.map (·.1 )
1846-
18471854/-- The main module data that will eventually be used to construct the publicly accessible constants. -/
18481855private def ImportedModule.publicModule? (self : ImportedModule) : Option ModuleData := do
18491856 let (baseMod, _) ← self.parts[0 ]?
18501857 return baseMod
18511858
1859+ private def ImportedModule.getData? (self : ImportedModule) (level : OLeanLevel) : Option ModuleData := do
1860+ -- Without the module system, we only have the exported level.
1861+ let level := if (← self.publicModule?).isModule then level else .exported
1862+ self.parts[level.toCtorIdx]?.map (·.1 )
1863+
1864+ /-- The main module data that will eventually be used to construct the kernel environment. -/
1865+ private def ImportedModule.mainModule? (self : ImportedModule) : Option ModuleData :=
1866+ self.getData? (if self.importAll then OLeanLevel.private else .exported)
1867+
18521868/-- The module data that should be used for server purposes. -/
18531869private def ImportedModule.serverData? (self : ImportedModule) (level : OLeanLevel) :
1870+ Option ModuleData :=
1871+ -- fall back to .exported outside the server
1872+ self.getData? (if level ≥ .server then level else .exported)
1873+
1874+ /-- The module data that should be used for codegen purposes. -/
1875+ private def ImportedModule.irData? (self : ImportedModule) (level : OLeanLevel) :
18541876 Option ModuleData := do
1855- let (baseMod, _) ← self.parts[0 ]?
1856- self.parts[if baseMod.isModule && level != .exported then 1 else 0 ]?.map (·.1 )
1877+ let level :=
1878+ if level ≥ .server then level
1879+ else .ir
1880+ self.getData? level
18571881
18581882structure ImportState where
18591883 private moduleNameMap : Std.HashMap Name ImportedModule := {}
@@ -1888,12 +1912,15 @@ private def findOLeanParts (mod : Name) : IO (Array System.FilePath) := do
18881912 let mut fnames := #[mFile]
18891913 -- Opportunistically load all available parts.
18901914 -- Necessary because the import level may be upgraded a later import.
1891- let sFile := OLeanLevel.server .adjustFileName mFile
1915+ let sFile := OLeanLevel.ir .adjustFileName mFile
18921916 if (← sFile.pathExists) then
18931917 fnames := fnames.push sFile
1894- let pFile := OLeanLevel.private.adjustFileName mFile
1895- if (← pFile.pathExists) then
1896- fnames := fnames.push pFile
1918+ let sFile := OLeanLevel.server.adjustFileName mFile
1919+ if (← sFile.pathExists) then
1920+ fnames := fnames.push sFile
1921+ let pFile := OLeanLevel.private.adjustFileName mFile
1922+ if (← pFile.pathExists) then
1923+ fnames := fnames.push pFile
18971924 return fnames
18981925
18991926partial def importModulesCore
@@ -2084,9 +2111,23 @@ def finalizeImport (s : ImportState) (imports : Array Import) (opts : Options) (
20842111 base.public := publicBase
20852112 realizedImportedConsts? := none
20862113 }
2087- env := env.setCheckedSync { env.base.private with extensions := (← setImportedEntries env.base.private.extensions moduleData) }
2114+ let mut extensions ← setImportedEntries env.base.private.extensions moduleData
2115+ let extDescrs ← persistentEnvExtensionsRef.get
2116+ if let some declMapExt := extDescrs.find? (·.name == `Lean.IR.declMapExt) then
2117+ for h : modIdx in [:modules.size] do
2118+ let mod := modules[modIdx]
2119+ if mod.irPhases != .runtime then
2120+ if let some irData := mod.irData? level then
2121+ if let some (_, entries) := irData.entries.find? (·.1 == declMapExt.name) then
2122+ extensions := unsafe declMapExt.toEnvExtension.modifyStateImpl extensions fun s =>
2123+ { s with importedEntries := s.importedEntries.setIfInBounds modIdx entries }
2124+ env := env.setCheckedSync { env.base.private with extensions }
2125+ let irData := modules.filterMap (·.irData? level)
20882126 let serverData := modules.filterMap (·.serverData? level)
2089- env := { env with serverBaseExts := (← setImportedEntries env.base.private.extensions serverData) }
2127+ env := { env with
2128+ irBaseExts := (← setImportedEntries env.base.private.extensions irData)
2129+ serverBaseExts := (← setImportedEntries env.base.private.extensions serverData)
2130+ }
20902131 if leakEnv then
20912132 /- Mark persistent a first time before `finalizePersistenExtensions`, which
20922133 avoids costly MT markings when e.g. an interpreter closure (which
0 commit comments