Skip to content

fix(clang-mlir): prevent llvm.mlir.undef on scalar brace initialization - #446

Open
Jimmy-Hu wants to merge 4 commits into
llvm:mainfrom
Jimmy-Hu:fix-brace-init-undef
Open

fix(clang-mlir): prevent llvm.mlir.undef on scalar brace initialization#446
Jimmy-Hu wants to merge 4 commits into
llvm:mainfrom
Jimmy-Hu:fix-brace-init-undef

Conversation

@Jimmy-Hu

Copy link
Copy Markdown

Intercepts empty InitListExpr for scalar types to explicitly emit arith.constant 0 instead of allocating uninitialized memory (llvm.mlir.undef). This fixes a bug where modern C++ brace initialization ({}) for basic types would crash strict MLIR consumers like CIRCT during High-Level Synthesis.

Intercepts empty `InitListExpr` for scalar types to explicitly emit `arith.constant 0` instead of allocating uninitialized memory (`llvm.mlir.undef`). This fixes a bug where modern C++ brace initialization (`{}`) for basic types would crash strict MLIR consumers like CIRCT during High-Level Synthesis.
…ization

When parsing modern C++ zero-initialization for scalars (e.g., `std::size_t index{};`), Clang does not always produce an empty `InitListExpr`. Instead, it often produces an `InitListExpr` with exactly one element: an `ImplicitValueInitExpr`.

Previously, this bypassed the `getNumInits() == 0` check in `MLIRScanner::VisitInitListExpr`, falling back to the default memory allocation path without initialization, which yielded an un-synthesizable `llvm.mlir.undef`.

This commit extends the scalar fast-path to also intercept single-element `InitListExpr`s containing an `ImplicitValueInitExpr`. It safely emits `arith.constant 0` (or `0.0`) as an RValue, preventing `undef` propagation and satisfying strict MLIR consumers like CIRCT/Calyx during High-Level Synthesis.
In `MLIRScanner::VisitCXXScalarValueInitExpr`, scalar zero-initialization only checked for `melem.isa<mlir::IntegerType>()`. When types like `std::size_t` or array indices are lowered to `mlir::IndexType`, they bypass this check and fall through to the floating-point fallback path, causing type mismatches or uninitialized values.

Replaced `isa<mlir::IntegerType>()` with `melem.isIntOrIndex()` to ensure all index and integer scalar zero-initializations emit valid zero constants.
Similar to `CXXScalarValueInitExpr`, scalar zero-initialization represented by `ImplicitValueInitExpr` previously used a strict `dyn_cast<mlir::IntegerType>`. This caused `mlir::IndexType` (e.g., `std::size_t`) to bypass the constant zero emission, leading to synthesis failures.

Replaced the strict `IntegerType` check with `Mty.isIntOrIndex()` to handle both integers and array indices gracefully, maintaining the original coding style.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant