This repository was archived by the owner on Feb 21, 2026. It is now read-only.
[CIR] Implement static variable initialization with guarded init#2045
Draft
lanza wants to merge 1 commit intogh/lanza/19/basefrom
Draft
[CIR] Implement static variable initialization with guarded init#2045lanza wants to merge 1 commit intogh/lanza/19/basefrom
lanza wants to merge 1 commit intogh/lanza/19/basefrom
Conversation
lanza
added a commit
that referenced
this pull request
Dec 3, 2025
Add support for C++ static local variables with non-trivial destructors
and dynamic initialization. This implements the guarded initialization
pattern required by the C++ standard for one-time initialization.
**New CIR Operation: GuardedInitOp**
- Defined in CIROps.td as `cir.guarded.init`
- Represents the guarded initialization pattern for static locals
- Contains an `init_region` for initialization code
- Attributes: `thread_safe`, `perform_init`
- Parameters: guard variable (pointer), static variable (symbol)
**CIRGen Changes:**
- CIRGenFunction: Added `emitCXXGuardedInit()` and `emitCXXGlobalVarDeclInit()`
- CIRGenCXXABI: Added virtual `emitGuardedInit()` method for ABI abstraction
- CIRGenItaniumCXXABI: Core implementation with guard variable creation
- Follows Itanium C++ ABI specification
- Guard variable mangling: `_ZGVZ{function}E{variable}`
- Guard type: i64 (generic ABI) or i8 (internal linkage)
- Zero-initialized with same linkage as guarded variable
- CIRGenDecl: Integration at two call sites
- Dynamic initialization (constant emission fails)
- Constant init with non-trivial destructor
**Lowering Implementation:**
- LoweringPrepare: Converts GuardedInitOp to control flow
- Pattern: `if (!guard) { init_code; guard = 1; }`
- Thread-safe guards marked as NYI (requires __cxa_guard_* runtime calls)
**Verifier:**
- Validates guard variable is pointer type
- Ensures init_region has exactly one block
- Confirms termination with cir.yield
Follows ClangIR's deferred lowering principle:
- CIRGen emits high-level GuardedInitOp with initialization semantics
- LoweringPrepare handles platform-specific lowering
- Enables future optimizations (e.g., guard elision)
Copies CodeGen structure from:
- `clang/lib/CodeGen/CGDecl.cpp:353-402` (AddInitializerToStaticVarDecl)
- `clang/lib/CodeGen/CGDeclCXX.cpp:176-232` (EmitCXXGlobalVarDeclInit)
- `clang/lib/CodeGen/ItaniumCXXABI.cpp:2691-2906` (EmitGuardedInit)
**New Test:**
- `clang/test/CIR/CodeGen/static-var-init.cpp`
- Tests CIR emission and LLVM lowering
- Covers: destructor-only, dynamic init, constant init cases
- Validates guard variable creation and initialization pattern
**Crash Tests Fixed:**
- `static-var-guarded-init.cpp` - Static with non-trivial destructor
- `static-var-dyn-cast.cpp` - Static with template constructor
- Both updated with CHECK directives, XFAIL removed
✅ Static variables with non-trivial destructors
✅ Static variables with dynamic initialization
✅ Static variables with constant init + non-trivial destructor
✅ Reference static variables
⏳ Thread-safe guards (NYI, marked for future work)
Implements Section 3.3.2 "One-time construction API":
- Guard variable semantics (first byte = initialization status)
- Proper mangling for guard variables
- Destructor registration via existing __cxa_atexit mechanism
All code follows ClangIR standards:
- CIRGen: camelBack for members/parameters/variables
- Formatted with clang-format
- Includes comprehensive comments explaining design
Thread-safe guards (Phase 2):
- Implement __cxa_guard_acquire/release/abort calls
- Add atomic operations for guard variable access
- Handle exception cleanup during initialization
Potential optimizations:
- Guard elision when initialization proven safe
- Constant folding for always-initialized cases
- TLS optimization for thread-local statics
ghstack-source-id: 55a883a
Pull-Request: #2045
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Stack from ghstack (oldest at bottom):
Add support for C++ static local variables with non-trivial destructors
and dynamic initialization. This implements the guarded initialization
pattern required by the C++ standard for one-time initialization.
New CIR Operation: GuardedInitOp
cir.guarded.initinit_regionfor initialization codethread_safe,perform_initCIRGen Changes:
emitCXXGuardedInit()andemitCXXGlobalVarDeclInit()emitGuardedInit()method for ABI abstraction_ZGVZ{function}E{variable}Lowering Implementation:
if (!guard) { init_code; guard = 1; }Verifier:
Follows ClangIR's deferred lowering principle:
Copies CodeGen structure from:
clang/lib/CodeGen/CGDecl.cpp:353-402(AddInitializerToStaticVarDecl)clang/lib/CodeGen/CGDeclCXX.cpp:176-232(EmitCXXGlobalVarDeclInit)clang/lib/CodeGen/ItaniumCXXABI.cpp:2691-2906(EmitGuardedInit)New Test:
clang/test/CIR/CodeGen/static-var-init.cppCrash Tests Fixed:
static-var-guarded-init.cpp- Static with non-trivial destructorstatic-var-dyn-cast.cpp- Static with template constructor✅ Static variables with non-trivial destructors
✅ Static variables with dynamic initialization
✅ Static variables with constant init + non-trivial destructor
✅ Reference static variables
⏳ Thread-safe guards (NYI, marked for future work)
Implements Section 3.3.2 "One-time construction API":
All code follows ClangIR standards:
Thread-safe guards (Phase 2):
Potential optimizations: