fix(codegen): declare a hidden-visibility global across codegen units - #11817
Merged
Merged
Conversation
added 2 commits
October 3, 2026 16:18
external_decl_for_global stripped only linkage keywords, so a definition carrying a visibility keyword returned None. Closure-info records are emitted `hidden constant` (fn_info.rs), and on ELF/COFF, where generated globals are not replicated, every cross-unit reference to one is declared through this function. Splitting a module as large as effect's Schema.ts into codegen units then panicked with "cannot form external declaration for generated global". Parse the preemption and visibility keywords in LLVM's order and keep them on the declaration, so `hidden constant` becomes `external hidden constant`.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing (3)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
Author
|
The four red jobs are pre-existing on
The test this PR adds, and the rest of |
This was referenced Oct 3, 2026
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.
Symptom
Compiling OpenCode v1.18.30 on Linux x86_64 with
mainaborts in codegen (exit 134):Cause
When a module is split into codegen units, a global defined in one unit and referenced from another needs an
externaldeclaration in the referencing unit.external_decl_for_globalbuilds it, but it only stripped linkage keywords (private,internal,linkonce_odr, …) before expectingconstantorglobal. Closure-info records are emitted as@…$info = hidden constant {…}(fn_info.rs, whose own tests assert that form) —hiddenis a visibility keyword, so nothing matched, the function returnedNone, andmodule.rs:1083panicked.It is Linux/COFF-specific: on ELF and COFF generated globals are not replicated, so every cross-unit reference goes through this function. Mach-O replicates globals instead (
promote_global_for_units), which is why the same OpenCode build never hit this on macOS. It needs a module big enough to split and a cross-unit reference to a closure-info record — effect'sSchema.tsis both.Fix
Parse the optional preemption (
dso_local/dso_preemptable) and visibility (default/hidden/protected) keywords in LLVM's order after the linkage, and keep them on the declaration, sohidden constant {…}declares asexternal hidden constant {…}. The existing thread-local handling (#10399) is unchanged and composes with it;unnamed_addr/local_unnamed_addrdescribe only the definition and are dropped as before. Anything still unrecognised keeps returningNone, so a genuinely unexpected form stays loud.A scan of every
@global = …prefix the codegen emits shows they are all declarable after this change: linkage forms are stripped,external …returns early, TLS andunnamed_addrwere already handled, andhidden constantis the only visibility form emitted. Nothing emitsaddrspaceor DLL storage on a global.Test
module::tests::external_decl_keeps_hidden_visibility_of_closure_infocovers the closure-info shape,dso_local hidden global, andhidden thread_local global.left: None,right: Some("@perry_closure_m__247$info = external hidden constant { ptr, i16, i16 }").perry-codegenmodule::tests pass (--test-threads=1), including the existingexternal_decl_keeps_thread_local.cargo fmt --all -- --checkis clean on this head. The changelog fragment follows in a second commit once this PR has a number.Summary by CodeRabbit