17#include "llvm/ADT/StringRef.h"
18#include "llvm/Support/Casting.h"
19#include "llvm/Support/FormatVariadic.h"
26#define GEN_PASS_DEF_MLGOADDREFLECTIONMAPPASS
27#include "mlir/Dialect/EmitC/Transforms/Passes.h.inc"
30constexpr const char *mapLibraryHeader =
"map";
31constexpr const char *stringLibraryHeader =
"string";
34 bool patternApplied =
false;
36 void notifyOperationInserted(
Operation *op,
38 patternApplied =
true;
42IncludeOp addHeader(
OpBuilder &builder, ModuleOp module, StringRef headerName) {
44 return IncludeOp::create(builder, module.getLoc(), includeAttr,
48class MLGOAddReflectionMapPass
49 :
public impl::MLGOAddReflectionMapPassBase<MLGOAddReflectionMapPass> {
50 using MLGOAddReflectionMapPassBase::MLGOAddReflectionMapPassBase;
51 void runOnOperation()
override {
52 mlir::ModuleOp moduleOp = getOperation();
57 PatternMatchListener listener;
62 if (!listener.patternApplied)
66 bool hasMapHdr =
false;
67 bool hasStringHdr =
false;
68 for (
auto &op : *moduleOp.getBody()) {
69 IncludeOp includeOp = llvm::dyn_cast<IncludeOp>(op);
73 if (includeOp.getIsStandardInclude()) {
74 auto include = includeOp.getInclude();
76 hasMapHdr |= include == mapLibraryHeader;
77 hasStringHdr |= include == stringLibraryHeader;
80 if (hasMapHdr && hasStringHdr)
84 mlir::OpBuilder builder(moduleOp.getBody(), moduleOp.getBody()->begin());
86 addHeader(builder, moduleOp, mapLibraryHeader);
89 addHeader(builder, moduleOp, stringLibraryHeader);
135 includedFieldAttrs(includedFieldAttrs) {}
141 emitc::OpaqueType mapType = mlir::emitc::OpaqueType::get(
142 context,
"const std::map<std::string, char*>");
147 std::vector<std::pair<StringRef, StringRef>> fieldNames;
148 classOp.walk([&](FieldOp fieldOp) {
149 for (
const auto &attr : includedFieldAttrs) {
151 dyn_cast_if_present<ArrayAttr>(fieldOp->getDiscardableAttr(attr));
156 if (!arrayAttr.empty() && isa<StringAttr>(arrayAttr[0])) {
157 fieldNames.emplace_back(cast<StringAttr>(arrayAttr[0]).getValue(),
164 if (fieldNames.empty())
168 std::string reflectionMapContents;
169 reflectionMapContents +=
"{ ";
171 for (
const auto &[name, value] : fieldNames) {
173 reflectionMapContents +=
", ";
176 reflectionMapContents += llvm::formatv(
177 "{ \"{0}\", reinterpret_cast<char*>(&{1}) }", name, value);
179 reflectionMapContents +=
" }";
183 auto funcs = classOp.getBlock().getOps<FuncOp>();
184 auto it = funcs.begin();
185 if (it != funcs.end())
198 FieldOp reflectionMapField = FieldOp::create(
199 rewriter, classOp.getLoc(), rewriter.
getStringAttr(
"reflectionMap"),
200 nullptr, TypeAttr::get(mapType),
201 emitc::OpaqueAttr::get(context, reflectionMapContents));
204 emitc::OpaqueType nameType =
205 emitc::OpaqueType::get(rewriter.
getContext(),
"std::string");
206 emitc::OpaqueType charType =
207 emitc::OpaqueType::get(rewriter.
getContext(),
"char");
208 emitc::PointerType valType =
209 emitc::PointerType::get(rewriter.
getContext(), charType);
210 FuncOp getBufferForNameFunc = FuncOp::create(
211 rewriter, reflectionMapField->getLoc(),
"getBufferForName",
212 FunctionType::get(rewriter.
getContext(), {nameType}, {valType}));
215 rewriter.
createBlock(&getBufferForNameFunc.getBody(), {}, {nameType},
216 {reflectionMapField->getLoc()});
218 GetFieldOp mapField = GetFieldOp::create(
219 rewriter, reflectionMapField->getLoc(), mapType,
"reflectionMap");
221 MemberCallOpaqueOp lookupCall = MemberCallOpaqueOp::create(
222 rewriter, reflectionMapField->getLoc(), valType, mapField.getResult(),
223 "at", ArrayAttr{}, ArrayAttr{},
ValueRange{nameArg});
224 ReturnOp::create(rewriter, reflectionMapField->getLoc(),
225 lookupCall.getResult(0));
Rewrites a emitc::ClassOp to generate a reflection map of member fields and a lookup method.
LogicalResult matchAndRewrite(ClassOp classOp, PatternRewriter &rewriter) const override
MLGOAddReflectionMapClass(MLIRContext *context, llvm::ArrayRef< std::string > includedFieldAttrs)
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
StringAttr getStringAttr(const Twine &bytes)
MLIRContext * getContext() const
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents a saved insertion point.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Operation is the basic unit of execution within MLIR.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
void populateMLGOAddReflectionMapPatterns(RewritePatternSet &patterns, ArrayRef< std::string > includedFieldAttrs)
Include the generated interface declarations.
void walkAndApplyPatterns(Operation *op, const FrozenRewritePatternSet &patterns, RewriterBase::Listener *listener=nullptr)
A fast walk-based pattern rewrite driver.
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})