From b328a460250db6a1058614e24562a2aa10e10de5 Mon Sep 17 00:00:00 2001 From: jimmyhu <5549662+Jimmy-Hu@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:11:44 +0800 Subject: [PATCH 1/4] fix(clang-mlir): prevent llvm.mlir.undef on scalar brace initialization 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. --- tools/cgeist/Lib/clang-mlir.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/cgeist/Lib/clang-mlir.cc b/tools/cgeist/Lib/clang-mlir.cc index b944cbda2e04..20b477776ccb 100644 --- a/tools/cgeist/Lib/clang-mlir.cc +++ b/tools/cgeist/Lib/clang-mlir.cc @@ -1095,6 +1095,22 @@ ValueCategory MLIRScanner::VisitPredefinedExpr(clang::PredefinedExpr *expr) { } ValueCategory MLIRScanner::VisitInitListExpr(clang::InitListExpr *expr) { + if (expr->getNumInits() == 0) { + mlir::Type elemType = getMLIRType(expr->getType()); + + if (elemType.isIntOrIndex()) { + auto zero = builder.create( + getMLIRLocation(expr->getBeginLoc()), + builder.getIntegerAttr(elemType, 0)); + return ValueCategory(zero, false); + } + else if (elemType.isa()) { + auto zero = builder.create( + getMLIRLocation(expr->getBeginLoc()), + builder.getFloatAttr(elemType, 0.0)); + return ValueCategory(zero, false); + } + } mlir::Type subType = getMLIRType(expr->getType()); bool isArray = false; bool LLVMABI = false; From f35b97a0872d04846a46663f0b6325c887b11407 Mon Sep 17 00:00:00 2001 From: jimmyhu <5549662+Jimmy-Hu@users.noreply.github.com> Date: Mon, 31 Aug 2026 15:34:54 +0800 Subject: [PATCH 2/4] fix(clang-mlir): handle ImplicitValueInitExpr in scalar brace initialization 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. --- tools/cgeist/Lib/clang-mlir.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/cgeist/Lib/clang-mlir.cc b/tools/cgeist/Lib/clang-mlir.cc index 20b477776ccb..a33c0a498446 100644 --- a/tools/cgeist/Lib/clang-mlir.cc +++ b/tools/cgeist/Lib/clang-mlir.cc @@ -1095,7 +1095,8 @@ ValueCategory MLIRScanner::VisitPredefinedExpr(clang::PredefinedExpr *expr) { } ValueCategory MLIRScanner::VisitInitListExpr(clang::InitListExpr *expr) { - if (expr->getNumInits() == 0) { + if (expr->getNumInits() == 0 || + (expr->getNumInits() == 1 && llvm::isa(expr->getInit(0)))) { mlir::Type elemType = getMLIRType(expr->getType()); if (elemType.isIntOrIndex()) { From 8577dbacc294f9e5d5b45144370637ec50f4cca3 Mon Sep 17 00:00:00 2001 From: jimmyhu <5549662+Jimmy-Hu@users.noreply.github.com> Date: Mon, 31 Aug 2026 18:10:04 +0800 Subject: [PATCH 3/4] fix(clang-mlir): support IndexType in VisitCXXScalarValueInitExpr In `MLIRScanner::VisitCXXScalarValueInitExpr`, scalar zero-initialization only checked for `melem.isa()`. 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()` with `melem.isIntOrIndex()` to ensure all index and integer scalar zero-initializations emit valid zero constants. --- tools/cgeist/Lib/clang-mlir.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cgeist/Lib/clang-mlir.cc b/tools/cgeist/Lib/clang-mlir.cc index a33c0a498446..1d76605be33a 100644 --- a/tools/cgeist/Lib/clang-mlir.cc +++ b/tools/cgeist/Lib/clang-mlir.cc @@ -1526,7 +1526,7 @@ MLIRScanner::VisitCXXScalarValueInitExpr(clang::CXXScalarValueInitExpr *expr) { mlir::Type melem = Glob.getMLIRType(expr->getType(), &isArray); assert(!isArray); - if (melem.isa()) + if (melem.isIntOrIndex()) return ValueCategory(builder.create(loc, 0, melem), false); else if (auto MT = dyn_cast(melem)) return ValueCategory( From 3f6833cc5590b18c2cbce8a3478f023c7599a7d5 Mon Sep 17 00:00:00 2001 From: jimmyhu <5549662+Jimmy-Hu@users.noreply.github.com> Date: Tue, 1 Sep 2026 11:07:34 +0800 Subject: [PATCH 4/4] fix(clang-mlir): support IndexType in VisitImplicitValueInitExpr Similar to `CXXScalarValueInitExpr`, scalar zero-initialization represented by `ImplicitValueInitExpr` previously used a strict `dyn_cast`. 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. --- tools/cgeist/Lib/clang-mlir.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cgeist/Lib/clang-mlir.cc b/tools/cgeist/Lib/clang-mlir.cc index 1d76605be33a..dd78d0aacaa3 100644 --- a/tools/cgeist/Lib/clang-mlir.cc +++ b/tools/cgeist/Lib/clang-mlir.cc @@ -747,8 +747,8 @@ MLIRScanner::VisitImplicitValueInitExpr(clang::ImplicitValueInitExpr *decl) { return ValueCategory(builder.create( loc, APFloat(FT.getFloatSemantics(), "0"), FT), /*isReference*/ false); - if (auto IT = dyn_cast(Mty)) - return ValueCategory(builder.create(loc, 0, IT), + if (Mty.isIntOrIndex()) + return ValueCategory(builder.create(loc, 0, Mty), /*isReference*/ false); if (auto MT = dyn_cast(Mty)) return ValueCategory(