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) {
150 auto arrayAttr = dyn_cast_if_present<ArrayAttr>(fieldOp->getAttr(attr));
155 if (!arrayAttr.empty() && isa<StringAttr>(arrayAttr[0])) {
156 fieldNames.emplace_back(cast<StringAttr>(arrayAttr[0]).getValue(),
163 if (fieldNames.empty())
167 std::string reflectionMapContents;
168 reflectionMapContents +=
"{ ";
170 for (
const auto &[name, value] : fieldNames) {
172 reflectionMapContents +=
", ";
175 reflectionMapContents += llvm::formatv(
176 "{ \"{0}\", reinterpret_cast<char*>(&{1}) }", name, value);
178 reflectionMapContents +=
" }";
182 auto funcs = classOp.getBlock().getOps<FuncOp>();
183 auto it = funcs.begin();
184 if (it != funcs.end())
197 FieldOp reflectionMapField = FieldOp::create(
198 rewriter, classOp.getLoc(), rewriter.
getStringAttr(
"reflectionMap"),
199 TypeAttr::get(mapType),
200 emitc::OpaqueAttr::get(context, reflectionMapContents));
203 emitc::OpaqueType nameType =
204 emitc::OpaqueType::get(rewriter.
getContext(),
"std::string");
205 emitc::OpaqueType charType =
206 emitc::OpaqueType::get(rewriter.
getContext(),
"char");
207 emitc::PointerType valType =
208 emitc::PointerType::get(rewriter.
getContext(), charType);
209 FuncOp getBufferForNameFunc = FuncOp::create(
210 rewriter, reflectionMapField->getLoc(),
"getBufferForName",
211 FunctionType::get(rewriter.
getContext(), {nameType}, {valType}));
214 rewriter.
createBlock(&getBufferForNameFunc.getBody(), {}, {nameType},
215 {reflectionMapField->getLoc()});
217 GetFieldOp mapField = GetFieldOp::create(
218 rewriter, reflectionMapField->getLoc(), mapType,
"reflectionMap");
220 MemberCallOpaqueOp lookupCall = MemberCallOpaqueOp::create(
221 rewriter, reflectionMapField->getLoc(), valType, mapField.getResult(),
222 "at", ArrayAttr{}, ArrayAttr{},
ValueRange{nameArg});
223 ReturnOp::create(rewriter, reflectionMapField->getLoc(),
224 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={})