An imported module's top-level statements run from a global constructor (#447) - #500
Merged
Merged
Conversation
…or (#447) A module with a top-level statement (`print("module init")` beside its exports), imported as source, failed to compile under every memory model: "Global is referenced by parentless instruction". The importer reads the module as declarations (its own object holds the bodies) or, under the JIT without its cache, with its bodies; either way processStatements generated the module's code statements at the importer's module level, outside any function. - An imported module's code statements are no longer generated at the importer's level (processStatements' new skipCode). Read as declarations, they are its own object's to run; included with its bodies, they run from a global constructor of their own (generateModuleInitCode), after the module's variables are initialized. - A root that is not the program's entry point (no --entry-point under --emit=obj, a module the JIT cache compiles for an import, a DLL) runs its top level from a global constructor too, where generateGlobalEntryCode gave it a `main` of its own: linked beside the program, that was a second `main`. import-source/import_toplevel.ts and toplevel_module.ts check that the module's statements run once, before main: compiled, -shared, JIT with -shared, and JIT with its cache; the JIT without its cache was checked by hand under every model. Closes #447 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A module with a top-level statement (
print("module init")beside its exports) failed to compile when another module imported it as source, under every memory model:The importer reads such a module in one of two ways:
Either way,
processStatementsgenerated the module's code statements at the importer's module level, outside any function.The fix has two parts:
skipCodeflag onprocessStatements). Read as declarations, they belong to the module's own object. Included with its bodies, they run from a global constructor of their own (generateModuleInitCode), after the module's variables are initialized.--entry-pointunder--emit=obj, a module the JIT cache compiles for an import, and a DLL. PreviouslygenerateGlobalEntryCodegave such a root its ownmain, which was a secondmainonce linked beside the program. The JIT cache already compiled imported modules expecting exactly this ("its top level run from its global constructors").New tests
import-source/import_toplevel.ts+toplevel_module.tscheck that the module's statements run once, beforemain. They run four ways: compiled,-shared, JIT with-shared, and JIT with its cache. The JIT without its cache (--jit-cache=false, thegenerateModuleInitCodepath) printsmodule initthendone.under gc, rc, none and own.weakref_basicis gc-only, as onmain)--entry-point, so through the new path)Closes #447
🤖 Generated with Claude Code