Conversation
| , stage0 `cabalFlag` "minimal" | ||
| , stage0 `cabalFlag` "no-uncommon-ncgs" |
There was a problem hiding this comment.
I wonder if we actually should care about hadrian, or not.
d627df0 to
b5c275f
Compare
257a3dc to
e808dde
Compare
e808dde to
537b3a7
Compare
6d59cbf to
b3cd485
Compare
luite
left a comment
There was a problem hiding this comment.
Nice cleanup of the register code and organizing stubs.
In the current revision, there are some code that checks HAVE_INTERPRETER as a condition to import some GHC.StgToJS modules, even though those are guarded by a different flag in ghc.cabal.in. It's way too easy to make this kind of mistakes and correcting them by hand is tedious.
For maintainability I think it's essential to automatically prevent this.
Some ideas:
- a flag to have GHC immediately error when an "unlisted" (i.e. not explicitly named on the command line, even if its source is available in the
hs-source-dirs) module from the current package is imported - move every set of flag-guarded modules to a specific
hs-source-dirthat's only added when that flag is active
Perhaps we'd also need to have a testsuite test that checks the dependencies between the modules for when all optional components have been turned off (unless any mistake would already guarantee failure of stage1 to build)
| } | ||
| } | ||
| #else | ||
| -- MINIMAL build: no plugin support, no IC modifications |
There was a problem hiding this comment.
There are a bunch of references to MINIMAL still in the source, in comments and panic messages. Maybe some LLM can sweep them up quickly.
| -- | Calculate the maximum number of register colors that could be | ||
| -- denied to a node of this class due to having this virtual reg as a neighbour. | ||
| targetVirtualRegSqueeze :: Platform -> RegClass -> VirtualReg -> Int | ||
| targetVirtualRegSqueeze platform = rtVirtualRegSqueeze (selectRegTarget platform) |
There was a problem hiding this comment.
I saw some {-# INLINE virtualRegSqueeze #-} in the source that may or may not suggest that this code is performance sensitive. Given the way it's being used I don't expect the pragma to actually be beneficial. Is there any measurable performance difference before and after this change?
There was a problem hiding this comment.
Good observation. Yes we'll only know once we have good performance testing ... on complex applications :(
|
|
||
| -- Code Generation Backends | ||
| if flag(js-backend) | ||
| cpp-options: -DHAVE_JS_BACKEND |
There was a problem hiding this comment.
this flag is never checked, looks like some checks are still on HAVE_INTERPRETER
05a4bf8 to
f9d6769
Compare
There was a problem hiding this comment.
I really, really hat this module. Preferrably we wouldn't need stubs at all.
This to me signals for each of the stubs we have here, we unintentionally use some of this in places we shouldn't even use this to begin with.
| +x86-ncg +aarch64-ncg | ||
| -ppc-ncg -riscv64-ncg -loongarch64-ncg | ||
| -js-backend -wasm-backend | ||
| +llvm-backend | ||
| -interpreter -dynamic-linker |
There was a problem hiding this comment.
I think we might want to disable llvm-backend by default. And only enable +x86-ncg with a conditionalif arch(x86), same for aarch64?
9a43f87 to
f139792
Compare
9cbe6d3 to
a206e83
Compare
f139792 to
7e3e08e
Compare
There was a problem hiding this comment.
Pull request overview
This PR implements a "minimal stage1" build of GHC by making interpreter support, various native code generators, and other backends optional through Cabal flags. The primary goal is to reduce compilation time and binary size for stage1 builds, which only need to compile the compiler itself, not run Template Haskell or GHCi.
Changes:
- Added Cabal flags to make NCGs (X86, AArch64, PPC, RISC-V64, LoongArch64), backends (JS, Wasm, LLVM), interpreter, and dynamic linker optional
- Introduced CPP guards throughout the compiler to conditionally compile code based on these flags
- Created stub types module for interpreter-less builds
- Split
GHC.Hs.Instancesinto multiple modules for better parallel compilation - Modified stage1 configuration to disable most optional features
Reviewed changes
Copilot reviewed 54 out of 55 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| hadrian/src/Settings/Packages.hs | Added "minimal" and "no-uncommon-ncgs" flags for stage0 builds |
| ghc/ghc-bin.cabal.in | Added frontend-plugins flag to control plugin loading support |
| ghc/Main.hs | Added CPP guards for frontend plugin functionality |
| compiler/ghc.cabal.in | Added flags for NCGs, backends, interpreter, and dynamic linker; made module compilation conditional |
| compiler/GHC/Runtime/Interpreter/Stubs.hs | New stub types module for interpreter-less builds |
| compiler/GHC/Hs/Instances*.hs | Split Data instances into separate modules for parallel compilation |
| compiler/GHC/CmmToAsm/Reg/Target.hs | Refactored to use GADT-based dispatch for architecture-specific operations |
| cabal.project.stage1 | Configured stage1 to disable ghci library and optional features |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Clarify dependency explanation in GHC.Hs.Instances.Parsed comment - Add DEPRECATED pragma to empty GHC.Hs.Instances.Transitions module - Clarify toRegNo helper comment in Dwarf/Constants.hs as a fallback - Log a message when initializePlugins is skipped (no interpreter) - Fix wrong function name in panic: runHscPhase -> runHscBackendPhase
b7fc7be to
fd5fec4
Compare
05e1a0c to
7968d7c
Compare
Add +minimal and +no-uncommon-ncgs flags to compiler/ghc.cabal.in and cabal.project.stage1, plus -frontend-plugins flag for ghc-bin. The +minimal flag removes bytecode interpreter, JavaScript backend, WebAssembly backend, GHCi, and Template Haskell execution from stage1. The +no-uncommon-ncgs flag removes PPC, RISC-V 64, and LoongArch64 native code generators. Adds comprehensive CPP guards throughout the compiler to support minimal builds that can compile code without interpreter/GHCi support. Co-authored-by: Luite Stegeman <stegeman@gmail.com>
Replace the broad MINIMAL/NO_UNCOMMON_NCGS CPP defines with granular per-topic flags using positive (opt-in) HAVE_* defines: - HAVE_X86_NCG, HAVE_AARCH64_NCG, HAVE_PPC_NCG, etc. - HAVE_JS_BACKEND, HAVE_WASM_BACKEND, HAVE_LLVM_BACKEND - HAVE_INTERPRETER, HAVE_DYNAMIC_LINKER Refactor NCG register dispatch from repetitive CPP to a GADT-based pattern with ArchKind data type, RegOps typeclass, and per-architecture instances. Reduces CPP blocks from ~25 to ~5 (one per arch). Update cabal.project.stage1 to use the new granular flags.
Create GHC.Runtime.Interpreter.Stubs module containing all stub type definitions for builds without interpreter support, eliminating duplication across 6+ files. Guard all interpreter-dependent modules (Init.hs, Config/Interpreter.hs, Eval.hs) with HAVE_INTERPRETER for clean no-interpreter builds. Fix incorrect CPP guard around hscCheckSafeImports that caused Safe Haskell metadata inconsistencies in stage1-compiled .hi files. Add missing ghc-platform to cabal.project.stage1. Fix ghc.cabal.in module lists for rebase compatibility. Address PR review comments: split HAVE_INTERPRETER vs HAVE_JS_BACKEND guards, clean up "MINIMAL build" references, fix PPC/CodeGen.hs import ambiguity from GADT refactor.
Split the monolithic GHC.Hs.Instances module (344 Data instances, 14MB object file) into 5 parallel-compilable sub-modules: - GHC.Hs.Instances.Common (phase-independent instances) - GHC.Hs.Instances.Transitions (LR types spanning multiple phases) - GHC.Hs.Instances.Parsed (GhcPs instances) - GHC.Hs.Instances.Renamed (GhcRn instances + HsLocalBinds deps) - GHC.Hs.Instances.Typechecked (GhcTc instances) The wrapper module GHC.Hs.Instances re-exports all sub-modules for backward compatibility. Add stub object-code linker functions to GHC.Runtime.Interpreter that panic when called (initObjLinker, lookupSymbol, loadDLL, etc.) for no-interpreter builds. Guard Interpreter/Init.hs and Config/Interpreter.hs with HAVE_INTERPRETER.
Add new flags to further reduce stage1 compilation: - -llvm-backend: Exclude LLVM codegen (~17 modules, ~4200 lines). Guard LlvmConfigCache, CodeOutput, Pipeline/Execute LLVM phases. Move CmmToLlvm.Version modules to unconditional section (needed by GHC.Driver.Errors.Ppr and GHC.SysTools). - +host-ncg-only: Restrict NCG to host architecture using Cabal's arch() condition. Saves 8-10 modules per platform. - -hpc: Gate GHC.HsToCore.Coverage behind conditional. Stub out writeMixEntries and hpcInitCode when disabled (~540 lines). - Move GHC.Stg.BcPrep behind interpreter flag (~200 lines). Restore debug RTS default for ghc-bin (accidentally changed when adding -frontend-plugins flag).
…for stage1 - Guard GHC.HsToCore.Foreign.JavaScript import and ArchJavaScript pattern matches in dsFImport/dsFExport behind #if defined(HAVE_JS_BACKEND), matching the existing HAVE_INTERPRETER guard pattern for Wasm. - Move 11 JS-related modules (GHC.HsToCore.Foreign.JavaScript, GHC.JS.*) from unconditional Exposed-Modules to the if flag(js-backend) section in ghc.cabal.in. These modules are only needed when the JS backend is enabled and were being compiled unconditionally in stage1 despite -js-backend. - Set library-for-ghci: False in cabal.project.stage1. Stage1 never loads libraries interactively, so generating GHCi-compatible .o files from every .a archive is pure waste. Stage2 retains library-for-ghci: True. Estimated stage1 build time savings: 3-7% on top of existing minimal-stage1.
fd5fec4 to
a55ed28
Compare
This is a continuation of @luite's shrinkstage1 MR.