parent
159f069863
commit
5bf590e710
13 changed files with 81 additions and 27 deletions
9
.vscode/tasks.json
vendored
9
.vscode/tasks.json
vendored
|
|
@ -11,6 +11,15 @@
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "build stage2",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make -C build/release stage2 -j$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": {
|
||||||
|
"kind": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "build-old",
|
"label": "build-old",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
|
|
||||||
|
|
@ -1230,7 +1230,14 @@ def instantiateRevRangeArgs (e : Expr) (beginIdx endIdx : Nat) (args : Array (Ar
|
||||||
else
|
else
|
||||||
e.instantiateRevRange beginIdx endIdx (args.map (·.toExpr))
|
e.instantiateRevRange beginIdx endIdx (args.map (·.toExpr))
|
||||||
|
|
||||||
/-- Lookup function for compiler extensions with sorted persisted state that works in both `lean` and `leanir`. -/
|
/--
|
||||||
|
Lookup function for compiler extensions with sorted persisted state that works in both `lean` and
|
||||||
|
`leanir`.
|
||||||
|
|
||||||
|
`preferImported` defaults to false because in `leanir`, we do not want to mix information from
|
||||||
|
`meta` compilation in `lean` with our own state. But in `lean`, setting `preferImported` can help
|
||||||
|
with avoiding unnecessary task blocks.
|
||||||
|
-/
|
||||||
@[inline] def findExtEntry? [Inhabited σ] (env : Environment) (ext : PersistentEnvExtension α β σ) (declName : Name)
|
@[inline] def findExtEntry? [Inhabited σ] (env : Environment) (ext : PersistentEnvExtension α β σ) (declName : Name)
|
||||||
(findAtSorted? : Array α → Name → Option α')
|
(findAtSorted? : Array α → Name → Option α')
|
||||||
(findInState? : σ → Name → Option α') : Option α' :=
|
(findInState? : σ → Name → Option α') : Option α' :=
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,13 @@ def isValidMainType (type : Expr) : Bool :=
|
||||||
isValidResultName resultName
|
isValidResultName resultName
|
||||||
| _ => false
|
| _ => false
|
||||||
|
|
||||||
|
/-- A postponed call of `compileDecls`. -/
|
||||||
structure PostponedCompileDecls where
|
structure PostponedCompileDecls where
|
||||||
|
/-- Declaration names of this mutual group. -/
|
||||||
declNames : Array Name
|
declNames : Array Name
|
||||||
deriving BEq, Hashable
|
/-- Options at time of original call, to be restored for tracing etc. -/
|
||||||
|
options : Options
|
||||||
|
deriving BEq
|
||||||
|
|
||||||
/--
|
/--
|
||||||
Saves postponed `compileDecls` calls.
|
Saves postponed `compileDecls` calls.
|
||||||
|
|
@ -101,16 +105,20 @@ builtin_initialize postponedCompileDeclsExt : SimplePersistentEnvExtension Postp
|
||||||
{ exported := #[], server := #[], «private» := es.toArray }
|
{ exported := #[], server := #[], «private» := es.toArray }
|
||||||
}
|
}
|
||||||
|
|
||||||
def resumeCompilation (declName : Name) : CoreM Unit := do
|
def resumeCompilation (declName : Name) (baseOpts : Options) : CoreM Unit := do
|
||||||
let some decls := postponedCompileDeclsExt.getState (← getEnv) |>.find? declName | return
|
let some decls := postponedCompileDeclsExt.getState (← getEnv) |>.find? declName | return
|
||||||
|
let opts := baseOpts.mergeBy (fun _ base _ => base) decls.options
|
||||||
|
let opts := compiler.postponeCompile.set opts false
|
||||||
modifyEnv (postponedCompileDeclsExt.modifyState · fun s => decls.declNames.foldl (·.erase) s)
|
modifyEnv (postponedCompileDeclsExt.modifyState · fun s => decls.declNames.foldl (·.erase) s)
|
||||||
withOptions (compiler.postponeCompile.set · false) do
|
-- NOTE: we *must* throw away the current options as they could depend on the specific recursion
|
||||||
|
-- we did to get here.
|
||||||
|
withOptions (fun _ => opts) do
|
||||||
Core.prependError m!"Failed to compile `{declName}`" do
|
Core.prependError m!"Failed to compile `{declName}`" do
|
||||||
(← compileDeclsRef.get) decls.declNames
|
(← compileDeclsRef.get) decls.declNames baseOpts
|
||||||
|
|
||||||
namespace PassManager
|
namespace PassManager
|
||||||
|
|
||||||
partial def run (declNames : Array Name) : CompilerM Unit := withAtLeastMaxRecDepth 8192 do
|
partial def run (declNames : Array Name) (baseOpts : Options) : CompilerM Unit := withAtLeastMaxRecDepth 8192 do
|
||||||
/-
|
/-
|
||||||
Note: we need to increase the recursion depth because we currently do to save phase1
|
Note: we need to increase the recursion depth because we currently do to save phase1
|
||||||
declarations in .olean files. Then, we have to recursively compile all dependencies,
|
declarations in .olean files. Then, we have to recursively compile all dependencies,
|
||||||
|
|
@ -141,11 +149,14 @@ partial def run (declNames : Array Name) : CompilerM Unit := withAtLeastMaxRecDe
|
||||||
|
|
||||||
-- Now that we have done all input checks, check for postponement
|
-- Now that we have done all input checks, check for postponement
|
||||||
if (← getEnv).header.isModule && (← compiler.postponeCompile.getM) then
|
if (← getEnv).header.isModule && (← compiler.postponeCompile.getM) then
|
||||||
modifyEnv (postponedCompileDeclsExt.addEntry · { declNames := decls.map (·.name) })
|
modifyEnv (postponedCompileDeclsExt.addEntry · { declNames := decls.map (·.name), options := ← getOptions })
|
||||||
-- meta defs are compiled locally so they are available for execution/compilation without
|
-- meta defs are compiled locally so they are available for execution/compilation without
|
||||||
-- importing `.ir` but still marked for `leanir` compilation so that we do not have to persist
|
-- importing `.ir` but still marked for `leanir` compilation so that we do not have to persist
|
||||||
-- module-local compilation information between the two processes
|
-- module-local compilation information between the two processes
|
||||||
if !decls.any (isMarkedMeta (← getEnv) ·.name) then
|
if decls.any (isMarkedMeta (← getEnv) ·.name) then
|
||||||
|
-- avoid re-compiling the meta defs in this process; the entry for `leanir` is not affected
|
||||||
|
modifyEnv (postponedCompileDeclsExt.modifyState · fun s => decls.foldl (·.erase ·.name) s)
|
||||||
|
else
|
||||||
trace[Compiler] "postponing compilation of {decls.map (·.name)}"
|
trace[Compiler] "postponing compilation of {decls.map (·.name)}"
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -157,7 +168,7 @@ partial def run (declNames : Array Name) : CompilerM Unit := withAtLeastMaxRecDe
|
||||||
let .let { value := .const c .., .. } .. := c | return
|
let .let { value := .const c .., .. } .. := c | return
|
||||||
-- Need to do some lookups to get the actual name passed to `compileDecls`
|
-- Need to do some lookups to get the actual name passed to `compileDecls`
|
||||||
let c := Compiler.getImplementedBy? (← getEnv) c |>.getD c
|
let c := Compiler.getImplementedBy? (← getEnv) c |>.getD c
|
||||||
resumeCompilation c
|
resumeCompilation c baseOpts
|
||||||
|
|
||||||
let decls := markRecDecls decls
|
let decls := markRecDecls decls
|
||||||
let manager ← getPassManager
|
let manager ← getPassManager
|
||||||
|
|
@ -200,9 +211,9 @@ where
|
||||||
|
|
||||||
end PassManager
|
end PassManager
|
||||||
|
|
||||||
def main (declNames : Array Name) : CoreM Unit := do
|
def main (declNames : Array Name) (baseOpts : Options) : CoreM Unit := do
|
||||||
withTraceNode `Compiler (fun _ => return m!"compiling: {declNames}") do
|
withTraceNode `Compiler (fun _ => return m!"compiling: {declNames}") do
|
||||||
CompilerM.run <| PassManager.run declNames
|
CompilerM.run <| PassManager.run declNames baseOpts
|
||||||
|
|
||||||
builtin_initialize
|
builtin_initialize
|
||||||
compileDeclsRef.set main
|
compileDeclsRef.set main
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ that fulfill the requirements of `shouldGenerateCode`.
|
||||||
def compile (declNames : Array Name) : CoreM Unit := do profileitM Exception "compiler new" (← getOptions) do
|
def compile (declNames : Array Name) : CoreM Unit := do profileitM Exception "compiler new" (← getOptions) do
|
||||||
withOptions (compiler.postponeCompile.set · false) do
|
withOptions (compiler.postponeCompile.set · false) do
|
||||||
withTraceNode `Compiler (fun _ => return m!"compiling: {declNames}") do
|
withTraceNode `Compiler (fun _ => return m!"compiling: {declNames}") do
|
||||||
LCNF.main declNames
|
LCNF.main declNames {}
|
||||||
|
|
||||||
builtin_initialize
|
builtin_initialize
|
||||||
registerTraceClass `Compiler
|
registerTraceClass `Compiler
|
||||||
|
|
|
||||||
|
|
@ -711,11 +711,11 @@ breaks the cycle by making `compileDeclsImpl` a "dynamic" call through the ref t
|
||||||
to the linker. In the compiler there is a matching `builtin_initialize` to set this ref to the
|
to the linker. In the compiler there is a matching `builtin_initialize` to set this ref to the
|
||||||
actual implementation of compileDeclsRef.
|
actual implementation of compileDeclsRef.
|
||||||
-/
|
-/
|
||||||
builtin_initialize compileDeclsRef : IO.Ref (Array Name → CoreM Unit) ←
|
builtin_initialize compileDeclsRef : IO.Ref (Array Name → Options → CoreM Unit) ←
|
||||||
IO.mkRef (fun _ => throwError m!"call to compileDecls with uninitialized compileDeclsRef")
|
IO.mkRef (fun _ _ => throwError m!"call to compileDecls with uninitialized compileDeclsRef")
|
||||||
|
|
||||||
private def compileDeclsImpl (declNames : Array Name) : CoreM Unit := do
|
private def compileDeclsImpl (declNames : Array Name) : CoreM Unit := do
|
||||||
(← compileDeclsRef.get) declNames
|
(← compileDeclsRef.get) declNames {}
|
||||||
|
|
||||||
-- `ref?` is used for error reporting if available
|
-- `ref?` is used for error reporting if available
|
||||||
def compileDecls (decls : Array Name) (logErrors := true) : CoreM Unit := do
|
def compileDecls (decls : Array Name) (logErrors := true) : CoreM Unit := do
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import Lean.Server.Watchdog
|
||||||
import Lean.Server.FileWorker
|
import Lean.Server.FileWorker
|
||||||
import Lean.Compiler.LCNF.EmitC
|
import Lean.Compiler.LCNF.EmitC
|
||||||
import Init.System.Platform
|
import Init.System.Platform
|
||||||
|
import Lean.Compiler.Options
|
||||||
|
|
||||||
/- Lean companion to `shell.cpp` -/
|
/- Lean companion to `shell.cpp` -/
|
||||||
|
|
||||||
|
|
@ -340,7 +341,10 @@ def ShellOptions.process (opts : ShellOptions)
|
||||||
| 'I' => -- `-I, --stdin`
|
| 'I' => -- `-I, --stdin`
|
||||||
return {opts with useStdin := true}
|
return {opts with useStdin := true}
|
||||||
| 'r' => -- `--run`
|
| 'r' => -- `--run`
|
||||||
return {opts with run := true}
|
return {opts with
|
||||||
|
run := true
|
||||||
|
-- can't get IR if it's postponed
|
||||||
|
leanOpts := Compiler.compiler.postponeCompile.set opts.leanOpts false }
|
||||||
| 'o' => -- `--o, olean=fname`
|
| 'o' => -- `--o, olean=fname`
|
||||||
return {opts with oleanFileName? := ← checkOptArg "o" optArg?}
|
return {opts with oleanFileName? := ← checkOptArg "o" optArg?}
|
||||||
| 'i' => -- `--i, ilean=fname`
|
| 'i' => -- `--i, ilean=fname`
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,18 @@ def setConfigOption (opts : Options) (arg : String) : IO Options := do
|
||||||
|
|
||||||
public def main (args : List String) : IO UInt32 := do
|
public def main (args : List String) : IO UInt32 := do
|
||||||
let setupFile::irFile::c::optArgs := args | do
|
let setupFile::irFile::c::optArgs := args | do
|
||||||
IO.println s!"usage: leanir <setup.json> <module> <output.ir> <output.c> <-Dopt=val>..."
|
IO.println s!"usage: leanir <setup.json> <output.ir> <output.c> [--stat] <-Dopt=val>..."
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
let setup ← ModuleSetup.load setupFile
|
let setup ← ModuleSetup.load setupFile
|
||||||
let modName := setup.name
|
let modName := setup.name
|
||||||
|
|
||||||
|
let mut printStats := false
|
||||||
let mut opts := setup.options.toOptions
|
let mut opts := setup.options.toOptions
|
||||||
for optArg in optArgs do
|
for optArg in optArgs do
|
||||||
|
if optArg == "--stat" then
|
||||||
|
printStats := true
|
||||||
|
else
|
||||||
opts ← setConfigOption opts optArg
|
opts ← setConfigOption opts optArg
|
||||||
opts := Compiler.compiler.inLeanIR.set opts true
|
opts := Compiler.compiler.inLeanIR.set opts true
|
||||||
opts := maxHeartbeats.set opts 0
|
opts := maxHeartbeats.set opts 0
|
||||||
|
|
@ -127,12 +131,15 @@ public def main (args : List String) : IO UInt32 := do
|
||||||
modifyEnv (postponedCompileDeclsExt.setState · (decls.foldl (fun s e => e.declNames.foldl (·.insert · e) s) {}))
|
modifyEnv (postponedCompileDeclsExt.setState · (decls.foldl (fun s e => e.declNames.foldl (·.insert · e) s) {}))
|
||||||
for decl in decls do
|
for decl in decls do
|
||||||
for decl in decl.declNames do
|
for decl in decl.declNames do
|
||||||
resumeCompilation decl
|
try
|
||||||
|
resumeCompilation decl (← getOptions)
|
||||||
|
finally
|
||||||
|
addTraceAsMessages
|
||||||
|
for msg in (← Core.getAndEmptyMessageLog).unreported do
|
||||||
|
IO.eprintln (← msg.toString)
|
||||||
catch e =>
|
catch e =>
|
||||||
unless e.isInterrupt do
|
unless e.isInterrupt do
|
||||||
logError e.toMessageData
|
logError e.toMessageData
|
||||||
finally
|
|
||||||
addTraceAsMessages
|
|
||||||
|
|
||||||
let .ok (_, s) := res? | unreachable!
|
let .ok (_, s) := res? | unreachable!
|
||||||
let env := s.env
|
let env := s.env
|
||||||
|
|
@ -155,4 +162,6 @@ public def main (args : List String) : IO UInt32 := do
|
||||||
out.write data.toUTF8
|
out.write data.toUTF8
|
||||||
|
|
||||||
displayCumulativeProfilingTimes
|
displayCumulativeProfilingTimes
|
||||||
|
if printStats then
|
||||||
|
env.displayStats
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ def run_leanir(module: str) -> None:
|
||||||
cmd=[
|
cmd=[
|
||||||
"leanir",
|
"leanir",
|
||||||
*sys.argv[1:],
|
*sys.argv[1:],
|
||||||
*("-Dprofiler=true", "-Dprofiler.threshold=9999999"),
|
"--stat", "-Dprofiler=true", "-Dprofiler.threshold=9999999",
|
||||||
],
|
],
|
||||||
output=WRAPPER_OUT,
|
output=WRAPPER_OUT,
|
||||||
topics=[f"{BENCHMARK}/module/ir/{module}"],
|
topics=[f"{BENCHMARK}/module/ir/{module}"],
|
||||||
|
|
@ -81,6 +81,19 @@ def run_leanir(module: str) -> None:
|
||||||
seconds = seconds / 1000
|
seconds = seconds / 1000
|
||||||
save_measurement(f"{BENCHMARK}/profile/ir/{name}//wall-clock", seconds, "s")
|
save_measurement(f"{BENCHMARK}/profile/ir/{name}//wall-clock", seconds, "s")
|
||||||
|
|
||||||
|
# Output of `leanir --stat`
|
||||||
|
stat = Counter[str]()
|
||||||
|
for line in stdout.splitlines():
|
||||||
|
if match := re.fullmatch(r"number of (imported .*):\s+(\d+)$", line):
|
||||||
|
name = match.group(1)
|
||||||
|
count = int(match.group(2))
|
||||||
|
stat[name] += count
|
||||||
|
for name, count in stat.items():
|
||||||
|
if count > 0:
|
||||||
|
if name.endswith("bytes"):
|
||||||
|
save_measurement(f"{BENCHMARK}/stat/ir/{name}//bytes", count, "B")
|
||||||
|
else:
|
||||||
|
save_measurement(f"{BENCHMARK}/stat/ir/{name}//amount", count)
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
@ -12,7 +12,7 @@ rm -f "$1.measurements.jsonl"
|
||||||
if [[ -n $DO_COMPILE ]]; then
|
if [[ -n $DO_COMPILE ]]; then
|
||||||
run_before "$1"
|
run_before "$1"
|
||||||
|
|
||||||
lean --c="$1.c" "${TEST_LEAN_ARGS[@]}" "$1" || fail "Failed to compile $1 into $1.c"
|
lean --c="$1.c" -Dcompiler.postponeCompile=false "${TEST_LEAN_ARGS[@]}" "$1" || fail "Failed to compile $1 into $1.c"
|
||||||
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -o "$1.out" "${TEST_LEANC_ARGS[@]}" "$1.c" || fail "Failed to compile $1.c"
|
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -o "$1.out" "${TEST_LEANC_ARGS[@]}" "$1.c" || fail "Failed to compile $1.c"
|
||||||
|
|
||||||
# Measure .out binary size
|
# Measure .out binary size
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ if [[ -n $DO_COMPILE ]]; then
|
||||||
echo "Compiling and executing lean file"
|
echo "Compiling and executing lean file"
|
||||||
run_before "$1"
|
run_before "$1"
|
||||||
|
|
||||||
lean --c="$1.c" "${TEST_LEAN_ARGS[@]}" "$1" || fail "Failed to compile $1 into $1.c"
|
lean --c="$1.c" -Dcompiler.postponeCompile=false "${TEST_LEAN_ARGS[@]}" "$1" || fail "Failed to compile $1 into $1.c"
|
||||||
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -o "$1.out" "${TEST_LEANC_ARGS[@]}" "$1.c" || fail "Failed to compile $1.c"
|
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -o "$1.out" "${TEST_LEANC_ARGS[@]}" "$1.c" || fail "Failed to compile $1.c"
|
||||||
|
|
||||||
capture_only "$1" \
|
capture_only "$1" \
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ if [[ -n $DO_COMPILE ]]; then
|
||||||
|
|
||||||
TOPIC="compiled/$(basename "$1" .lean)"
|
TOPIC="compiled/$(basename "$1" .lean)"
|
||||||
|
|
||||||
lean --c="$1.c" "${TEST_LEAN_ARGS[@]}" "$1" || fail "Failed to compile $1 into $1.c"
|
lean --c="$1.c" -Dcompiler.postponeCompile=false "${TEST_LEAN_ARGS[@]}" "$1" || fail "Failed to compile $1 into $1.c"
|
||||||
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -o "$1.out" "${TEST_LEANC_ARGS[@]}" "$1.c" || fail "Failed to compile $1.c"
|
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -o "$1.out" "${TEST_LEANC_ARGS[@]}" "$1.c" || fail "Failed to compile $1.c"
|
||||||
|
|
||||||
capture_only "$1" \
|
capture_only "$1" \
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ run_before "$1"
|
||||||
|
|
||||||
# `--root` to infer same private names as in the server
|
# `--root` to infer same private names as in the server
|
||||||
# Elab.inServer to allow for arbitrary `#eval`
|
# Elab.inServer to allow for arbitrary `#eval`
|
||||||
|
# compiler.postponeCompile for immediate trace output
|
||||||
capture_only "$1" \
|
capture_only "$1" \
|
||||||
lean --root=.. -DprintMessageEndPos=true -Dlinter.all=false -DElab.inServer=true "${TEST_LEAN_ARGS[@]}" "$1"
|
lean --root=.. -DprintMessageEndPos=true -Dlinter.all=false -DElab.inServer=true -Dcompiler.postponeCompile=false "${TEST_LEAN_ARGS[@]}" "$1"
|
||||||
normalize_mvar_suffixes
|
normalize_mvar_suffixes
|
||||||
normalize_reference_urls
|
normalize_reference_urls
|
||||||
normalize_measurements
|
normalize_measurements
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# LEAN_EXPORTING needs to be defined for .c files included in shared libraries
|
# LEAN_EXPORTING needs to be defined for .c files included in shared libraries
|
||||||
lean --c=SnakeLinter.c SnakeLinter.lean
|
lean --c=SnakeLinter.c -Dcompiler.postponeCompile=false SnakeLinter.lean
|
||||||
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -DLEAN_EXPORTING -shared -o SnakeLinter.so SnakeLinter.c
|
leanc ${LEANC_OPTS-} -O3 -DNDEBUG -DLEAN_EXPORTING -shared -o SnakeLinter.so SnakeLinter.c
|
||||||
|
|
||||||
capture_only SnakeLinter.lean \
|
capture_only SnakeLinter.lean \
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue