[Mlir-commits] [mlir] [mlir][EmitC] Create a pass to add a reflection map to a class (PR #205464)

ioana ghiban llvmlistbot at llvm.org
Thu Jun 25 05:02:47 PDT 2026


================
@@ -0,0 +1,188 @@
+//===- AddReflectionMap.cpp - Add a reflection map to a class --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/Dialect/EmitC/Transforms/Passes.h"
+#include "mlir/Dialect/EmitC/Transforms/Transforms.h"
+#include "mlir/IR/Attributes.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Transforms/WalkPatternRewriteDriver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace mlir;
+using namespace emitc;
+
+namespace mlir {
+namespace emitc {
+#define GEN_PASS_DEF_ADDREFLECTIONMAPPASS
+#include "mlir/Dialect/EmitC/Transforms/Passes.h.inc"
+
+namespace {
+constexpr const char *mapLibraryHeader = "map";
+constexpr const char *stringLibraryHeader = "string";
+
+IncludeOp addHeader(OpBuilder &builder, ModuleOp module, StringRef headerName) {
+  StringAttr includeAttr = builder.getStringAttr(headerName);
+  return IncludeOp::create(builder, module.getLoc(), includeAttr,
+                           /*is_standard_include=*/builder.getUnitAttr());
+}
+
+class AddReflectionMapPass
+    : public impl::AddReflectionMapPassBase<AddReflectionMapPass> {
+  using AddReflectionMapPassBase::AddReflectionMapPassBase;
+  void runOnOperation() override {
+    mlir::ModuleOp moduleOp = getOperation();
+
+    RewritePatternSet patterns(&getContext());
+    populateAddReflectionMapPatterns(patterns, fieldAttrName,
+                                     excludedFieldAttrs);
+
+    walkAndApplyPatterns(moduleOp, std::move(patterns));
+    bool hasMapHdr = false;
+    bool hasStringHdr = false;
+    for (auto &op : *moduleOp.getBody()) {
+      IncludeOp includeOp = llvm::dyn_cast<IncludeOp>(op);
+      if (!includeOp)
+        continue;
+
+      if (includeOp.getIsStandardInclude()) {
+        auto include = includeOp.getInclude();
+
+        hasMapHdr = include == mapLibraryHeader;
+        hasStringHdr = include == stringLibraryHeader;
+      }
+
+      if (hasMapHdr && hasStringHdr)
+        return;
+    }
+
+    mlir::OpBuilder builder(moduleOp.getBody(), moduleOp.getBody()->begin());
+    if (!hasMapHdr)
+      addHeader(builder, moduleOp, mapLibraryHeader);
+
+    if (!hasStringHdr)
+      addHeader(builder, moduleOp, stringLibraryHeader);
+  }
+};
+
+} // namespace
+} // namespace emitc
+} // namespace mlir
+
+class AddReflectionMapClass : public OpRewritePattern<ClassOp> {
+public:
+  AddReflectionMapClass(MLIRContext *context, StringRef attrName,
+                        llvm::ArrayRef<std::string> excludedFieldAttrs)
+      : OpRewritePattern<ClassOp>(context), fieldAttrName(attrName),
+        excludedFieldAttrs(excludedFieldAttrs.begin(),
+                           excludedFieldAttrs.end()) {}
+
+  LogicalResult matchAndRewrite(ClassOp classOp,
+                                PatternRewriter &rewriter) const override {
+    MLIRContext *context = rewriter.getContext();
+
+    emitc::OpaqueType mapType = mlir::emitc::OpaqueType::get(
+        context, "const std::map<std::string, char*>");
+
+    // Collect all field names
+    std::vector<std::pair<std::string, std::string>> fieldNames;
+    classOp.walk([&](FieldOp fieldOp) {
+      if (Attribute attr = fieldOp->getAttrDictionary().get(fieldAttrName)) {
+        if (ArrayAttr arrayAttr = dyn_cast<mlir::ArrayAttr>(attr)) {
+          StringAttr stringAttr = cast<mlir::StringAttr>(arrayAttr[0]);
+          fieldNames.emplace_back(stringAttr.getValue().str(),
+                                  fieldOp.getName().str());
+          return;
+        }
+      }
+
+      bool shouldIgnore = false;
+      for (const std::string &ignoreAttr : excludedFieldAttrs) {
+        if (fieldOp->hasAttr(ignoreAttr)) {
+          shouldIgnore = true;
+          break;
+        }
+      }
+
+      if (shouldIgnore)
----------------
ioghiban wrote:

almost, this should work (needs formatting)
```suggestion
      bool ShouldIgnore = llvm::any_of(excludedFieldAttrs, [&fieldOp](StringRef ignoreAttr){ return fieldOp->hasAttr(ignoreAttr); });
      if (ShouldIgnore)
```

https://github.com/llvm/llvm-project/pull/205464


More information about the Mlir-commits mailing list