54 auto pattern = llvm::dyn_cast<ArrayAttr>(rawPattern);
60 size_t expectedChunkCount = parameterCount + 1;
61 if (pattern.size() != expectedChunkCount) {
63 << expectedChunkCount <<
" literal chunk(s) for " << parameterCount
64 <<
" template parameter(s), but found " << pattern.size();
66 for (
size_t index = 0; index < pattern.size(); ++index) {
67 if (!llvm::isa<StringAttr>(pattern[index])) {
69 <<
" to be a StringAttr";
81LogicalResult checkForNameConflict(SymbolTableCollection &tables, SymbolOpInterface op) {
86 return op.emitOpError()
87 .append(
"name conflicts with an existing symbol")
88 .attachNote(res->get()->getLoc())
89 .append(
"symbol already defined here");
97 return checkForNameConflict(tables, *
this);
105 if (failed(checkForNameConflict(tables, *
this))) {
111 Operation *thisOp = this->getOperation();
113 assert(parentTemplate &&
"per ODS");
114 LogicalResult errorState = success();
115 auto checkUses = [
this, &parentTemplate, &errorState](Operation *symTableOp, bool) {
117 for (SymbolTable::SymbolUse
use : uses.value()) {
119 auto usedSym = llvm::dyn_cast<FlatSymbolRefAttr>(
use.getSymbolRef());
121 InFlightDiagnostic diag = this->emitOpError().append(
122 "initialization cannot use a symbol defined by another `",
125 diag.attachNote(
use.getUser()->getLoc()).append(
"symbol ", usedSym,
" used here");
127 diag.attachNote(def.getLoc()).append(
"defined here");
134 checkUses(thisOp,
true);
135 if (succeeded(errorState)) {
136 SymbolTable::walkSymbolTables(thisOp,
true, checkUses);
143 if (!region.hasOneBlock()) {
144 return emitOpError(
"expected initializer region with a single block");
146 Block &block = region.back();
147 if (!llvm::isa<YieldOp>(block.getTerminator())) {
148 return emitOpError(
"expected initializer region to end with a '")
152 std::optional<InFlightDiagnostic> illegalOpDiagnostic;
153 auto walkRes = block.walk([&illegalOpDiagnostic](Operation *p) {
154 auto emitIllegalOpError = [&illegalOpDiagnostic, p](
const Twine &description) {
155 illegalOpDiagnostic.emplace(
156 p->emitOpError() << description <<
" is not allowed within a `"
162 if (llvm::isa<function::CallOp>(p)) {
163 emitIllegalOpError(Twine(
"'") + p->getName().getStringRef() +
"' op");
164 return WalkResult::interrupt();
166 if (llvm::isa<global::GlobalRefOpInterface>(p) && !isMemoryEffectFree(p)) {
167 if (llvm::isa<global::GlobalReadOp>(p)) {
172 emitIllegalOpError(Twine(
"'") + p->getName().getStringRef() +
"' op");
174 return WalkResult::interrupt();
176 return WalkResult::advance();
178 if (walkRes.wasInterrupted()) {
179 assert(illegalOpDiagnostic);
180 illegalOpDiagnostic->report();
188 assert(region.hasOneBlock() &&
"per `verifyRegions()`");
189 YieldOp yieldOp = llvm::dyn_cast<YieldOp>(region.back().getTerminator());
190 assert(yieldOp &&
"per `verifyRegions()`");
191 return yieldOp.
getVal().getType();
202 if (failed(getParentRes)) {
205 if (!*getParentRes) {
208 <<
"' that targets an operation with a '"
215 return this->emitOpError()
216 .append(
"references unknown symbol \"", name,
'"')
217 .attachNote(getParentRes->getLoc())
218 .append(
"must reference a param or expr of this template");
221 if (std::optional<Type> paramType = bindingOp.getTypeOpt()) {
222 if (llvm::isa<TypeVarType>(*paramType)) {
223 return this->emitOpError().append(
224 "cannot target \"", name,
"\" because it is a type variable"
227 if (this->getType() != *paramType) {
228 return this->emitOpError().append(
229 "type ", this->getType(),
" does not match constant param type ", *paramType
247 if (map.getNumResults() != 1) {
248 return emitOpError(
"must produce exactly one value");
252 unsigned mapDims = map.getNumDims();
253 if (getNumOperands() != mapDims + map.getNumSymbols()) {
254 return emitOpError(
"operand count must equal affine map dimension+symbol count");
256 return emitOpError(
"dimension operand count must equal affine map dimension count");
263 SmallVector<Attribute> operands;
269 operands.push_back(attr);
272 SmallVector<Attribute> result;
273 bool hasPoison =
false;
274 auto folded =
getMap().constantFold(operands, result, &hasPoison);
275 if (failed(folded) || hasPoison || result.size() != 1) {
278 return result.front();
287 return emitOpError() <<
"input type " <<
getInput().getType() <<
" and output type "
288 <<
getResult().getType() <<
" are not unifiable";
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
static constexpr ::llvm::StringLiteral getOperationName()
::mlir::IntegerAttr getNumDimsAttr()
::mlir::OpFoldResult fold(FoldAdaptor adaptor)
::llvm::LogicalResult verify()
GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute > > FoldAdaptor
::mlir::AffineMap getMap()
::mlir::FlatSymbolRefAttr getConstNameAttr()
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::llvm::LogicalResult verifyRegions()
::mlir::Region & getInitializerRegion()
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::mlir::Type getType()
Returns the type of the poly.yield op in the initializer region.
::std::optional<::mlir::Type > getTypeOpt()
static constexpr ::llvm::StringLiteral getOperationName()
OpT getConstNamed(::mlir::StringRef find)
Return the op of type OpT with the given name within the body region if it exists,...
bool hasConstNamed(::mlir::StringRef find)
Return true if there is an op of type OpT with the given name within the body region.
::llvm::LogicalResult verify()
Verify the optional transform-carried name pattern against current parameters.
static constexpr ::llvm::StringLiteral getOperationName()
size_t numConstOps()
Return the number of ops of type OpT within the body region.
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::llvm::LogicalResult verify()
::mlir::TypedValue<::mlir::Type > getInput()
::mlir::TypedValue<::mlir::Type > getResult()
static constexpr ::llvm::StringLiteral getOperationName()
::mlir::TypedValue<::mlir::Type > getVal()
static constexpr ::llvm::StringLiteral getOperationName()
constexpr llvm::StringLiteral TEMPLATE_NAME_PATTERN_ATTR
Metadata carried across transformation passes preserving the literal chunks of a partially-instantiat...
bool isInTemplate(Operation *op)
FailureOr< TemplateOp > verifyInTemplate(Operation *op)
mlir::FailureOr< SymbolLookupResultUntyped > lookupTopLevelSymbol(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, mlir::Operation *origin, bool reportMissing=true)
std::optional< mlir::SymbolTable::UseRange > getSymbolUses(mlir::Operation *from)
Get an iterator range for all of the uses, for any symbol, that are nested within the given operation...
FailureOr< TemplateOp > getConstResolutionTemplate(SymbolTableCollection &tables, Operation *origin)
OpClass getParentOfType(mlir::Operation *op)
Return the closest surrounding parent/ancestor operation that is of type 'OpClass'.
LogicalResult verifyTypeResolution(SymbolTableCollection &tables, Operation *origin, Type ty)
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)